CLAUDE.md and AGENTS.md: One Rulebook All Three Agents Read
Sep 14, 2026 · AI & BuildingThere is one piece of advice about CLAUDE.md and AGENTS.md that every guide gives, and it is good advice: keep one canonical file, and make the others thin shims that import it. Anthropic's own documentation says exactly this — “Claude Code reads CLAUDE.md, not AGENTS.md. If your repository already uses AGENTS.md for other coding agents, create a CLAUDE.md that imports it.” I follow it. My root CLAUDE.md is three lines long and the first one is an import.
It solved the wrong half of the problem. Reconciling the filenames is the easy half, and it is the half everybody writes about. The half nobody writes about is that the three tools do not agree on which directories to collect those files from. Fix the names and you still get two agents, launched in the same folder, holding materially different rulebooks — and the one holding less has no idea.
I only found this because I measured it. Here is what came back.
Quick answer: from a single working directory three levels deep in my workspace, Claude Code loaded 55,986 bytes of instructions and Codex loaded 24,150. The missing 30,058 bytes — 54% of the rulebook — were not trimmed for length and triggered no warning. They sat above a nested repository's own Git root, and Codex starts its search at the Git root. The famous 32 KiB cap had nothing to do with it: the Codex chain finished with 8,618 bytes to spare. Length was never the failure mode. Repository topology was.
The Three Loaders Disagree About Where “The Project” Starts
Every one of these rules is documented, none of them is a secret, and I had read all three before I built the layout that broke. They only become a problem when you put them side by side, which is not something any single vendor's documentation does for you.
| Tool | Reads | Which directories it collects from | Size behaviour |
|---|---|---|---|
| Claude Code | CLAUDE.md, CLAUDE.local.md |
“your current working directory and every directory above it.” No Git boundary appears in the rule. Subdirectory files load on demand when it reads files there | Loads a file up to 4 MiB in full, skips larger. Advises under 200 lines for adherence |
| Codex | AGENTS.override.md, then AGENTS.md, then your configured fallbacks |
“Starting from the Git root down to your current directory.” A nested .git becomes the ceiling |
“stops adding files once the combined size reaches the limit defined by project_doc_max_bytes (32 KiB by default)” |
| Gemini CLI | GEMINI.md by default; context.fileName accepts another name or a list, including AGENTS.md |
Home-directory file, then configured workspace directories, then “that directory and its ancestors up to a trusted root” | No published byte cap; concatenates general to specific, deepest last |
Read the middle column again. Claude Code walks up and does not stop at a repository edge. Codex walks down from the repository edge and cannot see past it. Those two rules point in opposite directions from the same starting point, and in a flat single-repo project they happen to agree, which is why almost nobody notices. Put one .git inside another and they stop agreeing completely.
The Measurement: 55,986 Against 24,150
My workspace is a root repository with nine sibling repositories inside it, one per area of work, and one of those has a repository of its own nested a level deeper. That structure exists for reasons that have nothing to do with agents — separate histories, separate commit granularity. It is also an ordinary shape. Any monorepo with vendored submodules has it.
I launched from the deepest directory and counted what each tool's documented rule would collect. Directory names are genericised here; byte counts are untouched.
The 30,058 bytes are the workspace root rulebook and the tier above the nested repository: the failure-registry triggers, the naming rules, the single-committer Git convention, the instruction never to claim something is done without the artifact that proves it. All of it in force for Claude Code. None of it reaching Codex, from the same folder, on the same machine, in the same minute.
Why the 32 KiB Cap Is the Wrong Thing to Worry About
The cap is real, and it is the single most-cited number in this corner of the internet. OpenAI's documentation states it plainly: Codex “concatenates files from the root down” and “stops adding files once the combined size reaches the limit defined by project_doc_max_bytes (32 KiB by default)”. There is an open issue on the Codex repository reporting that when it fires there is no warning in the terminal UI, no log line and nothing in the editor extension. I checked my own config.toml while writing this: project_doc_max_bytes is unset, so the 32,768-byte default is what I am running.
And it was irrelevant to my failure. The Codex chain came in at 24,150 bytes with a quarter of the budget unspent. Every word I wrote was inside the cap. The cap is a length control, and I did not have a length problem — I had a reachability problem, which is the failure the cap is not designed to catch and the guides do not mention.
The distinction matters because the two have opposite fixes. A length problem is fixed by trimming, and trimming is what every article about these files tells you to do. A reachability problem gets worse when you trim, because you are shortening files the agent was already reading while the ones it cannot see stay exactly as invisible as before. I spent a session trimming before I thought to measure, and it bought me nothing.
The five-second check, before you rewrite anything. If one agent follows a rule and another ignores it, run git rev-parse --show-toplevel from the directory you launch the agent in. If that path is below the file holding the rule, a Git-root-anchored tool was never going to read it, and no amount of rewording will change that.
The Import Trick Covers Two Tools Out of Three
The standard fix — one canonical file, shims that import it — works beautifully where it works. Claude Code's import syntax resolves relative to the importing file and recurses to a maximum depth of four hops. Gemini CLI supports the same idea. Both can be pointed at a single AGENTS.md, and mine are: my CLAUDE.md files in two pillars are eleven bytes each — one import line and a newline, nothing else.
Codex is the one that cannot play. I read its instruction-file documentation end to end looking for an include directive, because I assumed I had missed it. It documents discovery order, precedence, AGENTS.override.md for temporary global overrides, and configurable project_doc_fallback_filenames — and no import or include syntax of any kind. A Codex instruction file has to physically contain its own text.
So a three-tool setup has exactly two honest shapes, and you have to pick one:
| Shape | How it works | What it costs |
|---|---|---|
Canonical AGENTS.md(use this inside a repo) |
AGENTS.md holds every shared rule. CLAUDE.md is one import line plus any Claude-only additions. Gemini CLI either imports it or has AGENTS.md added to context.fileName |
Nothing, inside one repository. Breaks the moment a rule needs to live above a nested Git root |
| Mirrored portable block (use this for home-directory files) |
The shared rules live between two marker comments and are copied byte-for-byte into each tool's home file. Tool-specific content goes outside the markers | It is a copy, so it will drift. Non-negotiable: a scripted diff that fails loudly |
The home-directory files are the case where the import genuinely cannot save you, because there is no shared repository to be canonical in. Mine use the mirror, and the drift check is one command:
I ran it against both mirrors while writing this page and both returned clean: a 4,886-byte, 720-word, 60-line block, byte-identical across all three home files. The wrapper files around it differ — 7,497, 6,660 and 6,675 bytes — because each carries the mechanics only its own tool has. That difference is the point. The block that must be identical is identical and is proven identical on demand; the parts that should differ are free to.
A symlink is the third option and Anthropic documents it, with the caveat that it needs Administrator privileges or Developer Mode on Windows and that the import is the better choice there. It also leaves you nowhere to put tool-specific content, which is usually why the shim exists.
The Layout That Survives All Three
Four rules. The first is the one I did not have, and it is the only one that addresses the failure above.
1. Every nested repository opens its instruction file with an inheritance block. A tool that starts at the Git root cannot walk up to the parent rulebook, but it can be told to open it. Name the parent files by relative path, in the first section, before anything else. Tools that already walked up lose nothing; tools that start at the Git root gain the thing they were structurally missing. This converts a silent omission into one explicit instruction, and it is the cheapest fix in this entire article.
2. Budget the chain, not the file. The 32 KiB cap applies to root-to-working-directory concatenation, so the number to watch is the sum along the deepest path, not the size of any one file. Keep each chain under roughly 24 KB and the strictest tool never gets to decide what you meant. This is also where Claude Code's under-200-lines advice belongs — as a target for adherence, well below anyone's hard limit.
3. A pointer file holds no rules. If CLAUDE.md is a shim, it must be a shim: an import and, at most, a sentence saying where the rules actually are. The moment a real rule gets added to the pointer “just this once,” you have two sources of truth and one of them is invisible to two thirds of your tools. Mine says so in its own text, which is a note to the next person as much as to the agent.
4. Conditional content leaves the always-loaded file. Everything above is about reach — making sure the right files are seen. The separate question is what belongs in them at all, and the answer is: only what is true for every task. Anything that applies under a stated condition should sit in its own file behind a trigger, which costs a line of budget instead of a section. Claude Code now has a first-class mechanism for this in path-scoped rules under .claude/rules/, which load only when it touches matching files. For the portable version — and for the specific case of corrections you have had to give an agent twice — I wrote that up separately in Your AGENTS.md Gets Worse Every Time You Fix It, which is the companion to this page: that one is about what goes in the file, this one is about which files get read.
Running more than one agent in the same repo?
I run a free community for people building real data and AI pipelines — warehouse modeling, analytics, and AI-augmented workflows. No course, no paywall, just practitioners shipping.
Join the free AI community →Frequently Asked Questions
project_doc_max_bytes, 32 KiB by default and raisable in config.toml — note that the cap is on the combined chain, not one file, and an open issue reports it fires with no warning anywhere. Claude Code loads a CLAUDE.md up to 4 MiB in full, skips larger, and advises under 200 lines for adherence rather than capacity. Practically: size for the advice, not the cap, and keep any single root-to-working-directory chain well under 32 KiB..git becomes a Git root, and for any tool that starts its search there, everything above stops being visible. Open each nested repository's file with a short block naming the parent files by path and telling the agent to open them directly. It costs one section and converts a silent omission into an explicit instruction.Related reading: Your AGENTS.md Gets Worse Every Time You Fix It — the companion to this page: what belongs inside the file, once you know which files get read. I Ran Claude Code and Codex Head-to-Head — the two tools above, working the same spec in the same repo, blind-judged. Multi-Model Verification — the same don't-trust-one-pass discipline applied to output instead of instructions. AI as an Operations Layer — where these agents actually run. For the hardware they run on, see Blendlogic Tech.
What would make this wrong
- The byte counts are what the documented rules select, not a packet capture. I counted the files each tool's published discovery rule would collect from that directory and summed them. I did not instrument the agents and read back what actually entered the context window. If a loader deviates from its own documentation — skips a file, deduplicates, applies an exclusion I did not account for — my totals are off. The 30,058-byte gap follows from two documented rules pointing in opposite directions, which I am confident about; the precise figure assumes both implementations match their docs.
- n=1, and it is my own layout. One workspace, ten repositories, designed by the person now writing about how it failed. The nested-repository shape is common enough that I think the finding generalises, but I have not reproduced it on anyone else's tree, and a flat single-repo project will never see it at all.
- Claude Code's rule is a documented absence, not a documented presence. Its docs say “your current working directory and every directory above it” and simply never mention Git boundaries. I am reading silence as “no boundary,” which matches the behaviour I see, but a stated rule would be better evidence than an unstated one.
- This is a moving target, and the docs moved while I wrote. Two of the three documentation URLs I fetched had been redirected to new homes since I last read them. Every quote here was pulled on 2026-09-14; the
project_doc_max_bytesdefault, the import depth and the fallback mechanism are all implementation details that can change in a point release, and the Codex truncation issue is open rather than resolved. - My own chain is four times past the advice I am repeating. Claude Code recommends under 200 lines per file; the chain it loads for me is 743 lines across seven files. The reach problem and the length problem are genuinely separate, which is this article's argument — but having fixed the first, I still have the second, and I would rather print that than imply the layout is finished.
- Harness features may absorb all of this. Path-scoped rules already do a better job than a hand-built trigger for the conditional-content case. If discovery converges — every tool reading a shared filename with a shared traversal rule — the inheritance block becomes a workaround for a gap that closed. The durable part is the four-rule layout; the part most likely to be obsoleted is the mirroring.
Get the build notes
Real AI experiments — what shipped, what failed, and the setups behind them. Straight to your inbox.
No spam, unsubscribe anytime · Privacy
You're in — check your inbox for a welcome note.