The pattern shows up in code review every week. A working endpoint arrives in the diff. Tests it wrote pass on the first run. The reviewer reads more carefully and finds a Jest helper that does not exist in this project, a TypeScript file in a JavaScript codebase, and a database query that every other handler delegates to a service. The agent that wrote it was doing what it was trained to do. The codebase it was working in was invisible to it, and so the agent reached for the closest reasonable defaults from a thousand other repositories.
That gap between “what the agent can guess” and “what the agent actually needs to know” is the entire problem context files solve. The reason most context files fail is that they try to bridge the gap with more words, when what the agent needs is fewer words in the right places.
Where the budget actually goes
The single number that matters is the size of the context window, because every piece of information an agent uses during a session competes for the same finite buffer. A typical debugging session spends twelve thousand tokens on the system prompt and tool definitions before the agent does anything, more on every file the agent opens, and thousands more on the stack trace the agent needs to read in order to fix the bug.
The mechanism that makes a long instructions file counterproductive is something Anthropic has written about under the name context rot. As the buffer fills, the model’s ability to retrieve a specific instruction gets worse. The agent is not ignoring rules out of stubbornness. Its attention budget gets thinner as more material competes for it. A long file makes that worse, not better, because every line you add takes attention away from the stack trace the agent needs to read next.
This is the part that overturns the standard instinct. Most engineers approach context files with the same reflex they bring to documentation: write more, cover more cases, leave less to chance. But documentation is read by a person who can skim. A context file is read by an attention budget that has to weigh every line against every other line. The file you can read aloud in under a minute is closer to the right size than the file that covers every edge case you can think of.
The practical budget for a context file in a real session is small. A five-thousand-token file competes with the stack trace. A six-hundred-token file that points at the right paths lets the agent read the code itself, which is what agents are good at. The whole question of whether to write a context file at all reduces to: does the agent need this fact, or can it derive the fact by reading the surrounding code? If it can derive it, the context file should stay quiet about it.
Three layers with three different costs
The shape that holds up treats context as three layers and pays for each at the rate the layer actually gets used.
The always-loaded layer lives at the root of the repository and gets pulled in at the start of every session, whether the job is a typo fix or a migration. This file costs the same on every request, so it covers only what is true for the whole codebase, and it stays short enough to read in under a minute. Anything that only applies to a subset of work belongs somewhere else.
Nested files make up the scoped layer. They only get pulled in when the work happens inside a particular directory. Rules about the API layer sit next to the API code, so a task that touches the frontend never pays the cost of those rules. The agent walks the directory tree, picks up every context file it finds, and treats the file closest to the file being edited as the strongest signal. That single rule, that proximity wins, is what makes scoping work at all.
An on-demand layer is the cheapest of the three. It is ordinary documentation that the root file references by path rather than copying inline. A path reference costs only a handful of tokens, while the document behind it might run a couple of thousand tokens. So the agent only spends that budget when the task actually calls for it. The closest analogy is the first week of a new engineer: nobody memorizes the architecture document on day one. They remember that it exists and go read it when they need it.
A small TypeScript service laid out this way has roughly an always-loaded file at the root, a couple of generated vendor-specific files next to it, a hand-written glob-scoped rule file for the one tool that supports glob scoping, a settings file that runs a context linter, an on-demand skill file describing one common workflow, the architecture and testing docs, and a directory of decision records for choices nobody has time to re-derive. The companion repository linked from the resources section has the full layout if a working example helps.
Why one source of truth, not four
The reason this gets complicated is that every vendor picked a different filename for the same idea, and engineers end up maintaining four near-identical files. The fix is to make one file the source of truth and generate the rest.
There is now a shared convention called AGENTS.md, governed by the Agentic AI Foundation (which sits under the Linux Foundation). It is plain Markdown with no required schema, and the four major tools read it natively: Claude Code, Cursor, Copilot, and Codex. A long tail of other tools also reads it, including Gemini CLI, Aider, Windsurf, and Zed. Nested files are part of the spec, the file closest to the code being edited takes precedence over files higher in the tree, and anything typed directly into the chat overrides what the files say.
Each major tool has its own format alongside the shared one, because each format does something the shared one cannot. Claude Code resolves @path/to/file imports inline, which lets its generated file stay a pointer plus a handful of tool-specific instructions rather than duplicating the whole document. Cursor stores rules as .mdc files with YAML frontmatter that can scope a rule to a glob pattern, which is more expressive than the shared format but is also the least portable, since nothing outside Cursor reads it. Copilot reads a single instructions file at the repository root and does not support nested scoping. Codex reads AGENTS.md directly with no extra step.
The practical answer is to write the shared file once, generate the rest from it, and hand-write a separate file only when a tool offers something the shared format cannot express. In practice that means Cursor’s glob scoping, and the rest are pointers. The cheapest generation is a symlink, which works fine on Mac and Linux but breaks for contributors on Windows and trips some CI checkout configurations. A small script is the more reliable option. The script writes a banner comment into every file it generates, which stops a well-meaning teammate from editing the wrong copy and silently losing their work on the next sync.
What actually belongs in the root file
The instinct most engineers bring to writing the root file is the same instinct they bring to writing a README: tell the agent everything, so it does not have to ask. That instinct produces files that fail in the field. A better test for every line is: would removing this line cause the agent to make a mistake? If the answer is no, the line is costing attention budget and buying nothing, so it goes.
The kind of file the test is designed to catch reads like a generic engineering values list. Most of it is advice that any decent agent already knows. Some of it is restating what a glance at the file tree would tell you. Some of it is a JavaScript tutorial from 2015 phrased as a project convention. Every line there fails the test. Meanwhile the one thing an agent genuinely cannot work out on its own, which is that this project deliberately has no dependencies, ends up nowhere in the file, because that fact is too boring to feel worth saying.
A working root file is short and reads like a constraint list rather than a guide. It names the test runner, says the project has no dependencies and that is on purpose, lists the command to start the server, lists the command to regenerate the vendor context files, and adds two or three conventions that are not visible from the code. That is the entire always-loaded layer. It is roughly two hundred and fifty tokens. Every line passes the editing test, because every line covers a fact the agent genuinely cannot infer from the surrounding code.
Trade-offs
This shape is not free, and the costs land in four predictable places.
- The always-loaded file is a tax on every single session, including the typo fix. If the file gets long, the symptom is the agent ignoring rules you clearly wrote down. Keep it under five hundred tokens and re-read it once a month.
- Syncing across formats only works if one file is the source of truth. If two engineers edit
AGENTS.mdandCLAUDE.mdindependently, the next sync silently throws away one set of edits. The banner comment in every generated file is a weak defense. The real defense is a linter that fails the CI build when the generated files diverge from the source. - The on-demand layer only works if the root file points to it by path. If a two-thousand-token architecture document gets inlined into the always-loaded file, the budget that would have paid for the conversation is already gone. Resist the urge.
- Scoped files are scoped in the model the agent uses, not in any single editor. A teammate on Cursor and another on Claude Code will see different rule sets from the same directory tree, because the two tools differ on how they read nested files. Test both before declaring victory.
The single highest-value addition is a linter that runs on every change and checks three things: that the always-loaded file is under the token budget, that every path it references actually exists, and that the generated files match the source. Run it from a pre-commit hook and from CI. Failing the linter should block the merge. Without it, the codebase will eventually ship a context file that describes a directory tree that has since been deleted, which is worse than no context file at all. The second highest-value addition is keeping the file close to the code it describes: when a service file moves, the AGENTS.md next to it should move with it, in the same commit. The file is part of the codebase, not a wiki page that drifts on its own schedule.