architecture
Persistent Memory: Claude That Remembers
Memory tiers in Claude Code. CLAUDE.md, /memory directories, auto-memory hooks. How to make Claude remember without overflowing context.
The Problem
Cold Start Every Session
Every Claude session starts empty. No memory of what worked last week. No client context. No learned patterns. Session 100 is no smarter than session 1.
The cost of forgetting
- 10-15 minutes re-explaining context at the start of every session
- Repeated mistakes that were already solved and documented
- No compound improvement: each session resets to zero
Without memory
With persistent memory
Architecture
4 Memory Tiers
Persistent memory is not a single file. It is a layered system: each tier has a different speed, scope, and lifespan.
Vector Memory
Semantic similarity search across all stored knowledge. Finds concepts related to a topic, not just exact keyword matches.
Example: "What have we learned about Slack integrations?" returns every relevant session even if the word Slack never appeared.
Episodic Memory
Event sequences with temporal context. Remembers when things happened and in what order.
Example: "What happened during client onboarding week 1?" returns the full sequence of events in order.
Semantic Memory
Knowledge graphs of concepts and relationships. Builds a network: Client → Engineer → Tech Stack → Known Blockers.
Example: "Which engineer is best at n8n?" Graph traversal connects profiles to outcomes to technology tags.
Working Memory
Active context via attention mechanisms. Fast access to what is most relevant right now, like RAM vs. storage.
Example: During a session, working memory holds: client name, current project, recent blockers, last communication.
Foundation
CLAUDE.md Best Practices
CLAUDE.md is the simplest form of persistent memory. It is injected at the top of every context window, the one thing Claude always reads before anything else.
Keep it under 200 lines
Claude reads CLAUDE.md in full on every session. Long files waste context tokens and bury important instructions. Prune aggressively. If a rule is not enforced in 90% of sessions, remove it.
Use sections with clear headers
Organise by: Stack, Commands, Conventions, Architecture, DO NOT. Clear headers help Claude retrieve the right section quickly when it performs in-context search.
Put blocking rules in the DO NOT section
List hard constraints explicitly. "DO NOT use npm or yarn" is clearer than burying it in the stack section. Negatives get top-of-mind attention.
Reference, don't repeat
Use @filename.md to pull in project-specific files. Keep CLAUDE.md as the index, not the encyclopedia. Put the details in the referenced files.
Review and prune every 30 sessions
Rules decay. A constraint that was critical in month 1 may be solved by tooling in month 3. Dead rules add noise and reduce the signal-to-noise ratio for the model.
# CLAUDE.md - minimal structure ## Stack - Next.js 15, TypeScript strict, Tailwind v4 - pnpm only ## Commands - pnpm dev / pnpm build / pnpm test ## Conventions - Server Components by default - cn() from lib/utils.ts ## DO NOT - Use npm or yarn - Add `any` types - Access DB from client components
File System
/memory/ Directory Structure
A /memory/ directory in your project root extends CLAUDE.md into a multi-file memory system. Each file is scoped, versioned, and retrievable.
project-root/
├── CLAUDE.md # Global instructions (always loaded)
├── .claude/
│ └── settings.json # Hook definitions
└── memory/
├── README.md # Index - what lives where
├── stack.md # Tech decisions + rationale
├── patterns.md # Learned patterns from sessions
├── blockers-resolved.md # Solved problems, don't repeat
├── clients/
│ ├── client-a.md # Per-client context
│ └── client-b.md
└── sessions/
└── YYYY-MM-DD.md # Session logs (auto-written by hook)patterns.mdAccumulates learned patterns from sessions
Format: Short bullet: problem → solution → why it works
Example: n8n webhook nodes require explicit 30s timeout in prod; default 10s drops on Vercel edge.
blockers-resolved.mdDocuments every solved blocker so it never recurs
Format: Date · Symptom · Root cause · Fix · Prevention
Example: 2026-04 · Prisma type errors on deploy · prisma generate not in build script · add to pnpm build.
sessions/YYYY-MM-DD.mdTimestamped session log written by auto-memory hook
Format: Goal → Actions → Decisions → Learnings
Example: Auto-written on session end by the PostToolUse hook.
Automation
Auto-Memory Hooks
Manual memory is fragile. Hooks make memory automatic: learnings are captured without any deliberate action from you or Claude.
Stop hook: session logger
Fires when a Claude session ends. Writes a timestamped summary to memory/sessions/. Captures what was built, decisions made, and patterns observed.
// .claude/settings.json
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [{
"type": "command",
"command": "node scripts/memory-logger.js"
}]
}
]
}
}PostToolUse hook: pattern extractor
Fires after every tool call. When Claude writes a file or runs a command, this hook checks for patterns worth persisting: new conventions, resolved errors, repeated solutions.
// .claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Bash",
"hooks": [{
"type": "command",
"command": "node scripts/pattern-extractor.js"
}]
}
]
}
}memory-logger.js: minimal implementation
// scripts/memory-logger.js
const fs = require("fs")
const path = require("path")
const date = new Date().toISOString().split("T")[0]
const dir = path.join(process.cwd(), "memory", "sessions")
fs.mkdirSync(dir, { recursive: true })
const entry = [
`# Session - ${date}`,
`## Timestamp`,
new Date().toISOString(),
`## Learnings`,
process.env.CLAUDE_LEARNINGS ?? "(none captured)",
"",
].join("\n")
fs.appendFileSync(path.join(dir, `${date}.md`), entry)Retrieval
Retrieval at Session Start
Writing memory is only half the system. Claude must also read the right memory at the right time, without loading everything into context at once.
Pre-session briefing via hook
A PreSession hook (or a prompt prefix) runs memory/README.md through a small script that identifies the most recent session log and any open patterns. The output is prepended to the context as a briefing block.
Targeted retrieval with /read
For specific topics, instruct Claude to read the relevant memory file directly. "Read memory/clients/client-a.md before we continue" loads exactly what is needed without touching everything else.
Semantic search via SAFLA or similar
For large memory stores (100+ session logs), a vector memory layer lets Claude query by concept rather than filename. Ask "what do we know about n8n timeouts" and get ranked results back in seconds.
Working memory injection
At session start, keep the active working memory slim: current project state, last 3 decisions, and top 5 open patterns. Everything else stays on disk until needed.
Maintenance
Pruning Strategies
Memory that is never pruned becomes noise. Stale patterns and obsolete rules waste context and mislead the model. Prune on a schedule.
| Cadence | What to prune | Method |
|---|---|---|
| Every session | Working memory: clear active context on stop | Stop hook resets working-memory.md to empty template |
| Weekly | Session logs older than 7 days: archive or compress | Cron script moves logs to memory/archive/YYYY-MM/ |
| Monthly | patterns.md: remove patterns solved by tooling or config | Manual review + git diff to confirm removal |
| Quarterly | CLAUDE.md rules: remove dead constraints | Review each rule: is it enforced? Does tooling now handle it? |
| On demand | Contradicting patterns: two entries with opposite advice | Search for keyword overlap, resolve in patterns.md, delete stale entry |
The pruning rule of thumb
If a memory entry has not influenced a session decision in 30 days, archive it. If it has not been referenced in 90 days, delete it. Memory quality beats memory quantity: a 50-line CLAUDE.md that is always relevant outperforms a 500-line file that is 80% stale.
Impact
Before vs. After
| Scenario | Without memory | With persistent memory |
|---|---|---|
| Session start | Re-explain project from scratch (~15 min) | Auto-briefing from memory/ loads in seconds |
| Repeated bug | Debug again, same root cause as last month | blockers-resolved.md surfaces the fix immediately |
| Client context | Dig through notes and Slack history manually | memory/clients/ has full context, preferences, history |
| Session 50 vs. session 1 | Identical capability, no compounding | 50 sessions of learned patterns, far faster execution |
Want this running in your stack?
AY Automate builds agent systems, RAG pipelines, and Claude Code setups for production teams.