All sections

01Foundations

The mental model

Claude Code's configuration is not one system. It is seven independent subsystems that happen to share a .claude/ directory, with different file formats, different discovery rules, and sometimes opposite precedence rules.

Prose, config, and code

The single most useful distinction to hold in your head is what kind of thing you are writing. Every mechanism in Claude Code falls into one of three families, and the family determines what happens when two pieces of configuration disagree.

Kind Mechanism What “conflict” means
Prose CLAUDE.md, rules, skills, output styles Text concatenated into the prompt. Conflicts are resolved by the model’s judgement, i.e. non-deterministically
Config settings.json, agent frontmatter, permissions Structured values. Conflicts resolved by a defined precedence order, deterministic
Code Hooks Shell commands that run and can block. Not a conflict at all, it either fires or it doesn’t

The one-line takeaway: prose is a request, config is a rule, hooks are enforcement. If something absolutely must happen every time, it belongs in a hook, not in CLAUDE.md.

That framing resolves most design questions before you have to think about them. “Never commit directly to main” is not a preference, it is a rule that must hold, so it is a hook. “Prefer table-driven tests” is a preference the model should weigh against context, so it is prose. “Use this JDK” is a value, so it is a setting.

The layer stack

graph TD
    subgraph ENFORCE["Enforcement deterministic, blocking"]
        H["Hooks<br/>PreToolUse / PostToolUse / SessionStart<br/>shell commands that can block a tool call"]
    end

    subgraph CONFIG["Configuration deterministic precedence"]
        S["settings.json<br/>env, permissions, model, outputStyle"]
        P["Permissions<br/>allow / ask / deny"]
    end

    subgraph ISOLATE["Isolation separate context windows"]
        A["Subagents<br/>.claude/agents/*.md<br/>own prompt, tools, model"]
    end

    subgraph PROSE["Prose concatenated, model-arbitrated"]
        M["CLAUDE.md family<br/>always in context"]
        R["Rules<br/>.claude/rules/*.md<br/>path-scoped"]
        K["Skills<br/>description always,<br/>body on demand"]
        O["Output styles<br/>replaces system prompt"]
    end

    subgraph PACKAGE["Packaging"]
        PL["Plugins<br/>bundle any of the above<br/>for distribution"]
    end

    PL -.->|"can contain"| M
    PL -.->|"can contain"| K
    PL -.->|"can contain"| A
    PL -.->|"can contain"| H
    PL -.->|"can contain"| S

Plugins sit outside the stack rather than on top of it. A plugin is a distribution format, not a behaviour: it bundles memory, skills, agents, hooks and settings so a second repository can adopt the whole set in one command.

Cost profile

Not every layer costs the same in context tokens. This matters a lot as a project grows, and it is the reason “put everything in CLAUDE.md” stops working.

Mechanism Context cost when unused Context cost when used
CLAUDE.md Full text, every turn Same
Rules with paths: ~Zero until a matching file is touched Full text
Rules without paths: Full text, every turn Same
Skill Only the description line Description + full body
Skill with disable-model-invocation: true Zero, description not loaded either Full body
Subagent Only its description Runs in a separate context window; only a summary returns
Output style Replaces part of the system prompt Same
Hook Zero Zero, runs outside the model

CLAUDE.md is the most expensive place to put anything, because it is paid for on every single turn whether relevant or not. A 600-line CLAUDE.md in a monorepo is charged in full during a session that only touches one CSS file.

What that costs in practice

Take a monorepo with four languages and a 900-line CLAUDE.md holding every style guide. Roughly:

Arrangement Tokens on a TypeScript-only session
Everything in CLAUDE.md ~12,000, of which ~9,000 is Java, Go and Python convention
Split into .claude/rules/*.md with paths: ~3,000, the rest never loads
Reference material moved into skills ~3,000 plus ~40 tokens of skill descriptions

The second and third arrangements are also more reliable, not just cheaper. Adherence measurably degrades on long instruction files, so cutting the file down improves how closely the remaining instructions are followed.

Two properties that surprise people

Nested memory and path-scoped rules load lazily. A CLAUDE.md in a subdirectory you never open costs nothing; it enters context the moment Claude reads a file in that directory. A rule with paths: ["**/*.go"] is simply absent from a TypeScript session. This is the whole monorepo pattern.

Only some layers actually override each other. Memory files and rules are additive: every discovered file is concatenated and nothing wins. Settings, skills, and agents genuinely override. Hooks are additive again, and all of them run. Conflicting rules covers each case, including the two subsystems that resolve in opposite directions.

Where to go next

If you are configuring a repository for the first time, read what loads at session start, then memory files and rules. If you are debugging something that already exists and is misbehaving, skip straight to conflicting rules and the checklist at the end of it.