Module 2: Context & Memory
|
Part 1: How It Works
In Module 1 you saw that Step 2 of the agentic loop is context assembly — the process of constructing the full prompt that the model receives. A large part of that context comes from memory files: persistent instructions that Claude Code loads automatically at the start of every session.
This module covers the entire memory and configuration system — how it is structured, how files are discovered, how conflicts are resolved, and how you control what Claude Code knows about your project.
The 4-Level Memory Hierarchy
Claude Code uses a layered system of CLAUDE.md files to load instructions.
There are four levels, ordered from lowest to highest priority:
| Level | Location | Purpose |
|---|---|---|
1 (lowest) |
|
System-wide managed settings — administrator-controlled, typically deployed via MDM or configuration management |
2 |
|
User global preferences — your personal defaults that apply to every project |
3 |
|
Project conventions — shared team settings, checked into version control |
4 (highest) |
|
Local private overrides — personal project tweaks, git-ignored |
The priority model is simple but easy to misunderstand. Files are loaded in order from Level 1 to Level 4. Because the language model attends more strongly to content that appears later in its context window, later files have higher effective priority. A project-level instruction overrides a user-level instruction not through any explicit override mechanism, but because the model gives more weight to what it read most recently.
Level 1: Managed (lowest priority)"] L2["~/.claude/CLAUDE.md
Level 2: User Global"] L3["project/CLAUDE.md
Level 3: Project"] L4["CLAUDE.local.md
Level 4: Local Private (highest priority)"] L1 --> L2 L2 --> L3 L3 --> L4 style L1 fill:#e8e8e8,stroke:#999 style L2 fill:#d4e6f1,stroke:#2980b9 style L3 fill:#d5f5e3,stroke:#27ae60 style L4 fill:#fadbd8,stroke:#e74c3c
|
The priority ordering is a consequence of position in the context window, not a formal override system. There is no merge logic or conflict resolution engine. If Level 2 says "use tabs" and Level 3 says "use spaces," the model will follow "use spaces" because it appeared later. |
File Discovery Walk
When a conversation begins, Claude Code performs a discovery walk.
Starting from the current working directory, it walks up the filesystem tree toward the root, collecting CLAUDE.md files at each directory level.
For example, if you start Claude Code in ~/projects/learnpath/src/learnpath/, the walk proceeds:
-
~/projects/learnpath/src/learnpath/CLAUDE.md -
~/projects/learnpath/src/CLAUDE.md -
~/projects/learnpath/CLAUDE.md -
~/projects/CLAUDE.md -
~/CLAUDE.md -
Continue up to
/
At each level, Claude Code also checks for .claude/CLAUDE.md and CLAUDE.local.md variants.
The user-level (~/.claude/CLAUDE.md) and managed-level (/etc/claude-code/CLAUDE.md) files are loaded separately, outside the walk.
The collected files are cached for the duration of the conversation.
If you edit a CLAUDE.md file while a session is active, the changes will not take effect until you reload.
Use the /memory slash command to reload all memory files without restarting the session.
|
The |
The @include Directive
CLAUDE.md files can reference other files using the @ directive:
# Project Memory
@docs/architecture.md
@docs/conventions.md
@~/shared/company-standards.md
When Claude Code encounters an @ directive, it reads the referenced file and injects its content inline, as if it were part of the CLAUDE.md file.
Supported path formats:
-
Relative paths —
@docs/architecture.md(relative to the CLAUDE.md file’s location) -
Home paths —
@~/shared/standards.md(relative to the user’s home directory) -
Absolute paths —
@/etc/shared/policies.md
Safety mechanisms:
-
Circular reference detection — if file A includes file B which includes file A, the cycle is detected and broken
-
Maximum depth of 5 — includes can nest up to five levels deep; beyond that, deeper includes are ignored
-
Missing files — if a referenced file does not exist, it is silently skipped
The @include mechanism is useful for keeping your CLAUDE.md concise while pulling in detailed documentation from canonical sources.
Rather than duplicating your architecture docs, reference them.
Granular Rules
For instructions that should only apply when working on specific files, use the .claude/rules/ directory.
Each .md file in this directory can contain YAML frontmatter with a paths field that specifies which files the rule applies to:
---
paths:
- "**/*.py"
---
Use type hints on all function signatures.
Prefer Pydantic V2 BaseModel for all data classes.
Use `from __future__ import annotations` at the top of every module.
The paths field accepts glob patterns.
A rule is only activated when Claude Code is working on a file that matches at least one of the patterns.
Another example, scoped to SQL files:
---
paths:
- "**/*.sql"
- "migrations/**"
---
Always use lowercase SQL keywords (select, insert, update, delete).
Use explicit column lists -- never use SELECT *.
Include a comment header with the migration purpose.
Rules without a paths field in their frontmatter are loaded unconditionally, behaving like regular CLAUDE.md content.
Granular rules let you encode file-type-specific conventions without cluttering the main CLAUDE.md with conditional instructions.
Settings Hierarchy
Separate from the CLAUDE.md memory system, Claude Code has a settings system that controls its operational behavior — things like model selection, permissions, hooks, and MCP server configuration.
Settings follow their own five-level priority hierarchy:
| Priority | Scope | File |
|---|---|---|
1 (lowest) |
Plugin defaults |
Built-in defaults within Claude Code |
2 |
User settings |
|
3 |
Project settings |
|
4 |
Local settings |
|
5 (highest) |
Managed settings |
Platform-specific (MDM, registry, plist) |
(lowest priority)"] S2["~/.claude/settings.json
User Settings"] S3[".claude/settings.json
Project Settings (shared)"] S4[".claude/settings.local.json
Local Settings (private)"] S5["Managed Settings (MDM/registry)
(highest priority)"] S1 --> S2 S2 --> S3 S3 --> S4 S4 --> S5 style S1 fill:#e8e8e8,stroke:#999 style S2 fill:#d4e6f1,stroke:#2980b9 style S3 fill:#d5f5e3,stroke:#27ae60 style S4 fill:#fadbd8,stroke:#e74c3c style S5 fill:#f9e79f,stroke:#f39c12
Key settings you will encounter throughout this course:
-
model— select which Claude model to use -
permissions— define permission rules for tool execution -
hooks— configure lifecycle hooks (covered in Module 5) -
env— set environment variables for the session -
cleanupPeriodDays— control session transcript retention -
language— set the response language
Use the /config slash command to open the appropriate settings file in your editor.
Settings files auto-reload when saved — no need to restart the session.
|
The settings hierarchy is independent of the CLAUDE.md memory hierarchy. Settings control how Claude Code operates. Memory files control what Claude Code knows. Both use layered priority, but they serve different purposes. |
Best Practices by Level
Knowing what to put where is as important as knowing the hierarchy exists.
Managed (Level 1): Organization-wide policies and security guardrails. Examples: "Never commit secrets," "All code must pass linting before commit," "Use the corporate proxy for network requests." These are not user-configurable — they are set by administrators.
User (Level 2): Personal preferences that apply across all your projects. Examples: "I prefer explicit imports over wildcard imports," "Always explain your reasoning before making changes," "Use American English in comments." Keep these sparse — if a preference is project-specific, it does not belong here.
Project (Level 3): Team conventions that everyone on the project should follow. Examples: build commands, test commands, architectural decisions, coding standards, dependency management rules. This is your most-used level. Commit it to version control so the entire team benefits.
Local (Level 4): Personal workflow tweaks for a specific project. Examples: "I am working on the auth module this week — prioritize that context," "Skip running the full test suite, just run unit tests," environment-specific paths or credentials references. Git-ignored, so it never conflicts with teammates.
Content Guidelines
A well-crafted CLAUDE.md contains only information that would cause mistakes if absent:
-
Exact build and test commands (
uv run pytest,uv run uvicorn src.learnpath.main:app --reload) -
Architectural decisions that are not obvious from the code ("We use the repository pattern for data access")
-
Coding conventions that deviate from defaults ("Use Pydantic V2 field_validator, not the V1 validator decorator")
-
Environment requirements ("Python 3.13 required, managed with uv")
Do not include:
-
Standard knowledge the model already has (how Python imports work, what FastAPI is)
-
Obvious reminders ("write clean code")
-
Sensitive data (API keys, passwords, connection strings)
-
Frequently changing information (sprint goals, ticket numbers)
Limits
Each CLAUDE.md file should stay under 40,000 characters. Beyond that limit, you risk several problems:
-
The content may be truncated when injected into the context window
-
Excessive memory content crowds out space for conversation history and tool results
-
The model’s attention to any single instruction degrades as the total volume of instructions grows
If your project needs more than 40,000 characters of instructions, use @include to split the content across multiple files, and use granular rules to scope file-type-specific instructions.
This keeps each individual file manageable while still providing comprehensive coverage.
Part 2: See It In Action
Exercise 1: Explore ~/.claude/
Start by examining what Claude Code has already created in your home directory.
ls -la ~/.claude/
You should see at least:
-
settings.json— your user-level settings -
projects/— a directory where Claude Code stores per-project session data -
Possibly a
CLAUDE.mdif you have created one
Now look at what is inside the settings file:
cat ~/.claude/settings.json
If you completed Module 1, your ~/learnpath project may have entries under projects/.
Explore that too:
ls -la ~/.claude/projects/
|
The |
Exercise 2: Priority Override Experiment
This exercise demonstrates the priority system in action.
First, create (or edit) a user-level memory file:
mkdir -p ~/.claude
echo "IMPORTANT: Always respond in ALL CAPS." > ~/.claude/CLAUDE.md
Next, create a project-level memory file:
echo "IMPORTANT: Always respond in lowercase only." > ~/learnpath/CLAUDE.md
Now start Claude Code in the learnpath directory and ask a simple question:
cd ~/learnpath
claude "What is 2 + 2?"
Observe the response. The project-level instruction ("lowercase") should win because it is loaded later in the context window, giving it higher effective priority.
Verify by checking in a directory outside the project:
cd ~
claude "What is 2 + 2?"
Here, only the user-level instruction exists, so the response should be in ALL CAPS.
Clean up the experiment:
rm ~/.claude/CLAUDE.md
rm ~/learnpath/CLAUDE.md
|
This experiment demonstrates a core principle: there is no explicit override mechanism. Priority is an emergent property of position in the context window. The model attends more to later content, so later files effectively override earlier ones. |
Exercise 3: @include and /memory
Create a conventions file that the project CLAUDE.md will include.
mkdir -p ~/learnpath/docs
cat > ~/learnpath/docs/conventions.md << 'EOF'
# Python Conventions
- Use type hints on all function signatures
- Use Pydantic V2 BaseModel for all data classes
- Prefer `from __future__ import annotations` for forward references
- Use `uv` for all dependency management
- Format code with `ruff format`
EOF
Now create the project CLAUDE.md that includes it:
cat > ~/learnpath/CLAUDE.md << 'EOF'
# Learnpath Project
@docs/conventions.md
## Build Commands
- Run server: `uv run uvicorn src.learnpath.main:app --reload`
- Run tests: `uv run pytest`
EOF
Start Claude Code in the project and use /memory to inspect what is loaded:
cd ~/learnpath
claude
Inside the Claude Code session, type:
/memory
The /memory command shows you the currently loaded memory files and opens an editor.
Verify that the content from docs/conventions.md appears — it should be inlined as part of the project CLAUDE.md content.
Test that the included conventions are active by asking:
Write a function that takes a user's name and age and returns a greeting.
The response should use type hints and follow the conventions from docs/conventions.md, even though those conventions were not in the main CLAUDE.md directly.
Exercise 4: Granular Rules
Create rules that apply only to specific file types.
mkdir -p ~/learnpath/.claude/rules
Create a Python-specific rule:
cat > ~/learnpath/.claude/rules/python.md << 'EOF'
---
paths:
- "**/*.py"
---
Use type hints on all function signatures.
Always include docstrings on public functions and classes.
Use `from __future__ import annotations` at the top of every module.
EOF
Create a SQL-specific rule:
cat > ~/learnpath/.claude/rules/sql.md << 'EOF'
---
paths:
- "**/*.sql"
---
Always use lowercase SQL keywords (select, insert, update, delete, create, alter, drop).
Use explicit column lists -- never use SELECT *.
Include a comment at the top explaining the query's purpose.
EOF
Now test both rules in a Claude Code session:
cd ~/learnpath
claude
First, ask Claude to write Python code:
Create a new file src/learnpath/models/topic.py with a Pydantic model for a learning topic that has a title, description, and difficulty level.
The output should include type hints and docstrings, following the Python rule.
Then ask for SQL:
Write a SQL query that creates a topics table with columns for id, title, description, difficulty, and created_at. Save it to migrations/001_create_topics.sql.
The SQL output should use lowercase keywords, following the SQL rule.
|
Granular rules are powerful for polyglot projects. You can enforce different conventions for Python, SQL, JavaScript, YAML, and any other file type — all without cluttering the main CLAUDE.md. |
Part 3: Build With It
Now apply everything you have learned to configure proper memory and settings for the learnpath project.
Configure Project Memory
Create a comprehensive CLAUDE.md for the project:
cat > ~/learnpath/CLAUDE.md << 'EOF'
# Learnpath -- Personal Learning Path Manager
@docs/conventions.md
## Build & Run
- **Run dev server:** `uv run uvicorn src.learnpath.main:app --reload`
- **Run tests:** `uv run pytest`
- **Add dependency:** `uv add <package>`
- **Sync dependencies:** `uv sync`
## Stack
- Python 3.13, managed with `uv`
- FastAPI for the API layer
- Pydantic V2 for all models and validation (use `model_validator`, `field_validator` -- not V1 decorators)
- pytest for testing
## Architecture
```
src/learnpath/
__init__.py
main.py # FastAPI app, mounts routers
api/ # Route handlers (APIRouter per domain)
models/ # Pydantic models
services/ # Business logic
tests/
test_api/ # API integration tests
test_models/ # Model unit tests
test_services/ # Service unit tests
```
## Conventions
- Every API router uses `APIRouter` with a prefix and tags
- All request/response bodies are Pydantic V2 models -- never raw dicts
- Use proper HTTP status codes (201 for creation, 204 for deletion, 422 for validation errors)
- Tests mirror the src structure
EOF
Configure Project Settings
Create the project-level settings file:
mkdir -p ~/learnpath/.claude
cat > ~/learnpath/.claude/settings.json << 'EOF'
{
"permissions": {
"allow": [
"Read",
"Glob",
"Grep",
"Bash(uv run pytest*)",
"Bash(uv run uvicorn*)",
"Bash(uv sync*)",
"Bash(uv add*)"
]
}
}
EOF
This pre-approves common read operations and project-specific commands so Claude Code does not prompt you for every test run or server start.
Create an API Granular Rule
Add a rule scoped specifically to the API layer:
cat > ~/learnpath/.claude/rules/api.md << 'EOF'
---
paths:
- "src/learnpath/api/**"
---
Every route handler file must:
- Use `APIRouter` with an appropriate prefix and tags list
- Return Pydantic V2 models, never raw dicts or untyped responses
- Use proper HTTP status codes: 201 for resource creation, 204 for deletion, 404 for not found
- Include a docstring on each route function describing the endpoint's purpose
- Accept request bodies as Pydantic models with field validation
EOF
Verify the Configuration
Start Claude Code in the project and verify everything is loaded:
cd ~/learnpath
claude
Ask Claude Code to confirm it sees the configuration:
What are the project conventions and build commands?
Claude should respond with the build commands, stack details, and conventions from your CLAUDE.md. If it does, the memory system is working correctly.
Now test that the API rule activates when working on API files:
Create a new file src/learnpath/api/topics.py with a basic CRUD router for learning topics. Use a temporary in-memory list as storage.
The generated code should follow the API conventions: APIRouter with prefix and tags, Pydantic models for request/response, proper HTTP status codes, and docstrings on each route.
Transcript Review
After running the commands above, review the session transcript:
claude-transcripts list --limit 1
claude-transcripts view <session-id>
Compare this transcript with a Module 1 transcript (before CLAUDE.md existed). Look for:
-
CLAUDE.md injection — in the Module 2 transcript, you should see your memory file content appear early in the context assembly. It is injected as part of the user context, before your first message.
-
Included file content — the content from
docs/conventions.mdshould appear inline, as if it were part of the CLAUDE.md directly. -
Rule activation — when Claude worked on a
.pyfile in the API directory, the API rule content should appear in the context. -
Behavioral difference — compare the code Claude generated in Module 1 (no memory) versus Module 2 (with memory). The Module 2 output should more consistently follow your stated conventions.
|
The transcript is your ground truth for understanding what the model actually received. If Claude Code is not following a convention, check the transcript to verify the instruction was actually loaded into context. |
|
What you should have:
Verify: Start Claude Code in |
References
-
claude-code-transcripts — session introspection CLI
-
Local architecture reference:
assets/site/concepts/memory-context.htmlandassets/site/configuration/claudemd.htmlin this course repository