Why the format exists
Before it, every coding agent invented its own instruction file. A repository worked on by a team using different tools accumulated several of them, each holding a slightly divergent copy of the same rules — and the divergence was the problem, because the copy that drifted was invisible until an agent acted on it.
AGENTS.md is the convergence: one file, one format, read by most agents. It deliberately specifies almost nothing. There are no required fields, no schema, no frontmatter — it is standard Markdown, and the headings are whatever you find useful. That is a design decision rather than an omission: a format with required fields would need a validator, a version and a migration path, and agents read prose perfectly well.
Why not just use README.md?
Because the two have different readers who need different things, and merging them makes both worse.
A README is for a human evaluating or joining a project: what it does, why it might interest you, how to get started. An agent needs the exact build invocation, which test command to run before reporting work as done, which directories are generated, and the conventions that apply here specifically. Putting that in the README buries the human-facing content under operational detail; leaving it out means the agent guesses.
The specification puts it as keeping "READMEs concise and focused on human contributors" while giving agents "a clear, predictable place for instructions". Predictable is the operative word — the value of a convention is that a tool can find the file without being told where it is.
What goes in it
The format requires nothing, but the sections that recur across projects using it are:
- Project overview — what this is and how it is put together, in a few sentences.
- Build and test commands — the exact invocations, not a description of them. An agent that has to infer your test command will infer wrong in a monorepo.
- Code style — naming, structure, error handling, and anything that differs from the language's default conventions.
- Testing instructions — what to run, what must pass, and what counts as done.
- Security considerations — what must never be touched, logged, or committed.
- Commit and pull request guidelines — message format, branch naming, what belongs in one change.
The highest-value content is usually the part that is specific to your project rather than good practice in general. An agent already knows how to write a test; it does not know that your integration tests need a local Postgres running, or that the e2e suite is excluded from the default command because it takes nine minutes.
# AGENTS.md
Scheduling tool for independent clinics. Next.js App Router,
Postgres via Drizzle, deployed on Fly. Booking works; billing
is partial; notifications are not started.
## Commands
- `npm run dev` — local dev server
- `npm test` — unit tests. Must pass before a change is done.
- `npm run test:e2e` — Playwright. Slow (~9 min), not part
of `npm test`.
- `npm run db:migrate` — after any schema change
## Conventions
- Errors: throw `AppError` with a machine code. Never return
`{ error: string }`.
- Dates are stored UTC, formatted at the edge. Never format
in a query.
- New routes go under `src/app/`, colocated with their tests.
## Do not
- Do not edit `src/db/schema.generated.ts` — it is generated
by `db:migrate`.
- Do not add a dependency without asking. Size is budgeted.
- Do not weaken a test to make it pass. Say it is failing.
## Pull requests
Conventional commits. One concern per PR. Include the failing
case you fixed.Which tools read it
Everything above is the convention itself. This section is different: it is vendor behaviour, it is the part most likely to be out of date by the time you read it, and "supported" covers a wider range of behaviour than it sounds like. Check your own tool's documentation before relying on a detail here.
The specification lists over twenty compatible tools, among them Codex, Cursor, VS Code, GitHub Copilot, Jules, Aider, goose and Devin. Two are worth spelling out because their behaviour is more specific than "supported" suggests.
Cursor picks up an AGENTS.md in your project root automatically, and supports nested ones in subdirectories that combine hierarchically, with the more specific file taking precedence. It also has its own project rules in .cursor/rules/ as .mdc files — the extension matters, because a plain .md file there is ignored for having no frontmatter. The difference is that AGENTS.md is plain Markdown, where .mdc rules carry frontmatter that can scope a rule to particular file globs. When rules conflict, Cursor's documented precedence is Team Rules, then Project Rules, then User Rules. It also reads CLAUDE.md the same way it reads AGENTS.md, which is useful to know if your repository already has one.
On .cursorrules specifically: it is not gone. Cursor's documentation describes the root .cursorrules file as legacy and slated for deprecation, and gives migration steps — move its contents into a rule under .cursor/rules/ set to always apply, then delete the original. It still works today. Treat it as something to migrate rather than something to start with.
Claude Code is the case most likely to surprise, because support is conditional rather than absolute. It reads CLAUDE.md as its own instruction file, and by default reads AGENTS.md only when there is no CLAUDE.md in your working directory or any directory above it. A CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md in that chain suppresses AGENTS.md; a personal ~/.claude/CLAUDE.md, an organisation's managed file, and .claude/rules/ files do not — those load alongside it. Reading AGENTS.md directly requires Claude Code v2.1.277 or later.
Our recommendation, rather than anything the specification requires: for a mixed-tool team, keep the real content in AGENTS.md and have CLAUDE.md reference it with an @AGENTS.md import. Every tool then reads the same single source, and there is no second copy to drift. It is the arrangement we use in the workspaces we build.
@AGENTS.md # Claude-specific notes Anything above applies to every agent. Only Claude-specific guidance belongs here.
Nesting and precedence
A monorepo can hold more than one. The rule in the specification is that agents "automatically read the nearest file in the directory tree, so the closest one takes precedence" — a package with its own AGENTS.md gets its own conventions, without the root file having to enumerate every sub-project's quirks.
repo/ ├── AGENTS.md conventions shared by everything ├── packages/ │ ├── api/ │ │ └── AGENTS.md overrides for the API: its own tests │ └── web/ │ └── AGENTS.md overrides for the frontend └── package.json
Claude Code applies its own version of this. At session start it loads every AGENTS.md and .claude/AGENTS.md from the working directory upwards; a subdirectory's AGENTS.md loads later, when it first reads a file in that subdirectory and that subdirectory has no CLAUDE.md of its own. Files it does not read at all: AGENTS.local.md, AGENTS.override.md, and anything under a .agents/ directory.
The practical guidance is to put in a nested file only what genuinely differs. Duplicating the root file into each package produces the drift the format exists to prevent, one directory at a time.
Common mistakes
- 01Writing it once and never again. An AGENTS.md describing last quarter's architecture is worse than none — the agent follows it confidently and cites your file as the reason. Update it in the same change as the work it describes.
- 02Documenting general best practice. "Write clean, readable code" costs attention and changes nothing. What earns its place is what an agent could not infer: your error type, your generated files, your slow test suite.
- 03Making it enormous. Everything in the file competes for context. A page that is entirely load-bearing beats ten pages where the agent has to guess which parts still apply.
- 04Describing commands instead of giving them. "Run the tests before finishing" leaves an agent to guess between npm test, npm run test:all and the one in the CI config. Give the exact string.
- 05Keeping parallel copies per tool. The whole point of a shared format is one source. If you need a tool-specific file, have it import AGENTS.md rather than restate it.
Common questions
Do I need AGENTS.md if I already have CLAUDE.md?
Only if you use more than one agent, which most teams eventually do. Claude Code reads CLAUDE.md and by default ignores AGENTS.md whenever a CLAUDE.md is present, so nothing breaks either way. The portable arrangement is to hold the content in AGENTS.md and have CLAUDE.md import it with @AGENTS.md — one source, read by every tool, no second copy to drift.
Does AGENTS.md replace .cursorrules?
For new projects, treat AGENTS.md as the starting point rather than .cursorrules. Cursor's own documentation calls the root .cursorrules file legacy and slated for deprecation, and documents how to migrate it into .cursor/rules/ — but it still works today, so there is no emergency. Use .mdc project rules when you need frontmatter to scope a rule to particular file globs, and AGENTS.md when you want plain instructions that every other agent can also read.
Should AGENTS.md be committed to the repository?
Yes. It is project documentation, and the value is that everyone's agent follows the same conventions — which only happens if the file is shared. Keep genuinely personal preferences out of it; those belong in a tool-specific local file that is gitignored.
Will an agent always follow what is in it?
No, and it is worth being clear about this. Instruction files are context, not enforcement — an agent weighs them against everything else in the session and can decide otherwise. Claude Code's documentation states this directly and points to hooks for anything that must be blocked regardless. If a rule genuinely cannot be broken, back it with something mechanical: a test, a lint rule, a CI check, a pre-commit hook.
What if my instructions contradict each other?
The agent may pick one arbitrarily, which is the worst outcome because it looks like it worked. This is the real cost of nested files and per-tool copies, and it is why nested files should hold only genuine differences. Re-read the whole set when a rule changes, not just the file you edited.