Chapter 8: Configuration Management and Claude Code

Learning Objectives

Pre-Quiz: Configuration Files

1. When Claude Code discovers CLAUDE.md files at multiple scopes, how are they combined?

The most specific file completely overrides all broader files.
They are concatenated from broadest to most specific, with specific files read last.
Only the user-scope file at ~/.claude/CLAUDE.md is loaded.
They are merged field by field like JSON settings.

2. A teammate wants to guarantee that Claude can never run a destructive delete. Why is a line in CLAUDE.md insufficient?

CLAUDE.md is context that strongly influences but does not enforce behavior; a PreToolUse hook is needed to hard-block.
CLAUDE.md files are only read once and then discarded.
CLAUDE.md cannot contain rules about shell commands.
CLAUDE.md is loaded before the system prompt, so it is ignored.

3. In the settings.json precedence chain, which scope always wins and cannot be overridden?

User (global) settings at ~/.claude/settings.json.
Project (shared) settings at .claude/settings.json.
Managed (enterprise) settings at platform-specific paths.
Plugin defaults bundled with installed plugins.

4. For the 4.6 generation and later, what does a dateless model ID like claude-opus-4-8 represent?

An evergreen pointer that always resolves to the newest available model.
A fixed, canonical pinned snapshot whose weights never change.
A placeholder that must be replaced with a dated ID before use.
A beta alias only usable in headless mode.

5. What is the correct division of labor between managed CLAUDE.md and managed settings.json?

Managed settings.json handles technical enforcement; managed CLAUDE.md handles behavioral guidance.
Both are purely advisory and neither can enforce anything.
Managed CLAUDE.md blocks tools; managed settings.json only sets the model.
They are interchangeable and either can be used for any purpose.

1. Configuration Files

Key Points

Configuration rests on two file-based pillars. CLAUDE.md is a plain-text markdown file of human-authored instructions — coding standards, workflows, architecture notes. Claude reads it in full at session start and treats it as context, not enforced configuration: it is delivered as a user message after the system prompt, so it strongly influences behavior but does not guarantee it. To hard-block an action you need a PreToolUse hook, not a line in CLAUDE.md. Think of CLAUDE.md as the employee handbook and the hook as the locked door.

Claude Code runs two complementary memory systems: CLAUDE.md files written by you (loaded in full every session) and Auto memory written by Claude itself (the first 200 lines or 25 KB of its MEMORY.md index loads per session).

The CLAUDE.md scope hierarchy

CLAUDE.md files live at four scopes and do not override one another — every discovered file is concatenated from broadest scope down to most specific.

ScopeLocationPurposeShared with
Managed policy (enterprise)OS-specific paths (e.g. Linux/WSL: /etc/claude-code/CLAUDE.md)Org-wide instructions (security, compliance, standards)All users in org
User instructions~/.claude/CLAUDE.mdPersonal preferences across all your projectsJust you (all projects)
Project instructions./CLAUDE.md or ./.claude/CLAUDE.mdTeam-shared project contextTeam, via source control
Local instructions./CLAUDE.local.md (gitignored)Personal, project-specific notesJust you (current project)

At session start, Claude walks up the directory tree loading every CLAUDE.md and CLAUDE.local.md, concatenating from filesystem root down to the working directory. The managed-policy CLAUDE.md loads before all others and cannot be excluded by any individual setting. Files can pull in others via @path imports (max depth of four hops); rules under .claude/rules/ can be path-scoped with a paths: glob. Keep each CLAUDE.md under 200 lines — longer files paradoxically reduce adherence.

graph TD A["Managed policy CLAUDE.md: org-wide, cannot be excluded"] --> B["User instructions: ~/.claude/CLAUDE.md"] B --> C["Project instructions: ./CLAUDE.md or ./.claude/CLAUDE.md"] C --> D["Local instructions: ./CLAUDE.local.md (gitignored)"] D --> E["Concatenated context: more-specific files read last, carry more weight"]

settings.json precedence

Where CLAUDE.md carries instructions, settings.json carries behavior — model, permissions, hooks, env. Claude Code reads JSON from four hierarchical scopes and merges them, with more-specific and higher-authority scopes winning field by field.

PriorityScopeLocationRole
1 (lowest)Plugin defaultsbundled with pluginsBaseline defaults
2User (global)~/.claude/settings.jsonPersonal preferences
3Project (shared).claude/settings.jsonTeam settings, version-controlled
4Local (personal).claude/settings.local.jsonPersonal overrides, gitignored
5 (highest)Managed (enterprise)platform-specific pathsEnforced policy — cannot be overridden
graph TD A["1. Plugin defaults: baseline from installed plugins"] --> B["2. User global: ~/.claude/settings.json"] B --> C["3. Project shared: .claude/settings.json (version-controlled)"] C --> D["4. Local personal: .claude/settings.local.json (gitignored)"] D --> E["5. Managed enterprise: platform paths, cannot be overridden"] E --> F["Merged settings: higher scope wins field by field"]

Key settings include model, permissions (allow / deny / ask / defaultMode), hooks (a PreToolUse hook is the mechanism for enforcement), and env. The division of labor is clean: managed settings.json handles technical enforcement (blocking tools via permissions.deny, forcing sandbox, setting env), while managed CLAUDE.md handles behavioral guidance. Run /config to open the settings UI; edits reload automatically.

Model version pinning and prompt versioning

Every Claude model ID identifies a pinned version — Anthropic never mutates an existing ID's weights; new versions ship under new IDs. From the 4.6 generation on, dateless IDs (claude-sonnet-4-6, claude-opus-4-8) are themselves fixed snapshots, not evergreen pointers. (Before 4.6, dated snapshots had short aliases that genuinely were evergreen.) In Claude Code, unpinned aliases (fable, opus, sonnet, haiku) resolve to a provider default; pin explicit versions before rolling out. Treat CLAUDE.md and rules as version-controlled artifacts tied to the model ID they were validated against — the pinned-ID analogy is a Docker image referenced by digest, not by the latest tag.

Animation slot: layered stack showing CLAUDE.md files concatenating (bottom-up) alongside settings.json scopes merging field-by-field, with managed policy locked at the top.
Post-Quiz: Configuration Files

1. When Claude Code discovers CLAUDE.md files at multiple scopes, how are they combined?

The most specific file completely overrides all broader files.
They are concatenated from broadest to most specific, with specific files read last.
Only the user-scope file at ~/.claude/CLAUDE.md is loaded.
They are merged field by field like JSON settings.

2. A teammate wants to guarantee that Claude can never run a destructive delete. Why is a line in CLAUDE.md insufficient?

CLAUDE.md is context that strongly influences but does not enforce behavior; a PreToolUse hook is needed to hard-block.
CLAUDE.md files are only read once and then discarded.
CLAUDE.md cannot contain rules about shell commands.
CLAUDE.md is loaded before the system prompt, so it is ignored.

3. In the settings.json precedence chain, which scope always wins and cannot be overridden?

User (global) settings at ~/.claude/settings.json.
Project (shared) settings at .claude/settings.json.
Managed (enterprise) settings at platform-specific paths.
Plugin defaults bundled with installed plugins.

4. For the 4.6 generation and later, what does a dateless model ID like claude-opus-4-8 represent?

An evergreen pointer that always resolves to the newest available model.
A fixed, canonical pinned snapshot whose weights never change.
A placeholder that must be replaced with a dated ID before use.
A beta alias only usable in headless mode.

5. What is the correct division of labor between managed CLAUDE.md and managed settings.json?

Managed settings.json handles technical enforcement; managed CLAUDE.md handles behavioral guidance.
Both are purely advisory and neither can enforce anything.
Managed CLAUDE.md blocks tools; managed settings.json only sets the model.
They are interchangeable and either can be used for any purpose.
Pre-Quiz: Claude Code Core Components

1. What primarily distinguishes a Skill from a Rule in Claude Code?

Skills are written in JSON while rules are markdown.
Rules load every session (or on matching files) while skills load on demand when relevant or invoked.
Skills can only be created by Anthropic; rules are user-defined.
Rules run as shell commands while skills are pure text.

2. Where does Agent Memory (auto memory) come from, in the mental model of the chapter?

It is what Claude tells itself — learnings Claude writes across sessions.
It is what you tell Claude — the same as CLAUDE.md.
It is a copy of the managed enterprise policy.
It is generated only by running slash commands.

3. What does running /init in a repository do?

Deletes all existing configuration and starts fresh.
Analyzes the codebase and generates a starter CLAUDE.md tailored to what it finds.
Installs the plugin marketplace.
Switches the session into headless mode.

4. A slash command like /code-review marked [Skill] differs from a built-in command such as /clear because it is:

A prompt handed to Claude that Claude can also invoke automatically, rather than logic coded into the CLI.
Only available in enterprise deployments.
Recognized anywhere in a message, not just at the start.
Unable to accept any arguments.

5. You want a rollback step applied only when Claude edits files under migrations/. What is the cleanest fit?

A path-scoped rule with a paths: glob in its frontmatter.
A managed enterprise settings.json entry.
An entry in auto memory written by Claude.
A one-time interactive slash command.

2. Claude Code Core Components

Key Points

Rules are .claude/rules/*.md (project) or ~/.claude/rules/*.md (user) files holding modular instructions. Without paths: frontmatter they load unconditionally at launch, at the same priority as .claude/CLAUDE.md. With a paths: glob they become path-scoped, loading only when Claude works with matching files.

Skills package repeatable workflows that load on demand — when invoked explicitly or when Claude judges them relevant. The distinction from rules is when they load; the distinction from a plain slash command is richness (reach for a command for an explicit entry point, a skill for a fuller auto-applied workflow). Commands (slash commands) control the session and are recognized only at the start of a message.

Agents (subagents) are markdown files with YAML frontmatter in .claude/agents/ or ~/.claude/agents/ — specialized helpers Claude delegates to, each able to maintain its own auto memory. Agent Memory is Claude's own notebook: learnings written across sessions into ~/.claude/projects/<project>/memory/ (a MEMORY.md index plus topic files). The first 200 lines or 25 KB of MEMORY.md loads per session; it is machine-local and shared across git worktrees of the same repo.

flowchart LR CC["Claude Code session"] CC --> R["Rules: load every session or on matching paths"] CC --> S["Skills: load on demand when relevant or invoked"] CC --> CMD["Commands: explicit entry points at message start"] CC --> AG["Agents/subagents: delegated specialized helpers"] CC --> AM["Agent Memory: Claude's cross-session notebook"]

Repository initialization and slash commands

The fastest way to give a repo a memory is /init: Claude analyzes languages, build tooling, layout, and conventions, then generates a starter CLAUDE.md. Setting CLAUDE_CODE_NEW_INIT=1 upgrades this to an interactive, multi-phase flow. Initialization is a starting point — the high-value context comes from editing the file afterward, after which it becomes shared, reviewable memory the whole team inherits.

Slash commands come in four flavors:

As of v2.1.199, skills can be chained: /skill-a /skill-b do XYZ loads up to six named skills, passing the trailing text to each as arguments.

Animation slot: a Claude Code session firing off its five components, each labeled with its activation trigger (every session, on demand, at message start, delegated, self-authored).
Post-Quiz: Claude Code Core Components

1. What primarily distinguishes a Skill from a Rule in Claude Code?

Skills are written in JSON while rules are markdown.
Rules load every session (or on matching files) while skills load on demand when relevant or invoked.
Skills can only be created by Anthropic; rules are user-defined.
Rules run as shell commands while skills are pure text.

2. Where does Agent Memory (auto memory) come from, in the mental model of the chapter?

It is what Claude tells itself — learnings Claude writes across sessions.
It is what you tell Claude — the same as CLAUDE.md.
It is a copy of the managed enterprise policy.
It is generated only by running slash commands.

3. What does running /init in a repository do?

Deletes all existing configuration and starts fresh.
Analyzes the codebase and generates a starter CLAUDE.md tailored to what it finds.
Installs the plugin marketplace.
Switches the session into headless mode.

4. A slash command like /code-review marked [Skill] differs from a built-in command such as /clear because it is:

A prompt handed to Claude that Claude can also invoke automatically, rather than logic coded into the CLI.
Only available in enterprise deployments.
Recognized anywhere in a message, not just at the start.
Unable to accept any arguments.

5. You want a rollback step applied only when Claude edits files under migrations/. What is the cleanest fit?

A path-scoped rule with a paths: glob in its frontmatter.
A managed enterprise settings.json entry.
An entry in auto memory written by Claude.
A one-time interactive slash command.
Pre-Quiz: Claude Code Features and Modes

1. What is the primary purpose of headless mode (-p/--print)?

To run the same agent loop non-interactively over stdin/stdout for automation and CI/CD.
To disable the agent loop and only echo the prompt.
To open a graphical UI instead of the terminal.
To permanently change the default model.

2. A CI job must parse Claude's answer as a structured object matching a defined shape. Which output configuration fits?

--output-format text with no schema.
--output-format json combined with --json-schema.
Interactive mode with /compact.
Headless mode with no output format flag at all.

3. Which output format emits one self-contained JSON object per line for real-time consumption?

text
json
stream-json
yaml

4. Why does /compact re-read the project-root CLAUDE.md after summarizing the conversation?

So your pinned instructions survive the context summarization and stay stable.
Because compaction deletes all configuration files.
To switch the session into headless mode automatically.
Because CLAUDE.md must be regenerated on every message.

5. Which combination best supports a multi-day, large-scale codebase modernization?

Headless mode with stream-json, committed CLAUDE.md rules, and a pinned model version.
Interactive mode with a floating model alias and no rules.
Text output only, edited by hand file by file.
A single interactive session left running with no version pinning.

3. Claude Code Features and Modes

Key Points

Interactive session mode is the default terminal UI, driven by slash commands. Two deserve emphasis: /compact summarizes the conversation to reclaim context window space (re-reading project-root CLAUDE.md afterward so pinned instructions survive), and /resume reopens a prior session so long-running work spans multiple sittings.

Headless mode (non-interactive or print mode) runs the identical agent loop without the terminal UI. Add -p with a prompt: Claude runs its loop, prints a result, and exits. Because it reads stdin and writes stdout, it is the primary mechanism for automation. If interactive mode is a phone call, headless mode is sending a letter — you compose the whole request up front and receive one complete reply. As of v2.1.205 a subset of slash commands works in -p mode, but changes apply to the current session only.

flowchart TD A["Same agent loop"] --> B{"Terminal UI needed?"} B -->|"Yes: conversational work"| C["Interactive mode: slash commands like /compact, /resume"] B -->|"No: automation, CI/CD"| D["Headless mode: -p / --print over stdin/stdout"] D --> E{"--output-format"} E --> F["text: plain result string"] E --> G["json: structured object, optional --json-schema"] E --> H["stream-json: one JSON event per line, real-time"]

Output formats and codebase modernization

Headless mode supports --output-format with three values: text (a plain result string), json (one structured object with result plus metadata; combined with --json-schema it returns schema-conforming output in a structured_output field), and stream-json (every line is one JSON event, enabling real-time streaming). Example pipeline:

cat error.log | claude -p "Summarize the root cause and suggest a one-line fix" --output-format json --json-schema schema.json

Headless mode plus streaming is the engine behind large-scale codebase modernization — framework upgrades, dependency migrations, systematic refactors. You script Claude to run the same well-specified task repeatedly, capture structured output per file, and feed results into review. stream-json lets a monitoring layer observe progress event by event, while committed CLAUDE.md rules keep every invocation aligned. Pin the model version first so a multi-day migration stays consistent throughout.

Animation slot: split-screen contrasting a back-and-forth interactive chat against a single-shot headless pipe (log → claude -p → schema-conforming JSON), then a fan-out modernization loop across many files.
Post-Quiz: Claude Code Features and Modes

1. What is the primary purpose of headless mode (-p/--print)?

To run the same agent loop non-interactively over stdin/stdout for automation and CI/CD.
To disable the agent loop and only echo the prompt.
To open a graphical UI instead of the terminal.
To permanently change the default model.

2. A CI job must parse Claude's answer as a structured object matching a defined shape. Which output configuration fits?

--output-format text with no schema.
--output-format json combined with --json-schema.
Interactive mode with /compact.
Headless mode with no output format flag at all.

3. Which output format emits one self-contained JSON object per line for real-time consumption?

text
json
stream-json
yaml

4. Why does /compact re-read the project-root CLAUDE.md after summarizing the conversation?

So your pinned instructions survive the context summarization and stay stable.
Because compaction deletes all configuration files.
To switch the session into headless mode automatically.
Because CLAUDE.md must be regenerated on every message.

5. Which combination best supports a multi-day, large-scale codebase modernization?

Headless mode with stream-json, committed CLAUDE.md rules, and a pinned model version.
Interactive mode with a floating model alias and no rules.
Text output only, edited by hand file by file.
A single interactive session left running with no version pinning.
Pre-Quiz: Managing Configuration at Scale

1. What is the best-practice way to pin a plugin dependency in production?

Reference a branch name so it always tracks the latest work.
Pin to a specific commit SHA for reproducibility.
Pin to a moving tag that can be re-pointed.
Avoid pinning so updates arrive automatically.

2. Which files should be committed so the whole team inherits them?

.claude/settings.json, ./CLAUDE.md, .claude/rules/, .claude/commands/, .claude/agents/.
.claude/settings.local.json and ./CLAUDE.local.md.
Only the managed enterprise policy files.
Nothing — all Claude Code config must stay local.

3. Why is pinning a plugin to a SHA compared to a package-manager lockfile?

Both are convenient but mutable ranges.
A SHA is a fingerprint resolving to exactly one version, unlike a mutable semver range.
A SHA lets the plugin auto-update on each install.
Lockfiles and SHAs both point at branch tips.

4. What does keeping configuration in version control give a team?

Instruction changes flow through the same review, blame, and rollback machinery as code.
It disables managed enterprise policy.
It forces every developer onto the same laptop.
It converts CLAUDE.md into a binary artifact.

5. Which three pinning practices together deliver end-to-end reproducibility?

Pin the model ID, pin plugin SHAs, and commit CLAUDE.md/rules tied to the validated model.
Use floating aliases, branch refs, and uncommitted local notes.
Disable memory, disable plugins, and disable settings.
Rely solely on managed policy and skip all version control.

4. Managing Configuration at Scale

Key Points

Claude Code ships a full plugin marketplace — centralized discovery, version pinning, automatic updates, permission controls, and multiple source backends (GitHub, npm, GitLab, local paths). A plugin bundles reusable configuration (commands, skills, agents, even default settings) into an installable unit.

For dependencies, pinning strategy is everything. A catalog can pin a plugin entry to a specific commit SHA; a manifest can pin itself to a semver string. The best practice is to pin to a SHA in production: referencing a branch or tag means a push or moved tag can silently change what installs, whereas a SHA guarantees reproducibility (the catalog can override the manifest by pinning to a SHA). This is exactly why lockfiles exist — a semver range like ^2.1.0 is convenient but mutable, while a pinned SHA is a fingerprint resolving to one and only one version. Anthropic maintains an official managed directory at anthropics/claude-plugins-official.

Sharing configuration and version control

The scope model is what makes team sharing work. The rule of thumb: commit what the team should share; gitignore what is personal.

Because CLAUDE.md, rules, settings.json, custom commands, and subagent definitions are all plain-text files, they diff cleanly and review naturally through pull requests. An instruction change goes through the same review, blame, and rollback machinery as a code change. Combine the three pinning practices — pin the model ID, pin plugin SHAs, and commit CLAUDE.md/rules tied to the validated model — for end-to-end reproducibility that behaves the same for every teammate today and again six months from now.

graph TD A["Model ID pinned: stable behavior"] --> D["End-to-end reproducibility"] B["Plugin SHAs pinned: fixed dependencies"] --> D C["CLAUDE.md and rules committed: reviewed instructions tied to validated model"] --> D D --> E["Same behavior for every teammate, today and months later"]
Animation slot: a three-lever control panel (model ID, plugin SHA, committed prompts) all locking into place, then a team of developers pulling the identical reproducible configuration from version control.
Post-Quiz: Managing Configuration at Scale

1. What is the best-practice way to pin a plugin dependency in production?

Reference a branch name so it always tracks the latest work.
Pin to a specific commit SHA for reproducibility.
Pin to a moving tag that can be re-pointed.
Avoid pinning so updates arrive automatically.

2. Which files should be committed so the whole team inherits them?

.claude/settings.json, ./CLAUDE.md, .claude/rules/, .claude/commands/, .claude/agents/.
.claude/settings.local.json and ./CLAUDE.local.md.
Only the managed enterprise policy files.
Nothing — all Claude Code config must stay local.

3. Why is pinning a plugin to a SHA compared to a package-manager lockfile?

Both are convenient but mutable ranges.
A SHA is a fingerprint resolving to exactly one version, unlike a mutable semver range.
A SHA lets the plugin auto-update on each install.
Lockfiles and SHAs both point at branch tips.

4. What does keeping configuration in version control give a team?

Instruction changes flow through the same review, blame, and rollback machinery as code.
It disables managed enterprise policy.
It forces every developer onto the same laptop.
It converts CLAUDE.md into a binary artifact.

5. Which three pinning practices together deliver end-to-end reproducibility?

Pin the model ID, pin plugin SHAs, and commit CLAUDE.md/rules tied to the validated model.
Use floating aliases, branch refs, and uncommitted local notes.
Disable memory, disable plugins, and disable settings.
Rely solely on managed policy and skip all version control.

Your Progress

Answer Explanations