Module 3: CLAUDE.md and the memory system

The Memory Hierarchy in Claude Code

The Memory Hierarchy in Claude Code

Overview

Claude Code doesn't take context from a single place. Multiple sources shape every response, each with a different priority. When two sources contradict each other, Claude follows the higher-priority one. Understanding this hierarchy is understanding how Claude thinks.

In this capsule you'll learn the 4 CLAUDE.md scopes, the role of .claude/rules/ for modular rules, imports with @path, and the conceptual levels of precedence. By the end, you'll understand exactly why Claude makes each decision it makes.

Note: In earlier versions of this guide we talked about "6 levels" (counting training data and system prompt as levels 1-2). We keep that pedagogical framing, but the official documentation focuses on the 4 CLAUDE.md scopes that you control: Managed policy, Project, User, and Local. Those are the levels where you actually make decisions.


The 4 CLAUDE.md scopes (official)

The official Claude Code documentation organizes the hierarchy into 4 scopes, ordered from most general to most specific:

ScopeLocationPurposeShared with
Managed policy/Library/Application Support/ClaudeCode/CLAUDE.md (macOS)
/etc/claude-code/CLAUDE.md (Linux/WSL)
C:\Program Files\ClaudeCode\CLAUDE.md (Windows)
Organization rules (IT/DevOps)The whole org
Project./CLAUDE.md or ./.claude/CLAUDE.mdShared project instructionsThe team (via git)
User~/.claude/CLAUDE.mdPersonal preferences for all your projectsOnly you (all projects)
Local./CLAUDE.local.mdPersonal preferences for the current projectOnly you (current project) — goes in .gitignore

How conflicts get resolved: More specific locations win over broader ones. Within the same scope, CLAUDE.local.md loads AFTER CLAUDE.md, so your personal notes are the last thing Claude reads at that level.

How they're discovered: Claude walks upward from your current directory, looking for CLAUDE.md and CLAUDE.local.md at every level. Everything it finds gets concatenated, not overwritten.

.claude/rules/ — modular rules by topic

For large projects, you can split the instructions into modular files inside .claude/rules/:

your-project/
├── .claude/
│   ├── CLAUDE.md           # Main instructions
│   └── rules/
│       ├── code-style.md   # Code style
│       ├── testing.md      # Test conventions
│       └── security.md     # Security requirements

The key advantage: files in .claude/rules/ can carry a YAML frontmatter with paths so they load ONLY when Claude works with files matching the pattern:

---
paths:
  - "src/api/**/*.ts"
---

# API Development Rules

- Every endpoint must include input validation
- Use the standard error response format
- Include OpenAPI comments

This rule only loads when Claude reads or edits files in src/api/. For other files it doesn't load, saving context.

Supported patterns:

PatternMatches
**/*.tsEvery .ts file in any directory
src/**/*Everything under src/
src/components/*.tsxReact components in a specific location
src/**/*.{ts,tsx}TS and TSX with brace expansion

User-level rules: ~/.claude/rules/ applies to all your projects. Useful for personal preferences that aren't project-specific.

Imports with @path/to/file

CLAUDE.md can import other files with the @path/to/import syntax. Imported files get expanded and included in context at the start:

See @README for project overview and @package.json for npm commands.

# Additional Instructions
- git workflow @docs/git-instructions.md
  • Accepts relative paths (resolved from the importing file, not the working dir) and absolute ones
  • Max 5 levels of recursive importing
  • The first time Claude Code hits external imports, it shows an approval dialog

AGENTS.md — cross-tool compatibility

If your repo already uses AGENTS.md for other coding agents (Aider, Continue, etc.), create a CLAUDE.md that imports it:

@AGENTS.md

## Claude Code

Use plan mode for changes under `src/billing/`.

Claude Code reads only CLAUDE.md, not AGENTS.md directly. The import lets you share instructions across tools without duplicating them.


The 6 pedagogical levels (mental model)

Beyond the 4 CLAUDE.md scopes you control, there are conceptually 6 sources that shape every Claude response. We keep this framing because it helps you understand how Claude prioritizes information:


The 6 levels: overview

HIGHEST PRIORITY (wins conflicts)
         ▲
         │
  ┌──────┴──────┐
  │ 6. Session  │  ← Your current conversation
  │    context  │
  └──────┬──────┘
  ┌──────┴──────┐
  │ 5. CLAUDE.md│  ← Per-subdirectory overrides
  │    subdir   │
  └──────┬──────┘
  ┌──────┴──────┐
  │ 4. CLAUDE.md│  ← Your file at the project root
  │    project  │
  └──────┬──────┘
  ┌──────┴──────┐
  │ 3. CLAUDE.md│  ← Organization rules (enterprise)
  │    company  │
  └──────┬──────┘
  ┌──────┴──────┐
  │ 2. System   │  ← Anthropic's internal prompt
  │    prompt   │
  └──────┬──────┘
  ┌──────┴──────┐
  │ 1. Training │  ← The base model's knowledge
  │    data     │
  └─────────────┘
         │
         ▼
LOWEST PRIORITY (gets overridden)

The precedence rule: Higher levels override lower ones. If your CLAUDE.md says "use snake_case" but your conversation says "for this file use camelCase", the conversation wins.


Level 1: Training data (the model's knowledge)

What it is

Everything Claude knows from its training. It includes knowledge of programming languages, frameworks, best practices, library documentation, and common development patterns.

What it provides

  • Language knowledge (Python, TypeScript, Rust, Go, etc.)
  • Framework and library documentation
  • Design patterns (MVC, Repository, Factory, etc.)
  • General software engineering best practices
  • Tool knowledge (git, npm, pip, Docker, etc.)

Who controls it

Anthropic — through the model's training process. You can't modify this level.

When it takes precedence

When there is no more specific information at the higher levels. If no CLAUDE.md states which naming convention to use, Claude uses whatever it considers "best practice" from its training.

Practical example

With no CLAUDE.md and no instructions:

You: "Create a class to handle users in Python"

Claude uses its training:
→ Uses snake_case (Python convention)
→ Creates a class with __init__, __repr__
→ Follows PEP 8
→ Uses type hints (modern Python)

Claude makes these decisions because its training data says that's conventional in Python. If your project uses a different style, you have to tell it at a higher level.

Limitations

  • It doesn't know YOUR specific project
  • It doesn't know YOUR conventions
  • It doesn't know which versions you use
  • It doesn't know which files exist in your codebase
  • It may hold out-of-date information (knowledge cutoff)

Level 2: System prompt (Anthropic's internal prompt)

What it is

A prompt Anthropic injects automatically before every session. It defines Claude Code's base behavior: how it interacts, which tools it has available, which permissions it asks for, and which safety constraints it follows.

What it provides

  • Behavior instructions (be concise, ask for confirmation before running destructive commands)
  • The definition of available tools (read file, write file, execute command, etc.)
  • Safety constraints (don't run malicious code, ask for confirmation on dangerous operations)
  • Output format (how it presents code, explanations, etc.)

Who controls it

Anthropic — you can't see or modify the system prompt directly.

When it takes precedence

Over the training data, but below any CLAUDE.md. The system prompt sets the "rules of the game" for Claude Code as a tool, but your instructions (via CLAUDE.md) take priority over most behaviors.

Practical example

The system prompt says something like:
"Before running commands that modify the filesystem,
 ask the user for confirmation."

That's why, when Claude wants to run:
> rm -rf node_modules && npm install

It asks you:
"Claude wants to run this command. Allow? [y/n/always]"

That comes from the system prompt, not from your configuration.

What you can influence

Even though you can't change the system prompt directly, you can shape Claude's behavior through:

  • Settings: configure allowedTools to pre-approve tools
  • CLAUDE.md: give instructions that complement or adjust the default behavior

Level 3: Enterprise/organization CLAUDE.md

What it is

In enterprise environments (companies running Claude Code at scale), administrators can define an organization-level CLAUDE.md that applies to every project in the company.

What it provides

  • Company standards (coding standards, security policies)
  • Global constraints (don't use certain libraries, don't generate certain kinds of code)
  • Conventions shared across all teams
  • Compliance and security rules

Who controls it

Organization administrators — platform teams, DevOps, or technical leads.

When it takes precedence

Over the system prompt and the training data. But it can be overridden by the project's CLAUDE.md (level 4) or above.

Practical example

# CLAUDE.md (Enterprise — defined by the platform team)

## Corporate standards
- Every project must use TypeScript strict
- Don't generate code that uses eval()
- Logging is mandatory in the corporate format: JSON structured
- Every endpoint requires authentication
- Don't use npm packages with a GPL license
- Tests are mandatory: minimum 80% coverage

This CLAUDE.md applies to EVERY project in the organization. An individual developer doesn't have to repeat "don't use eval()" in every project — it's already at the enterprise level.

Who this matters to

  • Enterprise teams: if your company runs Claude Code on an enterprise plan, this applies
  • Individual developers: you probably don't have this level. You go straight to level 4

Analogy

It's like operating-system environment variables. PATH is defined globally and every program inherits it. The enterprise CLAUDE.md is Claude Code's "PATH" in your organization.


Level 4: The project's CLAUDE.md (project root)

What it is

The CLAUDE.md you create at the root of your project. It's the level we covered in depth in the previous capsule. It's the most important level for most developers.

What it provides

  • Project description
  • Tech stack
  • File structure
  • Code conventions
  • Available commands
  • Rules and constraints

Who controls it

You (or your team, if you commit it to the repo).

When it takes precedence

Over levels 1-3 (training, system prompt, enterprise). It gets overridden by subdirectory CLAUDE.md files (level 5) and the current conversation (level 6).

Practical example

The enterprise CLAUDE.md says:
"Every project uses TypeScript strict"

Your project CLAUDE.md says:
"Stack: Python 3.12, FastAPI"

→ Claude uses Python because your project CLAUDE.md carries more
  priority than the enterprise one for stack decisions.
  (The enterprise rule applies to TypeScript projects; this isn't one)

This is the one you commit

The project CLAUDE.md is normally committed to git so the whole team shares it:

git add CLAUDE.md
git commit -m "docs: add CLAUDE.md for project context"

That guarantees every developer on the team has the same context when they use Claude Code.


Level 5: Subdirectory CLAUDE.md

What it is

CLAUDE.md files placed in specific subdirectories of the project. They provide extra context or overrides when Claude works on files in that directory.

What it provides

  • Rules specific to one area of the codebase
  • Convention overrides for certain kinds of files
  • Extra context for directories with particular logic

Who controls it

You or your team.

When it takes precedence

When Claude works on files inside that subdirectory. A CLAUDE.md in /tests/ takes priority over the root CLAUDE.md when Claude is writing or reading files in /tests/.

Practical example

my-project/
├── CLAUDE.md                    ← Level 4 (project)
├── src/
│   └── ...
├── tests/
│   ├── CLAUDE.md                ← Level 5 (subdirectory)
│   ├── unit/
│   └── integration/
└── docs/
    └── CLAUDE.md                ← Level 5 (subdirectory)

Root CLAUDE.md (level 4):

## Conventions
- Don't use any
- Absolute imports
- camelCase for variables

tests/CLAUDE.md (level 5):

## Testing conventions
- any is acceptable in mocks and fixtures
- Use the describe/it pattern
- Shared fixtures in conftest.py
- Test naming: test_[feature]_[scenario]_[expected]
- Mocks live next to the test, not in a separate folder
- Don't use real production data in tests

In this example, the root rule "don't use any" gets relaxed inside /tests/, where "any is acceptable in mocks". Claude knows this because the subdirectory CLAUDE.md has higher priority.

When to create a subdirectory CLAUDE.md

SituationCreate a subdirectory CLAUDE.md
Tests with different conventions✅ /tests/CLAUDE.md
Documentation with a specific style✅ /docs/CLAUDE.md
A legacy module with its own rules✅ /src/legacy/CLAUDE.md
Frontend and backend with different stacks✅ /frontend/CLAUDE.md, /backend/CLAUDE.md
A subdirectory with the same style as the rest❌ Not needed

Example: a monorepo with multiple CLAUDE.md files

monorepo/
├── CLAUDE.md                  ← "Monorepo. Each package has its own stack."
├── packages/
│   ├── api/
│   │   ├── CLAUDE.md          ← "FastAPI, Python 3.12, pytest"
│   │   └── src/
│   ├── web/
│   │   ├── CLAUDE.md          ← "Next.js 14, TypeScript, Vitest"
│   │   └── src/
│   └── shared/
│       ├── CLAUDE.md          ← "Pure TypeScript, no frameworks"
│       └── src/
└── infra/
    ├── CLAUDE.md              ← "Terraform, AWS CDK"
    └── modules/

Each subdirectory CLAUDE.md gives specific context to its area. Claude adapts its behavior to wherever you're working.


Level 6: The current conversation's context

What it is

Everything you say and everything Claude answers during the current session. It includes your instructions, your corrections, the files Claude read, and the output of the commands it ran.

What it provides

  • Instructions specific to the current task
  • Real-time corrections ("no, use X instead of Y")
  • Context from files read during the session
  • Results of commands that were run
  • Decisions made during the conversation

Who controls it

You — directly, with every message you send.

When it takes precedence

Always. It's the highest-priority level. If CLAUDE.md says "use snake_case" but you say "for this file use camelCase", Claude uses camelCase for that file.

Practical example

CLAUDE.md says:
"Always use Vitest for testing"

You: "For this module specifically, write the tests with Jest
     because it integrates better with the library we're testing."

→ Claude uses Jest for this module because your conversational
  instruction takes priority over CLAUDE.md

What does NOT survive

The conversational context is lost when:

  • You run /clear
  • The session ends
  • Compaction kicks in (it gets summarized, detail is lost)
  • You start a new session

That's why instructions that always apply belong in CLAUDE.md (level 4), not in the conversation (level 6). The conversation is temporary; CLAUDE.md is permanent.


How Claude resolves contradictions

The precedence rule

When two levels contradict each other, the higher-priority one wins:

Conversation > Subdir CLAUDE.md > Project CLAUDE.md >
Enterprise CLAUDE.md > System prompt > Training data

Scenario 1: Training vs CLAUDE.md

Training data: "In Python, use snake_case per PEP 8 convention"
CLAUDE.md: "Convention: camelCase for everything (legacy Java→Python project)"

→ Claude uses camelCase
→ CLAUDE.md (level 4) > Training data (level 1)

Scenario 2: Root CLAUDE.md vs subdirectory

Root CLAUDE.md: "Don't use any"
tests/CLAUDE.md: "any is acceptable in mocks"

When Claude writes a mock in tests/:
→ It uses any without hesitation
→ Subdir CLAUDE.md (level 5) > Project CLAUDE.md (level 4)

When Claude writes code in src/:
→ It doesn't use any
→ Only the project CLAUDE.md (level 4) applies

Scenario 3: CLAUDE.md vs conversation

CLAUDE.md: "Always include type hints"
You: "Generate this quick script without type hints, it's a one-off"

→ Claude skips the type hints for this script
→ Conversation (level 6) > CLAUDE.md (level 4)

→ In the NEXT message (if you say nothing about types):
→ Claude goes back to using type hints
→ The conversational instruction was for that specific task

Scenario 4: every level in action

Training:     "Python uses snake_case"
System:       "Ask for confirmation before rm"
Enterprise:   "Don't use eval()"
Project:      "Stack: Python 3.12, FastAPI. Naming: snake_case"
Subdir:       tests/CLAUDE.md: "Mocks may use any"
Conversation: "For this test, use camelCase in the helpers"

Result when Claude writes a test:
- ✅ Uses Python (training + project)
- ✅ Asks for confirmation on destructive commands (system)
- ✅ Doesn't generate eval() (enterprise)
- ✅ Uses FastAPI patterns (project)
- ✅ Allows any in mocks (subdir)
- ✅ Uses camelCase in this test's helpers (conversation)

Every level contributes something. When there's a conflict, the higher one wins.


Analogy: environment variables

The memory hierarchy works like environment variables in programming:

# Level 1 (Training) ≈ operating system defaults
# They're already there, you don't define them

# Level 2 (System prompt) ≈ /etc/environment
# Global system configuration, you don't touch it

# Level 3 (Enterprise) ≈ /etc/profile.d/company.sh
# The company defines variables for everyone

# Level 4 (Project) ≈ the project's .env
# You define variables for this project

# Level 5 (Subdir) ≈ a .env in a subdirectory
# A specific override for one area

# Level 6 (Conversation) ≈ export in the terminal
# A temporary override, just for this session

If you define DATABASE_URL in .env (level 4) and then run export DATABASE_URL=other in the terminal (level 6), the terminal wins. The same thing happens with Claude's memory.


Comparisons and decisions

Working with 1 level vs multiple levels

AspectRoot CLAUDE.md onlyMultiple levels
SimplicityHigh — a single fileMedium — multiple files
GranularityLow — the same rules everywhereHigh — rules per area
MaintenanceEasyMedium (more files to update)
For teamsWorkableIdeal (enterprise + project + local)
For monoreposInsufficientNecessary

When you need more than one level

  • 1 level is enough for small projects (1 developer, 1 stack, <20 files)
  • 2-3 levels for mid-size projects (a team, testing with its own rules, docs)
  • 4+ levels for enterprise and monorepos (multiple stacks, teams, policies)

What goes at each level

LevelKind of informationExample
Enterprise (3)Global company policies"No GPL, JSON logging"
Project (4)Stack, structure, conventions"FastAPI, snake_case, pytest"
Subdirectory (5)Overrides per area"tests: any ok, describe/it"
Conversation (6)Instructions for the current task"For this file use X"

Common patterns

Pattern 1: Root CLAUDE.md + tests/CLAUDE.md

The most common pattern. A root CLAUDE.md for the project, plus an extra CLAUDE.md in /tests/ with testing conventions:

project/
├── CLAUDE.md          → Stack, conventions, commands
└── tests/
    └── CLAUDE.md      → Testing-specific conventions

Pattern 2: Monorepo with one CLAUDE.md per package

monorepo/
├── CLAUDE.md          → "Monorepo with independent packages"
├── packages/
│   ├── api/CLAUDE.md  → API stack (Python, FastAPI)
│   ├── web/CLAUDE.md  → Frontend stack (TypeScript, Next.js)
│   └── cli/CLAUDE.md  → CLI stack (Rust)

Pattern 3: A temporary override via conversation

When you need to break a rule for one specific case:

You: "I know CLAUDE.md says don't use any, but for this
     generated-types file I need any. Go ahead."

Claude respects the conversational instruction without you having to touch CLAUDE.md.

Pattern 4: Progressive evolution

You don't need all 6 levels on day 1. Start at level 4 and add as you need:

Week 1:      Create the root CLAUDE.md (level 4)
Week 2:      Add tests/CLAUDE.md if you have testing conventions (level 5)
Month 2:     Add CLAUDE.local.md for personal preferences
As it scales: Consider an enterprise CLAUDE.md (level 3)

Pitfalls and edge cases

Pitfall 1: Assuming the conversation persists between sessions

Session 1:
You: "Always use verbose logging"
Claude: [uses verbose logging for the whole session]

Session 2 (new):
You: "Create an endpoint"
Claude: [does NOT use verbose logging — the instruction is gone]

Fix: If it always applies, put it in CLAUDE.md (level 4),
not in the conversation (level 6).

Pitfall 2: Unintentional contradictions between levels

Root CLAUDE.md: "Absolute imports always"
src/utils/CLAUDE.md: "Relative imports for internal utils"

What happens when Claude imports a util from another util?
→ It uses a relative import (the subdir has priority)

Is that what you wanted? Maybe, maybe not.
Be explicit about the scope of each rule.

Pitfall 3: A subdirectory CLAUDE.md that's too permissive

tests/CLAUDE.md:
"Code restrictions don't apply in tests."

That cancels EVERY rule from the root CLAUDE.md inside /tests/.
Claude could generate tests with eval(), any, console.log,
and no type hints — because "restrictions don't apply."

Fix: Be specific about what you're relaxing, don't write a global override:
"In tests: any is acceptable in mocks. Every other rule from the
 root CLAUDE.md applies normally."

Pitfall 4: Not knowing which level is causing a behavior

Claude generates code with a pattern you didn't expect.
Where is it coming from?

Diagnostic checklist:
1. Did you say it in the conversation? → Level 6
2. Is there a CLAUDE.md in the subdirectory? → Level 5
3. Is it in the root CLAUDE.md? → Level 4
4. Is there an enterprise CLAUDE.md? → Level 3
5. Is it default Claude Code behavior? → Level 2
6. Is it a standard convention of the language? → Level 1

Tip: Ask Claude:
"Why did you use X instead of Y? Where does that decision come from?"

Pitfall 5: Forgetting that auto memory is another level

Auto memory (capsule 04) adds an extra level to the system. If you corrected Claude ("don't use var, use const") and Claude saved it as an auto memory, that correction persists across sessions — even if it isn't in CLAUDE.md.

This can produce "ghost" behaviors where Claude does something you didn't explicitly ask for, but learned from an earlier correction.


Complete worked example

Scenario: a monorepo with multiple levels

ecommerce/
├── CLAUDE.md                         ← Level 4: Project
├── packages/
│   ├── api/
│   │   ├── CLAUDE.md                 ← Level 5: API
│   │   ├── src/
│   │   └── tests/
│   │       └── CLAUDE.md             ← Level 5: API tests
│   ├── storefront/
│   │   ├── CLAUDE.md                 ← Level 5: Storefront
│   │   └── src/
│   └── admin/
│       ├── CLAUDE.md                 ← Level 5: Admin
│       └── src/

Root CLAUDE.md (level 4):

# E-Commerce Platform

Monorepo with 3 packages: api, storefront, admin.

## Global rules
- Commits in English: "type(scope): description"
- Don't commit secrets
- Each package has its own stack (see its CLAUDE.md)
- Shared types in packages/shared/types/

packages/api/CLAUDE.md (level 5):

# API Package

## Stack
- Python 3.12, FastAPI 0.109, SQLAlchemy 2.0
- Pytest + httpx

## Conventions
- snake_case for everything
- Pydantic v2 for schemas
- Alembic for migrations

## Commands (run from packages/api/)
- Dev: `uvicorn src.main:app --reload`
- Test: `pytest -v`

packages/storefront/CLAUDE.md (level 5):

# Storefront Package

## Stack
- TypeScript 5.3, Next.js 14 (App Router)
- Tailwind CSS 3.4, shadcn/ui

## Conventions
- camelCase for variables, PascalCase for components
- Server Components by default
- CSS: Tailwind utilities, no CSS modules

## Commands (run from packages/storefront/)
- Dev: `npm run dev`
- Build: `npm run build`

packages/api/tests/CLAUDE.md (level 5, nested):

# API Tests

- Shared fixtures in conftest.py
- any acceptable in mocks
- One test file per module: test_{module}.py
- Factory pattern to create test data
- Use database isolation: every test in a transaction that rolls back

Resolution in action

You (working in packages/api/):
"Create an endpoint to search orders"

Claude applies:
- Level 1 (Training): it knows Python and FastAPI
- Level 4 (Project): "Commits in English, no secrets"
- Level 5 (API): "snake_case, Pydantic v2, uvicorn"
→ Generates a FastAPI endpoint with snake_case and Pydantic schemas

You (working in packages/storefront/):
"Create a product search page"

Claude applies:
- Level 1 (Training): it knows TypeScript and Next.js
- Level 4 (Project): "Commits in English, no secrets"
- Level 5 (Storefront): "PascalCase components, Tailwind, Server Components"
→ Generates a Server Component with Tailwind CSS

Same project. Different subdirectory CLAUDE.md files.
Completely different behavior. That's the power of the hierarchy.

Practice exercises

Exercise 1: Identify the levels in your setup

Take stock of your current Claude Code configuration. How many levels do you have active?

  1. Do you have a CLAUDE.md at the project root? (Level 4)
  2. Do you have a CLAUDE.md in any subdirectory? (Level 5)
  3. Do you use Claude Code in an organization with an enterprise configuration? (Level 3)
  4. Are there any auto memories saved? (Varies)
How to check
# Check for CLAUDE.md at the root
ls CLAUDE.md

# Look for CLAUDE.md in subdirectories
find . -name "CLAUDE.md" -not -path "./.git/*"

# Check auto memories
ls -la .claude/

# Check settings
cat .claude/settings.json 2>/dev/null
cat ~/.claude/settings.json 2>/dev/null

Most users only have level 4 (the root CLAUDE.md). That's fine to start with. The additional levels get added when you need them.

Exercise 2: Create a subdirectory CLAUDE.md

If your project has a test folder (tests/, __tests__/, spec/), create a CLAUDE.md in it with testing-specific conventions:

  • The naming pattern for tests
  • Which kinds of mocks are acceptable
  • Fixtures and setup
  • Which root-project conventions get relaxed in tests
Template
# Testing Conventions

## Structure
- Files: test_{module}.py (Python) or {module}.test.ts (TypeScript)
- Each test file corresponds to a module in src/

## Conventions
- describe/it (or class/def test_) to organize tests
- any acceptable in mocks and stubs
- Shared fixtures in conftest.py / setup.ts
- Factory functions to create test data

## Rules
- Don't use real production data
- Every test must be independent (no ordering dependencies)
- Clean up side effects after every test
- Mocks next to the test, not in a separate folder

Exercise 3: Simulate a conflict between levels

  1. In your root CLAUDE.md, add: "All comments in English"
  2. In a Claude Code session, say: "For this file, write the comments in Spanish"
  3. Verify that Claude uses Spanish (the conversation has priority)
  4. In the next message, ask it to create another file WITH no language instruction
  5. Verify that Claude goes back to English (back to the root CLAUDE.md)
What to watch for

This demonstrates:

  • Level 6 (conversation) > Level 4 (CLAUDE.md) for specific instructions
  • When there's no conversational instruction, Claude falls back to CLAUDE.md
  • Conversational instructions are temporary, not persistent

If Claude does NOT go back to English in step 5, it may be because:

  • The Spanish instruction "leaked" into the general context
  • Fix: be more explicit: "Only for the previous file use Spanish. For everything else, follow CLAUDE.md."

Exercise 4: Design the hierarchy for your project

Sketch out the CLAUDE.md structure your project would need. Do you only need the root? Tests? Specific subdirectories?

Criteria:

  • Are there areas with different conventions? → A subdirectory CLAUDE.md
  • Are there areas with different stacks? → A subdirectory CLAUDE.md
  • Is it a monorepo? → One CLAUDE.md per package
  • Do you work on a team? → Consider CLAUDE.local.md (capsule 05)
Examples by project type

A simple project (1 stack, 1 developer):

project/
└── CLAUDE.md      ← Level 4 only, enough

A project with differentiated tests:

project/
├── CLAUDE.md      ← Level 4: Stack, conventions
└── tests/
    └── CLAUDE.md  ← Level 5: Testing rules

A monorepo:

monorepo/
├── CLAUDE.md            ← Level 4: Global rules
├── frontend/CLAUDE.md   ← Level 5: Frontend stack
├── backend/CLAUDE.md    ← Level 5: Backend stack
└── shared/CLAUDE.md     ← Level 5: Shared conventions

An enterprise project:

company/
├── [enterprise CLAUDE.md]  ← Level 3: Managed by the platform team
├── my-project/
│   ├── CLAUDE.md           ← Level 4: My project
│   ├── CLAUDE.local.md     ← Personal (not in git)
│   └── tests/CLAUDE.md     ← Level 5: Testing

Exercise 5: Ask Claude where a decision came from

In your next Claude Code session, when Claude generates code with a pattern or convention, ask it:

"Why did you choose [pattern X] instead of [pattern Y]?
 Where does that decision come from?"

Try to identify whether the decision came from:

  • Training data (a standard convention of the language)
  • CLAUDE.md (a rule you defined)
  • The conversation (something you said earlier in this session)
What to watch for

Claude can usually explain where a decision came from:

  • "I followed the CLAUDE.md convention that says..."
  • "It's the standard Python/TypeScript convention..."
  • "Based on what you told me earlier..."

If Claude can't explain it, it was probably a training decision (level 1) — "general best practices" it internalized during training.

This exercise helps you calibrate your CLAUDE.md: if Claude makes decisions you don't want, you need a more explicit rule in CLAUDE.md.


Summary

  • 6 memory levels determine how Claude Code makes decisions, from lowest to highest priority:
    1. Training data — the model's knowledge
    2. System prompt — Claude Code's base behavior
    3. Enterprise CLAUDE.md — the organization's rules
    4. Project CLAUDE.md — your configuration (the most important one)
    5. Subdirectory CLAUDE.md — overrides per area
    6. Conversation context — your current instructions
  • Higher levels override lower ones when there's a conflict.
  • The root CLAUDE.md (level 4) is enough for most projects.
  • A subdirectory CLAUDE.md (level 5) is for tests, monorepos, or areas with different conventions.
  • The conversation (level 6) has the highest priority but is temporary — it's lost between sessions.
  • What always applies goes in CLAUDE.md. What's temporary goes in the conversation.
  • Diagnosis: If Claude does something unexpected, walk the 6 levels to find the source.
  • Analogy: It works like environment variables: the more local scopes override the global ones.

Next capsule: 04 - Auto memory and settings — how Claude learns implicitly and how to configure permissions across 3 scopes.


Additional resources

  1. Claude Code Memory — Anthropic Docs — Official documentation on the full memory hierarchy
  2. Claude Code Settings — How settings interact with the memory hierarchy
  3. Claude Code Best Practices — Recommendations for managing context across multiple levels
  4. Claude Code Overview — General architecture and how the levels work internally
  5. Claude Code CLI Reference — Commands for managing CLAUDE.md and memory
  6. Claude Code Interactive Mode — How the hierarchy affects interactive sessions