How to Use Nested AGENTS.md for Monorepo
One giant root AGENTS.md fit waste context and go stale. See how nested files keep service commands, conventions, and agent guidance close to each directory.
Wetin nested AGENTS.md mean for monorepo
Nested AGENTS.md for monorepo mean say one small file dey repository root, and another file dey inside each service directory. Root file get the few rules wey apply everywhere, plus map of where the other files dey. Each service file get the commands and conventions wey apply only to that directory. Agent wey dey edit services/worker/queue.py go first read root file and worker file, and e no go waste any context for front end wey e no go touch.
You no need install anything. AGENTS.md na convention, and upstream project talk am clearly:
AGENTS.md na standard Markdown. Use any headings wey you like; the agent simply parses the text wey you provide.
Na why e good make you learn this technique well. The format no go change under you. Na placement and maintenance dey cause problem, and na you get responsibility for both.
Why one big root AGENTS.md no dey work?
One 600-line AGENTS.md for the root of repository wey hold web app, background worker, and Terraform directory fit fail for four different ways.
E dey become outdated, because nobody own am. The engineer wey rename test script for apps/web dey edit files under apps/web. Root AGENTS.md no dey inside that diff, so no reviewer go see the mismatch. Six weeks later, the file still dey describe build step wey no longer exist, and the person wey cause the problem don forget the change.
E dey use context for every task. These files load when session start, before agent know wetin you wan ask. Claude Code documentation give one number: "target under 200 lines per CLAUDE.md file. Longer files consume more context and reduce adherence." Codex stop merging instruction files once their combined size reach 32 KiB, the default project_doc_max_bytes. Root file wey document four services dey use that budget for three of dem on every task.
Instructions start to contradict each other. The web directory need pnpm test. The worker need pytest -q. Once you write both rules for one file, each rule correct only sometimes, so agent must guess which one apply. Claude Code docs describe the result: "if two rules contradict each other, Claude may pick one arbitrarily." Per-directory file remove the guess, because only one of the two rules go ever dey inside context. When rule wey you sure say you write clearly still get skipped, working through the reasons why instruction no dey take effect better than rewriting the wording for fourth time.
E dey fill with facts wey agent fit read from the code. Directory tree, dependency list, summary of wetin each package dey do. Claude Code's /doctor check dey exist to remove exactly this kind content. E "cuts content Claude can derive from the codebase, such as directory layouts, dependency lists, and architecture overviews" and keep "pitfalls, rationale, and conventions that differ from tool defaults." That sentence na the best test I know to check whether any line really belong inside the file.
Agent dey read root file, or na only the nearest one?
Na here plenty people dey understand the model wrong, so e make sense to quote the upstream convention instead of paraphrase am:
Put another AGENTS.md inside each package. Agents go automatically read the nearest file for the directory tree, so the closest one get priority and every subproject fit ship instructions wey match am.
And for conflicts:
The AGENTS.md wey dey closest to the file wey you edit wins; direct user chat prompts override everything.
“Get priority” dey sound to many people like “root file no dey considered”. No be so. For tools wey implement this convention, dem dey read every file for the path from repository root reach working directory, then join everything together. The nearest file only wins when two files give different instructions about the same matter.
Codex explain the mechanism clearly: “Codex dey concatenate files from the root go down, and join dem with blank lines. Files wey dey closer to your current directory override earlier guidance.” Claude Code dey follow the same path for its own file name. Files for directory hierarchy above the working directory “dey load complete when launch start”, and “All discovered files dey concatenate into context instead of overriding each other.” Directories below the working directory dey behave differently: Claude Code loads those files on demand, “when Claude reads files inside those directories.”
Two practical results follow. The root file dey become prefix for every session inside the repository, so treat every line for there as a line wey you go pay for hundred times every week. A per-directory file no cost anything when agent dey work for another place, so detail cheap for there and na there e suppose dey.
We check this behaviour against Codex and Claude Code documentation for August 2026. Tools dey implement the convention small-small differently, and dem fit change, so confirm the loading rules for the agent wey your team dey run.
Layout wey work for repository wey get three services
repo/
AGENTS.md rules true everywhere, plus the map
apps/web/AGENTS.md TypeScript client, Vite, Vitest
services/worker/AGENTS.md Python queue consumer, pytest
infra/AGENTS.md Terraform and the deploy scriptsThe root file short on purpose. E dey show where to look, and e carry only rules wey apply for every directory.
# AGENTS.md
This is a monorepo. Each top-level directory ships its own AGENTS.md.
Read this file and the AGENTS.md nearest the code you are editing
before you change anything.
- `apps/web` browser client
- `services/worker` queue consumer
- `infra` Terraform and deploy scripts
## Rules for the whole repository
- The package manager is `pnpm`. `npm install` writes a second lockfile
that CI ignores, so the install you tested is not the install that ships.
- Any `generated/` directory is build output. Edit the schema in
`schemas/` and run `pnpm codegen` instead.
- `.env.local` holds real credentials. Do not read it and do not print it.
- If you change code in a directory, update that directory's AGENTS.md
in the same commit.Na the per-directory file dey carry the details, and e fit long as much as the directory need.
# apps/web
Browser client. Vite and React, TypeScript with `strict` on.
## Commands
- `pnpm dev` serves on port 5173.
- `pnpm test` runs Vitest once and exits.
- `pnpm typecheck` runs `tsc --noEmit`.
## Conventions
- One component per file under `src/components/`.
- All HTTP goes through `src/api/client.ts`. Do not call `fetch` directly,
because the client attaches the auth header and retries on 429.
## Traps
- `pnpm build` does not type check. Vite strips the types instead of
checking them, so a broken type still produces a green build.
Run `pnpm typecheck` as a separate step.The worker file get the same format but different content: the install command, pytest -q, why the consumer must remain idempotent, and the migration wey must run before the tests pass. Na the infra file you go use write rules wey stop agent from causing damage. Never run terraform apply. Run terraform plan and stop there, then name the state backend wey don already configure so the agent no go try initialise another one.
Notice wetin no dey inside any of these files: description of wetin each service dey do. Na humans suppose handle that one. Upstream draw the same boundary, as e talk say "README.md files na for humans: quick starts, project descriptions, and contribution guidelines", while AGENTS.md carry "the extra, sometimes detailed context coding agents need: build steps, tests, and conventions." The difference between AGENTS.md and README wey humans dey read explain that boundary sentence by sentence, and DESIGN.md wey record why the code get that structure cover the third file, the one wey explain decisions instead of commands.
Who dey update the file when code change?
Put one rule for the root file: anybody wey change code inside a directory must update that directory's AGENTS.md for the same commit.
This one work for mechanical reason, no be cultural reason. The per-directory file dey inside the same diff with the code, so the person wey review the pull request go see both together. Root file belong to everybody, and that mean e belong to nobody. E no dey inside the diff wey anybody already dey read.
Support the rule with check for the pull request. The check go find the nearest AGENTS.md above each changed file, then report when dem no touch that file.
#!/usr/bin/env bash
# Warn when code changed but the nearest AGENTS.md above it did not.
changed=$(git diff --name-only origin/main...HEAD)
nearest_doc() {
d=$(dirname "$1")
while [ "$d" != "." ]; do
if [ -f "$d/AGENTS.md" ]; then echo "$d/AGENTS.md"; return; fi
d=$(dirname "$d")
done
echo "AGENTS.md"
}
printf '%s\n' "$changed" | while read -r f; do
[ -n "$f" ] || continue
case "$f" in AGENTS.md|*/AGENTS.md) continue ;; esac
doc=$(nearest_doc "$f")
printf '%s\n' "$changed" | grep -Fqx "$doc" && continue
echo "note: $f changed but $doc was not updated"
doneFor branch wey change the API client but no touch the docs, the output go look like this:
note: apps/web/src/api/client.ts changed but apps/web/AGENTS.md was not updatedMake am warning instead of failure. Hard gate go teach people to add empty line to the file just to make CI green. File wey person edit only to satisfy robot worth less than no file at all. The warning give reviewer one question to ask, and na that part dey actually work.
How I fit know say AGENTS.md don stale?
You fit run two checks today, and you go see one symptom inside a session.
Compare the age of each file with the age of the code wey e describe. %cs prints the commit date as YYYY-MM-DD.
for f in $(git ls-files '*AGENTS.md'); do
d=$(dirname "$f")
printf '%s doc:%s code:%s\n' "$f" \
"$(git log -1 --format=%cs -- "$f")" \
"$(git log -1 --format=%cs -- "$d")"
doneapps/web/AGENTS.md doc:2026-02-11 code:2026-08-07
services/worker/AGENTS.md doc:2026-07-29 code:2026-08-09
infra/AGENTS.md doc:2026-08-01 code:2026-08-01If doc date dey six months behind code date, e no prove say the file wrong. E only tell you which file to read first. Na all you need from check wey dey take one second.
Look for paths wey no dey exist again. Documentation dey rot for one specific way: e continues to describe code wey dem don delete. Dem write every path for these files inside backticks, so e easy to pull dem out and test.
grep -o '`[^`]*`' apps/web/AGENTS.md | tr -d '`' | grep '/' | while read -r p; do
[ -e "$p" ] || [ -e "apps/web/$p" ] || echo "missing: $p"
doneRead the output instead of wiring this one into CI. E also flags globs like src/**/*.ts and any URL wey you quote, because both get slash and neither one be file for disk.
The symptom for a session. The agent reads the file, tries to open src/api/client.ts because the file tell am to, and the tool returns:
No such file or directorySo e do the reasonable thing and write im own fetch wrapper. Na that be the real cost of stale file. The agent no ignore your documentation. E follows the documentation, reaches path wey dem delete three months ago, and rebuilds code wey you already get. A skill like Ponytail, wey dey hold agent to the smallest change wey go work, fit make this rebuilding instinct happen less often, but e no fit find helper wey your file point to wrong place.
Claude Code dey read AGENTS.md files?
No. E important make we talk am clearly because the nested layout depend on this. As of August 2026, the documentation talk say: "Claude Code reads CLAUDE.md, not AGENTS.md." The pattern still work, but you need put one CLAUDE.md beside each AGENTS.md.
The import form correct when you want add tool-specific lines on top the shared ones. Put this inside services/worker/CLAUDE.md:
@AGENTS.md
## Claude Code
Use plan mode for changes under `services/worker/migrations/`.The symlink form correct when you no get any tool-specific setting to add.
git ls-files '*AGENTS.md' | while read -r f; do
ln -s AGENTS.md "$(dirname "$f")/CLAUDE.md"
done
ls -l apps/web/CLAUDE.mdln no print anything when e succeed, so check the listing: apps/web/CLAUDE.md -> AGENTS.md. Then start one session and run /context, where the loaded files go show under Memory files. For Windows, symlink need Administrator rights or Developer Mode, so use the @AGENTS.md import instead.
One trap dey here too. After /compact, the root file dey read again from disk, but nested files for subdirectories no dey inject again. Dem go come back the next time the agent reads one file for that directory. If per-directory rule stop to apply halfway through one long session, na usually this cause am, and touching any file for the directory go bring am back.
Settings wey point other agents to AGENTS.md
Codex dey read AGENTS.md natively. For each level, e first check AGENTS.override.md, so one directory fit get local override without editing the shared file. E stop merging when the combined size reach 32 KiB, the default project_doc_max_bytes, and na another reason to keep the root file small.
Aider dey take am through .aider.conf.yml with the line read: AGENTS.md.
Gemini CLI dey take am through .gemini/settings.json with { "context": { "fileName": "AGENTS.md" } }.
Upstream documentation get backward-compatible rename for repositories wey still dey use the older singular name: mv AGENT.md AGENTS.md && ln -s AGENTS.md AGENT.md.
For one very large monorepo, Claude Code's claudeMdExcludes setting fit skip ancestor files by path or glob. This useful when another team's directory dey above your own.
Wetin make this different from agent memory, or from a skill?
These mechanisms look alike, but dem dey fail for completely different ways. So e good make we precise about which one you dey use.
Na you write AGENTS.md, you commit am to git, and you review am for pull request. E dey the same for everybody wey clone the repository. Agent memory na the agent dey write am, e dey store am outside the repository, and e dey apply only to one machine. Claude Code documentation draw the same line: CLAUDE.md hold "Instructions and rules" wey you write, while auto memory hold "Learnings and patterns" wey Claude write. The memory directory no dey share between machines. The test simple. If one fact must dey true for colleague wey just clone the repository, e no fit dey memory. How agent memory dey persist between sessions cover that part of the matter.
A skill na the third thing. AGENTS.md na context wey dey load every session; skill na procedure wey dey load when e needed. Claude Code docs give one useful rule: "If an entry is a multi-step procedure or only matters for one part of the codebase, move it to a skill or a path-scoped rule instead." The second part of that sentence na exactly wetin nested AGENTS.md dey solve. The first part na wetin agent skills dey for. And when you need the same procedure for more than one repository, share the skill across repos instead of pasting the same paragraphs inside ten different AGENTS.md files.
Upstream note say "at time of writing the main OpenAI repo has 88 AGENTS.md files". That number na the complete argument. Big repository no need bigger file. E need more small files. Each file suppose dey beside the code wey e describe, and the person wey last change that code suppose own am.
FAQ
Nested AGENTS.md root file replace am, or e dey add join am?
E dey add join am. Upstream talk say “the closest one takes precedence”, but that one dey explain wetin happen when conflict dey, no be wetin dem load. Codex “concatenates files from the root down, joining them with blank lines”, and Claude Code dey concatenate every file wey e find as e dey move up from working directory, instead of overriding dem. The nearest file only win when two files give different instructions about the same subject. Write shared rules for root once, and no repeat dem for every directory.
How big root AGENTS.md suppose be?
Make e small enough say you no go mind if dem paste am on top of every request wey you make for that repository, because na so e dey happen. Claude Code documentation suggest say target under 200 lines for each file, and e warn say longer files “reduce adherence”. Codex stop merging instruction files when dem reach 32 KiB combined by default. If your root file document four services, most of am na dead weight for any single task. Move the details go per-directory files, then leave map behind.
How I fit stop these files from becoming stale?
Put one rule for root file: anybody wey change code for a directory must update that directory AGENTS.md for the same commit. Putting the file beside the code na wetin make the rule stick, because the change go enter the same pull request diff wey human dey already read. Add CI warning wey map each changed path to the nearest AGENTS.md above am, and sometimes compare git log -1 --format=%cs for each file with the same command wey you run for the directory wey e document.
Claude Code dey read AGENTS.md files?
No. As of August 2026, the documentation talk say “Claude Code reads CLAUDE.md, not AGENTS.md.” Create CLAUDE.md for the same directory with @AGENTS.md for the first line. This go load the shared file and allow you add Claude-specific instructions under am. Symlink wey you create with ln -s AGENTS.md CLAUDE.md go work when nothing extra dey to add, but for Windows e need Administrator rights or Developer Mode. Run /context for a session and confirm say the file show under Memory files.
Where I suppose put rule wey only matter sometimes?
No put am for AGENTS.md. That file dey load for every session, so every line inside am dey compete for attention with the request wey you actually type. Procedure wey get several steps and wey you only need sometimes suppose dey inside skill, wey dey load when you request am. Rule wey apply to one directory suppose dey inside that directory AGENTS.md. Fact wey agent fit read directly from code, like directory tree or dependency list, no suppose dey for either one.