Your Claude Code session forgets everything when you close it. This fixes that.
It distills every session into a readable HANDOFF.md — decisions, dead ends, and next steps — and re-injects it automatically when you resume. No more cross-session amnesia.
You close Claude Code. You come back tomorrow. The conversation is gone: the decisions you made, the three things you already tried that didn't work, what was left to do. You re-explain everything. Or worse: Claude walks back into the same dead end you already ruled out.
--continue reloads the whole conversation (and bloats it). /compact summarizes aggressively. CLAUDE.md has to be maintained by hand. None of them capture why something didn't work.
claude-handoff is a pure plugin (hooks + skill + markdown) that does two things:
- On close → distills the session into
.claude/HANDOFF.md: summary, decisions, dead ends, next steps, git state, and how to resume. - On resume → re-injects that handoff as context, automatically (including after a compaction).
During the session ── /handoff ──▶ .claude/HANDOFF.md (live model, best quality)
On close ── SessionEnd ──▶ distill in background ──▶ .claude/HANDOFF.md (safety net)
On resume/compact ── SessionStart ─▶ HANDOFF.md ──▶ context restored
In Claude Code:
/plugin marketplace add andresleecom/claude-handoff
/plugin install claude-handoff@claude-handoff
That's it. Zero dependencies, nothing to configure.
| Piece | Event | What it does |
|---|---|---|
inject.mjs |
SessionStart (startup/resume/clear/compact) |
Reads .claude/HANDOFF.md and injects it as context. |
/handoff |
manual | The live model (which already has everything in context) writes the best possible handoff. |
capture.mjs → distill.mjs |
SessionEnd |
Safety net: if you forgot /handoff, it distills the transcript in the background with a cheap model (Haiku). It never blocks the close. |
The handoff lives at .claude/HANDOFF.md and is added to your .gitignore by default: these are personal notes, they don't clutter the repo.
Other plugins store "memory". claude-handoff explicitly captures what you should not repeat:
# 🤝 Handoff — my-project
_Last updated: 2026-06-04 18:20 · Branch: feature/auth_
## 📝 Summary
Implementing login. The happy path works; token refresh is missing.
## ✅ Decisions made
- JWT in an httpOnly cookie — why: avoids exposing the token to JS.
## ⛔ Dead ends (do not repeat)
- In-memory session tokens → lost on server restart. Dropped.
- Refresh inside an axios interceptor → infinite loop on the 401. Abandoned.
## 🔜 Next steps
- [ ] POST /refresh endpoint with token rotation.
## 🌳 Git state
- Branch: `feature/auth`
- Uncommitted: src/auth/session.ts
## ▶️ How to resume
`npm run dev` and test login at /login. Start with src/auth/session.ts.| claude-handoff | claude-mem | memory-toolkit | CLAUDE.md | |
|---|---|---|---|---|
| Automatic capture on close | ✅ | ✅ | ✅ | ❌ |
| Automatic re-injection on resume | ✅ | ✅ | ✅ | partial |
| Dead-end tracking | ✅ | ❌ | ❌ | ❌ |
| 100% human-readable (markdown) | ✅ | ❌ (DB) | ✅ | ✅ |
| Git-aware (branch/commits/dirty) | ✅ | ❌ | partial | ❌ |
| Zero dependencies | ✅ | ❌ | ❌ | — |
| Cross-platform (incl. native Windows) | ✅ | partial | partial | ✅ |
| Environment variable | Effect |
|---|---|
CLAUDE_HANDOFF_AUTO=0 |
Disables the automatic safety net (manual /handoff only). |
CLAUDE_HANDOFF_MODEL |
Model for the background distiller (default claude-haiku-4-5-20251001). |
Does it work offline? Re-injection and /handoff do (they're local). The automatic safety net on close needs a model call.
How much does it cost? Re-injection and /handoff add no extra cost. The safety net uses Haiku (cheap) and only when you didn't write a fresh handoff. Disable it with CLAUDE_HANDOFF_AUTO=0.
Does it work on Windows? Yes. The hooks are pure Node.js (no bash/jq), tested on Windows, macOS, and Linux.
Does it commit HANDOFF.md? Not by default: it's added to .gitignore as personal notes. Remove it from there if you want to share it with your team.
How do I disable automatic capture? Set CLAUDE_HANDOFF_AUTO=0 in your environment. Re-injection and /handoff keep working.
Doesn't it loop by calling itself? No: the distillation uses claude -p --bare (no plugin auto-discovery) plus an anti-recursion environment guard.
claude-handoff runs hooks automatically and spawns a background process, so it takes a few precautions — see SECURITY.md for the full threat model. In short: the background distiller validates CLAUDE_HANDOFF_MODEL against a strict whitelist (no command injection), high-confidence secret patterns are redacted before anything is written or re-injected, the handoff is gitignored by default, and re-injected content is framed as reference data, not instructions. Found something? Open a private security advisory on GitHub.
- Per-branch memory (
.claude/handoff/<branch>.md). - Token budget / selective injection.
-
PreCompacthook that refreshes the handoff before compaction. - Cross-tool support (other agents reading the same
HANDOFF.md). - Handoff history and search.
Issues and PRs welcome. The plugin is deliberately small and dependency-free; let's keep it that way.
MIT © Andres Lee
