Skip to main content

Mental Model

CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt itself. Claude actively judges whether instructions are relevant and may deprioritize them. They are advisory, not enforced configuration. Every design decision in your CLAUDE.md should account for this.

The Load Order

Claude Code uses a layered discovery system with five scopes, loaded in a specific order. Each layer consumes tokens before you type a single character.

OrderComponentApprox. TokensNotes
1System prompt~4,200Core behavior, tool definitions. Identical for all users (enables prompt caching).
2Auto memory (MEMORY.md)~680First 200 lines or 25KB. Claude's self-written notes from previous sessions.
3Environment info~280Working directory, platform, shell, OS version, git status.
4MCP tools (deferred)~120Tool names only. Full schemas load on demand.
5Skill descriptions~450One-line descriptions. The only startup component that does NOT survive compaction.
6~/.claude/CLAUDE.md (User)~320Global preferences across all projects.
7Project CLAUDE.md~1,800./CLAUDE.md or ./.claude/CLAUDE.md. The most impactful file you control.
8CLAUDE.local.mdvariesPersonal project-specific overrides. Appended after CLAUDE.md at the same directory level.

Total startup overhead before your first prompt: ~7,850 tokens minimum. A bloated CLAUDE.md pushes this past 15,000.

The Five Scopes

Every CLAUDE.md file belongs to exactly one scope. Understanding where each scope lives determines who it affects and whether it can be excluded.

ScopeLocationWho It AffectsExcludable?
Managed policyOS-specific system pathAll users on the machineNo — cannot be excluded by any setting
User~/.claude/CLAUDE.mdYou, across all projects✓ Yes
Project./CLAUDE.md or ./.claude/CLAUDE.mdTeam members via source control✓ Yes
Local./CLAUDE.local.mdYou, in this repository only (gitignored)✓ Yes
Subdirectory./src/CLAUDE.md, ./packages/api/CLAUDE.mdLoaded on demand when Claude reads files in that directoryYes, via claudeMdExcludes

The managed policy scope exists for enterprise deployments. On macOS it lives at /Library/Application Support/ClaudeCode/CLAUDE.md, on Linux/WSL at /etc/claude-code/CLAUDE.md, on Windows at C:\Program Files\ClaudeCode\CLAUDE.md. No setting can override it.

The five scopes create a layered filesystem structure:

/etc/claude-code/CLAUDE.md              # Managed policy (Linux/WSL)
~/.claude/CLAUDE.md                     # User scope
~/projects/my-app/
├── CLAUDE.md                           # Project scope (committed)
├── CLAUDE.local.md                     # Local scope (gitignored)
├── src/
│   ├── api/
│   │   └── CLAUDE.md                   # Subdirectory scope (lazy loaded)
│   └── web/
│       └── CLAUDE.md                   # Subdirectory scope (lazy loaded)
└── .claude/
    └── settings.local.json             # Exclude subdirectory files

To exclude subdirectory CLAUDE.md files you do not need, add claudeMdExcludes to your local settings:

{
  "claudeMdExcludes": [
    "**/packages/ios-app/CLAUDE.md",
    "**/packages/legacy-service/**"
  ]
}

Directory Walking

Two distinct loading behaviors govern when subdirectory instructions enter context.

Ancestor loading (immediate): When Claude Code starts in foo/bar/, it walks upward — loading foo/bar/CLAUDE.md, then foo/CLAUDE.md, and any CLAUDE.local.md alongside each, all the way to the filesystem root.

Descendant loading (lazy): CLAUDE.md files in subdirectories below your working directory are NOT loaded at startup. They load on demand when Claude reads or edits files in those subdirectories.

Sibling isolation: If your cwd is frontend/, CLAUDE.md files in backend/ never load. They are neither ancestors nor descendants. This isolation is a feature — it prevents cross-contamination in monorepos.

Precedence and Conflict Resolution

All discovered CLAUDE.md files are concatenated into context. There is no explicit override mechanism. When instructions conflict, three factors determine what Claude follows:

  1. Recency bias. Files loaded later take precedence. Within each directory, CLAUDE.local.md is appended after CLAUDE.md, giving personal notes last-word advantage at that level.
  2. Specificity wins in practice. Subdirectory-level instructions tend to override project-root instructions because they load later in the conversation.
  3. Genuine conflicts resolve arbitrarily. If two files give contradictory guidance for the same behavior, Claude may follow either one. There is no deterministic resolution — only probabilistic tendencies.

This means your CLAUDE.md architecture should avoid conflicts entirely rather than relying on precedence to resolve them.

Context Window Positioning

CLAUDE.md content is injected as a user message positioned between the system prompt and your first conversational message. Two implications:

  1. The system prompt always has higher priority — it appears first and you cannot modify it via CLAUDE.md.
  2. Your conversational messages appear after CLAUDE.md content, so recent conversation can override CLAUDE.md instructions through recency bias.

To elevate instructions to system prompt level, use the --append-system-prompt CLI flag. This must be passed every invocation, making it suited for CI/CD scripts rather than interactive use.

claude --append-system-prompt "CRITICAL: All output must use JSON format. Never include explanatory text outside JSON."

What Survives Compaction

Compaction is where most instruction architectures break down. Understanding what persists and what disappears determines how reliable your setup is across long sessions.

ComponentAfter /compactAfter /clear
Project-root CLAUDE.mdRe-read from disk, re-injectedFull reload from disk
Nested CLAUDE.md filesNOT re-injected; reloads lazily when Claude touches those directories againFull reload
Skill descriptionsNOT re-injected (only invoked skills survive)Full reload
Auto memoryRe-read from diskFull reload
Conversation contextSummarizedCleared

The project-root CLAUDE.md is the only instruction file guaranteed to survive compaction automatically. Design your most critical rules to live there, not in subdirectory files or skills.

When CLAUDE.md Is Re-Read

  • Session start: All ancestor files and CLAUDE.local.md files load immediately.
  • During session: Subdirectory files load lazily when Claude touches files in those directories.
  • After /compact: Project-root re-injects from disk. Nested files reload on next directory access.
  • After /clear: Everything reloads fresh.
  • External edits during session: The InstructionsLoaded hook fires and Claude picks up changes. The ConfigChange hook can track these changes separately.
  • HTML comments: Block-level HTML comments (<!-- notes -->) are stripped before injection. Use them for human-only notes at zero token cost.
# Build & Test
- `pnpm test` runs vitest
 
<!-- TODO: add integration test command after CI migration is complete -->
<!-- Last reviewed: 2026-03-15 by @dakota -->
 
## Architecture
- Express API in src/api/

The two comment lines above cost zero tokens at runtime but keep maintenance notes visible when editing the file.

Token Budget Math

With a 200K context window (standard models) or 1M (Opus 4.6/Sonnet 4.6):

  • A 200-line CLAUDE.md costs roughly 2,000-4,000 tokens
  • A CLAUDE.md that @imports README.md, package.json, and three doc files can hit 10,000+ tokens
  • Startup overhead plus a bloated CLAUDE.md means 15-20% of a 200K context gone before you type anything
  • Performance degrades at 20-40% context fill, well before any hard limit
  • Manual compaction is recommended when context reaches ~50%

Frontier models follow roughly 150-200 instructions before compliance drops. Claude Code's system prompt consumes ~50 of those slots, leaving ~100-150 for your rules. Every vague or redundant instruction in your CLAUDE.md wastes one of those slots.

The Instruction Attention Budget

Think of your CLAUDE.md as having an attention budget, not just a token budget. Claude can hold ~100-150 instructions from your CLAUDE.md reliably. Each instruction competes for the same finite attention window.

High-attention instructions: Concrete, verifiable, unfamiliar to Claude. "Run pnpm test -- --run for unit tests" takes one slot and is followed consistently.

Low-attention instructions: Vague, obvious, or matching Claude's defaults. "Write clean code" wastes a slot and teaches nothing.

Negative-attention instructions: Contradictory or negation-based rules actively confuse the model. "Do NOT use semicolons" forces Claude to process the concept then negate it — error-prone by design.

The priority positioning technique exploits this: place rules Claude violates most often at the very top (first 5 lines) and the very bottom (last 5 lines) of your CLAUDE.md. Put less critical rules in the middle. This leverages both primacy and recency bias in LLM attention.

Emphasis Escalation

Claude Code officially acknowledges that emphasis markers improve adherence:

IMPORTANT: Always use pnpm, never npm or yarn.
YOU MUST run tests before committing.
CRITICAL: Never modify files in src/generated/

Use this sparingly. If every instruction is marked IMPORTANT, the emphasis loses its signal. Reserve it for the 3-5 rules that cause the most damage when violated.

Positive Framing Over Negation

Language models process negation unreliably. The model reads the concept first, then applies the negation — and sometimes drops the negation.

Instead ofWrite
"Do NOT use semicolons""Omit semicolons in JavaScript files"
"Don't import from src/internal""Import only from src/public API surfaces"
"Never commit directly to main""All changes go through feature branches"

Every negation-based instruction in your CLAUDE.md is a probabilistic failure point. Reframe as positive directives wherever possible.

Practical Implications

Three facts shape every CLAUDE.md decision:

  1. CLAUDE.md is advisory, not enforced. If a rule must be followed 100% of the time, use a hook instead. CLAUDE.md is for guidance; hooks are for guarantees.
  2. Token cost is paid on every session. A 200-line CLAUDE.md costs 2,000-4,000 tokens whether you need those instructions or not. Move rarely-needed content to skills.
  3. Compaction is the reliability boundary. Only the project-root CLAUDE.md survives compaction automatically. Everything else requires re-loading or re-injection via hooks.

Design your instruction architecture around these constraints, not against them.