AI Coding / From Assistants to Agents
How a tool sees a whole codebase.
Reviewed by Yuvaraj
A production codebase can run to millions of tokens, while a model's context window holds only a small fraction of that. Yet capable AI coding tools routinely make correct changes across repositories they have never fully loaded. They manage this not by reading everything, but by reading the right things. Repository understanding is the discipline of selecting, from a large repository, the minimal set of files, symbols, and signals a model needs to answer one specific request, and no more.
The model reasons only over the tokens currently in its window. The other several hundred files effectively do not exist for that inference call. Provide too little of the relevant code and the model invents APIs that were never defined; provide too much and the useful signal is buried among distractors while cost and latency climb. Precision, not volume, is the goal.
For a curious beginner
Picture a brilliant consultant with no long-term memory who can only read the pages you place in front of them. Hand over the wrong pages and they will confidently guess; hand over a thousand and they lose the thread. Your job is to hand them exactly the pages that matter for this question.
How it is actually used
The tool sits between the repository and the model. Given a request, it retrieves candidate code, ranks it, and packs the highest-value spans into a fixed token budget. A missed file becomes a hallucinated API; an over-stuffed prompt lowers the signal-to-noise ratio and inflates cost with no accuracy gain.
The underlying mechanism
Treat the window as a budget . Each candidate chunk has a relevance and a token cost ; selection maximizes subject to , a knapsack problem. Because attention spreads across every token, each added irrelevant chunk actively dilutes the useful ones, so recall and precision both matter.
Ask about this lesson, or about anything in AI. Answers cite the lessons they draw on.
Finished this lesson?
Mark it complete to earn XP, keep your streak, and schedule a review.
No single method suffices, so tools combine several. Semantic retrieval embeds files or chunks as vectors and returns the nearest neighbors of the embedded query, strong for intent-based questions such as "where is authentication handled?" where the wording does not match. Lexical and symbol search answer exact questions: ripgrep for raw text, and structural tools such as ctags, tree-sitter, and the Language Server Protocol (LSP) for where a symbol is defined and everywhere it is used. Dependency and call-graph traversal expands from a seed file along imports and call edges to its callers, callees, and types. Finally, cheap project signals, the README, configuration, and tests, reveal conventions and intended behavior.
| Technique | Answers | Precision | Tooling |
|---|---|---|---|
| Semantic retrieval | Where is a capability handled? | Fuzzy | Embeddings and a vector index |
| Symbol / reference lookup | Where is a symbol defined or used? | Exact | LSP, ctags, tree-sitter |
| Lexical search | Where does this text appear? | Exact | grep / ripgrep |
| Graph traversal | What depends on this file? | Structural | Import and call graph |
Fuzzy finds, exact confirms
Semantic retrieval is good at locating the neighborhood of relevant code; symbol and reference lookup is good at being complete within it. Robust tools use the first to seed and the second to guarantee coverage.
getUser everywhereConsider the request "rename the function getUser everywhere and update its callers." Loading the whole repository would be wasteful and may not even fit the window. Instead the tool works structurally, pulling in only what the edit touches.
Only a handful of files ever enter the context, yet the change is complete and verifiable, because the selection was driven by the code's structure rather than by a fuzzy guess.
These two strategies trade simplicity against scale, and the right choice depends almost entirely on repository size.
Common mistakes