Claude Code Workflow Files: AGENTS.md, CLAUDE.md, Skills, and Repo Maps

Table of content

by Ray Svitla


most “Claude Code is amazing” posts assume one config file. real repos end up with six.

CLAUDE.md at the root. AGENTS.md from someone’s last cursor experiment. a .claude/rules/ directory the frontend lead added. a .claude/skills/ folder nobody can list from memory. a .claude/settings.json with hooks. a .mcp.json pointing at servers that may not still exist. plus an architecture.md the agent reads when it feels like it.

each surface loads at a different moment, with a different scope, against a different cost. confuse them and the agent ignores instructions you “wrote.” or worse: it follows instructions you forgot you wrote, on a file you forgot you committed.

this is the router. one table for where each thing belongs, one repo layout that works, one cleanup pass for when the surfaces drift.

it assumes you’ve already picked Claude Code. for a tool-by-tool filename comparison, see AGENTS.md vs CLAUDE.md vs INSTRUCTIONS.md . for what to actually put inside AGENTS.md once you have one, AGENTS.md: how to write instructions for AI coding agents . for the pre-session walkthrough that uses these files, the Claude Code session preflight .


if you only do one thing

write one CLAUDE.md at the project root, keep it under 200 lines, and treat it as a router — not a database. point at docs/architecture.md, package.json, AGENTS.md, the test command. don’t paste them. that single file does most of the work; everything below is how to handle the rest without losing your mind.


solo operator default

if you’re the only person on the repo: root CLAUDE.md + .claude/settings.local.json + .claude/skills/<name>/ only when you’ve repeated yourself twice. skip AGENTS.md, skip .claude/rules/, skip nested CLAUDE.md until the repo grows past one head. half the surfaces below exist for teams. you don’t need them yet — but knowing where they go means you won’t paint yourself into a corner the day a second contributor lands.


the surface map

surfacewhen it loadsscopewhat to put here
CLAUDE.md (project root)every session, full fileprojectbuild/test commands, conventions, hard rules
CLAUDE.local.mdevery session, gitignoredpersonal-in-repolocal URLs, your test creds path, scratch context
~/.claude/CLAUDE.mdevery session of every projectyou, globallypersonal voice, default tone, universal preferences
nested <subdir>/CLAUDE.mdon demand — when Claude reads files in that subdirsubdirectorymodule rules that override the root
.claude/rules/*.md (no paths)every session, full fileprojecttopic-organized rules: testing, security, style
.claude/rules/*.md (with paths)only when matching files are touchedsubset of projectAPI-only or frontend-only rules
.claude/skills/<name>/SKILL.mddescription always; body on invoke or path matchprojectrepeatable procedures, multi-step playbooks, slash commands
~/.claude/skills/<name>/SKILL.mdsame as aboveyou, globallypersonal procedures you reuse across repos
.claude/settings.json (+ .local.json)every session — machine-enforced, not LLM contextproject (+ personal)permissions, hooks, env, MCP config
.mcp.jsonsession start — servers run externalprojectshared MCP servers for the team
reference docs (docs/architecture.md, ADRs)on demand — only when CLAUDE.md tells the agent to read themvariesdeep architecture, ADRs, generated maps

three loading patterns to memorize:

  1. always-on context — root CLAUDE.md, CLAUDE.local.md (appended after, last word wins), .claude/rules/*.md without paths, user-level CLAUDE.md. burns tokens every turn. should be small.
  2. on-demand or path-scoped — nested <subdir>/CLAUDE.md (loads when Claude reads files there, not at session start), rules with paths, skill bodies, reference docs. cost is zero until needed. skill descriptions are always in context; only bodies wait.
  3. machine-enforcedsettings.json permissions, hooks. the model doesn’t see these as instructions; the harness enforces them regardless of what the model decides.

confuse these and you’ll write a “rule” the model never reads, or stuff the architecture into something that loads on every turn.


the AGENTS.md correction

Claude Code reads CLAUDE.md, not AGENTS.md. Anthropic’s documentation is explicit on this. if your repo uses AGENTS.md for codex or another agent, bridge the two with an import:

# CLAUDE.md
@AGENTS.md

## Claude Code only

- use plan mode for changes under `src/billing/`
- prefer `pnpm` for this repo

@path/to/file expands at session start. relative paths resolve against the file containing the import. the imported content lands in context as if pasted in.

this is better than a symlink: you can layer Claude-specific instructions below the AGENTS.md import without polluting the shared file. if you don’t run other agents, you don’t need AGENTS.md. just write CLAUDE.md.


a repo layout that doesn’t drift

your-repo/
├── CLAUDE.md                          # 1. project entrypoint, < 200 lines
├── CLAUDE.local.md                    # 2. personal, gitignored
├── AGENTS.md                          # 3. only if you also run codex/cursor
├── .claude/
│   ├── settings.json                  # 4. team-shared permissions, hooks, MCP
│   ├── settings.local.json            # 5. personal overrides, gitignored
│   ├── rules/
│   │   ├── testing.md                 # 6. always-on rules per topic
│   │   ├── security.md
│   │   └── api.md                     # 7. with `paths: src/api/**`, scoped
│   └── skills/
│       ├── commit/SKILL.md            # 8. /commit
│       └── deep-research/SKILL.md     # 9. runs in subagent
├── .mcp.json                          # 10. shared MCP servers
├── docs/
│   ├── architecture.md                # 11. read on demand from CLAUDE.md
│   └── adr/                           # 12. ADRs, same pattern
└── packages/
    └── frontend/
        └── CLAUDE.md                  # 13. nested, frontend-only overrides

if any cell of the surface map surprises you, your current instructions are probably routed to the wrong file.


where does the next thing go?

a five-question router for whatever instruction you’re about to add.

  1. must the model see it on every turn? yes → CLAUDE.md or .claude/rules/*.md without paths. no → keep going.

  2. does it only apply to a specific area of the repo? yes → nested <subdir>/CLAUDE.md, or .claude/rules/*.md with paths. no → keep going.

  3. is it a multi-step procedure or a slash command? yes → .claude/skills/<name>/SKILL.md. add disable-model-invocation: true if it has side effects (deploy, commit, send) so the model can’t trigger it on its own. no → keep going.

  4. must the harness enforce it regardless of what the model decides? yes → .claude/settings.json (permissions, hooks). the model can want to run rm -rf; the harness still says no. no → keep going.

  5. is it big, deep, and rarely needed? yes → docs/architecture.md or similar, referenced from CLAUDE.md with one line. read on demand. no → it probably isn’t agent instruction at all. it’s a comment, a code change, or a README update.

if every answer is “kind of,” you’re either writing a rule too vague to follow, or a rule that should be code.


three “put this here” examples

walk-throughs for the three most common adds.

1. test command → root CLAUDE.md.

## commands

- test: `pnpm test`
- typecheck: `pnpm typecheck`
- build: `pnpm build`

one line per command, one source of truth, the agent quotes it back when it runs. if the command changes, you update one file and the rule updates everywhere it was referenced.

2. dangerous command denial → .claude/settings.json.

{
  "permissions": {
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git push --force *)",
      "Bash(git reset --hard *)"
    ]
  }
}

the harness blocks the call regardless of what the model intends. this beats “always remember to ask first” written in CLAUDE.md, because a CLAUDE.md rule depends on the model reading it, weighting it, and choosing to obey. the deny list doesn’t.

3. multi-step publish flow → .claude/skills/publish/SKILL.md.

---
name: publish
description: build, sign, and push the static site to the production bucket. invoke only on /publish.
disable-model-invocation: true
---

1. run `pnpm build`.
2. confirm `dist/` size hasn't dropped >20% vs last release.
3. run `./scripts/sign.sh`.
4. run `./scripts/upload.sh`.
5. tag the commit `release-<date>`.

the description loads on every turn so /publish autocompletes. the body loads only when you trigger the slash command. the frontmatter flag means the model can’t auto-fire it even if a user prompt sounds publish-shaped.

three different surfaces, three different cost profiles, three different enforcement levels. pick by what the instruction actually needs.


skills vs rules vs MCP

three surfaces people confuse most.

rules (.claude/rules/)skills (.claude/skills/)MCP servers
primary jobshape behavior across many tasksexecute a specific proceduregive the agent new tools
invocationalways-loaded or path-scopedmodel-invoked by description match, /slash-command, or pathstool calls during reasoning
token costfull body in context (always or on path match)description in context; body only on invokeserver replies count, descriptions count
best for“always validate API input,” “use 2-space indent”“/commit,” “/deploy,” “/research X”database access, web search, browser automation
worst forstep-by-step procedures (overflows the always-on budget)universal style rules (description-matching is fuzzy)static knowledge a markdown file would handle

custom commands have collapsed into skills. a file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy. skills are the recommended shape now because they support invocation control via frontmatter and supporting files. existing .claude/commands/ files still work.

for MCP picks, see best MCP servers for Claude Code . for discovery and the curation layer, Claude Hub . for the broader ecosystem, best Claude Code plugins .


drift prevention

three rules.

1. one source of truth per concept. if pnpm test is the test command, it appears once — in CLAUDE.md, or .claude/rules/testing.md, or package.json referenced by @package.json import. not in three places. when it changes, you update one file.

2. import, don’t duplicate. imports keep AGENTS.md, README, and CLAUDE.md from contradicting each other. write the canonical content once, import it where needed.

3. the agent updates the rules, with a paper trail. when Claude makes a mistake you’ve corrected before, ask it to add a rule. when a rule no longer applies, ask it to remove it. commit those changes like code — they belong in PR review, not in machine-local notes.


stale instruction cleanup

run this monthly. quarterly minimum.

an instruction file that hasn’t been pruned in six months is a liability, not an asset. the agent follows what’s there, including the wrong things.


verification checklist

after editing any workflow file, before you trust the result. for the wider pre-session walkthrough, see the Claude Code session preflight .

if any item fails, the agent is operating on different instructions than you think. that’s the failure mode behind most “the agent ignored my CLAUDE.md” complaints.


common failure modes

stuffing the architecture into CLAUDE.md. files past ~200 lines burn context every turn and dilute the rules that matter. move detailed reference into docs/architecture.md, point at it with one line, let Claude read it on demand. for path-specific guidance, .claude/rules/*.md with paths.

writing rules a hook should enforce. “never commit secrets” is not a CLAUDE.md rule — it’s a pre-commit hook that fails the commit. “always run tests before pushing” is not a CLAUDE.md rule — it’s a settings hook that intercepts the bash tool when it sees git push. CLAUDE.md guides; hooks enforce. don’t ask the model to police itself when the harness can do it. for the broader pattern, see agent failure modes .

skill descriptions that don’t match user phrasing. the model loads skills by matching descriptions against what the user typed. if your /research skill is described as “deep investigation of source-backed claims,” and the prompt is “look this up,” the description doesn’t match, the skill never loads, and you don’t realize it. front-load the use case, include the natural phrases users actually say, verify with /-menu autocomplete. for activation mechanics, see the skills system in Claude Code .


the operator point

the model is the part you rent. the workflow files are the part you own.

every surface above is a place to express something durable about your codebase to whatever agent runs against it next week, after the next CLI version, after the next model release. the dist-tag changes weekly. the model behind it changes too. the workflow files don’t.

that’s the leverage. write them like infrastructure: small files, single sources of truth, machine-enforced where it matters, audit-friendly when it doesn’t. when you’re done, you should be able to onboard a new contributor — human or agent — by handing them the repo and walking away.


the Claude Code session preflight — the pre-session walkthrough that consumes these files → AGENTS.md vs CLAUDE.md vs INSTRUCTIONS.md — filename comparison across coding agents → AGENTS.md: how to write instructions for AI coding agents — what belongs inside AGENTS.md once you have one → why your CLAUDE.md sucks — anti-patterns to avoid in instruction files → best MCP servers for Claude Code — server picks worth installing → Claude Hub — discovery layer for skills and curated lists → the skills system in Claude Code — how skills load, activate, and compose


Topics: claude-code claude-md agents-md skills workflow mcp