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 ↓
768,268
tokens — the 66 changed files, pasted whole
43,769
tokens — what diffctx selects instead
17.6× smaller
at the default budget, one command

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. One of the 66 files is a 158k-token generated test snapshot; without it the whole-file baseline is 610k and the ratio 13.9×. Against the other baseline — the raw git diff of the same commit, 169,809 tokens — it is 3.9×, and the selection carries the callers, types and config the patch alone does not show. 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 768,268 → 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

--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).