Module 2: Agent Memory and Scopes
2. Memory Scopes in Depth
2. Memory Scopes in Depth
Description
In the previous capsule you saw the problem — amnesiac subagents that repeat analysis, forget conventions, and start from scratch each session. You also saw the solution at the conceptual level: three memory scopes (user, project, local) and a MEMORY.md file that persists context. Now it's time to implement it.
Configuring memory in a subagent is adding a field to the YAML frontmatter. But choosing the right scope, writing instructions that guide the subagent on what to remember, and verifying that persistence actually works — that takes deliberate practice. A subagent with poorly configured memory is worse than one without memory: it accumulates noise, reaches the 200-line limit with irrelevant information, and its decisions get contaminated with stale context.
In this capsule you're going to configure memory in the three scopes, write system prompts that instruct the subagent to curate its own memory, verify persistence across sessions, and apply everything to the reviewer and implementer of capsule 05's project.
The memory Field in the Frontmatter
Configuration syntax
Enabling memory is adding a line to the subagent file's YAML frontmatter:
---
name: code-reviewer
description: Reviews code for quality
memory: project
---
The memory field accepts exactly three values:
| Value | MEMORY.md location | Shareable |
|---|---|---|
user | ~/.claude/agent-memory/{name}/MEMORY.md | No — personal, all projects |
project | .claude/agent-memory/{name}/MEMORY.md | Yes — via git, the whole team |
local | .claude/agent-memory-local/{name}/MEMORY.md | No — private, gitignored |
If you don't include the memory field, the subagent has no persistence. Each session starts with no previous context.
What happens when you enable memory
When you add memory: project to a subagent named code-reviewer, Claude Code:
- Creates the directory
.claude/agent-memory/code-reviewer/if it doesn't exist - Creates an empty
MEMORY.mdin that directory if it doesn't exist - Injects the first 200 lines of
MEMORY.mdinto the subagent's system prompt at the start of each session - Automatically enables the Read, Write, and Edit tools so the subagent can manage its memory file
- Adds instructions to the system prompt telling the subagent how to read and write in its memory directory
Those tools are enabled in addition to the ones you define in tools. If your reviewer has tools: Read, Glob, Grep, with memory: project it will have access to Read, Glob, Grep plus Write and Edit — but only for files inside its memory directory.
Without memory:
available tools = [Read, Glob, Grep]
With memory: project:
available tools = [Read, Glob, Grep]
+ Write/Edit enabled ONLY for .claude/agent-memory/code-reviewer/*
user Scope: Universal Personal Knowledge
When to use it
The user scope stores memory in your home directory (~/.claude/agent-memory/{name}/). It isn't associated with any project — it's yours, available in any repository where you use that subagent.
---
name: style-enforcer
description: Enforces personal coding style preferences across all projects
memory: user
---
What to store in user scope
- 📝 Personal style preferences (indentation, naming, comments)
- 📝 Patterns you use frequently in any project
- 📝 Personal documentation conventions
Example: personal style enforcer
Create ~/.claude/agents/style-enforcer.md:
---
name: style-enforcer
description: Enforces personal coding style preferences across all projects
tools: Read, Glob, Grep
disallowedTools: Write, Edit
model: haiku
maxTurns: 10
memory: user
---
## Role
You enforce coding style preferences. You read code and report
deviations from the style preferences stored in your memory.
You NEVER modify code files.
## Memory Management
On first run (empty MEMORY.md):
- Ask what style preferences the user wants to enforce
- Save preferences to MEMORY.md in structured format
On subsequent runs:
- Read MEMORY.md for established preferences
- Apply preferences to code review
- Add new preferences if the user mentions them
## Output Format
### Style Report
**Preferences applied:** [count from memory]
#### Deviations Found
- **[file:line]** — Expected: [preference] | Found: [deviation]
#### Summary: [n] deviations in [n] files
The first time you run this subagent, MEMORY.md is empty and it will ask for your preferences. The second time it already knows them and applies them directly.
project Scope: Team Knowledge
When to use it
The project scope stores memory in .claude/agent-memory/{name}/ — inside the project, versionable with git. It's the most powerful scope because it lets the whole team share the subagent's accumulated knowledge.
What to store in project scope
- 🏗️ Project architectural decisions
- 🏗️ Team code conventions
- 🏗️ Common codebase patterns
- 🏗️ Recurring bugs and their solutions
Example: reviewer with project memory
Update your .claude/agents/reviewer.md from Module 1:
---
name: reviewer
description: Reviews recent code changes for quality, security, and best practices
tools: Read, Glob, Grep, Bash
disallowedTools: Write, Edit
model: haiku
maxTurns: 15
permissionMode: plan
memory: project
---
## Role
You are a code reviewer. You analyze recent git changes and produce
a structured report. You NEVER modify any file except your MEMORY.md.
## Memory Management
Update your agent memory as you discover codepaths, patterns, library
locations, and key architectural decisions. This builds up institutional
knowledge across conversations. Write concise notes about what you found
and where.
When updating MEMORY.md:
- Add patterns you observe repeatedly
- Record architectural decisions mentioned in comments or PR descriptions
- Note recurring issues so you can flag them proactively next time
- Keep entries concise: one line per pattern/decision
- If MEMORY.md exceeds 150 lines, consolidate redundant entries
## Review Process
1. Read MEMORY.md for context on known patterns and previous findings
2. Run `git diff HEAD~3 --name-only` to identify changed files
3. Read each changed file completely
4. Apply review criteria WITH context from memory
5. Update MEMORY.md with new patterns discovered
6. Produce the report
## Output Format
### Code Review Report
**Date:** [current date]
**Files reviewed:** [list]
**Memory context:** [relevant patterns from MEMORY.md applied]
#### CRITICAL (must fix)
- **[file:line]** — Description
#### WARNING (should fix)
- **[file:line]** — Description
#### Summary
- Critical: [n] | Warnings: [n] | Suggestions: [n]
- Verdict: PASS | PASS_WITH_WARNINGS | NEEDS_REVISION
#### Memory Updates
- [list what was added to MEMORY.md this session]
How the reviewer's memory evolves
Session 1 — empty MEMORY.md:
# Reviewer Memory
## Architecture
- FastAPI project with SQLAlchemy ORM
- Routes in src/routes/, models in src/models/
## Conventions
- Snake_case for all Python identifiers
- Type hints required on all public functions
Session 3 — accumulation:
# Reviewer Memory
## Architecture
- FastAPI + SQLAlchemy + Alembic + PostgreSQL
- Background tasks in src/tasks/ using Celery
- Redis caching layer in src/cache/
## Conventions
- Snake_case for all Python identifiers
- All endpoints return standardized {data, error, meta} response
- Exceptions use custom AppError hierarchy (src/exceptions.py)
## Resolved Issues
- routes/products.py:45 SQL injection — FIXED in commit abc123
The reviewer now knows the architecture, the conventions, and the previous issues. When it reviews new code, it applies this context without you repeating anything.
Sharing with the team
git add .claude/agent-memory/reviewer/MEMORY.md
git commit -m "chore: update reviewer memory with project patterns"
git push
When a colleague pulls, their reviewer subagent inherits all that knowledge.
local Scope: Private Project Knowledge
When to use it
The local scope stores memory in .claude/agent-memory-local/{name}/ — inside the project, but gitignored automatically. For information that shouldn't be shared.
What to store in local scope
- 🔒 Development-environment tokens and credentials
- 🔒 Test results from your specific machine
- 🔒 Personal notes about the project
Example: tester with local memory
---
name: tester
description: Runs test suites and reports results
tools: Bash, Read, Glob
disallowedTools: Write, Edit
model: haiku
maxTurns: 10
memory: local
---
## Role
You are a test runner and reporter. You NEVER modify source code.
## Memory Management
Track test results across sessions:
- Record pass/fail counts per module after each run
- Note flaky tests (tests that sometimes pass, sometimes fail)
- Track coverage percentages over time
Keep MEMORY.md under 100 lines — summarize old results, keep recent ones.
## Output Format
### Test Report
**Comparison with last run:** [improved/degraded/stable]
#### Results
- ✅ Passed: [n] (previous: [n from memory])
- ❌ Failed: [n] (previous: [n from memory])
#### Coverage
| Module | Current | Previous | Trend |
|--------|---------|----------|-------|
| [module] | [%] | [% from memory] | ↑/↓/= |
#### Verdict: ALL_PASS | FAILURES | ERROR
The tester uses local because the results depend on your machine — versions, local database, environment variables. It makes no sense to commit that.
Comparison: Which Scope for What?
Decision table
| Information | Scope | Justification |
|---|---|---|
| My personal style preferences | user | Applies to all my projects |
| Team code conventions | project | The team needs to see them |
| Project architecture | project | Shared decision |
| My development tokens | local | Secrets, don't share |
| Test results from my machine | local | Environment-dependent |
| Common patterns I use in Python | user | They're mine, not the project's |
| Recurring project bugs | project | The team should know them |
| Notes about a pending refactor | local | Personal ideas |
| Decision: "we use PostgreSQL" | project | Team decision |
The three-question rule
When you don't know which scope to use:
1. Is this information for ALL my projects? → user
2. Does the team need this information? → project
3. Is it specific to MY environment? → local
On-disk structure
my-project/
├── .claude/
│ ├── agents/
│ │ ├── reviewer.md # memory: project
│ │ ├── implementer.md # memory: project
│ │ └── tester.md # memory: local
│ └── agent-memory/
│ ├── reviewer/
│ │ └── MEMORY.md # ← shared via git
│ └── implementer/
│ └── MEMORY.md # ← shared via git
├── .claude/agent-memory-local/
│ └── tester/
│ └── MEMORY.md # ← gitignored
└── .gitignore
~/.claude/
└── agent-memory/
└── style-enforcer/
└── MEMORY.md # ← personal, all projects
Memory Instructions in the System Prompt
Why what you write matters
Enabling memory: project creates the infrastructure. But the quality of the memory depends on what the subagent decides to store. Without clear instructions, a subagent may store everything (memory saturated on the first session), store nothing (memory enabled but empty), or store irrelevance (noise that confuses).
Pattern: structured instructions
## Memory Management
Update your agent memory as you discover codepaths, patterns, library
locations, and key architectural decisions. This builds up institutional
knowledge across conversations. Write concise notes about what you found
and where.
### What to Remember
- Architecture patterns (directory structure, design patterns in use)
- Team conventions (naming, formatting, error handling approach)
- Key decisions (why X library over Y, why this architecture)
- Recurring issues (bugs that keep appearing, common mistakes)
### What NOT to Remember
- Specific code content (it changes — reference files instead)
- One-time issues already fixed
- Personal opinions or subjective assessments
### Format Rules
- One line per entry when possible
- Group by category (Architecture, Conventions, Issues, Patterns)
- If MEMORY.md exceeds 150 lines, consolidate: merge similar entries,
remove outdated ones, summarize old sections
Pattern: active curation
## Memory Curation
Before writing to MEMORY.md, read it first. Then:
1. Check if the new information already exists — don't duplicate
2. Check if any existing entry is now outdated — update or remove it
3. If adding pushes past 150 lines, consolidate the oldest section
4. Always keep the most recent and most actionable items
Think of MEMORY.md as a living document, not a log.
Verifying Persistence
The smoke test
Step 1: Run the subagent and give it context it should remember.
Use the reviewer to analyze src/routes/products.py
Step 2: Verify that it wrote to MEMORY.md.
cat .claude/agent-memory/reviewer/MEMORY.md
Step 3: Close Claude Code completely.
Step 4: Reopen Claude Code and run the reviewer again.
Use the reviewer to analyze src/routes/users.py
Step 5: Verify that the report references context from the previous session. The reviewer should mention learned patterns or apply conventions it discovered in session 1.
Step 6: Inspect MEMORY.md again.
cat .claude/agent-memory/reviewer/MEMORY.md
It should have entries from both sessions, organized without duplicates.
Verification for project scope
git status
# You should see: new file: .claude/agent-memory/reviewer/MEMORY.md
Verification for local scope
git status
# It should NOT show files in .claude/agent-memory-local/
ls .claude/agent-memory-local/tester/MEMORY.md
# The file exists but git ignores it
Example: Implementer with Project Memory
The implementer needs to remember code conventions to apply them consistently:
---
name: implementer
description: Implements code changes in src/ following project conventions
tools: Read, Glob, Grep, Write, Edit, Bash
model: sonnet
maxTurns: 30
memory: project
---
## Role
You are a senior developer implementing code changes in src/.
Follow existing project conventions — never introduce new patterns.
## Memory Management
Update your agent memory with:
- Code conventions you observe (naming, structure, error handling)
- Architectural decisions referenced in code comments or CLAUDE.md
- Library-specific patterns (e.g., "sessions use context manager")
- File/module purposes you discover
Keep MEMORY.md organized by category. Consolidate if over 150 lines.
When implementing, ALWAYS check MEMORY.md first for conventions.
## Constraints
- ONLY modify files inside src/
- NEVER modify test files, config files, or CLAUDE.md
- Follow conventions from MEMORY.md — they represent team agreements
## Output Format
### Implementation Report
**Files modified:** [list]
**Conventions applied from memory:** [list]
**Changes made:**
1. **[file]** — Description of change
- Convention: [which memory entry guided this decision]
**Memory updates:** [what was added to MEMORY.md]
Connection to the Project
Toward capsule 05: Memory Hierarchy for 3 Subagents
In capsule 05 you'll implement a complete memory hierarchy:
reviewer → memory: project ← shares codebase patterns with the team
implementer → memory: project ← shares code conventions with the team
tester → memory: local ← test results are private
The configuration you did here is the building block. What capsule 05 adds is the coordination: what happens when the reviewer and the implementer have independent memories? How do you avoid inconsistencies? Capsule 03 (next) addresses exactly that.
Troubleshooting
"MEMORY.md is empty after running the subagent"
Cause: The system prompt doesn't include explicit enough memory instructions. The subagent has the ability to write but doesn't know what to store.
Fix: Add a ## Memory Management section with imperative instructions: "Update your agent memory as you discover..." not "You might want to remember..."
"MEMORY.md grew too fast — it already has 200+ lines"
Cause: The subagent stores everything without curating.
Fix: Add curation instructions:
If MEMORY.md exceeds 150 lines, before adding new entries:
1. Merge similar entries into summaries
2. Remove entries about files that no longer exist
3. Archive resolved issues
"The subagent doesn't read its MEMORY.md at startup"
Cause: The first 200 lines are injected automatically. If MEMORY.md has trivial information at the beginning, the injected context doesn't help.
Fix: Structure MEMORY.md with the most important sections first. Architecture, conventions, and frequent patterns go in the first 200 lines.
"The project scope doesn't appear in git status"
Cause: The .claude/agent-memory/ directory was added to .gitignore by mistake.
Fix:
cat .gitignore | grep agent-memory
# Only .claude/agent-memory-local/ should be in gitignore
# .claude/agent-memory/ (without -local) should NOT be in gitignore
"Two subagents with the same name share memory"
Cause: The memory directory uses the name from the frontmatter. Equal names = same directory.
Fix: Use unique names: reviewer-security and reviewer-performance, not two reviewer.
Exercises
Exercise 1: Enable basic memory (Easy)
Take the todo-finder subagent from Module 1 and add user scope to it. It should remember how many TODOs it found in each session to report trends.
See solution
---
name: todo-finder
description: Finds all TODO and FIXME comments across the codebase
memory: user
---
Search for comments containing TODO, FIXME, HACK, or XXX.
## Memory Management
After each scan, record in MEMORY.md:
- Date of scan and total count by type (TODO, FIXME, HACK, XXX)
- Compare with previous scan and note trend (increasing/decreasing)
Keep only the last 10 scan results in memory.
### TODO/FIXME Report
**Trend:** [count] total ([+/-n] vs last scan from memory)
#### FIXME (urgent)
- **[file:line]** — Comment text
#### TODO (planned)
- **[file:line]** — Comment text
**Total:** [count] items found
Verification: cat ~/.claude/agent-memory/todo-finder/MEMORY.md after running.
Exercise 2: Choose the right scope (Easy)
For each scenario, indicate the correct scope (user, project, or local):
- A subagent that remembers the staging API keys
- A subagent that remembers the architecture of a project with 5 devs
- A subagent that remembers your error-handling patterns across all your projects
- A subagent that remembers which tests were flaky on your laptop
- A subagent that remembers the project dependencies and why they were chosen
See solution
local— API keys are secrets that aren't committedproject— The architecture is shared team knowledgeuser— Personal preferences that apply to all projectslocal— Flaky tests depend on your machine/environmentproject— Dependencies and their justifications are team decisions
Exercise 3: Write memory instructions (Medium)
Write the ## Memory Management section for a dependency-auditor subagent that reviews the dependencies of a Python project. It should remember: current versions, vulnerabilities, and decisions about why each dependency was chosen.
See solution
## Memory Management
Update your agent memory after each audit:
### What to Remember
- Current dependency versions and when they were last audited
- Known vulnerabilities: severity, status (open/fixed/accepted-risk)
- Decisions: why each key dependency was chosen over alternatives
- Version constraints: why certain packages are pinned
- Incompatibilities discovered between packages
### What NOT to Remember
- Transitive dependencies (too many, too volatile)
- Exact vulnerability CVE details (link to advisory instead)
### Format
| Package | Version | Why Chosen | Last Audited |
|---------|---------|------------|--------------|
| fastapi | 0.104.0 | Team standard | 2026-03-10 |
### Curation Rules
- Update versions after each audit, don't append duplicates
- Remove vulnerability entries once fixed and verified
- If over 100 lines, archive old audit dates — keep only latest
Exercise 4: Verify persistence end-to-end (Medium)
Configure the reviewer with memory: project. Run these steps and document what you see:
- Run the reviewer on a project file
- Read
MEMORY.mdand verify it has content - Close Claude Code
- Reopen and run the reviewer on a different file
- Verify that the report references context from the previous session
- Confirm that
MEMORY.mdhas entries from both sessions without duplicates
See solution
# Step 1: Run reviewer
# > "Use the reviewer to analyze src/routes/products.py"
# Step 2: Verify
cat .claude/agent-memory/reviewer/MEMORY.md
# Expected: entries about products.py patterns
# Step 3: Close
# exit
# Step 4-5: Reopen and run on another file
# > "Use the reviewer to analyze src/routes/users.py"
# Expected: the report mentions context from session 1
# Step 6: Verify MEMORY.md
cat .claude/agent-memory/reviewer/MEMORY.md
# Expected: entries from BOTH sessions, organized without duplicates
If MEMORY.md duplicated entries, improve the curation instructions with "Check if the new information already exists — don't duplicate."
Exercise 5: Design the memory hierarchy (Hard)
You have a project with 4 subagents: reviewer, implementer, tester, doc-generator. Design which scope each one uses, which categories of information it stores, and justify the choice. Present it as a table.
See solution
| Subagent | Scope | Categories | Justification |
|---|---|---|---|
reviewer | project | Architecture, conventions, recurring bugs | The team needs consistency in reviews |
implementer | project | Code conventions, library patterns | The whole team should follow the same conventions |
tester | local | Results, flaky tests, coverage trends | The results depend on the local environment |
doc-generator | project | Documentation style, glossary | Documentation should be consistent across the team |
Reviewer and implementer share the project scope but have separate memories (different name = different directories). The tester is in local because your laptop's coverage isn't relevant for CI.
Exercise 6: Debug corrupted memory (Hard)
Your MEMORY.md has 250 lines: an 80-line session log, random notes, and the critical sections (Architecture, Conventions) are after line 200 (not injected). Restructure it so it fits in 150 lines with the priorities at the top.
See solution
Before (250 lines, poorly structured):
## Session Log
- 2026-01-15: Reviewed products.py...
... (80 entries)
## Random Notes
- The team uses PostgreSQL
- There might be a performance issue
## Architecture (line ~180)
- FastAPI + SQLAlchemy + Alembic
## Conventions (line ~220)
- Snake_case everywhere
After (25 lines, well structured):
# Reviewer Memory
## Architecture
- Stack: FastAPI + SQLAlchemy + Alembic + PostgreSQL
- Routes in src/routes/, models in src/models/
- Repository pattern for DB access
## Conventions
- Snake_case for all Python identifiers
- Type hints required on all public functions
## Active Issues
- routes/products.py: N+1 query (found 2026-01-19)
## Resolved Issues
- routes/products.py:45 SQL injection — fixed (2026-01-17)
## Review Summary
- 5 reviews completed (Jan 15-19, 2026)
Changes: Architecture and Conventions at the top (they get injected), session log replaced by a summary, random notes integrated into categories, from ~250 to ~25 lines.
Summary
- The
memoryfield in the frontmatter accepts three values:user,project,local user(~/.claude/agent-memory/{name}/) is personal and applies to all projectsproject(.claude/agent-memory/{name}/) is shared via git — team knowledgelocal(.claude/agent-memory-local/{name}/) is private and gitignored — secrets and local data- When you enable memory, MEMORY.md is injected (first 200 lines) into the system prompt automatically
- The subagent gets Read, Write, Edit enabled for its memory directory
- The quality of the memory depends on the instructions in the system prompt — be explicit about what to remember and when to curate
- Verifying persistence requires run → close → reopen → confirm retention
- The three-question rule: all my projects? →
user. Does the team need it? →project. Only my environment? →local - The first 200 lines are critical — put the most important thing at the top of MEMORY.md
- The 3 subagents with memory are the building block of capsule 05's project
Additional Resources
- Subagents — Persistent Memory (Anthropic Docs) — Official documentation of the
memoryfield and its scopes - Create Custom Subagents — Complete frontmatter reference including memory
- Claude Code Best Practices — Context-organization best practices applicable to MEMORY.md
- CLAUDE.md Documentation — How CLAUDE.md complements agent memory
- Claude Code Overview — General context of persistence in Claude Code
- Prompt Engineering: System Prompts — Principles transferable to memory instructions
- Claude Code Tips and Tricks — Tips on context organization
- Git Best Practices — Versioning shared configuration files
Next capsule: In capsule 03 you'll tackle the shared-memory problem. You have a reviewer and an implementer, both with memory: project, but with independent memories. How do you keep them from making contradictory decisions? You'll see strategies to share context between subagents without overwriting each other.