Teaching Claude Code to Remember: Building Session Memory That Actually Works
Claude Code has become a legitimate part of my workflow. It’s changed how I approach certain tasks—exploratory work, documentation, even debugging. But it has a maddening limitation: it forgets. Context compaction kicks in, the conversation gets summarized, and suddenly we’re back to square one. Close the terminal? Complete amnesia.
This isn’t just an inconvenience. It breaks the entire collaboration model. Real work happens across sessions. You dig into a problem, make progress, hit a wall, sleep on it, come back fresh. That’s how humans work. If your AI pair programmer can’t maintain continuity, you spend half your time re-explaining context instead of solving problems.
The Core Problem
Claude Code has a context window. When you fill it up, the system compacts the conversation—summarizing, discarding specifics. You lose:
- Which files you were actively modifying
- Decisions made during the session (and why)
- The exact state of half-finished work
- Your actual intent and goals
Starting a new session is worse. Claude has no idea what you were doing yesterday, even in the same project. Every session is a fresh start, which sounds nice until you realize it means “fresh start” as in “total ignorance of everything that came before.”
What I wanted: automatic capture of session state before it’s lost, automatic restoration when starting new sessions. A memory system that works without me thinking about it.
How It Works
Three components, working together:
PreCompact Hook — Fires automatically right before context compaction. Captures the full session state before Claude’s memory gets compressed into a summary.
SessionStart Hook — Fires when you launch Claude Code. Loads the most recent snapshot so Claude immediately knows what you were working on.
/save-state Command — Manual trigger for when you want to checkpoint before running /clear. Because sometimes you know you’re about to reset context and want to preserve state intentionally.
All snapshots go into .claude/snapshots/ within your project directory. This keeps contexts separate—your React work doesn’t bleed into your Python API sessions.
The Interesting Part: Mining the Transcript
Here’s what I didn’t expect: Claude Code keeps surprisingly detailed transcripts. The PreCompact hook receives a path to a JSONL file containing the full conversation history. Not the compacted version—the actual conversation.
Each line is a JSON object: user messages, assistant responses, file snapshots, summaries. The transcript format looks like this:
{"type": "user", "message": {"content": "Fix the login bug"}, "timestamp": "..."}
{"type": "assistant", "message": {"content": [{"type": "text", "text": "I'll help..."}]}}
{"type": "file-history-snapshot", "snapshot": {"trackedFileBackups": {"/src/auth.js": "..."}}}
{"type": "summary", "summary": "Fixed authentication bug in login flow"}
Mining this properly gives you everything: what files were touched, what the user actually asked for, what work got summarized away. The key insight is that the hook system gives you access to the raw data before compaction happens.
Implementation Details Worth Noting
A few things bit me during implementation:
Python import naming — You can’t import modules with hyphens in the filename. Seems obvious in retrospect, but precompact-snapshot.py had to become precompact_snapshot.py.
Content type handling — User message content is sometimes a string, sometimes a list. Assistant messages are almost always lists with typed objects. You need to handle both:
content = message.get("content", "")
if isinstance(content, list):
content = " ".join(
item.get("text", "") if isinstance(item, dict) else str(item)
for item in content
)
Path extraction from free-form text — Extracting file paths from conversation text requires multiple regex patterns and careful filtering to avoid matching URLs and domain names. It’s messier than it sounds.
System message filtering — The transcript includes system-generated content like command confirmations that shouldn’t be saved as “user requests.” Filter by prefix and strip XML-like tags.
The Configuration
In ~/.claude/settings.json:
{
"hooks": {
"PreCompact": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 ~/.claude/hooks/precompact_snapshot.py",
"timeout": 30
}
]
}
],
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 ~/.claude/hooks/sessionstart-load-snapshot.py",
"timeout": 10
}
]
}
]
}
}
The file structure ends up being:
~/.claude/
├── hooks/
│ ├── precompact_snapshot.py
│ ├── sessionstart-load-snapshot.py
│ └── manual-snapshot.py
├── commands/
│ └── save-state.md
└── settings.json
<your-project>/.claude/
└── snapshots/
├── 2026-01-26-00-08-session-snapshot.md
└── 2026-01-26-00-47-manual-snapshot.md
What This Reveals About AI Tooling
A thought I’ve been circling around for months: the gap between “AI can help with code” and “AI can be a genuine collaborator” is largely about memory and context.
We’re used to tools that maintain state. Your IDE remembers your project structure. Git remembers your history. Your build system knows what changed. But AI assistants start fresh every time, which puts the entire burden of context maintenance on the human.
This session memory system is a small step toward something bigger. If AI is going to write code faster than we can verify it—which is increasingly true—then the tooling around AI needs to grow up. We need trust frameworks, verification mechanisms, and yes, persistent memory.
The hook system in Claude Code is more powerful than it first appears. PreCompact gives you access to the full transcript, not just the summary. That’s a design choice that enables this kind of extension. More AI tools should think this way—expose the seams, let practitioners build what they need.
Limitations and Future Work
Things this doesn’t solve yet:
- Can’t programmatically trigger
/clearfrom a slash command - Very long sessions create large transcript files
- Quality depends on Claude’s automatic summarization
- Only tracks one active transcript per project
Things I want to add:
- Diff-based snapshots (only store changes)
- Searchable history across sessions
- Auto-cleanup of old snapshots
- Git integration to link snapshots to commits
The Takeaway
Session continuity transforms Claude Code from a stateless assistant into something that actually remembers our work together. The combination of automatic capture (PreCompact), automatic restoration (SessionStart), and manual checkpointing (/save-state) creates a robust system that preserves context across the natural boundaries of AI conversation limits.
A small step …