How to Write AGENTS.md and CLAUDE.md Correctly
Almost every team developing with AI coding agents now has an AGENTS.md or CLAUDE.md in their repo — but having the file doesn’t automatically mean it helps. Most files fall into one of two extremes: empty or generic to the point of being useless, or conversely too long and full of details that actually make the agent slower and more expensive to run. This article discusses how to write the content of both files correctly, based on context engineering principles and the latest research findings on their impact on agent performance — not just a template copy-pasted without rethinking.
The Problem: Why Most AGENTS.md Files Aren’t Effective
There are two most common failure patterns found in the field.
Pattern one — empty or generic. The team creates AGENTS.md once at the project start, fills it with a generic template (“write clean code”, “follow best practices”), then never touches it again. Such a file practically provides no information the model doesn’t already know from its own training.
Pattern two — over-generated. The team runs a command like /init that makes the agent analyze the entire codebase and automatically generate complete architecture documentation. The result looks impressive — page after page of structure details, data flows, conventions — but this is precisely what research finds most problematic.
Research from ETH Zurich and LogicStar.ai tested four coding agents (Claude Code with Sonnet 4.5, Codex with GPT-5.2 and GPT-5.1 Mini, and Qwen Code) under three conditions: no context file, an auto-generated context file, and a context file manually written by a developer. The results were consistent across all tested models: auto-generated context files lowered the task success rate by about 3% and raised inference costs by more than 20%. Manually written context files performed better — increasing the success rate by about 4% — but still raised costs by up to 19% and added to the number of steps the agent took before completing a task.
The explanation behind these numbers makes sense once thought through: every instruction line entering the context isn’t just “free information” — it’s something to be processed, considered, and sometimes makes the agent take extra verification steps that aren’t actually needed. If the instruction mentions architecture details, the agent tends to recheck that detail against the code even though it’s already clear from the task context. If the instruction is inaccurate or outdated, the agent follows the wrong information instead of reading the code directly.
flowchart LR
A[Empty / Generic] --> B[Ideal: Concise & Actionable] --> C[Over-Generated / Too Detailed]
A -.->|Low task success, no guidance| D[Poor Performance]
C -.->|High cost, extra steps, misdirected guidance| D
B -.->|Targeted guidance, controlled cost| E[Good Performance]The optimal point isn’t at either end of the spectrum, and it’s not about “the more detailed the better”. The following sections discuss concrete principles for reaching that point.
Principle 1 — Every Line Must Earn Its Place
The simplest test for each line you want to write: can the agent infer this itself from reading the code, package manifest, or existing documentation? If yes, that line is a strong candidate for deletion.
// ANTI-PATTERN — the agent can infer this from package.json
This project uses Express.js for the HTTP server and Prisma
as the ORM to interact with PostgreSQL.
// CORRECT — information that CANNOT be inferred from code
All endpoints MUST go through the rateLimiter middleware in
src/middleware/rate-limit.ts. New endpoints that don't
use it will fail security review, not just be a recommendation.
The first sentence in the anti-pattern example is easy for an agent to find just by reading package.json — rewriting it in AGENTS.md only adds tokens without adding new information. The second sentence is the opposite: business/process rules written nowhere in the code, with real consequences if violated.
This principle looks simple but is often violated because writing general descriptions feels “safe” — like explaining a project to a new person. The problem is, an agent isn’t a new person needing general orientation; an agent needs specific signals about things that will make it take wrong steps if it doesn’t know them.
Principle 2 — Don’t Duplicate What Already Exists
A README is written for humans, AGENTS.md is written for agents — two audiences with different needs even about the same project. Duplication between the two isn’t just wasteful, but according to follow-up research can actually lower task success because it makes the file longer without adding any value.
| Should NOT be in AGENTS.md | Should BE in AGENTS.md |
|---|---|
| General descriptions of “what this project is” (already in the README) | Exact test/build commands, including flags often forgotten |
| Dependency lists and versions (already in package.json/go.mod) | Files/folders the agent must not touch (e.g. src/generated/) |
| High-level architecture explanations already in docs/architecture.md | Critical business invariants not clearly visible from code (e.g. idempotency rules) |
| Tutorials for setting up the development environment (usually in the README) | Verifiable “done” criteria (e.g. specific commands that must pass) |
A practical way to check duplication: before adding a new line to AGENTS.md, search whether that information already exists in the README, package.json/go.mod, or architecture documentation. If it already exists, just reference its location (See docs/architecture.md for architecture details), don’t recopy its contents.
Principle 3 — Concrete Commands, Not Vague Instructions
Vague instructions force the agent to guess or trial-and-error, which means extra steps and potential mistakes.
// ANTI-PATTERN
Run the tests before submitting changes.
// CORRECT
Run `pnpm test:unit -- --grep auth` for only the auth module tests,
or `pnpm test:unit` for all unit tests. E2E tests
(`pnpm test:e2e`) need Docker running — don't run them if
Docker isn't up, they'll timeout after 5 minutes without a clear error message.
The “CORRECT” version above isn’t just a more specific command — it also includes the gotcha (e2e tests need Docker) which, if unwritten, makes the agent waste time debugging a problem that isn’t about the code, but about the environment.
The same pattern applies to other instructions: “follow the existing naming conventions” is vague, “use camelCase for functions, PascalCase for classes, and prefix private methods with an underscore” is concrete. “Update documentation if needed” is vague, “update docs/api-changelog.md with the format [date] - [breaking/non-breaking] - [description]” is concrete.
Principle 4 — Prioritize High Risk, Not Completeness
AGENTS.md isn’t the place to document the entire system architecture — that’s the job of separate architecture documentation. Its focus should be on things where, if the agent makes a wrong assumption, the impact is significant.
PRIORITIZE writing:
✓ Security boundaries (credentials, sensitive data access, PII)
✓ Business invariants not visible from code (idempotency,
transaction ordering, data consistency rules)
✓ Files/folders that must not be changed (generated code, old
already-applied migrations)
✓ Real consequences if instructions are violated (not just "should")
DON'T prioritize:
✗ Implementation details already clear from the code
✗ Style preferences with no functional impact
✗ History/rationale of old decisions that aren't actionable now
✗ General programming concept explanations the model already knows
A useful ratio as a reminder: one line preventing a real incident is worth far more than ten lines explaining what’s obvious. If you’re unsure whether an instruction deserves to be included, ask: “if this line didn’t exist, how likely and how severe would the impact be if the agent takes a wrong step here?” Lines answering “high likelihood, severe impact” clearly deserve inclusion. Lines answering “low likelihood, small impact” should be discarded.
Principle 5 — Written Instructions Aren’t a Guarantee, Technical Enforcement Is Still Needed
One important thing to realize: writing instructions in AGENTS.md, even explicit ones, isn’t an absolute guarantee the agent will comply. There’s a real case where a project whose AGENTS.md already contained 25 lines of instructions — including explicit warnings against over-assumption — still experienced failure: the agent replaced all SQLite-related code with MariaDB just because the word “MariaDB” appeared in a few code comments, then triggered a broad wrong inference about the stack actually in use. The carefully written context file still didn’t prevent that failure.
The lesson: AGENTS.md is a complement for automation and guidance, not a replacement for real technical enforcement. Truly critical rules — prohibitions on hardcoding credentials, access limits to sensitive data, rules whose violation could cause production incidents — still need to be guarded by stronger mechanisms: lint rules, pre-commit hooks, CI checks, or human code review for high-risk changes.
AGENTS.mdguides, but doesn’t block. For rules whose violations have serious consequences, don’t stop at writing instructions — add technical enforcement (lint, CI, or mandatory review).- Even well-written instructions can “lose” to other strong signals in the code (like misleading comments). Don’t assume a context file solves all classes of problems.
Good File Anatomy — Section by Section
A general structure proven useful across many projects, arranged from the most stable to the most frequently changing:
| Section | Required? | Example Content |
|---|---|---|
| Project overview | Optional (keep it brief) | Main language/framework with versions, one or two sentences of domain context |
| Commands | Required | Exact build, test, lint commands with flags — not general descriptions |
| Constraints | Required | Folders/files that must not be touched, dependencies that must not be added without approval |
| Business invariants | Required (for critical domains) | Rules not visible from code but crucial — idempotency, operation ordering, etc. |
| PR expectations | Optional | What to check before submitting — commit format, review checklist |
| Done-when criteria | Required | Verifiable completion criteria — specific commands that must pass, not “make sure everything works” |
| Project conventions | Optional | Only rules DIFFERENT from the language/framework default, not the entire style guide |
The “Project overview” section is deliberately marked optional and advised to be brief — this information is the easiest to become a duplicate of the README or package manifest. The “Commands” and “Done-when criteria” sections are the most important because there’s no other substitute for them — an agent can’t guess the correct test command just from reading code.
Size and Technical Limits
There’s a technical size limit to note: Codex CLI enforces a 32 KiB limit for AGENTS.md, and content beyond that limit is silently truncated without any warning — meaning if your file is too long, the ending instructions might never be read at all without you realizing it.
Regardless of that technical limit, the more important rule of thumb is about effectiveness, not just whether it fits. Start with a short file — around 10 to 30 lines for a new project — and add content only when proven needed, for example after several times the agent made the same mistake because it didn’t know a convention. This is the opposite of the habit of writing complete documentation upfront “to be safe” — that approach actually produces files that research shows perform worse.
SIZE NOTES:
□ Start with 10-30 lines for a new project
□ Add lines ONLY after concrete evidence they're needed
(e.g. the agent repeatedly makes wrong assumptions about the same thing)
□ Review periodically — remove instructions no longer relevant,
don't just pile on new additions
□ If using Codex CLI, make sure the total size stays under 32 KiB
Case Study: Before vs After
Let’s see the above principles applied to a real example — using the payment module from the multi-module e-commerce monolith case study we discussed earlier.
The “Bad” Version — Raw /init Output, Too Long and Generic
# AGENTS.md — payment module
## Overview
The payment module handles everything related to payments in this
e-commerce system. This module uses Go as the programming language
and PostgreSQL as the database. The code structure follows the clean
architecture pattern with domain, application, and infrastructure
layer separation.
## Code Structure
This module has several main folders:
- domain/ contains entities and business logic
- application/ contains use cases and services
- infrastructure/ contains database and external service implementations
- gateway/ contains payment provider integration
- testing/ contains unit test helpers
## Conventions
- Use descriptive variable names
- Write comments for complex functions
- Follow Go idiomatic style
- Make sure code is readable and maintainable
- Write unit tests for all new functions
- Use good error handling
Testing
Run the tests before making changes to make sure nothing is broken. Make sure all tests pass before submitting.
This file is 90% duplication (folder structure can be seen directly from `ls`, Go idiomatic conventions are already known to the model) and 10% vague instructions ("good testing", "good error handling" can't be executed concretely). Not a single one of the critical invariants we identified earlier — idempotency, state machine, audit trail — appears, even though those are the most important things for a payment module.
### The "Good" Version — Concise, Actionable, Focused on High Risk
```markdown
# AGENTS.md — payment module
## Invariants That MUST NOT Be Violated
- Charge/refund MUST be idempotent via the idempotency_key in the
transactions table — don't create a new idempotency mechanism.
- Transaction status ONLY changes through the state machine in
domain/transaction_state.go, don't update status directly.
- Every status change MUST write an audit_trail within the
same database transaction (not a separate best-effort).
## Test
- `go test ./modules/payment/... -run TestIdempotency` MUST pass
for every PR touching the charge/refund flow.
- External gateways are mocked via testing/mock_gateway.go — don't
call the real sandbox provider in unit tests (strict rate limits).
## Dependency
- Read order data through the application/OrderReader interface, DON'T
query the checkout module's orders table directly.
This version is much shorter but far more valuable — every line is something the agent can’t infer just from reading the code (business invariants, specific test commands, constraints with real consequences if violated), and not a single line duplicates what’s obvious from the folder structure or the programming language used.
| Aspect | Bad Version | Good Version |
|---|---|---|
| Length | ~20 lines, much generic | ~15 lines, all specific |
| Duplication from code/README | High (folder structure, language conventions) | None |
| Actionable instructions | Low (“good testing”) | High (exact test commands) |
| Critical business invariants | None | Present (idempotency, state machine, audit) |
Tips Specifically for CLAUDE.md
If your team uses Claude Code, CLAUDE.md has a slightly different role from AGENTS.md. For teams using several AI coding agents at once, the recommended pattern is making AGENTS.md the source of truth and CLAUDE.md a simple bridge:
# CLAUDE.md
@AGENTS.md
But there are cases where CLAUDE.md deserves its own additional instructions beyond that import line — specifically for things truly specific to Claude Code and irrelevant to other tools:
# CLAUDE.md
@AGENTS.md
## Claude Code Specific
- Custom skills for generating migrations are in .claude/skills/db-migration/
- An internal MCP server for querying the staging database is available as
the `staging_db_query` tool — use this instead of manual psql for
data investigation.
This “Claude Code Specific” section is deliberately separated from AGENTS.md so other tools (Cursor, Codex CLI) reading the same AGENTS.md aren’t confused by instructions irrelevant to them — for example references to skills or MCP tools only available in Claude Code.
AGENTS.md Writing Checklist
BEFORE COMMIT, CHECK EVERY LINE:
□ Can the agent infer this itself from the code/README/manifest?
If yes, remove it.
□ Is this a duplicate of another document? If yes, just reference
its location, don't recopy.
□ Is the instruction concrete enough to be directly executable
(exact command, exact path)? If vague, rewrite more
specifically or remove.
□ If this is a critical rule, is there already technical enforcement
(lint/CI) as a backup, not just relying on agent compliance?
□ Is the total file size still under a reasonable limit (for Codex CLI,
under 32 KiB)?
□ Has this file gone unreviewed for a long time? Schedule periodic
reviews, not just keep adding without ever trimming.
Summary
- The two most common failure patterns: empty/generic files that are useless, and over-generated files that actually lower the task success rate and raise costs per the ETH Zurich/LogicStar.ai research.
- Test every line: can the agent infer it itself from the code/README/manifest? If yes, remove it — redundancy is the main enemy of an effective context file.
- Commands must be concrete, not vague — “run
pnpm test:unit -- --grep auth” not “run the tests”.- Prioritize high risk: security boundaries, business invariants, forbidden files — not architecture documentation completeness.
- Written instructions aren’t an absolute guarantee — critical rules still need technical enforcement via lint, CI, or human review.
- The recommended structure: commands and done-when criteria required and concrete; keep the project overview brief to avoid README duplication.
- Start small (10–30 lines), add only based on evidence of real need, and review periodically to trim what’s no longer relevant.
- CLAUDE.md should ideally just be a bridge (
@AGENTS.md) plus truly Claude-Code-specific additional instructions, like skill references or internal MCP tools.