Compare

Graph Indexer vs grep for AI coding agents

Graph Indexer vs grep: a name search gives 12.8% real references on nestjs, Graph Indexer 99.7%. Side-by-side table and when grep is still the right tool.

Updated Graph Indexer 3.0.0 View as Markdown

Graph Indexer answers “who really uses this function?” with 99.7% precision against the TypeScript compiler on nestjs, while grep for the same names returns only 12.8% real references. Grep is exact about text but blind to meaning, so an AI coding agent that greps a name has to read the false hits to discard them. Graph Indexer binds each reference to the definition it points at, so the answer is short and the agent keeps its context for the work.

Why does grep flood an AI agent with false hits?

Grep matches the characters of a name, not the symbol behind it. A method called find or parse appears in comments, log strings, documentation, tests and in unrelated classes, and every one of those lines comes back. On 400 sampled nestjs symbols, 12.8% of the lines grep returned were real references: roughly seven false hits for every real one. On the Twenty monorepo (2.3 million lines) the share was 0.9%.

Each false hit costs the agent tokens twice: once to receive the line, and again when it opens the file to check. The checking is the expensive part, because it repeats for every hit, and the whole conversation is re-read by the model on every later call.

What does a false hit look like?

Take a class UserService with a method myFunc, and ask for its callers. Grep for myFunc returns all of this:

src/user/user.service.ts:41:  myFunc(id: string) {                 // the definition
src/user/user.controller.ts:18:  return this.users.myFunc(id);      // real call
src/user/user.service.ts:12:  // myFunc is called after login        // comment
src/user/audit.ts:33:  log("myFunc failed for", id);                  // string
docs/users.md:57:  Call `myFunc` to refresh the session.             // docs
src/team/team.service.ts:29:  this.teams.myFunc(slug);             // method of another class

Only the controller line is a caller of UserService.myFunc. find_references on that method returns the controller line and states which same-name call sites it could not bind to a definition. The comment, the string, the documentation and the call on TeamService are not in the answer. In a real repository the same pattern repeats dozens of times, which is how a name search turns into thousands of tokens of noise.

How do Graph Indexer and grep compare side by side?

grep (name search)Graph Indexer
Precision (real references among results)12.8% on nestjs, 0.9% on Twenty99.7% on nestjs, 99.9% on Twenty
Recallabout 99% (every text match)96.2% on nestjs, 92.4% on Twenty
Answer sizeevery matching line, decoys includedtypically 400 to 1,500 tokens, ranked, with unbound sites named
Understands overrides and interfacesnoyes, through the dispatch oracle
Stalenessnone, it reads the filesnone visible: the index is re-synced before every answer
Searches strings, config, docsyesyes, through search_text
Setupnonenpx graph-indexer init, Node.js 22.5+
Cost to the agentbaseline33% cheaper and 32% less time on 25 code questions

Precision and recall are measured against the TypeScript compiler; the full per-repository table is on the benchmarks page. Staleness is not a concern in practice: Graph Indexer re-syncs the changed files with the disk before each answer, so edits the agent made a second ago are included.

When is grep still the right tool?

Grep is the right tool whenever the question is about text, not about a symbol. Searching for an error message, a config key, an environment variable name, a TODO, a URL or a string in a template is a text question, and grep is exact and complete for it. Grep also needs no setup and no index, and it has the higher recall: it never misses a textual match, while Graph Indexer can miss references that depend on generics, reflection, any values or dependency-injection tokens, because it is not a type checker.

The honest division is simple. Use grep or search_text for text. Use find_references, call_graph and change_impact when the question is “what uses this symbol” or “what breaks if I change it”.

Does the agent keep grep when Graph Indexer is installed?

Yes. Graph Indexer does not remove or hide any tool. The agent keeps its own grep, file reads and edits, and gains eight read-only MCP tools. One of them, search_text, greps any text in the repository and adds the enclosing definition of each match, so even text searches come back with more context. In the benchmarks the best arrangement was grep plus Graph Indexer, not Graph Indexer alone.

The measured effect on agents, in real Claude Code sessions: code questions 16% cheaper and refactors 14% cheaper than with no index, and 12 of 12 exact answers against 9 of 12. Against grep alone, in sub-agent rounds, code questions were 33% cheaper and 32% faster on 25 tasks. Fixing real issues showed no measurable saving. Details and limits are on the benchmarks page and in the Graph Indexer FAQ.

How do I try it?

Run one command in your repository, then ask your agent a caller question.

npx graph-indexer init

It configures the agent clients it finds. For Claude Code there is also a plugin, covered in the install guide. Graph Indexer itself makes no network calls and sends no telemetry; the agent still sends what it reads to its model provider.

Frequently asked questions

Does Graph Indexer replace grep?

No. The agent keeps grep and its own file tools. Graph Indexer adds find_references, call_graph and change_impact for questions where name search is wrong, and its search_text tool still greps any text, including config and docs.

Why is grep imprecise for finding code references?

Grep matches text, not meaning. A search for a method name also returns comments, strings, docs and same-name methods of other classes. On nestjs only 12.8% of the lines grep returned for a symbol were real references.

Is Graph Indexer less complete than grep?

Slightly. Grep returns every textual match, so its recall is about 99%. Graph Indexer recall was 96.2% on nestjs, and it lists the same-name call sites it could not bind so the agent can check them.

Try it on your repo.

npx graph-indexer init
Using Claude Code? Install the plugin