- Claude Code
- Context Engineering
Write CLAUDE.md Files Without Poisoning Your AI Agents
Too many instructions do not merely consume tokens; they redirect Claude Code into unrecoverable doom loops.
An overloaded Markdown file misdirects Claude Code
An overloaded CLAUDE.md file behaves like a meeting where every role has permanent speaking time.
I ran into this on a project where CLAUDE.md had gradually become the place for every contributor to influence the coding agent.
The file included instructions for CSS styling, React patterns, testing, DevOps, product management, and prototyping. Each section made sense to the person who added it. Together, they created a document with no opinion about which information mattered for a given task.
The testing instructions made the problem visible. Even a small request could send the agent into the test directory, where it would read a large collection of test files and prepare to write a test that the task did not need. The agent was not merely consuming extra tokens. Its attention had been redirected toward an irrelevant workflow.
At first, that behavior looked like a problem with the model or its harness. The agent appeared too eager to explore, too slow to act, and unable to keep a narrow task narrow. It took longer than it should have to discover that the behavior was being induced by project context.
That changed how I evaluate instructions for coding agents. An instruction can be correct in isolation and still make the agent worse when it is injected into every task.
Root context should serve nearly every task
The root CLAUDE.md is loaded before the agent knows which parts of the project will matter. Backend changes, frontend changes, deployment work, debugging, documentation, and small maintenance tasks all begin with the same context.
That makes inclusion a tradeoff rather than a documentation exercise. For every proposed instruction, I want to know how often it helps, how likely it is to change, and what happens when it is irrelevant.
Inclusion Questions
- Share of tasks helped
- Cost when irrelevant
- Frequency of change
- Exploration avoided
- Automated alternative
- More specific documentation home
I do not expect every line to help every task. A short technology stack, for example, may not directly affect a copy edit. It still earns its place because it is cheap, stable, and prevents expensive exploration in a large share of coding tasks.
The dangerous instructions are narrow enough to pull the agent in a particular direction but broad enough to appear universally applicable. "Always write tests" sounds responsible until the task is an investigation, a configuration correction, or a one-line content change. The instruction starts deciding the shape of the work before the work is understood.
A small file can provide high-leverage grounding
Minimal does not mean empty. Some project facts give the agent a much better starting position for very few tokens.
The root file should act more like a map legend than a travel guide. It should identify the terrain, establish the project's durable vocabulary, and point toward deeper guidance without trying to carry all of it.
Technology Stack
I include the packages and platforms that are deeply rooted in the architecture on one comma-separated line. I do not reproduce package.json, and I avoid redundant information.
For a Next.js project, listing React adds little because React is already implied. For a Vite project, the UI framework is important because Vite alone does not tell the agent whether the application uses React, Vue, or something else. The database and ORM are usually worth naming because they strongly shape where data code lives and how it is written.
The result might look like Next.js, TypeScript, Drizzle ORM, PostgreSQL, Playwright. That one line can prevent the agent from spending far more context rediscovering the project's basic shape.
Directory Map
I also include a handful of stable, high-level directory patterns. This is an exception to avoiding specific file paths because a durable path such as src/components/** or src/routes/** can narrow exploration without coupling the instructions to an individual implementation file.
The distinction is volatility. A path to one current service, hook, or utility can become stale during an ordinary refactor. A high-level directory that defines a major project boundary changes much less often and helps with many kinds of work.
Ubiquitous Language
Project vocabulary also belongs in the root file when an ordinary word has a precise domain meaning. Terms such as User, Seller, Buyer, and Guest are easy for a person or an agent to interpret loosely, even when the product depends on exact distinctions.
I prefer the same symbol and capitalization used in the code. If Seller is an ORM table or domain type, writing it as Seller gives the agent a term it can search directly. A short definition then does two jobs: it removes semantic ambiguity and provides a high-signal entry point into the codebase.
This section should remain selective. It is not a complete product glossary. It is a list of stable terms whose ambiguity has a real cost during implementation.
Detailed guidance should be progressively disclosed
Testing guidance was useful in the project where I saw the agent go off course. It was simply delivered too early and too often.
I would move that material into .docs/testing.md and link to it from CLAUDE.md with a description of when to read it. The root file stays responsible for routing; the testing document becomes responsible for testing.
Documentation Index
A useful index does more than list filenames. Each entry tells the agent what kind of task makes the document relevant.
.docs/architecture.md— system boundaries or cross-cutting changes.docs/testing.md— test creation, test failures, or behavior changes requiring coverage.docs/frontend.md— interface implementation or styling work.docs/deployment.md— build, release, or runtime configuration work
The descriptions matter because progressive disclosure only works when the agent can decide what to disclose. A bare list of documents replaces one exploration problem with another.
As testing documentation grows, .docs/testing.md can become an index for more specific material. Unit-test conventions, browser-test setup, fixture design, and CI troubleshooting do not need to compete for attention in the root file. They can be disclosed one layer at a time as the task narrows.
This also reduces maintenance pressure on CLAUDE.md. Architecture, testing, and deployment guidance can evolve within their own boundaries without repeatedly rewriting the context injected into unrelated work.
Code conventions belong in executable constraints
I avoid putting specific code patterns in CLAUDE.md when a tool can enforce them instead.
Prose is a weak place to maintain rules such as which import is allowed, which component API to use, or which database fields may cross a boundary. The agent has to notice the instruction, interpret it correctly, retain it while working, and remember to check its output against it. Every task pays the context cost, including tasks that never touch the relevant code.
A custom lint rule, type constraint, or test places the rule where it becomes relevant and produces feedback when it is violated. It also applies to human contributors and other tools, rather than depending on one agent's injected context.
The distinction I use is between orientation and enforcement. CLAUDE.md should orient the agent toward the project. The codebase and its tooling should enforce project-specific code patterns.
Progressive disclosure makes behavior easier to trace
One large instruction file makes agent behavior harder to diagnose. When the model reads guidance for testing, frontend work, operations, and product decisions at the beginning of every task, any of those instructions may be influencing what it does next.
Smaller, task-routed documents create a clearer causal trail. If an agent reads .docs/testing.md before it starts exploring test fixtures, that context transition is visible in a trace. If it never read the testing guidance, the explanation lies somewhere else.
This does not make agent behavior perfectly attributable, but it reduces the number of competing explanations. It becomes easier to ask which context was active when the behavior changed instead of treating the entire repository instruction set as one opaque prompt.
Brevity also makes the file reviewable by humans
The final advantage of a short CLAUDE.md is ordinary code review.
Instructions accumulate because each addition is easy to justify locally. Contradictions emerge across sections: one instruction asks the agent to minimize changes while another tells it to add comprehensive tests; one establishes an architectural boundary while a later example quietly crosses it.
A brief, scannable file makes those conflicts easier to see. It also makes every addition feel appropriately expensive. The question is no longer whether an instruction is useful somewhere in the project. The question is whether it deserves to influence nearly every task initialized in the project.
That is the standard I keep coming back to. A good CLAUDE.md does not try to make every decision in advance. It gives the agent a stable orientation, a precise vocabulary, and a reliable route to the context the current task actually needs.