Large codebases and large context windows solve different problems. A million-token window means a model can technically hold a lot of text at once, but that does not mean you should hand it your entire repository on every request. Tokens cost money, latency grows with input size, and models still reason better over focused, relevant context than over a haystack of files they have to sift through. The real skill in working with big projects is not maximizing what you stuff into the window. It is deciding what belongs there in the first place.
This guide covers four techniques that work together: retrieval, summarization, compaction, and sub-agents. None of them are exotic. They are the same disciplines good engineers use to manage complexity for humans, applied to how you manage complexity for a model.
A bigger window is not a free pass
Anthropic’s current lineup includes Claude Opus 4.8 (claude-opus-4-8), Claude Sonnet 5 (claude-sonnet-5), Claude Haiku 4.5 (claude-haiku-4-5), and Claude Fable 5 (claude-fable-5), the most capable model in the family. Opus, Sonnet, and Fable all support a 1M-token context window, while Haiku supports 200K. That is a lot of room, but it is easy to fill with noise: stale file contents, irrelevant test fixtures, duplicated documentation, or long conversation histories that no longer matter.
Treat the context window like working memory, not storage. The question to ask before every call is not “can this fit” but “does the model need this to do the task well.” A smaller, well-curated context almost always beats a larger, unfiltered one, both in output quality and in cost.
Retrieval first: only load what is relevant
The most reliable way to manage a large codebase is to not load the whole thing. Instead, retrieve the specific files, functions, or documentation relevant to the current task and pass only those into the prompt.
- Static retrieval: use grep-style search, symbol indexes, or a code search tool to find the files that reference the function, class, or config the user is asking about.
- Semantic retrieval: embed your codebase and use vector search to pull the most relevant chunks for a natural-language query, useful when the user’s request does not map cleanly to a filename or symbol.
- Directory-aware retrieval: for monorepos, scope retrieval to the relevant package or service first, then narrow further, rather than searching the whole tree indiscriminately.
Retrieval is the first line of defense because it stops the problem before it starts. If you never load the irrelevant 90% of the repo, you never have to compact or summarize it later.
Summarize and layer your context
Some things are worth keeping in context in a compressed form rather than leaving out entirely. A good example is architectural context: how services communicate, what conventions the codebase follows, where key abstractions live. Rather than pasting entire README files or design docs on every call, maintain a living summary and refresh it periodically.
- Keep a short, current “project map” (a few paragraphs or a structured outline) describing the codebase’s shape, and update it when the architecture changes meaningfully.
- For any single file too large to include in full, generate a summary of its public interface (function signatures, exported types, key comments) and only pull the full source when the task requires implementation detail.
- Layer context by specificity: high-level project summary first, then module-level summary, then the actual file contents relevant to the task. This mirrors how a new engineer ramps up on unfamiliar code, and it works the same way for a model.
Summarization trades some detail for a large reduction in token count, and for most tasks (bug triage, code review, onboarding questions) the detail you lose is not the detail that matters.
Compact as you go
Long-running sessions, especially agentic ones that read files, run commands, and iterate over many turns, accumulate context fast. Tool outputs, file dumps, and old reasoning steps pile up in the conversation history even after they have stopped being useful.
Compaction means periodically condensing that history: replacing a long back-and-forth with a short summary of what was learned and decided, and dropping raw tool output once its conclusion has been extracted. Practical approaches include:
- Summarizing and replacing older turns once a session crosses a length threshold, keeping only the decisions and facts that still matter.
- Discarding full file contents from history once you have extracted the specific lines or functions needed, rather than keeping the entire file in the transcript.
- Separating “working context” (what the model needs right now) from “session log” (what happened), and only feeding the former back into subsequent calls.
On Claude 4.6 and later models, including Opus 4.8, Sonnet 5, and Fable 5, adaptive thinking (thinking: {type: "adaptive"}) lets the model allocate reasoning effort based on task difficulty rather than a fixed token budget. This matters for compaction because it means you do not need to over-provision context defensively. The model can reason efficiently over a tighter, well-curated input rather than needing extra room to “think out loud” through irrelevant material.
Delegate to sub-agents
For genuinely large or multi-part tasks, one model call over one context window is the wrong shape entirely. Sub-agent patterns split the work: a coordinating agent breaks a task into pieces, dispatches each piece to a focused sub-agent with only the context it needs, and then integrates the results.
A concrete pattern for a large codebase migration or audit:
- A coordinator agent (often a stronger model like Opus 4.8 or Fable 5) plans the task and identifies which parts of the codebase are affected.
- Sub-agents, potentially a faster model like Haiku 4.5 for narrower, well-defined subtasks, each receive a scoped slice of the codebase and report back findings or a diff.
- The coordinator merges results, resolves conflicts, and produces the final output, without ever having loaded the full codebase into its own context at once.
This also pairs well with Model Context Protocol (MCP), the open standard for connecting models to external tools and data sources. An MCP server can expose targeted, structured access to a codebase (file search, symbol lookup, test running) so that both coordinator and sub-agents pull exactly the data they need through a consistent interface, rather than each one reimplementing ad hoc file loading.
Here is a minimal example of scoping a sub-agent call to a specific model and task using the Python SDK:
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from the environment
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
thinking={"type": "adaptive"},
messages=[
{"role": "user", "content": f"Review this module for unused imports:\n\n{module_source}"}
],
)
Notice the sub-agent only receives one module’s source, not the whole repository. That scoping is the entire point.
Putting it together
In practice, these techniques stack. Retrieval decides what enters the window at all. Summarization compresses what would otherwise be too large to include in full. Compaction keeps long sessions from bloating over time. Sub-agents split work that is too large for any single context, no matter how big the window.
A useful mental check before any call: could a competent engineer, given only what I am about to send the model, actually do this task well? If the answer is no because there is too much irrelevant material, retrieve and summarize more aggressively. If the answer is no because there is too little, that is a signal to add targeted context, not to dump the whole codebase as a shortcut.
Takeaway
Large context windows, like the 1M-token windows on Opus, Sonnet, and Fable, give you room to work with, not a license to skip curation. The teams that get the best results from AI on big codebases are the ones who treat context as a scarce, valuable resource: retrieve only what is relevant, summarize what is bulky but important, compact sessions as they grow, and delegate to sub-agents when a task genuinely exceeds what one focused context should hold.
