ai
AGENTS.md, or writing for a reader that forgets

Somewhere in the last twelve months every coding assistant acquired a file it
reads before it does anything. Claude Code arrived in February looking for
CLAUDE.md. Cursor has its rules directory. Copilot reads
.github/copilot-instructions.md. Gemini CLI wants GEMINI.md. Codex read
AGENTS.md from the start, and in August a group of the vendors put a site
behind that name and proposed it as the one file everybody reads.
I do not much care which filename wins. I care that I have now written and rewritten one of these for a service repository at work three times since spring, and each rewrite removed more than it added. That is unusual for documentation, and it is worth working out why.
The reader arrives fresh every time
The mental model I started with was "a README for the robot". That model is wrong in one specific way that turns out to matter more than anything else: a person reads the README once, and thereafter carries the repository around in their head. The assistant reads the file at the start of every session and carries nothing over. Whatever it learned yesterday about how migrations work here, it learned by reading the code, and it will learn it again tomorrow the same way — unless the file tells it.
So the file is not documentation. Documentation is a reference you return to when you have forgotten something. This is a briefing for someone who has forgotten everything, delivered before every shift, and read in full every time. Those two properties — total amnesia, guaranteed attention — pull in opposite directions, and the tension between them is the whole craft.
What went in
The first draft was what you would expect: how to run the thing, how the tests
are laid out, the folder structure. Most of that survived, because it is the
kind of fact the assistant otherwise spends its first five minutes rediscovering
by running ls and reading package.json. Telling it once is cheaper than
watching it find out.
The things that earned their place, in the order I discovered they had:
Vocabulary. Our domain has words that mean one thing here and something adjacent everywhere else, and a model has seen "everywhere else" far more often than it has seen us. Left alone, it would name a new table with the general word rather than ours, and it would be perfectly consistent about it. A short glossary — this term, not that one, and here is the one banned synonym — fixed more review comments than anything else in the file.
Read-before-touching pointers. Not the content of how authentication works, but one line: before you change login or session flows, read this document. The model follows a pointer reliably. It does not reliably infer that a document exists.
The rules the code cannot express. We do not run migrations against shared environments from a laptop. Nothing in the code says that; it is a rule about the world around the code. The assistant needs to be told, because it will otherwise do the helpful thing, which is the wrong thing.
What came back out
The second and third drafts were mostly deletions.
Anything the code already says. I had written a paragraph about our error handling convention. The assistant could see the convention in any file it opened, and the paragraph drifted out of date the first time somebody changed the convention without changing the paragraph. A briefing that lies is worse than no briefing, and prose about code lies within a month. If the code demonstrates it, the file should not describe it.
Style guidance the formatter enforces. Two hundred words about quotes and semicolons, deleted, because Prettier runs on save and the assistant sees the result. Instructions about things that are mechanically enforced are pure weight.
Everything that made it long. This is the amnesia-and-attention tension made concrete. Because the file is read in full every session, every line has a cost on every session — in the model's context, and in how much attention the important lines get. A human skims a long README and finds the bit they need. The assistant reads all of it and weights all of it, so the paragraph about our logging preferences competes with the line about not running migrations. Short is not a stylistic preference here. It is what keeps the critical instructions critical.
The third draft was under a page. It is the best of the three by some distance.
One file, several readers
The practical problem this year is that the tools want different filenames.
The fix I settled on is unglamorous: AGENTS.md holds the content, and every
other file the tools look for is one line long — follow AGENTS.md. Claude
Code can import a file directly with an @ reference, which is neater still.
The point is that there is one briefing, and the per-tool files are pointers to
it, so it cannot fork.
I have also stopped thinking of the file as mine to write alone. When a session goes wrong in a way that a sentence would have prevented, the sentence goes in, and when a sentence turns out to be something the code now says, it comes out. It is the one document in the repository that gets tested every day by a reader that cannot fill gaps from memory — which, if I am honest, makes it a better proxy for the new colleague's first week than anything I wrote for actual colleagues.
The thing I did not expect
Writing for a reader that forgets made me a better writer for readers that do not. The discipline is the same: say what cannot be inferred, point at what can, cut what the tooling enforces, keep the whole thing short enough to be read rather than skimmed. I have started applying it to onboarding documents, and they are shorter and more correct than they were.
The assistant does not remember any of this tomorrow. That turned out to be the useful part.
Written by
Deyan Peev
Founding Engineer · Sofia, Bulgaria


