Rules Files and Scope
Write your agent rules once in ~/.agents/AGENTS.md, symlink every harness to it, and know exactly which files each harness loads and in what order.
The one line: rules files stack by scope like lexical scope, so write one global file, symlink every harness to it, and keep the per-project file for what is genuinely per-project.
Scopes stack, they do not override
Every harness reads plain markdown rules from a chain of locations, broadest first, and concatenates them. A project file adds to the global file, it never replaces it.
Claude Code loads, in order: managed policy (/Library/Application Support/ClaudeCode/CLAUDE.md on macOS), then user ~/.claude/CLAUDE.md, then the project ./CLAUDE.md or ./.claude/CLAUDE.md, then ./CLAUDE.local.md. Files in subdirectories load on demand, when the agent reads a file in that directory. See the memory docs.
Claude Code also loads every .md in .claude/rules/ and ~/.claude/rules/ at launch, with the same priority as .claude/CLAUDE.md. Add a paths: list to a rule's frontmatter and it loads only when Claude touches a matching file, which is how you keep the always-on file under 200 lines.
Codex walks a similar chain, but takes only one file per level: globally ~/.codex/AGENTS.override.md if it exists, otherwise ~/.codex/AGENTS.md; then one file per directory from the git root down to the current directory, an AGENTS.override.md winning over AGENTS.md in that directory, closer files last. The total is capped by project_doc_max_bytes, 32 KiB by default (Codex docs).
The important asymmetry: Claude Code reads CLAUDE.md, not AGENTS.md. Everyone else in the AGENTS.md ecosystem reads AGENTS.md, including Codex, Cursor, Gemini CLI, Zed, Aider and pi.
One file, symlinked into every harness
Maintaining the same rules in three places means they drift within a week. I keep exactly one real file at ~/.agents/AGENTS.md and point every harness at it with a symlink:
mkdir -p ~/.agents ~/.claude ~/.codex ~/.pi/agent
# move your existing rules into ~/.agents/AGENTS.md first, then:
ln -sf ~/.agents/AGENTS.md ~/.claude/CLAUDE.md
ln -sf ~/.agents/AGENTS.md ~/.codex/AGENTS.md
ln -sf ~/.agents/AGENTS.md ~/.pi/agent/AGENTS.mdOne file to edit, and every agent on the machine picks up the change on its next session.
The tradeoff, stated plainly: people running two subscriptions — Anthropic and OpenAI — sometimes want different rules per model, because the models behave differently. That is a real reason to keep separate files. I do not do it. One place to update beats slightly better tuning per model.
@ imports, Claude Code only
Claude Code expands @path/to/file inside a rules file into that file's contents. Paths resolve relative to the importing file, and imports nest up to 4 hops deep. Backticks around a path suppress the import. An import in a project rules file that resolves outside the working directory triggers a one-time approval dialog. Imports in ~/.claude/CLAUDE.md load without it.
This is how a project gets the shared rules without a symlink in the repo:
# CLAUDE.md
@AGENTS.md
@docs/architecture.mdCodex, Cursor and the rest treat @ as plain text. So keep shared content in AGENTS.md, where every harness finds it, and use @ only in .claude/CLAUDE.md for Claude-specific additions.
Imports do not save context: imported files load at launch, same as inline text. And no rules file enforces anything — it arrives as a user message after the system prompt. Anything that must never happen belongs in a hook, not in prose.
What actually belongs in the file
Aim for under 200 lines. Past that the docs say adherence drops, and you are paying context for every session. My global file has these sections:
- Communication style — concise, minimal explanation, no emojis, plus a note that dictated text arrives garbled so the agent reads through transcription errors.
- Programming rules — primary language, functional style, max lines per file, and a ban on referring to planning documents in code comments, so comments survive when the plans are deleted.
- TypeScript rules — maximize inference, derive types from source, extend instead of duplicating, JSDoc on new functions,
interfaceovertype. - Planning — keep plans terse, end every plan with unresolved questions.
- PRs and issues — one line that says load the
pr-issueskill before writing any PR or issue. The rules file stays short, the detail lives in the skill. - Sub-agents — prefer sub-agents and workflows for multi-step work, to keep the main context clean.
- External tools — one line naming the single gateway for every external service, so the agent stops inventing its own path to Jira or Notion.
That last pattern generalizes: a rules file works best as a router, short statements plus pointers to skills that hold the detail.
When usage is tight, the same file is where you downgrade sub-agents. One line telling the agent to spawn sub-agents on a cheaper model costs nothing to add and nothing to revert. For a hard guarantee, set model: haiku in the sub-agent's own frontmatter (~/.claude/agents/<name>.md or .claude/agents/<name>.md) instead.
Two tricks worth more than the rest of the file
Name the local environment quirks. If your dev server answers on a proxy domain instead of localhost, say so. Otherwise the agent curls localhost:3000, gets nothing, and spends three turns debugging a server that is running fine. The same goes for a non-default package manager, a required VPN, or a seeded database that must not be reset.
Clone the source of your key dependency and point at it. For a library your codebase leans on hard, check out its repository locally and put the path in the project rules. When the agent hits an API it does not know, it reads the library's own tests, which show intended usage with real arguments and match the version you have. That beats documentation, which lags and omits edge cases.
What to do
- Consolidate your rules into
~/.agents/AGENTS.mdand symlink~/.claude/CLAUDE.md,~/.codex/AGENTS.mdand~/.pi/agent/AGENTS.mdto it. - Verify with
ls -la ~/.claude/CLAUDE.mdthat the arrow points at the shared file. - Cut the global file to under 200 lines by moving detail into skills and leaving one-line pointers.
- Add your project's environment quirks to the project rules file: proxy domain, package manager, anything that makes
localhostlie. - Clone the source of your most-used dependency and name the path in the project rules.
- Move any rule that must never be broken out of prose and into a hook.