Repo Context: Why Tools Succeed or Fail on Big Codebases
Search, indexing, and memory files: how each tool finds what matters in 100k files.
AI coding tools work on big codebases when they can find the right slice of code for each request. Some search the repository the way a developer does, some build an index or a map of it, and the best setups add memory files that state the rules and conventions no amount of scanning can infer. Together, these let a model make sense of a hundred thousand files without reading them all.
Structured context usually beats raw volume. A model given a few relevant functions and the project's rules tends to do better than one handed half the repository, because long, noisy prompts dilute its attention. Last time we saw how verification lets you trust AI-written code. But trust also depends on the model having the right context when it writes that code, and on a big codebase that is the hardest part.
- 200k+ tokens
- Noisy context
- Lower accuracy
- Slower and more expensive
- ~10k tokens
- Relevant code only
- Higher accuracy
- Faster and cheaper
Why does a model that nails small projects fall apart on a monorepo?
A monorepo has cross-file dependencies, several languages, and years of decisions that no model can guess from a single file. Without a way to find what already exists, the model reimplements functions and ignores architectural rules. It simply lacks the information a developer who knows the codebase would have.
Imagine being dropped into a library with a million books and asked to find the one paragraph explaining why a checkout API (application programming interface) must hash user IDs before logging. You could read every book, but you would run out of time. With a card catalogue organized by topic, plus a map showing which shelves relate, you would find it in minutes. Repository context is that catalogue.
Alice, our developer from Part 3, starts the week with a feature request: add multi-factor authentication logs to a payments service. An agent that sees only the open file writes a new hashing function. A tool that can search the repository finds the shared utility in another service, reads its signature and docs, and calls it instead. The difference is a map.
How do the tools in this series find context?
The four tools in this series take three different routes, and comparing them is the quickest way to understand the trade-offs.
Claude Code keeps no index at all. It searches the repository with its tools, by file name and by text pattern, and reads the files that look relevant, the way a developer would, as What Claude Code Actually Is (an Agent in Your Terminal) explains. For broad searches it can send a subagent, which searches in its own context window and reports back only what matters. What it cannot find by searching, you tell it in CLAUDE.md, or in an AGENTS.md file, which it reads when there is no CLAUDE.md.
Cursor used to build a semantic index: it turned chunks of your code into embeddings on its servers and kept them in sync with a Merkle tree of file hashes. In July 2026 it phased that index out, because models had become good enough at searching that it no longer helped much, and its agent now searches with Instant Grep, an index built on your machine, plus an Explore subagent. Claude Code vs Cursor: How Each One Thinks tells that story in more detail.
Aider builds a repository map: a compact list of the most important classes and functions, ranked by how often the rest of the code refers to them, sent with every request within a token budget you set. Open Source Coding Agents: Aider, OpenHands, and Friends looks at how it works.
GitHub Copilot combines both approaches. According to the VS Code guide How Copilot understands your workspace, its agents use semantic search over an index (built remotely by GitHub for repositories hosted there, or locally for other folders) alongside text search, grep, file search and language intelligence such as finding usages. Without an index, they fall back to the other tools and still work.
So the field has two schools. Agentic search needs no index that can go stale, and it improves as models get better at searching. Semantic indexes find code by meaning even when you do not know its name, at the cost of building and syncing them. Many tools now mix the two.
How do enterprise indexers build a map of a huge repository?
Above the scale of one repository, companies run dedicated code intelligence platforms. These parse every source file, build a symbol graph of definitions, references and calls, keep a full-text index for keyword search, and sometimes add embeddings for search by meaning. Sourcegraph, for example, connects to code hosts such as GitHub and GitLab and indexes their repositories centrally, as its describes. Google's open-source Kythe captures what the compiler knows during your build and stores it in a language-agnostic graph that a cross-reference server can query.
But graphs and search only capture what the code is. They miss how it should be used and why decisions were made. That is where memory files come in.
What exactly goes into a memory file and why does it matter?
A memory file is a plain Markdown file of project instructions that a coding agent reads at the start of every session: conventions, architecture notes, and the commands to build and test. It gives the agent the team knowledge that scanning cannot recover.
The tools have converged on a shared convention. AGENTS.md is a simple, open format for guiding coding agents, now stewarded by the Agentic AI Foundation under the Linux Foundation, and Codex, Cursor, Gemini CLI, GitHub Copilot and others read it. Each tool also has its own file:
| Tool | Memory file it reads |
|---|---|
| Claude Code | CLAUDE.md; reads AGENTS.md when there is no CLAUDE.md, per its memory documentation |
| Cursor | .cursor/rules/*.mdc rule files, or AGENTS.md |
| GitHub Copilot | .github/copilot-instructions.md; its agents also read AGENTS.md |
| Aider | a conventions file you load with --read CONVENTIONS.md, as its conventions guide shows |
A useful checklist for what to put in one: what the system is (architecture, folder layout, technology stack), how to write code here (standards, naming, approved libraries), why things are the way they are (key decisions and constraints), and how to validate a change (the commands to run tests, lint and build).
Alice's team adds a line to its AGENTS.md: all API responses must be wrapped in a Result<T> type. The agent reads it at the start of the session and follows the rule. Without it, the agent might return raw data and break client contracts. Memory files carry the intent that scanning alone cannot recover.
How does retrieval pick the right few dozen snippets out of 100,000 files?
Retrieval combines search, graph traversal and ranking to choose a small set of context that is enough for the task. The goal is not to cram in as much code as possible but to pick the exact pieces that change what the model writes.
Research on repository-level code completion shows why this matters. RepoCoder repeated retrieval and generation in a loop, using each draft to search for better context, and improved on completion without retrieval by more than 10% in all its settings while consistently beating single-pass retrieval (Zhang et al. 2023, RepoCoder: Repository-Level Code Completion Through Iterative Retrieval and Generation). CodeRAG went further: it builds its search queries guided by the code model's own probabilities, searches several ways at once, and reranks the results with a BestFit reranker aligned to what the model will actually use (Zhang et al. 2025, CodeRAG: Finding Relevant and Necessary Knowledge for Retrieval-Augmented Repository-Level Code Completion).
The RepoExec benchmark measured the failure Alice saw, a model writing its own version of a function that already exists. It introduced the Dependency Invocation Rate (DIR), which counts how often generated code actually calls the dependencies it was given (Hai et al. 2024, On the Impacts of Contexts on Repository-Level Code Generation). Models did best when given the full implementations of the dependencies; with only signatures, performance dropped somewhat while the prompts got much shorter, which is the trade-off every retrieval system has to balance.
Hybrid setups make this practical. Structural queries follow the symbol graph, text search finds exact names, embeddings catch code you can only describe, and a reranker puts the most useful pieces first, producing a prompt that is dense with useful information.
Can a tool use context from other repositories and services?
Yes, with the right setup. Enterprise code search platforms keep a central index over all of a company's repositories and can resolve references across them, so the assistant can find a function in a service you have never cloned. Sourcegraph built its Cody assistant on such an index; in July 2025 Sourcegraph ended Cody Free and Pro and kept Cody for enterprise customers. Agents can also reach other repositories through tools, such as an MCP server for your code host, or by cloning what they need into the workspace.
Alice's feature needs a JWT (JSON Web Token) validation function that lives in an auth service written in Java. With cross-repository context, the tool finds that function's signature and how it is used. Without it, the agent invents its own client, which breaks during integration. Cross-repository context turns a research task into a lookup.
Quick Reference
| Property | Value |
|---|---|
| Agentic search | Search by name and pattern, then read files; no index to go stale (Claude Code; Cursor's agent since July 2026) |
| Semantic index | Embeddings for search by meaning; must be built and synced (Copilot's index; Cursor's until July 2026) |
| Repository map | Ranked symbols within a token budget (Aider) |
| Memory files | AGENTS.md (shared convention), CLAUDE.md, .cursor/rules, .github/copilot-instructions.md |
| Memory file checklist | What (architecture), How (conventions), Why (decisions), Validate (commands) |
| Retrieval granularity | Function-level snippets with their call relationships, not whole files |
| Dependency Invocation Rate (DIR) | How often generated code calls the dependencies it was given (RepoExec) |
| Staleness impact | Invented or missing APIs, broken imports, reimplemented utilities |
Frequently Asked Questions
Q: Doesn't a very large context window make all this unnecessary?
No. Even with large windows, long and noisy prompts dilute the model's attention, cost more and run slower. Retrieval that picks the right slice usually beats a bigger window filled with loosely related code.
Q: How often should I re-index?
It depends on the approach. Agentic search reads the files as they are, so there is nothing to refresh. Indexes need to keep up with merges: an index that is hours old can lead the model to call functions that were renamed or deleted. For critical repositories, aim for an index that catches up within minutes of a merge.
Q: Can I autogenerate memory files from existing code?
Partly. Claude Code's /init command, for example, drafts a CLAUDE.md from your codebase, and other tools offer similar starters. The "why" layer still needs a human. Start with the build, lint and test commands plus a short architecture description, then add a rule each time the agent repeats a mistake.
Q: What happens if the context is wrong or stale?
The model makes decisions based on wrong types or functions that no longer exist. You might see code that compiles but fails integration, or quiet reimplementations of shared utilities. Stale context is a common cause of broken imports and repeated work.
Q: How do I measure whether retrieval is working?
Borrow RepoExec's idea: for tasks where a dependency exists, track how often the generated code calls it instead of writing its own. Also watch how often generated code follows project-specific patterns rather than generic ones. If the agent keeps producing functions that already exist, it is not getting the right context.
Test yourself
Your team's AI agent adds logging to a service but does not use the standard structured logging wrapper from the shared library. The wrapper injects correlation IDs and is required across all Go services. The agent writes log.Printf instead. What likely went wrong, and how would you fix it?
Answer: The agent never saw the wrapper or the rule. Either the shared library was outside what it could search, or nothing told it the wrapper is mandatory. Fix both. Make the library reachable: add it to the workspace or index, or name its import path. Then write the rule in the project's memory file (AGENTS.md, or CLAUDE.md for Claude Code): "All logging must use logging.Wrap(…).Info(…) from the shared logging package. Never call log.Printf directly." Now the agent can find the wrapper's signature and knows it must use it. Over the next few tasks, check how often new logging calls use the wrapper, the same idea as RepoExec's Dependency Invocation Rate, and add a lint rule that rejects log.Printf so the convention holds even when the context misses.
Next: Open Source Coding Agents: Aider, OpenHands, and Friends. It opens up the open-source agents and shows how each handles context, safety and editing.
If you want deep dives on how real tools actually work under the hood every week, subscribe to Internals Decoded at internalsdecoded.com.
Sources
- How Copilot understands your workspace
- Sourcegraph documentation
- Kythe overview
- AGENTS.md
- Claude Code: Manage Claude's memory
- Aider: Specifying coding conventions
- RepoCoder: Repository-Level Code Completion Through Iterative Retrieval and Generation
- CodeRAG: Finding Relevant and Necessary Knowledge for Retrieval-Augmented Repository-Level Code Completion
- On the Impacts of Contexts on Repository-Level Code Generation
- Changes to Cody Free, Pro, and Enterprise Starter plans