Curriculum › Claude Code Configuration & Workflows · 20% of the exam

CLAUDE.md and project configuration

What you'll be able to do

  • State what CLAUDE.md is for and why it lives in git
  • Layer configuration from user scope down to directory scope correctly
  • Decide what belongs in CLAUDE.md versus a system prompt
  • Diagnose a bloated CLAUDE.md as a design problem, not a content problem

What you’ll be able to do

  • State what CLAUDE.md is for and why it lives in git
  • Layer configuration from user scope down to directory scope correctly
  • Decide what belongs in CLAUDE.md versus a system prompt

What you need to know

CLAUDE.md is project memory, checked into version control

CLAUDE.md is a plain-text file Claude Code reads automatically at the start of a session. It exists to answer the questions a new engineer would otherwise ask in the first ten minutes: how this repo is structured, which commands build and test it, which conventions are non-negotiable, and which shortcuts are actually landmines.

The detail that matters architecturally: it is versioned alongside the code it describes. When the build command changes, the person who changed it updates CLAUDE.md in the same commit. There is no separate system to keep in sync, and no drift between "what the docs say" and "what's actually true this week" — because if it drifts, the next PR that touches the build script is the one that fixes it.

Scope layers broad to specific

Claude Code resolves CLAUDE.md at more than one level, and the architecture question is which level owns which fact:

  • User-level — a person's own preferences that apply across every project they touch (their preferred verbosity, their editor conventions). This is about the human, not the repo.
  • Project-level (repo root) — facts true for anyone working in this codebase: the stack, the test command, the deploy process, the architectural rules everyone must follow.
  • Directory-level — narrower facts true only inside one package or service in a monorepo, layered on top of the project-level file rather than repeating it.

The design failure is copying the same project-wide fact into every directory's file "just in case." That's not defense in depth, it's N places to update the next time the fact changes — and N-1 of them will eventually be wrong.

What doesn’t belong in CLAUDE.md

CLAUDE.md is for durable, repo-true facts. It is not a place to restate the current request, and it is not a substitute for a system prompt in an API-driven application.

before — request-specific instruction dumped into project memory
## Notes - For today's task, only touch the billing module - Ignore the failing test in auth, it's unrelated - Use the new logging format for this PR
after — durable facts only; the request stays in the prompt
## Build & test - `npm run build`, `npm test` ## Conventions - All logging goes through `lib/logger`, structured JSON only - Billing module owns all Stripe interaction; no other module calls Stripe directly

The first version is stale the moment the task changes and actively misleads the next session. The second is still true a year later. A CLAUDE.md that needs editing every session is a sign the instructions belong in the prompt for that session, not in project memory.

Key concept

CLAUDE.md is versioned, layered project memory — durable facts about the repo, not the request. If a line stops being true when the task changes, it doesn’t belong there.

When a scenario describes a team's CLAUDE.md growing unreadable or contradicting itself across packages, the fix is almost always re-layering it by scope, not trimming prose.

Practice scenario

ScenarioA monorepo has one 400-line CLAUDE.md at the root. Three different teams keep editing the same file to add package-specific build steps, and merge conflicts on it are now a weekly occurrence.
Work it through, then open this

The root file should hold only what’s true for the whole repo — the shared conventions and the fact that packages exist. Each team’s package-specific build steps belong in a CLAUDE.md inside their own package directory, which Claude Code layers on top of the root file automatically. This removes the merge conflicts because each team edits a file the others never touch, and it removes noise because a session working in one package doesn’t need the other two teams’ build steps in context at all.

Build exercise — Audit a CLAUDE.md for scope leaks

Intermediate · 20 min

What you’ll learn

  • Spotting request-specific content that has leaked into project memory
  • Deciding what moves to a directory-level file versus staying at the root
  • Recognizing when a file’s size is a layering problem, not a content problem
  1. Open a project’s root CLAUDE.md and flag any line that would stop being true if the current task changed.

    • Why: Those lines are prompt content masquerading as project memory, and they’ll mislead the next unrelated session.
    • You should see: At least one line that’s really about “what I’m doing today,” not “what this repo is.”
  2. For a monorepo, check whether package-specific facts are duplicated at the root instead of living in that package’s own file.

    • Why: Duplication at the wrong scope is what turns CLAUDE.md into a merge-conflict magnet as the repo grows.
    • You should see: Either clean layering, or an opportunity to push a fact down to where it actually belongs.

Exam traps

Treating CLAUDE.md as a place for one-off, per-request instructions

It’s project memory, not a scratchpad for today’s task. Request-specific instructions belong in the prompt.

Duplicating the same convention across every subdirectory’s CLAUDE.md

Layering exists so a fact is stated once, at the scope where it’s true, and inherited everywhere below.

Assuming a single monolithic CLAUDE.md scales to a large monorepo

It becomes a merge-conflict bottleneck. Directory-level files scoped to each package solve this.

Putting secrets or environment-specific values in a file committed to git

CLAUDE.md is checked into version control and often shared broadly; secrets belong in environment configuration, not project memory.

Believing CLAUDE.md changes take effect mid-session without a reload

It’s read at session start. A running session doesn’t pick up an edit made to it in another terminal until it’s restarted.

Sources

Quick check

Select TWO.

Which two statements correctly distinguish Claude Code's settings.json hooks from a custom Agent SDK's lifecycle hooks? (Select TWO.)