Skip to content

10 min read

An entry that restates a default bills without changing anything

On this page

In March a payments team added a CLAUDE.md to the root of their monorepo. It came out of a two-hour session in which four engineers wrote down everything they wished a new contributor knew, and it landed at sixty-one lines — around 740 tokens by the tokenizer, which is roughly the length of this paragraph and the next four. Everyone agreed it was a good file. Three weeks later, in a retro on how the team's agent-assisted work was going, someone asked which tasks had gone differently since the file landed. Nobody could name one. Not "the improvement was small" — nobody could point at a single session and say that the agent had made a different choice because of a line in the file.

What they had written is an agent configuration file: an ordinary markdown document, checked into the repository alongside the code, which a coding agent reads at the start of every session and places at the front of its prompt as standing instructions. Different tools look for different filenames — Claude Code reads CLAUDE.md, several other tools read AGENTS.md, Cursor reads rules files under .cursor/, GitHub Copilot reads .github/copilot-instructions.md — and the mechanism underneath is the same in all of them, which is that whatever the file says is in the model's context before the engineer has typed a word about the task.

The file exists because an agent arrives at a repository knowing a great deal about software in general and nothing about this repository in particular. It can read the code, so it does not have to be told what the code says. What it cannot read is the part of the team's knowledge that was never written down anywhere the agent will look: which of the three plausible test commands is the one that actually works, that the API client under generated/ is produced by a generator rather than edited, that one package is not allowed to import from another for reasons that are about billing correctness rather than about layering. Without such a file, an engineer supplies that context by hand in every prompt, or the agent rediscovers it by reading files until it guesses well. Most teams meet the file for the first time in the form of a complaint — the agent confidently did something everybody on the team knows not to do — and the fix everyone reaches for is to write the knowledge down at the repository root, which is exactly what the payments team did.

Here is the part of it that matters, reproduced verbatim except for the package names:

markdown
## Conventions

- Prefer clean, readable code.
- Write tests for new behaviour.
- Be careful when touching migrations.
- Follow existing patterns in the surrounding files.
- Keep functions small and focused.
- Handle errors explicitly rather than swallowing them.

The file was loaded into every session for three weeks, on the order of 300 sessions across the team, and produced no observable change in behaviour. That is a specific and diagnosable failure, and the diagnosis is not that the lines are wrong. Every one of them is a defensible thing to believe about code.

What the six lines have in common

Each entry describes behaviour the model already produces without being asked. Ask a current model to add a feature and it writes tests for it; ask it to modify a function and it matches the surrounding style, because matching the surrounding style is what the training distribution rewards. "Prefer clean, readable code" is not a constraint on the output — it is a description of the output. When an instruction and the default coincide, the instruction is inert: there is no branch in the model's behaviour that the line moves it away from, so there is no task on which its presence and its absence differ.

"Be careful when touching migrations" looks more specific than the rest, and it is worth pausing on because it is the line the team defended hardest. Careful how? Read the migration before editing it, which the agent does anyway; refuse to edit it without asking, which is a real instruction the line does not give; run it against a scratch database first, which is a real instruction naming a command the line also does not give. The word careful names an attitude, and an attitude cannot be executed. When the agent reaches a migration file, it has to convert "be careful" into some concrete action, and whatever it picks it would have picked anyway.

This is where the extensibility landscape from 12.1 gets its sharpest edge. A config file is the layer that is loaded unconditionally, on every session, before anyone knows what the task is. Everything else in the landscape is invoked — a skill loads when its trigger matches, a tool runs when the model calls it, a hook fires on an event. The standing-instruction file has no trigger and no invocation, which is exactly what makes it powerful for the few things that must always hold and exactly what makes a weak entry expensive. A tool that is never called costs its schema; an instruction that never changes a decision costs its tokens on every session forever, and nobody notices, because nothing about the file's presence is observable.

One line that changes a decision

Set that file next to a single entry from a different repository:

markdown
Run one test file: `pnpm vitest run packages/billing/src/invoice.test.ts`
Run the package's suite: `pnpm --filter @acme/billing test`

Trace what happens on a specific task with and without it. The task is to fix a rounding bug in applyProration and confirm the fix. Without the line, the agent has to infer the test command from what it can see: it reads package.json, finds a test script that runs turbo run test, and runs that, because it is the most obvious command in the repo and it is not wrong. That command runs all fourteen packages. On this monorepo that takes four minutes and twelve seconds warm and closer to nine minutes cold, and it produces about 1,800 lines of output, of which the agent needs eleven. Some fraction of the time the run fails for a reason unrelated to the change — a flaky integration test in notifications — and the agent then spends a turn or three investigating a failure it did not cause.

With the line, the agent runs one file. The command takes 3.1 seconds, the output is twenty lines, and a failure in it is necessarily about the change. The difference is not stylistic. It is the difference between a feedback loop the agent can close four times in a minute and one it can close once every five minutes, and over a task requiring six iterations that is the difference between two minutes and half an hour. Something else follows from the speed: an agent whose test loop costs five minutes and produces noisy failures will, in a way that is hard to blame it for, run the tests less often.

The entry is useful because it is executable. Someone reading it can run it. If it stops being true, running it fails visibly. There is no interpretation step between reading the line and acting on it.

The two tests an entry can pass

An entry earns its place if it is precise enough to execute or precise enough to check. Those are different tests and they cover different kinds of content.

An entry is executable when it names a command, a path, or a value that the agent can act on directly: the test command above, the fact that the API client is regenerated by pnpm gen:api and not edited by hand, the fact that packages/billing is the only package allowed to import from packages/ledger. Executable entries are the ones that most often change what happens on the first task that touches their subject.

An entry is checkable when it states something with a truth value that a person or a script can confirm against the repository. "The billing package must never import from internal/experiments" is checkable — you can grep for it, and CI, the continuous-integration jobs a repository runs on every pull request, can enforce it. "Follow existing patterns" is not checkable, because there is no state of the repository that makes it false.

Rank the entries in a proposed file against those two tests before arguing about whether they are good advice. Take the four entries from a colleague's first draft of a config file for the monorepo above:

EntryExecutable?Checkable?The task where it changes a decision
The exact command to run a single test fileYes — the agent runs it verbatimYes — CI can run it in a clean checkoutAny task with a test loop; changes the first iteration
billing must never import from internal/experimentsNo, but it is a hard constraint on generated codeYes — one grep, or an ESLint boundary ruleA task that needs a helper that happens to live in internal/experiments; the agent chooses a different source
The monorepo's directory layoutPartly — it tells the agent where to look firstWeakly — the layout drifts and nothing noticesA task in an unfamiliar package; saves exploratory reads, changes no decision about the change itself
The team values readable codeNoNoNone that anyone has named

The ordering falls out of the table rather than out of taste. The test command changes behaviour on nearly every task. The import ban changes behaviour rarely but decisively, and when it fires it prevents a change that would have shipped and been caught in review at best. The directory layout is a genuine convenience whose value decays as the layout changes, and which nothing will notice when it goes stale. The readability note has no task attached to it and nobody has ever been able to name one.

Where precision is not the point

Two things this criterion does not do, both of which are easy to expect from it.

It does not make an entry correct. "Run the tests with yarn test" is perfectly executable and perfectly checkable, and if the repository migrated to pnpm it is also wrong in a way that will actively damage sessions. Precision is what makes an entry capable of changing behaviour; it says nothing about whether the change is the one you want. An imprecise entry cannot hurt much because it cannot do much. A precise entry that is wrong is the more dangerous artifact, and it is where this topic spends its middle chapters.

It does not make an entry obeyed. An instruction sits in a prompt alongside the user's request, the contents of the files the agent has read, and every other line of the same file. When two lines of the config apply to the same action and say different things, precision in each does not settle which one wins. Standing text is influence, not enforcement, and the gap between those two is where the worst incidents in this topic live.

Nor is a config file a place to put things humans need. A README is read by a person who chose to read it, once. This file is loaded into every session regardless of relevance. Onboarding prose, the history of why the service is called hermes, links to the design docs — all of it may be worth writing, and none of it belongs in a resident instruction file unless it changes what the agent does.

Why nothing gets trimmed later

The reasonable-sounding position on the four-entry file is to keep all of it. The file is short, the token cost is small, each entry might help on some task nobody has thought of yet, and you can always trim it when it grows. That position is what produces every bloated config file in existence, and it fails for a reason that has nothing to do with the arithmetic.

Nothing is trimmed later because by then nobody can say which entries were doing work. Six months on, the file is 180 lines contributed by eleven people, each line added in response to something. Deleting one means arguing that it does nothing, and the person who added it will say it might help, and that argument is unanswerable when no one ever established what any entry does. The trimming pass never happens, and when it does happen it is a token-count exercise that cuts by length rather than by effect.

The standard the file keeps for its whole life is the standard set on the day it was created. If a plausible-sounding line was enough on day one, a plausible-sounding line is enough forever, and the file fills with them. This is the strongest argument for the ranking discipline: not that the readability note costs much on its own, but that admitting it establishes that no entry needs to name a task.

Which raises the question the ranking above quietly assumes an answer to. The table says the test command changes behaviour on nearly every task and the readability note on none, and both of those are predictions — confident ones, informed by knowing what the model does by default, but predictions. The whole argument of this chapter rests on being able to tell the difference between an entry that works and one that merely sounds right, and so far the only instrument for telling them apart has been judgment. The next chapter is about what it takes to check a claim like that rather than assert it, and about why the obvious way of checking is worthless.

Agent configuration files (AGENTS.md, CLAUDE.md and equivalents) — read the current version at https://daviddominguez.dev/learn/en/agent-configuration-files-agents-md-claude-md-and/an-entry-that-restates-a-default-bills-without-changing-anything

Back to top