On this page
- How to read these results
- Is the call graph correct?
- Source audit across nine languages
- 1. Finding the right files
- How this number moved
- 2. What changes in a real agent loop
- The column that is not about any tool
- Why tokens and not dollars
- Where the saving is largest
- 3. Loading one commit's context
- 4. Command-output compression
- 5. Code health predicts defects
- 6. What it costs to run
- Limits
How to read these results
Each result names the population, competing field, control, and statistical test that produced it. Retrieval uses a sealed test split with deterministic grading. Agent-loop comparisons use byte-identical prompts and freshly built indexes on the same pinned commit.
A headline number is only useful when the denominator and the failure conditions stay attached to it.
This report keeps precision beside coverage, files served beside retrieval, and tool adoption beside token reduction. It separates one-payload compression from work saved across a complete agent session. Rows that fail their own controls are retained in the raw record and excluded from the claim.
Pre-register
Commit the question and expected test before a scored run spends anything.
Seal a split
Keep the held-out instances untouched until the final measurement.
Prove each arm is alive
A dead server and a weak tool both produce a plausible zero.
Publish the losses
A trade-off remains in the record even when it weakens the headline.
Independent reruns explain why these controls matter. JetBrains measured 8.5% against a claimed 65% saving for Caveman, while RTK's claimed 60 to 90% became 7.6% more expensive at low reasoning effort. Greptile's 82% became 45% under Augment's rerun. Measuring one context payload is easy. Measuring the work across a complete agent loop is harder.
One payload, not a session. It says our representation of a commit is smaller than the commit. Whether an agent finishes faster is a different question, and its answer is the more modest 31.6%. One repository, one commit, one prompt, and single-session questions of four to seven turns. Not a universal saving.
Is the call graph correct?
A call graph can fail in two directions: miss calls that are real, or invent calls that are not. Precision measures how many emitted edges are real. Recall measures how much of the real graph was found. Either number is easy to game alone, so this report keeps them paired.
Across seven compiler-graded cells, no measured tool that finds as much of the graph as Repowise gets more of it right.
The answer keys come from the Go team's own call-graph implementation and the TypeScript compiler's resolution of call sites. Repowise does not control either oracle. The field contains five tools and 37,853 oracle edges.
Compiler-graded call-graph quality
Precision / recall against call graphs generated by the Go and TypeScript toolchains. Both numbers must be read together.
Table view
| Oracle cell | Repowise | CodeGraph | codebase-memory | Graphify | code-review-graph |
|---|---|---|---|---|---|
| cobra / tests | 0.972 / 0.684 | 0.929 / 0.763 | 0.912 / 0.743 | 0.971 / 0.433 | 0.997 / 0.174 |
| gitleaks / no tests | 0.976 / 0.955 | 0.972 / 0.920 | 0.934 / 0.967 | 0.997 / 0.886 | 0.759 / 0.026 |
| gitleaks / tests | 0.974 / 0.914 | 0.971 / 0.895 | 0.922 / 0.945 | 0.995 / 0.832 | 0.800 / 0.032 |
| syft / no tests | 0.943 / 0.513 | 0.872 / 0.508 | 0.635 / 0.542 | 0.771 / 0.447 | 0.968 / 0.201 |
| syft / tests | 0.950 / 0.322 | 0.864 / 0.338 | 0.673 / 0.361 | 0.802 / 0.273 | 0.966 / 0.086 |
| zod / no tests | 0.992 / 0.703 | 0.729 / 0.373 | 0.987 / 0.694 | 0.825 / 0.248 | 0.932 / 0.652 |
| hono / no tests | 0.977 / 0.731 | 0.805 / 0.684 | 0.949 / 0.686 | 0.980 / 0.688 | 0.966 / 0.691 |
Scroll the table sideways to see every column.
Precision / recall in every cell. Five tools, seven cells, 37,853 oracle edges. No tool that finds as much of the graph as Repowise gets more of it right in any cell. Repowise does not lead recall in the five Go cells and is most precise outright in only one cell.
Source audit across nine languages
Compiler oracles cover Go and TypeScript. The wider audit uses the same seeded, stratified source-reading protocol on nine languages, with thirty rows per language per tool. Every graded call site and verdict is public.
Read our result in reverse too: roughly fifteen percent of the sampled Repowise edges were wrong. Four language cells separate from CodeGraph and five are ties. This is a two-tool comparison and does not transfer to the wider compiler field.
Source audit across nine languages
Thirty stratified call edges per language per tool, read from source with imports and enclosing scope open.
| Tool | Correct / n | 95% CI |
|---|---|---|
| repowise | 229 / 270 = 84.8% | 80.0–88.6 |
| CodeGraph 1.5.0 | 154 / 270 = 57.0% | 51.1–62.8 |
Scroll the table sideways to see every column.
540 rows across nine languages. Four language cells separate and five are ties. This comparison covers Repowise and CodeGraph only; the compiler-oracle table above covers the five-tool field on Go and TypeScript.
01Finding the right files
Before a tool can save an agent any work, it has to point at the right code. This section measures only that. Grading is deterministic and no LLM judge is involved anywhere in the number, which makes it the most reproducible result on the page: ContextBench ships gold file spans, and a tool either returns them or it does not.
Every figure below comes from instances this work has never seen. The 112 instances were split 70 / 42 by instance id, pinned before any of it started, and the 42 were kept sealed until the final measurement.
Finding the right files
File coverage on 42 ContextBench instances pinned before any of this work started and kept sealed until the final measurement. Grading is deterministic and no LLM judge is involved.
| Tool | File coverage | Precision | Files served |
|---|---|---|---|
| repowise (get_answer) | 0.876 | 0.087 | 19.2 |
| repowise (search_codebase) | 0.742 | 0.168 | 8.2 |
| CodeGraph | 0.610 | 0.093 | 14.0 |
| Graphify | 0.546 | 0.033 | 34.5 |
| code-review-graph | 0.445 | 0.240 | 5.4 |
Scroll the table sideways to see every column.
n = 42 sealed instances. Head to head against CodeGraph, get_answer wins 19, loses 1, ties 22, sign test p = 0.00004. The pooled 112-instance figure would be 0.835 and is deliberately not quoted: averaging the halves loses the only number that matters, which is how the tool does on instances it has never seen.
These are two different tools with two different profiles, and we would rather say so than average them into one claim. get_answer finds the most, from a list of about 19 files. search_codebase finds fewer but is the most efficient per file served, and if you are paying by the token that is the row to read.
| Tool | File coverage | Files served |
|---|---|---|
| repowise (get_answer) | 0.876 | 19.2 |
| repowise (search_codebase) | 0.742 | 8.2 |
| CodeGraph | 0.610 | 14.0 |
| Graphify | 0.546 | 34.5 |
| code-review-graph | 0.445 | 5.4 |
n = 42 sealed instances. Head to head against CodeGraph, get_answer wins 19, loses 1, ties 22, sign test p = 0.00004. The pooled 112-instance figure would be 0.835 and is deliberately not quoted: averaging the halves loses the only number that matters, which is how the tool does on instances it has never seen.
How this number moved, and why it is not benchmark tuning
We first ran this and came last, at 0.228. We published that. The cause turned out to be a bug: a query-time gate was discarding most candidates before ranking ever happened. Fixing that path is what moved the number, and it is a fix any user of the tool gets rather than a change shaped around these questions.
The check on that claim is the split, and it points the right way. Our score on the sealed half we never saw, 0.876, is higher than our score on the half we tuned against, 0.810. Overfitting makes the unseen half score worse.
And CodeGraph, which nobody tuned against either half, scores 0.6093 and 0.6095 on the two halves. Three decimal places apart. So the halves are equally hard and the gap is about the tool rather than about the questions.
We do not quote a pooled 112-instance figure, though it is easy to compute and would read 0.835. Averaging the halves loses the only number that matters, which is how the tool does on instances it has never seen.
Every arm builds its own index of every instance's repository at that instance's own base commit. Roughly 78 machine-hours for 1,129 graded cells. How we measured · raw data
02What changes in a real agent loop
This is the section modelled on the JetBrains reruns, and the one we would ask a skeptic to read first. Six arms: repowise, four competing tools, and a bare agent with no tools at all. Every arm got a byte-identical prompt, its full advertised tool surface, and a freshly built index on the same pinned commit. The bare-agent control was verified free of any local hooks, so it is a real control rather than a contaminated one.
Two things have to be true for a tool to be worth mounting. The agent has to actually call it, and the loop has to get leaner when it does. We ran this on two agent harnesses, because the answer turned out to depend on the harness as much as on the tools.
| Tool | Output tokens | vs bare agent |
|---|---|---|
| repowise | 1,250 | -31.6% |
| CodeGraph | 1,383 | -24.4% |
| Serena | 1,550 | -14.8% |
| Graphify | 1,658 | -8.9% |
| code-review-graph | 1,710 | -6.0% |
| bare agent (control) | 1,828 | baseline |
Codex (gpt-5.6-sol) on django/django at one pinned commit. Correcting for testing five tools at once, three reductions are solid and two are marginal. 5 of the 48 questions are missing from every arm equally because the run hit an API usage cap, so the figures are over the 43 questions all six arms completed; because all arms lost the same 5, the paired comparisons are unaffected.
What changes in a real agent loop, on Codex
Every question in django's question set, six arms, byte-identical prompts, each tool's full advertised surface, and a freshly built index on the same pinned commit. Every tool was called on every question, so this is like for like.
Table view
| Tool | Agent used it | Output tokens | vs bare agent | Tool calls | Leaner on | p |
|---|---|---|---|---|---|---|
| repowise | 44 / 44 | 1,250 | -31.6% | 3.8 | 37 of 44 | <0.0001 |
| CodeGraph | 44 / 44 | 1,383 | -24.4% | 4.0 | 37 of 44 | <0.0001 |
| Serena | 43 / 43 | 1,550 | -14.8% | 10.1 | 35 of 43 | <0.0001 |
| Graphify | 43 / 43 | 1,658 | -8.9% | 7.4 | 31 of 43 | 0.003 |
| code-review-graph | 43 / 43 | 1,710 | -6.0% | 7.2 | 26 of 43 | 0.046 |
| bare agent (control) | 0 / 44 | 1,828 | baseline | 7.2 | n/a | n/a |
Scroll the table sideways to see every column.
Codex (gpt-5.6-sol) on django/django at one pinned commit. Correcting for testing five tools at once, three reductions are solid and two are marginal. 5 of the 48 questions are missing from every arm equally because the run hit an API usage cap, so the figures are over the 43 questions all six arms completed; because all arms lost the same 5, the paired comparisons are unaffected.
repowise leaves the agent with the least work to do, and gets there in the fewest steps: 3.8 tool calls against the bare agent's 7.2, and 3.0 files opened instead of 7.2. One answered question replacing roughly six greps, visible directly in the call counts rather than inferred.
Correcting for testing five tools at once, three reductions are solid and two are marginal. CodeGraph is a genuine second at -24.4%, and the honest reading is that we lead a field in which more than one tool works, not that we are the only one that does. Serena is the interesting counter-case: it writes less than the bare agent while calling tools 42% more often. Busier, not leaner.
The second proof point, on Claude Code
The same six arms, the same servers and the same indexes, on a different agent harness. The result depends on the harness as much as on the tools.
Table view
| Tool | Tools advertised | Schema cost (chars) | Agent used it | Output tokens | vs bare agent | p |
|---|---|---|---|---|---|---|
| repowise | 10 | 17,561 | 15 / 15 | 2,420 | -15.9% | 0.035 |
| CodeGraph | 1 | 1,567 | 13 / 15 | 2,540 | -11.7% | 0.302 |
| Serena | 29 | 29,050 | 4 / 15 | 2,551 | -11.3% | 1.000 |
| code-review-graph | 30 | 28,118 | 0 / 15 | 2,768 | -3.8% | 0.302 |
| Graphify | 10 | 5,482 | 3 / 15 | 2,878 | 0.0% | 1.000 |
| bare agent (control) | 0 | 0 | n/a | 2,877 | baseline | n/a |
Scroll the table sideways to see every column.
Claude Code (claude-sonnet-5), 15 questions. Treat the "agent used it" column as unstable, including our own 15 of 15: rerunning the same setup on later days returned 4 of 15 and then 3 of 15 for us, and 2 of 14 for CodeGraph. It is a property of the pairing of tool and harness on a given day, not of the tool. No quality or cost figure may be compared across the two harnesses, which were graded by different judges.
The column that is not a fact about any tool
Under Claude Code most of these tools were barely called at all. code-review-graph never once, Graphify three times in fifteen. Nothing was different about the servers, the questions or the indexes between the two runs. Claude Code loads MCP tool schemas on demand, so the agent has to go looking before it can call anything, and frequently never does.
Treat that column as unstable, including our own 15 of 15.
Rerunning the same setup on later days returned 15 of 15, then 4 of 15, then 3 of 15 for us, and 2 of 14 for CodeGraph. Whether an agent calls a codebase server at all depends more on the harness than on the server. We used Sonnet here, and Sonnet reaches for MCP tools noticeably less than Codex does under an identical setup, so harness and model cannot be separated by this design. We plan to rerun this half on Opus and will add the result when we have it.
One thing this run does not show: it is a work-saved result, not a quality result. A blind judge scored every tool in the field, ours included, a fraction below the bare agent, in a range of 0.04 to 0.25 points on a 10-point scale. None of those differences is statistically distinguishable from zero, and all of them are smaller than the 0.69 points by which this benchmark moves when we rerun it unchanged. Ours is at the low end of that band, we are watching it, and we will say so if it turns into a real effect.
Why this section reports tokens and not dollars
Dollar cost per question is the number every tool in this category wants to quote, and it is close to meaningless as a measure of a tool. Here is the control that convinced us, run in our own harness.
A tool that did nothing came out 43% cheaper than the bare agent.
Under Claude Code, code-review-graph never called its server across all 15 questions. It is behaviourally identical to the bare agent, carrying an extra 28,118 characters of tool schema that should make it cost more. Measured on dollars, it produced a best-in-class saving.
The cause is prompt caching. Cached tokens bill at a fraction of fresh ones, so whichever arm happens to run first pays to warm the cache and every arm after it reads it cheaply. In our run the correlation between an arm's position in the cycle and its dollar cost was -0.487. That is not a property of any tool. It is a property of the schedule.
Output tokens are immune to this. They are never cached, and their correlation with run position is +0.010, which is nothing. So that is what we report. It is a smaller and less impressive number than the dollar figure would have been, and it is the one that survives. If you see a token-savings claim in this category that does not say whether it controls for cache state and arm ordering, this is the first thing to ask about.
Where the saving is largest
The effect is not uniform. repowise saves more on questions that require touching more of the codebase. Splitting the question set at the median by how much work the bare agent needed, the harder half saved 34.3% against the easier half's 27.2%, more than twice as many tokens per question, and the correlation between how much work a question demands and how much we save is +0.379. The mechanism is that pre-computed structure replaces exploration, and harder questions contain more exploration to replace.
Two honest limits on that. The median split was chosen after seeing the data, so it is post-hoc and weaker evidence than the pre-registered comparisons. And every question here is answered in a single session of roughly four to seven turns: we have not measured a long multi-hour task such as designing a feature across many files, and we will not imply a number for one.
About 13 hours of machine time and roughly $44 of API spend. Around a third of those runs are proof-of-life checks rather than headline numbers. How we measured · raw data
03Loading one commit's context, the easy number
This is the measurement almost every tool in this category publishes, and we are labelling it as such. It is a real measurement. It is not section 2, and it should not be read as though it were.
Loading one commit's context
The measurement almost every tool in this category publishes, labelled as such. Counted with deterministic tiktoken over the 30 most recent non-merge commits of pallets/flask.
| Strategy | Tokens per commit |
|---|---|
| naive, full contents of every changed file | 13,984 |
| git diff only | 1,408 |
| get_context | 393 |
Scroll the table sideways to see every column.
35.6x fewer than naive pooled, 29.3x as a mean of per-commit ratios, and 3.6x pooled against git diff. This is one payload, not a session. It says our representation of a commit is smaller than the commit; it does not say an agent finishes faster.
Lead with the pooled figure. Pooled is sum-of-tokens over sum-of-tokens, so it weights each commit by the tokens actually at stake. A mean of per-commit ratios does not: a one-line commit where get_context returns 40 tokens contributes a huge ratio that counts equally against a commit saving a hundred thousand. That is exactly how a 35x becomes a 209x in a press release, and it is why the pooled number is the one we print first.
04Command-output compression
repowise distill compresses command output before the agent reads it: errors first, exit code preserved, every omission recoverable through an inline marker. A pytest run with 11 failures compresses 61% with all 11 failure lines kept, and a 30-commit diff compresses 86%.
Two commands in the same set saved 0%, because distill never inflates output that is already compact. Reduction is also not comprehension: the bytes removed are measured, and the evidence they were safe to remove is narrower, being preserved failure lines plus CI-asserted fixtures.
05Code health predicts defects
A health score is worth something only if the files it flags are the files that break. Scores are taken at a historical commit, bug fixes are counted over the following six months, and nothing after the scoring commit feeds the score. Across 21 repositories, 9 languages and 2,826 files that gives an ROC AUC of 0.74, reaching 0.90 on individual repos. It survives controlling for file size, so it is not simply flagging the big files, and it beats recent churn by +0.10 AUC.
Code health against CodeScene
Both tools scored the same 2,770 files at the same leakage-free commit against the same defect labels. Paired tests throughout.
| Paired test | repowise | CodeScene | p |
|---|---|---|---|
| Recall at a 20%-of-lines review budget | 0.173 | 0.074 | 0.003 |
| Effort-aware ranking (Popt) | 0.607 | 0.462 | 0.003 |
| Defect density, size-normalized (Alert:Healthy) | 2.18x | 0.56x | 0.003 |
| Discrimination (ROC AUC) | 0.731 | 0.705 | 0.054, marginal |
| Precision at a 20%-of-lines review budget | 0.580 | 0.636 | 0.64, a tie |
Scroll the table sideways to see every column.
CodeScene's precision lead is not statistically significant, but the behaviour behind it is worth having: it flags about 27 files where we flag 132. That is a more conservative threshold, trading recall for a short list a team will actually work through, and it is a deliberate design choice rather than a weaker model. Our AUC edge is marginal, not significant at 0.05.
Where CodeScene is ahead, it is a real choice rather than a weaker model. Its nominal precision lead is not statistically significant, but the behaviour behind it is worth having: it flags about 27 files where we flag 132. That is a more conservative threshold, trading recall for a short list a team will actually work through. If what you want is a handful of files to fix this quarter rather than the ranking that catches the most defects, that operating point is the better one.
06What it costs to run
Two different clocks answer two different questions. Building only the call graph, Repowise has the lowest measured memory footprint and is roughly level on speed. Building the complete index, Repowise is the slowest tool in the field because it also mines git history, generates and embeds documentation, extracts decisions, and scores code health.
Call-graph construction cost
Graph construction only across the same 35 repositories. Three timed runs per cell after a discarded warmup; 175 cells and no failures.
| Tool | Median build | Median peak memory | Fastest on |
|---|---|---|---|
| repowise | 2.77s | 75 MB | 14 of 35 |
| CodeGraph | 3.65s | 757 MB | 16 of 35 |
| codebase-memory-mcp | 6.21s | 1,113 MB | 5 of 35 |
| code-review-graph | 9.97s | 361 MB | 0 |
| Graphify | 12.23s | 860 MB | 0 |
Scroll the table sideways to see every column.
Memory is a clean sweep: Repowise is lowest on 35 of 35 repositories. Speed is level rather than a win; CodeGraph is fastest on 16 repositories and Repowise on 14. Repowise builds this arm in memory without serialization, while CodeGraph writes SQLite.
Indexing time, the row we lose
We are the slowest indexer in the field, on every repo we measured, and it is not close. Measured on django/django.
| Tool | Index time | What it builds |
|---|---|---|
| CodeGraph | 16.4s | call graph |
| code-review-graph | 44.8s | call graph |
| Graphify | 141.5s | call graph, communities |
| repowise (--no-prose) | 366.8s | graph, git history, decisions, code health |
| repowise (default, prose on) | 1,058s | all of the above plus generated documentation |
Scroll the table sideways to see every column.
22x CodeGraph like for like, and 135x with prose on, which is what a default repowise init actually costs you. Both numbers ship. The reason is not an optimisation we forgot: in that same run repowise built 36,485 graph nodes, mined history across 2,630 files, rendered and embedded 3,392 wiki pages, extracted decision records and produced 5,317 health findings. It is also a one-time cost, since updates after the first index are incremental.
So "22x slower" and "the index contains categorically more" are both true, and neither one cancels the other.
If all you want is a call graph, CodeGraph builds one in 16 seconds and you should use it. The comparison that would be dishonest is quoting the ratio without the column beside it, which is why the column is there. It is also a one-time cost: updates after the first index are incremental.
Limits
Beyond the ones stated in each section:
- Retrieval is Python and Go. The compiler graph benchmark covers Go and TypeScript, and the source audit covers nine languages. Scope does not transfer from one section to another.
- Section 2 is one repository at one commit, which is in every model's training data.
- Nothing here measures a long engineering task. Every question is a single session of roughly four to seven turns.
- Precision is one half of graph quality. Repowise leads no Go recall cell against the compiler oracle and loses cross-file coverage on part of the build corpus.
- Two capability rows are not measured at all: documentation generation against DeepWiki, Google Code Wiki and Swimm, and PR review against CodeRabbit and Greptile. We would rather say "not measured" than let a checkmark do a number's job.
The full methodology, the pre-registration files with their commit timestamps, the arm-parity rules, the statistical tests, and the list of measurement traps that produced wrong numbers before we caught them all live in one repository. So does every raw run, kept permanently, including the invalidated ones with their invalidation notes attached.
repowise-bench