codebase → context engine

The minimum code an LLM needs to review a git diff.

Instead of pasting whole files, diffctx walks the dependency graph from the changed lines outward — and stops as soon as additional context stops paying for itself. Every trade-off optimized for comprehension-per-token.

watch it work ↓
169,809
tokens — the raw git diff of the commit
43,769
tokens — what diffctx selects, callers and types included
3.9× smaller
than pasting the diff, at the default budget

Measured on home-assistant/core@1d885bd0 — “Restrict device registry entries to a single config entry and subentry”, 66 files changed — with diffctx . --diff 1d885bd0^..1d885bd0 at the default auto budget, counted with the o200k_base tokenizer. Clone the repo and run the command to reproduce it. The selection is smaller than the patch and still carries the callers, types and config the patch alone does not show. Against pasting the 66 changed files whole — 768,268 tokens — it is 17.6× (13.9× without the one 158k-token generated test snapshot among them). The ratio is not a constant: it tracks how much of the changed files is unrelated to the change, so a wide refactor across large files compresses far more than a three-file fix, where diffctx often adds tokens because it pulls in the callers and types the diff alone does not show.

01

Five stages, one pass.

This is a live model of the pipeline — a toy repository of 18 fragments, scored and selected in your browser with the same rules the engine uses: relevance decays with graph distance, selection is greedy, and the budget is a hard wall. Step through the stages, then drag the dials. The token counts here belong to this 18-fragment toy; the 169,809 → 43,769 above was measured on the real home-assistant commit it links.

diffctx · toy-repo stage 1 — diff
context
0 tokens · 0 fragments
stdout -f yaml · o200k_base
02

Six ways code is related.

A diff rarely lives inside one file. Each edge family is a separate builder; their weighted union is the graph relevance flows across.

03

Scoring modes.

Pick one with --scoring. Three signals below, plus two fusion modes — rrf and pit — that combine ego and bm25. All of them feed the same greedy selector.

ego-network: the changed nodes plus their neighbours out to a bounded depth. PPR: Personalized PageRank, a random walk that restarts at the change with probability 1 − α. bm25: lexical similarity of a fragment's identifiers to the change. rrf: reciprocal rank fusion, ranks summed by position. pit: per-item top, each fragment keeps its best rank across modes. τ: the stop threshold — selection halts once the next fragment's marginal value falls below it. o200k_base: the GPT-4o tokenizer every count on this page is measured in.

ego

--scoring ego

Bounded ego-network expansion around the changed nodes. Fast, predictable radius, natural decay with distance.

ppr

--scoring ppr --alpha 0.6

Personalized PageRank with damping α. Global view, smoother decay, catches long-range structure — at a cost in speed.

bm25

--scoring bm25

Lexical retrieval of fragments against the diff hunks. The honest baseline — and the fallback when the graph is sparse.

04

Thirty seconds.

$ uvx diffctx . --diff HEAD~1zero-install, run once via uv
$ pipx install diffctxrecommended — isolated CLI
$ pipx install 'diffctx[mcp]'+ MCP server for Claude Code / Cursor / Zed
$ diffctx . --diff main..feature -cbranch context → clipboard → any LLM
$ diffctx . --diff main..feature --budget 8000the budget dial above, as a flag — hard token ceiling
$ diffctx . --diff main..feature --tau 0.2the τ dial above, raised — drop weak context, leaner output
$ diffctx graph . --summarycycles, hotspots, coupling

Free, local, offline. Works with any LLM. Python API and standalone binaries included. Theory: Budgeted Typed-Graph Retrieval for Diff-Aware Code Context Selection (Zenodo, 2026).