Skip to content
DiffwrightBeta

article

Find a PR discussion without knowing its words

Describe what you remember in your own words and Diffwright finds the PR or thread that discusses it. The model ships with the app.

All articles8 min read

You remember the discussion happened. You don’t remember the words. With 0.16.1, Diffwright searches your Pull Requests by meaning: a model installed with the app compares ideas instead of words, right on your computer. It’s in beta, the numbers come from a test corpus, and this post also covers what the feature doesn’t do yet.

At a glance

  • Type your question in your own words in ⌘K (“why did we drop the avatar cache?”): Diffwright looks for the PR, description or discussion thread that covers it, even when it was phrased differently.
  • A single “Results” list ranks PRs, comments and passages found by meaning together. Each row tells you why it’s there.
  • In a PR’s Info tab, the “Similar Pull Requests” card shows past PRs about the same thing.
  • Search runs on your computer: the model is installed with Diffwright, there’s no account and no API key, nothing is sent over the network for search, and nothing is written to the platform.
  • Available from 0.16.1 on Apple Silicon Macs and Windows. Not on Intel Macs.

We remember the meaning, not the words

In Contoso’s atlas-identity repository, someone explained a few months ago why users were being logged out after fifteen minutes. You can’t recall whether the PR said “timeout,” “expiry,” “session” or “token,” or whether it was written in English or French. Keyword search makes you guess the author’s word. Guess wrong and it finds nothing, and you can’t tell whether the discussion simply doesn’t exist.

Search by meaning starts from the other end. It compares what texts say, not which letters they contain: “logged out after fifteen minutes” can find a PR titled “Fix session timeout” without a single word in common.

What you see in ⌘K

From three characters on, search shows a single group, “Results.” PRs found by their title, comments (comment search was covered in the previous post) and passages found by meaning are ranked together by relevance. No more “PRs first, comments second.”

Each row shows:

  • where the match comes from: Title, Comment, Description or Meaning;
  • its “temperature,” as three bars: Very relevant, Relevant or Uncertain;
  • the matching excerpt, with your words highlighted when that helps.

A result found by meaning alone has to clear a closeness threshold to appear at all, and it stays marked “Uncertain” until the words or a comment back it up. Diffwright would rather show you fewer results than an unrelated one presented with confidence.

Search is also simpler: the “Meaning only,” “Everywhere” and “Sort” buttons are gone. It searches all projects (turning off Settings › Synchronization › “Search all projects” limits it to your favorites) and picks the order itself: relevance when you type text, signals (to review, recent) when you only use filters.

Two keyword-search improvements come along, with or without search by meaning:

  • PR descriptions are read: a word in a description brings the PR up (after the index next reads that PR; the title still ranks first);
  • fewer false matches: a word of four letters or more is no longer “found” in a long title where its letters just happen to be scattered. Typos are still tolerated.

How it works, without the jargon

For every Pull Request in the index, Diffwright splits the text into fragments: one for the header (title, description, branch names) and one per discussion thread. A compact model, EmbeddingGemma (released by Google, about 300 million parameters), turns each fragment into a series of numbers that captures its meaning. This model doesn’t write anything and doesn’t answer questions: it only measures how closely two texts talk about the same thing. The numbers are stored in the local search database, next to the word index.

When you search, two methods work together:

  • words, unbeatable for an identifier: a PR number, a function name, a branch name;
  • meaning, which catches rephrasings, synonyms and, to some extent, other languages.

Their results are merged into one list. In practice, for an everyday question it’s mostly meaning that does the ranking; for an identifier, it’s the words.

Measured on a test corpus, not on your team

The numbers below come from a synthetic corpus of 2,400 PRs and 114 questions, measured on October 14, 2026, on an M4 Pro Mac. They compare the methods with each other; they don’t predict what you’ll get on your own repositories. The metric: the share of expected PRs that show up in the top ten results.

Kind of questionWords onlyMeaning onlyWords + meaning
All questions36%52%61%
Rephrased, no word in common with the PR4%43%43%
Asked in the other language1%32%32%
Exact identifier (number, function name)100%55%100%

What to take away:

  • on a rephrased question, words alone find almost nothing, while meaning finds a little under half of the expected PRs;
  • across languages, meaning helps, but modestly: about one time in three;
  • the combination keeps the precision of words on identifiers, where meaning alone falters.

As for speed, turning the question into numbers takes about 37 ms, and the search itself up to about 26 ms on an index of 80,000 fragments: roughly 40 to 70 ms in total. Windows hasn’t been measured.

One caveat: the corpus’s “rephrased” questions were deliberately written with no word in common with their PR, the worst case for keyword search. Real teams reuse the words of their PRs more often. Relevance on a real history hasn’t been measured yet, and the tuning may change once it is.

What stays on your computer

  • The model is installed with Diffwright. The app doesn’t download a model, doesn’t need an account or an API key, and nothing is sent over the network for search. Offline, you search what’s already indexed; indexing itself needs to read the platform.
  • The index lives in ~/.diffwright/search/. You can purge it one repository at a time, or all at once, from Settings.
  • It doesn’t go through any AI engine (not claude, not Ollama, not an API-key provider) and doesn’t depend on the AI setting: turning AI off doesn’t turn search by meaning off. To turn it off, go to Settings › Semantic search.

That convenience has a cost, and you should know it:

  • the model weighs about 330 MB, which makes the installer and updates heavier;
  • once loaded, it uses about 1.1 GB of memory (development measurement); it only loads when first needed and is released after five minutes without indexing or searching;
  • it comes with its own terms (Google’s Gemma Terms of Use), reproduced in the “Licenses and legal notices” window (About).

Indexing that reads and never writes

Search by meaning is on by default. A first pass starts about 45 seconds after launch, then indexing continues in the background at low priority, and backs off on low battery, in power-saving mode or on a metered network.

It only reads, with a cap on requests per hour: 600 on Azure DevOps, 300 on GitLab, 150 on GitHub. It respects each platform’s rate limit and backs off when asked. No comments, no votes, no writes.

On Azure DevOps, that cap works out to about 300 to 600 PRs per hour. On a large organization, the first indexing pass therefore takes several hours of the app being open: 3,000 PRs is on the order of 5 to 10 hours. On GitHub and GitLab, only PRs Diffwright already knows (opened in the app, or received through notifications) are indexed.

In Settings › Semantic search, you can:

  • turn the feature on or off;
  • follow progress, pause it and resume it;
  • choose which repositories are indexed;
  • set the indexed history, from 6 months to 5 years (24 months by default);
  • see how much disk space it uses, and purge one repository or the whole index.

For a sense of scale: on the test corpus, a fragment takes about 900 bytes on disk, roughly 90 MB for 80,000 fragments. Discussions longer than the corpus’s will produce more fragments per PR.

“Similar Pull Requests”: the precedent at hand

During a review, the last card in the Info tab lists the PRs closest to the one you’re reading, labeled “Very similar” or “Similar,” never with a score. It helps at three moments:

  • spotting a duplicate before you comment;
  • finding a precedent (“we already handled this on the API side”);
  • understanding why a decision was made elsewhere.

A click opens the PR; ⌘-click (Ctrl-click on Windows) opens it in a new window. The comparison relies on the PR header: title, description and branches. On the test corpus, this was clearly more reliable than blending in every thread, because generic review remarks (“add a test”) make all PRs look alike. It reuses what’s already indexed, so the card never waits on the model.

The limits, stated plainly

  • Intel Macs: no search by meaning; the inference engine Diffwright uses isn’t available prebuilt for these Macs. Keyword search, descriptions included, works as usual.
  • macOS 13.4 minimum: Diffwright now requires macOS 13.4 or later.
  • Windows: the feature hasn’t been tried on a real Windows machine yet. If it misbehaves, turn it off in Settings › Semantic search and let me know: [CANAL-DE-RETOUR].
  • No real organization yet: relevance, request caps and indexing times haven’t been verified on a real organization. The numbers in this post come from the test corpus.
  • Code isn’t indexed: search by meaning covers PRs, their descriptions and their discussions, not file contents.
  • GitHub and GitLab are in beta in Diffwright, and only PRs the app already knows are indexed.
  • 0.16.0: its installers shipped without the model, which hid the feature. Update to 0.16.1.

Also in 0.16

  • GitHub and GitLab in the setup assistant. The “Connection” step offers Azure DevOps, GitHub and GitLab as cards you can drive with the arrow keys and ↵, with token-creation help for each platform. With a single project or repository, the assistant no longer offers favorites.
  • Shortcut help (⌘/) you can filter. Type a few letters: it finds a shortcut by its label or its keys, and lists the ones for the space you’re in first.
  • Collapsed panels you can read. The collapsed Review strip spells it out: “20/389 files reviewed,” “15 pending,” “7 open threads.”
  • A risk score that doesn’t falsely reassure. When Diffwright has only measured some of the files, the Risk card says “at least medium” or “incomplete” instead of “low.”

Try it

Update Diffwright to 0.16.1 from the app, or download it. Open ⌘K (Ctrl+K on Windows) and ask the question the way you’d ask a colleague. The answer comes from your own PRs, and the search runs on your computer.

Diffwright is in beta. Search by meaning is available from 0.16.1 on Apple Silicon Macs (macOS 13.4 or later) and Windows.