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. Write one global file, symlink every harness to it, keep the project file for what is genuinely per-project.
Scopes stack
Every harness reads plain markdown rules from a chain of locations, broadest first: a project file adds to the global file, it never replaces it. Claude Code loads managed policy (/Library/Application Support/ClaudeCode/CLAUDE.md on macOS), then ~/.claude/CLAUDE.md, then ./CLAUDE.md or ./.claude/CLAUDE.md, then ./CLAUDE.local.md; subdirectory files load when the agent reads a file there (memory docs).
Every .md in .claude/rules/ and ~/.claude/rules/ loads at launch too, at the same priority as .claude/CLAUDE.md. Give a rule a paths: list in its frontmatter and it loads only when Claude touches a matching file.
Codex takes 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 one, 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).
Claude Code reads CLAUDE.md, not AGENTS.md. Everyone else in the AGENTS.md ecosystem reads AGENTS.md: Codex, Cursor, Gemini CLI, Zed, Aider and pi.
One file, symlinked into every harness
Three copies of the same rules drift within a week. I keep one real file at ~/.agents/AGENTS.md and symlink every harness to it:
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.mdEdit one file, and every agent picks up the change next session.
Two subscriptions, Anthropic and OpenAI, is a real reason to split the rules per model. I still keep one file.
@ 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, imports nest up to 4 hops deep, and backticks suppress the import. A project-file import that resolves outside the working directory triggers a one-time approval dialog; one in ~/.claude/CLAUDE.md does not.
A project then 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 and use @ only for Claude-specific additions.
Imports save no context: imported files load at launch, same as inline text. And a rules file enforces nothing, it arrives as a user message after the system prompt, so anything that must never happen belongs in a hook.
What actually belongs in the file
Aim for under 200 lines. Past that the docs say adherence drops, and you pay the context every session. My sections:
- Communication style: concise, minimal explanation, no emojis, and a note that dictated text arrives garbled so the agent reads through it.
- Programming rules: language, functional style, max lines per file, and no pointing at planning documents in code comments, so comments survive the plans.
- TypeScript rules: maximize inference, derive types from source, extend instead of duplicating, JSDoc on new functions,
interfaceovertype. - Planning: terse plans, each ending with unresolved questions.
- PRs and issues: load the
pr-issueskill before writing any PR or issue. - Sub-agents: prefer sub-agents and workflows for multi-step work, to keep the main context clean.
- External tools: name the single gateway for every external service, so the agent stops inventing its own path to Jira or Notion.
A rules file works best as a router: short statements plus pointers to skills that hold the detail.
When usage is tight, one line in this file 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 frontmatter (~/.claude/agents/<name>.md or .claude/agents/<name>.md).
Two tricks worth the most
Name the local environment quirks. If your dev server answers on a proxy domain instead of localhost, say so, or the agent curls localhost:3000 and spends three turns debugging a healthy server. 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. With the path in the project rules, the agent reads the library's own tests for the version you have instead of guessing at an API it does not know.
What to do
- Move your rules into
~/.agents/AGENTS.mdand symlink~/.claude/CLAUDE.md,~/.codex/AGENTS.mdand~/.pi/agent/AGENTS.mdto it. - Check with
ls -la ~/.claude/CLAUDE.mdthat the arrow points at the shared file. - Cut the global file under 200 lines: move detail into skills, leave one-line pointers.
- Put your project's quirks in the project rules: proxy domain, package manager, anything that makes
localhostlie. - Clone 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.