AGENTS.md vs CLAUDE.md vs Cursor rules: a structure your team can maintain
Instruction files work when they have one source of truth, a clear scope, and an owner instead of copies of a 500-line handbook.

AGENTS.md should hold shared repository facts, CLAUDE.md should adapt them for Claude Code, and Cursor rules should carry tool- or path-specific guidance. That is the maintainable answer to AGENTS.md vs CLAUDE.md: one source of truth, explicit scope, and no copied handbook.
The worst repository instruction setup has three near-identical files that disagree about the test command. Every agent gets “context”; none gets a reliable instruction.
AGENTS.md, CLAUDE.md, and Cursor rules solve overlapping problems. Treat them as a configuration system with scope and precedence. Build a small set of statements that a developer can verify and an agent can apply at the right moment.
Tool behavior changes, so verify it before standardizing. As of August 2026, Claude Code’s memory documentation says it reads CLAUDE.md, not AGENTS.md; it supports importing AGENTS.md from CLAUDE.md, and it loads ancestor files as concatenated context rather than enforcing rules. Cursor’s rule format and discovery are documented in Cursor’s rules documentation. “Instruction” is behavioral guidance, not a security boundary: use repository controls, CI, permissions, and hooks for things that must be enforced.
Which tool reads which file
| Surface | Primary reader | Scope mechanism | Maintainable use |
| --- | --- | --- | --- |
| AGENTS.md | Agents and tools that adopt the shared convention | Repository or nested directory | Durable commands, boundaries, and shared facts |
| CLAUDE.md | Claude Code | Project and ancestor files; @import for shared material | Import the shared core, then add narrow Claude-specific workflow |
| .cursor/rules | Cursor | Focused rules, including path-based rules | Tool- or subtree-specific conventions |
Imports avoid drift when the same fact belongs to multiple readers. A symlink can also make two filenames resolve to one file, but it hides tool-specific intent and can behave awkwardly across editors and platforms. Prefer an explicit import where the tool supports it; verify discovery in a clean checkout.
Start with a decision tree
A rule can be shared, tool-specific, path-specific, or too large to deserve startup context. That classification decides where it belongs.
Use a decision packet when the agent needs product authority, and a product spec when that authority must carry into implementation and learning. A shared context layer can hold the durable facts those artifacts point to.
Three setups that survive contact with a real repository
1. A small application: one shared file
Use this when one team, one deployable, and a few developers share the same build and conventions.
AGENTS.md
Keep it to durable facts: commands that actually work, layout, style decisions that cannot be inferred, and completion expectations.
# Working agreement
- Install and test: `pnpm test`; type-check: `pnpm typecheck`.
- API handlers live in `app/api`; validate input at the boundary.
- Do not change generated files under `src/generated`.
- Before a PR, add or update the behavior-level test for a changed API contract.
If Claude is used, add a tiny CLAUDE.md containing @AGENTS.md. This adapts the shared source to a tool that otherwise does not load it.
2. A growing product: shared core plus tool adapters
Use this when the team uses more than one agent and each tool has a small, legitimate difference.
AGENTS.md # shared repository facts
CLAUDE.md # @AGENTS.md + Claude-only workflow
.cursor/rules/api.mdc # API-specific Cursor rule
.cursor/rules/frontend.mdc
Example: AGENTS.md owns “run pnpm verify before declaring work done.” CLAUDE.md may add “use plan mode for billing changes.” Cursor’s API rule may describe the response-envelope convention only when editing API code. Do not repeat the test command in all three.
3. A monorepo: a root contract and local contracts
Use this when a broad instruction is truly broad, but packages have different commands, owners, and risks.
AGENTS.md
apps/web/AGENTS.md
services/billing/AGENTS.md
CLAUDE.md
.cursor/rules/
The root document should say how to find the package rule and identify cross-cutting requirements. A package document should only add or narrow what applies there: its test target, local architecture, migrations, or boundary. Put an explicit conflict policy at the root: “nearest package instruction wins for local commands; root security and compatibility rules always apply.” Then make it true in every tool you support.
Decide precedence explicitly
Consider this conflict:
# root AGENTS.md
- Run `pnpm test` before requesting review.
# services/payments/AGENTS.md
- Run `pnpm --filter payments test:integration` before requesting review.
The second is not necessarily a contradiction; it can be an addition. Write it that way: “In addition to the root verification, run…” If the package command replaces the root command, say “For this package, test:integration is the required verification; do not run the root suite unless the change crosses packages.”
Now consider CLAUDE.md importing AGENTS.md and then saying “do not run tests automatically.” That is a direct contradiction that a model may resolve unpredictably. Replace it with a scoped condition: “For documentation-only changes, report why tests were not run.” The difference is a rule a reviewer can audit.
For Claude Code specifically, nested CLAUDE.md files are context concatenated in directory order; proximity changes what appears later, and the files still do not enforce policy. Write non-conflicting additions instead of relying on a “last rule wins” intuition.
Migrate in a controlled pass
- Inventory every instruction surface, including old
.cursorrules, nested files, onboarding docs, and CI messages. - Classify every line: shared fact, tool-specific behavior, path-specific convention, workflow, or stale advice.
- Write the shared core first. Delete lines that merely say “write clean code” or duplicate a formatter.
- Create adapters. For Claude, import the shared file rather than copy it. For Cursor, move genuinely scoped conventions into focused rules.
- Add one conflict policy and one owner for the instruction system.
- Ask two people to run the same small task with different agents. Compare which instructions were discoverable and which were ambiguous; fix the files, not the people’s prompts.
Avoid a blind rename from AGENTS.md to CLAUDE.md. It loses portability and can silently alter how a tool loads content. Preserve the shared source, add a tested adapter, and remove old copies only after the adapter behaves as intended. A symlink can provide a temporary compatibility bridge, but an explicit import documents why the relationship exists and leaves room for a small tool adapter.
Audit the setup when it changes
Run this audit after a tool migration, a repeated agent mistake, or every quarter.
- Can each line name its owner and the behavior that proves it?
- Is the command current in a clean checkout?
- Is the same rule duplicated in another file? If yes, is one an import rather than a copy?
- Is a local rule actually scoped to the files where it matters?
- Does the file contain a procedure better kept in a runbook?
- Does any statement contradict CI, repository policy, or a nearer instruction?
- Has a recent review comment exposed a rule worth adding or an obsolete rule worth deleting?
Keep a small changelog in the pull request that changes the rules: what moved, why, and how it was checked. Treat instruction files like production configuration. A stale line can alter work long after its author has forgotten it.
Write rules that have a chance of being followed
An instruction works best when it is short, concrete, and located next to the decision it governs. “Use sensible error handling” asks the agent to supply the standard. “Return the repository’s ApiError envelope from handlers in apps/api, including a stable error code” identifies the surface and the observable outcome.
Prefer a reason when the rule would otherwise look arbitrary: “Do not edit generated clients under src/generated; regenerate them from the schema command.” The reason lets an implementer recognize the boundary when a task looks like an exception. Do not explain obvious formatting twice; your formatter and linter already carry that load.
Keep global startup context deliberately narrow. Claude’s documentation recommends concise instructions and path-scoped rules when material applies only to part of a large project. Unrelated context consumes attention and invites accidental conflicts. A database migration convention belongs with migrations; a release procedure belongs in a runbook reached by a short trigger such as “For production migrations, follow docs/release-migrations.md.”
Finally, test discovery rather than assuming it. Open the tool in a nested package, ask it to identify the applicable test command and local rule, and compare the answer to your intended precedence. This inexpensive test catches the failure that static review misses: a beautifully organized instruction system that the tool never loaded.
What not to put in a rule file
Do not put credentials, URLs that only work on one person’s machine, a project plan, a transcript of architecture debates, or an ever-growing list of one-off mistakes. Do not promise enforcement through natural-language instructions. If an action must not happen, enforce it outside the model’s discretion.
Start with the repository’s next repeated correction. Put the durable, testable version in the shared core; make the tool adapter import it; remove the duplicate. Then open a nested package and verify that the agent can name the applicable test command and local rule.

