Every Claude Code session ends the same way: context window fills up, session compresses, and your AI forgets what it was doing.
I fixed this with one file.
The Problem
Claude Code has no persistent memory between sessions. When you start a new terminal, it reads your CLAUDE.md and starts fresh. Any decisions made, approaches tried, or context built up — gone.
For a single quick task, this is fine. For multi-day projects with complex state, it's a disaster.
The Fix: SESSION-HANDOFF.md
Every project gets a docs/SESSION-HANDOFF.md with this structure:
# Session Handoff
## Last Updated
2026-03-31 (Session 30)
## Current State
[What's working, what's deployed, what's in progress]
## What Was Done This Session
[Bullet points of completed work]
## What Failed
[Approaches that didn't work and why — so the next session doesn't repeat them]
## What's Next
[Prioritized list of next steps]
## Key Decisions
[Architectural choices made and the reasoning]
The Rule
The rule is simple and non-negotiable: CLAUDE.md mandates updating SESSION-HANDOFF.md before every session end or context compaction.
In my CLAUDE.md:
## Session Protocol (MANDATORY)
1. Start: MUST read docs/SESSION-HANDOFF.md
2. During: note decisions in SESSION-HANDOFF.md
3. Before end/compaction: MUST update SESSION-HANDOFF.md
Claude Code follows this because it's in CLAUDE.md — loaded on every session start.
Why This Works Better Than Memory
Claude Code has a built-in memory system (~/.claude/ memory files). It's useful for user preferences and project-level facts. But it's bad for session state because:
- Memory is unstructured. SESSION-HANDOFF.md has a fixed format — Claude knows exactly where to look.
- Memory is append-only. Session state changes completely each session. You need a full rewrite, not appended notes.
- Memory survives too long. A "what I was doing" note from 5 sessions ago is noise. SESSION-HANDOFF.md is always current.
Making It Bulletproof
Hook: Reminder Before End
Add a Stop hook in .claude/settings.json that reminds Claude to update the handoff:
{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "echo '{\"systemMessage\": \"REMINDER: Update SESSION-HANDOFF.md before ending!\"}'"
}]
}]
}
}
Hook: Auto-Read on Start
Add a SessionStart hook that reads the handoff file:
{
"hooks": {
"SessionStart": [{
"hooks": [{
"type": "command",
"command": "cat docs/SESSION-HANDOFF.md 2>/dev/null || echo 'No handoff file found'"
}]
}]
}
}
Now Claude reads the last session's state automatically on every start.
Real Example
Here's a compressed version of my trading bot project's handoff:
## Last Updated: Session 47
## Current State
- Bot running on VPS, 145 trades executed
- Dashboard: 18 pages, all functional
- OBV strategy v12 in production
## What Failed This Session
- Volume filter caused false negatives — rolled back in Deploy#47
- html2canvas timeout on complex dashboard pages
## What's Next
1. [P0] Fix trailing stop calibration for volatile coins
2. [P1] Add correlation matrix page to dashboard
3. [P2] Backtest new momentum strategy
Next session reads this and immediately knows: don't re-add the volume filter, focus on trailing stops.
Scaling to Multiple Agents
When you run multiple Claude Code instances (I run 6), each has its own SESSION-HANDOFF.md. A Boss agent can read all of them:
for f in ~/projects/*/docs/SESSION-HANDOFF.md; do
echo "=== $(dirname $(dirname $f)) ==="
head -20 "$f"
done
This gives the coordinator a snapshot of all projects in seconds.
The Pattern in 30 Seconds
- Add
docs/SESSION-HANDOFF.mdto your project - Add "MUST read/update SESSION-HANDOFF.md" to your
CLAUDE.md - Add SessionStart hook to auto-read it
- Add Stop hook to remind about updates
Total setup: 5 minutes. Saves hours of re-explaining context.
Running this pattern across 16 projects. Context persists. Sessions don't.
Top comments (0)