Dev

Your instruction files are addressing, not fragmentation

Merging every agent instruction file into a shared standard looks like deleting needless repetition, and for project setup it genuinely is. But most of what these documents hold is not a scattered copy of one thing; it is separate addresses, sorted by who a line applies to and who is allowed to write it. One of those boundaries is also a trust boundary, which is why the tidy fix of one universal file quietly hands repository text the authority of your own standing rules.

There is a tidy-minded impulse loose in the agent tooling world: one instruction file to rule them all. Every coding agent has grown its own dotfile, a CLAUDE.md or the equivalent, and a team that runs several of them ends up maintaining a small pile of near-duplicates that drift apart one careless edit at a time. Against that, a single standard every tool reads has obvious appeal, and the case for AGENTS.md was filed against Claude Code directly: a Claude-specific file does not travel well to collaborators on other tools, so let a shared standard carry the context and stop making everyone keep two copies. The duplication is real and the annoyance is earned.

Notice how that request actually got resolved. Not with one universal file that swallows the others, but with a pointer. The maintainer comment that closed it said to make your CLAUDE.md a one-line import of the shared file, an include of AGENTS.md, so the shared context loads at session start and any tool-specific lines sit alongside it rather than in place of it. A symlink between the two names is offered as well, but that one is the degenerate case: a symlink is a single file wearing two names, with nowhere for anything to sit alongside, so it is the right move only when you have no tool-specific lines to lose. The interesting option is the import, because the remedy for duplication turned out to be a reference and not a merge: keep the shared thing in one place, and keep the addressed thing addressed. Hold onto that shape, because it settles less than it looks like it does.

An import solves loading. It puts the shared file and the native file in front of one agent in one session, which is the entire problem the duplication complaint was about. What it does not touch is ownership: which lines belong to that repository and travel to whoever clones it, and which lines belong to me and must never be committed into a shared file at all. That is the distinction the merge-everything version of the pitch cannot see, because it reads these files as copies of one thing that got scattered. Some of them are. Most of them are not. They look alike because Markdown is the only format any of them has, the way a memo and a mortgage and a ransom note are all just text. Sameness of container is not sameness of content, and the instruction files a serious agent setup accumulates answer different questions, for different readers, under different rules about who is allowed to edit them. Collapse them because they share a file extension and you have not removed an accident. You have removed the addressing.

An address is just the pair of facts that decides where a line belongs: what it applies to, and how fast it changes. In a network the address is the thing that says who a packet is for, and the value of having distinct ones is not that addresses are pleasant to maintain, it is that without them nothing can be routed. Instruction files are the same. Each line is addressed, and the question that organizes them is not which tool parses it but what it is a fact about. There are three such scopes, and the reason the consolidation pitch sounds right is that it looks squarely at only one of them.

The first scope is the operator, which is to say me, independent of any project. How an agent should talk to me, when it must stop and ask instead of inventing a way around a wall, how it treats secrets, what it does after failing the same way three times. None of that is a fact about a codebase. It is the disposition I want every agent to carry into every repository it ever touches, and it lives above all of them, in my own configuration, injected into every session precisely because it is nobody's project property. Try to push it down into a per-repository file and your only options are to copy it, where it drifts into subtly different versions of the same rule, or to drop it. An import does not rescue you here, and the reason is exactly the ownership point: a shared repo file that tried to include my personal guide would either fail to find it in a teammate's checkout or pull in each person's different one. The operator layer is the layer that must not travel in the shared artifact, so the shared artifact is the one place it cannot go.

The second scope is the project. This stack, these conventions, this constraint that will bite you if you do not know it, the local truths an agent needs to be useful in this repository and nowhere else. This is the layer AGENTS.md fits and fits well, and the layer the import actually shares, because the build command and the test runner and the rule about never touching the generated file are true no matter which tool reads them. If the whole debate were only about this scope the consolidators would simply be right, and the honest version of their case is that they are. The dual-file proposals already sense this; they separate the shared setup from the tool-specific material rather than jamming both into one bucket. The mistake is only in the leap from a correct claim about the project layer to a claim about every layer.

The third scope is the environment: what is actually installed and running where the agent runs. The sub-agents this runtime has defined, the MCP servers provisioned and authorized here, the services and timers on this particular host. The instinct is that a line like hand this migration to the schema sub-agent is portable context that happened to land in a Claude file, and it is not, but the reason is more specific than other tools cannot do this. Other agents have sub-agents too, and MCP was built to be cross-client; the definitions are ordinary files that copy. What does not port is resolution: the reference means something only where the thing it names is actually set up. Drop it into a universal file read on a machine where that server was never provisioned and it is not shared context, it is a reference to nothing. Within this scope there is a fast axis and a slow one, a durable binding versus live state, but they answer the same question, which is what is true of this environment right now, and that question is not the project's and not mine. (Procedure files, the skills and slash commands addressed by what task you are doing rather than by scope, cut across all of this on a different axis; they are a real category and a separate argument, and I am setting them aside here.)

So far this is a case for keeping distinct files, which an import-based single entry point already honors, and a fair reader can still ask why it matters whether the lines live in one physical file or several stitched together. Here is why. Sort the same content not by what it applies to but by who is allowed to write it. A repository's shared file is writable by anyone who can open a pull request, and it arrives already written in every repository you clone from a stranger. My operator guide is writable only by me. Those are different trust levels, and today they are held apart by almost nothing except the fact that they are different files read with different standing. Merge them into one document the agent consumes with a single level of authority and you have let text a stranger can edit sit in the same file as the rule whose entire job is to say stop and ask a human. The operator layer is the only thing in the stack that can outrank a repository, which is the precise reason it must not live inside one. This is also why just use an include is not the rebuttal it sounds like: an include that pulls an untrusted repository file into the operator's trusted context is not the fix, it is the vulnerability, and the safe direction of reference is the exact opposite of the one the tidy version wants.

With that in hand the distinction is easy to name, and it is the one the merge pitch never does. Fragmentation is many files answering the same question: four AGENTS.md-shaped files across four tools all reciting the same build steps, which should absolutely be collapsed into one shared project file, and on that point the standard is a genuine win. Layering is a few files each answering a different question, at a different scope, under different write permissions. An import composes layers while keeping each one owned by whoever should own it; a fallback that reads the native file and stops does not compose anything, it just drops a layer. And notice how narrow the live disagreement actually is. Almost nobody argues for putting the operator's standing rules or the host's running services into a shared repo file; the moment you say it plainly it is obviously wrong. Only one boundary is genuinely contested, the operator boundary, and it is contested by nobody out loud, which is exactly how it erodes. Layers do not collapse because someone decrees a merge. They collapse because once a shared file is the convention it becomes the file people reach for, and operator-scoped and environment-scoped lines leak into it one convenient edit at a time.

I run a fair number of agents, and what keeps the system legible is not that everything lives in one file. It is that I can always answer a narrow question: which instruction reaches which agent, and who was allowed to put it there. The operating disposition sits in one place above every project, so there is one copy to change and it changes for everyone at once, and nothing a repository ships can overwrite it. Each project states its own truths and travels with its own repo. The environment layer stays where it resolves. AGENTS.md is a good fix for the layer it was built for, and the import that closed the debate is the right way to share that layer. What no shared-file proposal has answered, and what an import does not answer either, is precedence: when the project file says do this and my operator guide says never do this, a single merged file has exactly one rule, document order, and a stack of layers at least lets you say which one wins and why. That is the unsolved part, and it is an argument for keeping the layers nameable, not for blending them into a wall of text that is technically shorter and no longer answers the only question that matters.

Discussion

No comment section here — all discussions happen on X.

Max Nardit

Max Nardit

@mnardit

More articles

You can't verify a translation by reading it

Re-reading a translated document proves nothing, because judging the output asks for the exact fluency you handed to the machine. So you stop reading harder and move the judgment back into a language you can actually read.

Your multi-agent system is a distributed system

The failures people blame on their agents (many converging on the same wrong answer, a disagreement that hardens into sabotage, a success reported for work that never ran) are not gaps a stronger model closes. They are the oldest failures in distributed computing, and they yield to engineering the layer between the agents rather than to more intelligence inside each one.

The token tax on tools you never call

Every capability you expose to an agent spends context on its schema up front, so the price of its abilities tracks the size of your catalog and not the size of the job. The fix is not choosing CLIs over servers but treating the whole tool surface as a budget you spend only when the work reaches for a definition.