claude-code-handoff
v2.1.0
Published
Session continuity for Claude Code — 7 slash commands to save, resume, diagnose, and switch workstreams across /clear
Maintainers
Readme
claude-code-handoff
Session continuity for Claude Code. Pick up exactly where you left off — across
/clear, crashes, or context switches.
The Problem
Claude Code operates within a 200K token context window. As you work, every message, tool call, file read, and response consumes tokens. Eventually, the context fills up — and that's where things break.
With auto-compact ON (default)
When context usage approaches the limit, Claude Code triggers auto-compact: it summarizes the entire conversation into a compressed buffer of approximately 33K tokens. In theory, this lets you keep working without interruption. In practice, the summarization is lossy — Claude loses critical details:
- Exact file paths and line numbers discussed earlier
- Decision rationale ("why did we choose approach A over B?")
- Specific code patterns and variable names
- Nuanced context about edge cases and constraints
- What was already tried and failed
The result: Claude starts repeating mistakes, asking questions you already answered, and proposing solutions that were already rejected. Development quality degrades progressively with each compaction cycle.
With auto-compact OFF
If you disable auto-compact to preserve full-fidelity context, you hit a hard wall: when the 200K window fills up, you must /clear. Total context loss. You start from absolute zero — re-explaining the project, the architecture, what was done, what's next.
The real cost
Either way, you lose. Auto-compact gives you a degraded Claude that forgets. Manual clear gives you an amnesiac Claude that knows nothing. Both waste tokens, time, and developer patience.
This is the problem claude-code-handoff solves.
The Solution
Instead of relying on lossy compression or starting from zero, claude-code-handoff gives Claude structured persistent memory — 7 slash commands that capture exactly what matters and restore it cleanly:
| Command | Description |
|---------|-------------|
| /handoff | Auto-save session state — no questions asked |
| /resume | Resume from a saved session — interactive picker |
| /save-handoff | Save with options — choose where and how |
| /switch-context <topic> | Switch between parallel workstreams |
| /delete-handoff | Delete one or more saved handoffs |
| /auto-handoff | Enable/disable auto-handoff or adjust threshold |
| /context-doctor | Diagnose context bloat and optimize token usage |
The workflow becomes: work until context is full → /handoff → /clear → /resume → continue with full context. No degradation, no amnesia. Just clean handoffs.
Auto-handoff (beta, since v1.4) monitors your context usage and automatically triggers a handoff when the transcript reaches a configurable threshold (default: 90%) — so you never forget to save. Since v1.5, the threshold is configured as a percentage of context instead of fixed bytes. Disabled by default — enable it with /auto-handoff when you're ready to try it.
Session state is stored in .claude/handoffs/ (gitignored) — each developer keeps their own context, no conflicts.
Quick Start
cd your-project
npx claude-code-handoffThat's it. Open Claude Code and your 6 commands are ready. Auto-handoff is available but disabled by default (beta) — run /auto-handoff to enable it.
How It Works
Core Flow
graph LR
A[Work in Claude Code] --> B["/handoff"]
B --> C[State saved to _active.md]
C --> D["/clear"]
D --> E[New session]
E --> F["/resume"]
F --> G[Full context restored]
G --> AThe /handoff Command (Auto-Save)
No wizard, no questions. Claude analyzes the conversation and saves everything automatically.
flowchart TD
A["/handoff"] --> B[Analyze conversation]
B --> C{_active.md exists?}
C -->|Yes| D{Same workstream?}
C -->|No| F[Create new _active.md]
D -->|Yes| E[Append session to existing]
D -->|No| G[Archive old → Create new]
E --> H["✅ Handoff saved. Type /clear then /resume"]
F --> H
G --> HThe /resume Command
Interactive wizard that shows all available sessions and lets you pick one.
flowchart TD
A["/resume"] --> B[Scan handoffs/]
B --> C{Handoffs found?}
C -->|No| D["No handoffs found. Use /handoff to create one."]
C -->|Yes| E[Present interactive picker]
E --> F[User selects session]
F --> G[Load full handoff]
G --> I[Present summary + next steps]
I --> J[Wait for user instruction]The /switch-context Command
Manage parallel workstreams without losing state.
flowchart TD
A["/switch-context api-refactor"] --> B[Read current _active.md]
B --> C[Archive current → archive/current-slug.md]
C --> D{Target exists in archive?}
D -->|Yes| E[Load target → _active.md]
D -->|No| F[Create fresh _active.md]
E --> G[Show target context + next steps]
F --> GFile Architecture
graph TD
subgraph ".claude/handoffs/"
A["_active.md<br/><i>Current workstream (like git HEAD)</i>"]
subgraph "archive/"
B["auth-refactor.md"]
C["api-v2.md"]
D["bugfix-login.md"]
end
end
A <-->|"/switch-context"| B
A <-->|"/switch-context"| C
A <-->|"/switch-context"| D
style A fill:#2d5016,stroke:#4ade80,color:#fff
style B fill:#1e3a5f,stroke:#60a5fa,color:#fff
style C fill:#1e3a5f,stroke:#60a5fa,color:#fff
style D fill:#1e3a5f,stroke:#60a5fa,color:#fffAuto-Handoff (Context Monitor) — Beta
The biggest risk with handoffs is forgetting to save. You're deep in a task, context fills up, and everything is lost. Auto-handoff eliminates this by monitoring your transcript size and forcing Claude to save the handoff before it's too late.
Note: Auto-handoff is a beta feature and is disabled by default. Enable it with
/auto-handoffinside Claude Code.
How It Works
A Claude Code hook runs after every Claude response (Stop event). It reads the actual token count from Claude's API usage data in the JSONL transcript and compares it against the 200K token context window. When the threshold is exceeded, it blocks Claude's next action and forces an immediate handoff save.
flowchart TD
A[Claude responds] --> B[Stop hook fires]
B --> C["Transcript size > threshold?"]
C -->|No| D[Continue normally]
C -->|Yes| E{Already triggered this session?}
E -->|Yes| D
E -->|No| F[Create flag file in /tmp]
F --> G["Block Claude: force handoff save"]
G --> H[Claude writes _active.md]
H --> I["User: /clear → /resume"]Plan Selection
The context window varies by Claude plan. The hook adapts automatically based on your plan configuration:
| Plan | Context Window | Value |
|------|---------------|-------|
| Pro / Max / Team | 200K tokens | MAX_CONTEXT_TOKENS=200000 (default) |
| Enterprise | 500K tokens | MAX_CONTEXT_TOKENS=500000 |
| Custom | Any value | Set via /auto-handoff or env var |
Configure your plan via the /auto-handoff wizard or set the environment variable:
export CLAUDE_MAX_CONTEXT=500000 # EnterpriseThreshold Configuration
The threshold is configured as a percentage of your plan's context window. The hook reads the actual token count from Claude's API usage data in the transcript — no guesswork, no byte-to-token estimation.
| Preset | Value | Triggers at (200K) | Triggers at (500K) | Best for |
|--------|-------|---------------------|---------------------|----------|
| 90% | THRESHOLD_PERCENT=90 | 180K tokens | 450K tokens | Maximizing context usage |
| 80% (default) | THRESHOLD_PERCENT=80 | 160K tokens | 400K tokens | Balance between space and safety |
| 75% | THRESHOLD_PERCENT=75 | 150K tokens | 375K tokens | Short sessions, early handoff |
The calculation uses real data:
MAX_CONTEXT_TOKENS = 200000 (or 500000 for Enterprise, or custom)
THRESHOLD = MAX_CONTEXT_TOKENS × THRESHOLD_PERCENT / 100
# The hook reads input_tokens from the last assistant message in the JSONL
# This is the ACTUAL context size — not an estimateThree Ways to Configure
1. Environment variables (per-session override):
export CLAUDE_MAX_CONTEXT=500000 # Enterprise plan (500K)
export CLAUDE_CONTEXT_THRESHOLD=80 # Trigger at 80%2. Interactive wizard (/auto-handoff command):
you: /auto-handoff
claude: Auto-handoff is DISABLED (plan: Pro/Max/Team, threshold: 90%).
What would you like to do?
1. Enable
2. Enable with custom configuration
you: [selects "Enable with custom configuration"]
claude: Which is your Claude plan?
1. Pro / Max / Team — 200K tokens
2. Enterprise — 500K tokens
3. Other — Type a custom value
you: [selects plan]
claude: Which threshold do you want?
1. 90% (Recommended)
2. 80%
3. 75%
4. Other — Type a custom value3. Edit the script directly:
# In .claude/hooks/context-monitor.sh, change the defaults:
MAX_CONTEXT_TOKENS=${CLAUDE_MAX_CONTEXT:-200000} # change 200000 to your value
THRESHOLD_PERCENT=${CLAUDE_CONTEXT_THRESHOLD:-80} # change 80 to your valueSafety Mechanisms
- One-shot trigger: A flag file in
/tmp(per session ID) prevents infinite loops — the hook triggers exactly once per session, even if Claude's handoff response pushes the transcript further - Session cleanup: A
SessionStarthook automatically cleans up stale flag files older than 24 hours - Opt-in design: Auto-handoff only runs when
.claude/hooks/.auto-handoff-enabledexists (created by/auto-handoff). No file = disabled by default - Non-destructive: The hook only blocks and instructs — it never modifies files directly. Claude performs the actual handoff save
What Happens When It Triggers
When the threshold is hit, Claude receives a block message like:
⚠️ AUTO-HANDOFF: Context reached 90% of the limit. You MUST save the handoff NOW.
Claude will then:
- Analyze the full conversation
- Write the handoff to
.claude/handoffs/_active.md - Tell you: "Handoff saved automatically. Use
/clearthen/resumeto continue."
Install
Option A: npx (recommended)
cd your-project
npx claude-code-handoff@latestOption B: curl
cd your-project
curl -fsSL https://raw.githubusercontent.com/eximIA-Ventures/claude-code-handoff/main/install.sh | bashOption C: clone & run
git clone https://github.com/eximIA-Ventures/claude-code-handoff.git /tmp/claude-code-handoff
cd your-project
/tmp/claude-code-handoff/install.shWhat Gets Installed
your-project/
└── .claude/
├── commands/
│ ├── handoff.md ← /handoff (auto-save)
│ ├── resume.md ← /resume (interactive picker)
│ ├── save-handoff.md ← /save-handoff (wizard)
│ ├── switch-context.md ← /switch-context (workstream switch)
│ ├── delete-handoff.md ← /delete-handoff (remove handoffs)
│ ├── auto-handoff.md ← /auto-handoff (on/off + threshold)
│ └── context-doctor.md ← /context-doctor (diagnose bloat)
├── rules/
│ ├── session-continuity.md ← Auto-loaded behavioral rules (lean, ~10 lines)
│ └── auto-handoff.md ← Auto-handoff trigger rules
├── hooks/
│ ├── context-monitor.sh ← Stop hook (monitors context size)
│ ├── session-cleanup.sh ← SessionStart hook (cleans old flags)
│ └── .auto-handoff-enabled ← Enable flag (created by /auto-handoff)
├── settings.json ← Hook configuration
└── handoffs/ ← Session state (gitignored)
├── _active.md ← Current workstream
└── archive/ ← Paused workstreamsThe installer also:
- Creates the full
.claude/handoffs/archive/directory structure - Adds
.claude/handoffs/to.gitignore - Adds a
Session Continuitysection to.claude/CLAUDE.md(creates one if missing) - Configures auto-handoff hooks in
.claude/settings.json
Usage Examples
Daily workflow
you: [work on feature for a while]
you: /handoff
claude: Handoff saved. 5 actions recorded, 3 next steps.
You can now type /clear to free context.
you: /clear
── new session ──
you: /resume
claude: ## Resuming session
**Workstream:** auth-refactor
**Last updated:** 2026-02-16
### Last session summary
- Implemented JWT middleware in src/auth/middleware.ts
- Added refresh token rotation logic
- Fixed CORS headers for token endpoint
### Next steps
1. Add unit tests for token rotation
2. Update API docs for new auth endpoints
3. Test with frontend login flow
What would you like to do?Switching between features
you: /switch-context payments-v2
claude: ## Context switched
**From:** auth-refactor → archived
**To:** payments-v2
### State
- Last worked on Stripe webhook handler
- Next: add idempotency keys
What would you like to do?Saving with options
you: /save-handoff
claude: Where should this session's handoff be saved?
1. Update active (auth-refactor)
2. Save as new context
3. Replace activeAuto-handoff in action
you: [working normally on a long session...]
claude: [responds to your request]
── context reaches 90% ──
claude: ⚠️ AUTO-HANDOFF: Context reached 90% of the limit.
Handoff saved automatically.
Use /clear then /resume to continue.
you: /clear
── new session ──
you: /resume
claude: ## Resuming session
[full context restored, continues exactly where you left off]Adjusting auto-handoff threshold
you: /auto-handoff
claude: Auto-handoff is ENABLED (threshold: 90%). What would you like to do?
1. Disable
2. Adjust threshold
you: [selects "Adjust threshold"]
claude: Which threshold do you want?
1. 90% (Recommended)
2. 80%
3. 75%
you: [types "95" via Other]
claude: ✅ Threshold updated to 95%.What Gets Captured
The handoff file records everything Claude needs to resume cold:
| Section | Purpose | |---------|---------| | Active Workstream | What you're working on (name + description) | | Active Agent(s) | Any personas active (e.g., @dev, @architect) | | What Was Done | Session-by-session log with dates | | What's Next | Prioritized, actionable pending items | | Key Files | Files to read for context reload | | Current Document | The main file being worked on | | Decisions Registry | Architectural/design decisions with rationale |
Session History
Each /handoff or /save-handoff appends a new session entry. History is preserved — you can see the full timeline of work across sessions:
## What Was Done
### Session 3 (2026-02-16)
- Added rate limiting to API endpoints
- Fixed memory leak in WebSocket handler
### Session 2 (2026-02-15)
- Implemented JWT refresh token rotation
- Added CORS configuration
### Session 1 (2026-02-14)
- Set up Express server with TypeScript
- Created initial route structureArchitecture
Design Principles
_active.mdis likeHEADin git — it always points to your current workstream. No need to remember filenames.- Archive is like branches — paused workstreams live in
archive/, ready to be loaded anytime. - Append-only history — sessions are never deleted, only appended. You can always trace what happened.
- Gitignored by default — each developer has their own session state, no merge conflicts.
- Zero dependencies — the installer is pure bash/Node.js, the commands are plain markdown.
Command Comparison
graph TD
subgraph "Quick Save"
H["/handoff"]
H --> H1["No wizard"]
H --> H2["Auto-detects workstream"]
H --> H3["Appends or creates"]
end
subgraph "Save with Options"
S["/save-handoff"]
S --> S1["Interactive wizard"]
S --> S2["Choose: update / new / replace"]
S --> S3["Name your contexts"]
end
subgraph "Resume"
R["/resume"]
R --> R1["Lists all sessions"]
R --> R2["Shows summary per session"]
R --> R3["Lists key files (no read)"]
end
subgraph "Switch"
SW["/switch-context"]
SW --> SW1["Archives current"]
SW --> SW2["Loads target"]
SW --> SW3["Or creates fresh"]
end
style H fill:#2d5016,stroke:#4ade80,color:#fff
style S fill:#1e3a5f,stroke:#60a5fa,color:#fff
style R fill:#5c1e8a,stroke:#c084fc,color:#fff
style SW fill:#7c2d12,stroke:#fb923c,color:#fff| | /handoff | /save-handoff | /resume | /switch-context | /auto-handoff |
|---|---|---|---|---|---|
| When | Before /clear | When you need options | Start of session | Mid-session | Anytime |
| Interactive | No | Yes (wizard) | Yes (picker) | No (with arg) | Yes (wizard) |
| Creates files | Auto | User chooses | No | Auto | Toggle file |
| Reads files | _active.md | _active.md + archive/ | Handoff only (no key files) | _active.md + target | Hook config |
Context Optimization (v2.1)
Every line in CLAUDE.md and rules/ costs tokens on every single message. v2.1 aggressively minimizes the always-on footprint:
| Component | v2.0 | v2.1 | Savings |
|-----------|------|------|---------|
| session-continuity.md (rule) | 28 lines | 10 lines | -64% |
| CLAUDE.md section | 5 lines + auto-read | 2 lines, no auto-read | -60% |
| /resume Key File read | 50 lines | 0 (removed) | -100% |
| Handoff compaction | 200 line limit | 100 line limit, auto-compact | -50% |
Estimated savings: ~5-6K tokens per message for projects with moderate CLAUDE.md and rules.
/context-doctor — Diagnose context bloat
Run /context-doctor to get a full audit of your context usage:
you: /context-doctor
claude: ## Context Health Report
### Always-on context (loaded every message)
| Source | Lines | Est. tokens | Status |
|----------------|-------|-------------|---------|
| CLAUDE.md | 260 | ~3900 | BLOATED |
| rules/mcp.md | 176 | ~2640 | BLOATED |
| rules/cont.md | 10 | ~150 | OK |
| **Total** | **446** | **~6690** | — |
### Recommendations
1. Move rules/mcp.md to commands/ (saves ~2640 tokens/message)
2. Trim CLAUDE.md: remove code examples on lines 117-145
3. Compact handoff: 8 sessions → keep last 3
Want me to apply any of these optimizations?Tips for users
- Move reference docs from
rules/tocommands/— Rules are loaded every message. Commands are loaded only when invoked. If a rules file has >50 lines and is mostly reference material, move it tocommands/. - Keep CLAUDE.md lean — Remove generic instructions ("write clean code", error handling patterns, debugging tips). Claude already knows these. Only keep project-specific rules and guardrails.
- Run
/context-doctorafter installing new tools — MCP rules, agent definitions, and framework configs can bloat context silently.
Behavioral Rules
The installer adds a lean session-continuity.md rules file (~10 lines) that Claude auto-loads on every session:
- On session start: Claude knows
_active.mdexists but doesn't read it unless asked - During work: Claude proactively reminds you to save after significant milestones
- Command awareness: Claude understands all 7 commands natively
- Auto-handoff awareness: When the context monitor triggers, Claude saves the handoff immediately
Update
Update commands and rules to the latest version without touching your handoff data:
cd your-project
npx claude-code-handoff@latestOr via curl:
cd your-project
curl -fsSL https://raw.githubusercontent.com/eximIA-Ventures/claude-code-handoff/main/update.sh | bashThis will:
- Overwrite command files with the latest versions
- Update rules and hooks to latest
- Ensure hooks are configured in
settings.json - Remove legacy files if present (
auto-handoff-toggle.md, Portuguese commands) - Not touch your
.claude/handoffs/data or custom threshold settings
Uninstall
cd your-project
curl -fsSL https://raw.githubusercontent.com/eximIA-Ventures/claude-code-handoff/main/uninstall.sh | bashThe uninstaller:
- Removes all 7 command files (including legacy
auto-handoff-toggle.md) - Removes rules and hooks
- Cleans hooks from
settings.json(requiresjq) - Preserves handoff data if sessions exist (won't delete your session history)
- Cleans
.gitignoreentries - Leaves
CLAUDE.mdunchanged (remove the section manually if desired)
Or remove manually:
rm .claude/commands/{handoff,resume,save-handoff,switch-context,delete-handoff,auto-handoff}.md
rm .claude/rules/{session-continuity,auto-handoff}.md
rm .claude/hooks/{context-monitor,session-cleanup}.sh
rm -rf .claude/handoffs/ # ⚠️ deletes all session historyRequirements
- Claude Code CLI
- Any project directory (with or without existing
.claude/folder) - Node.js 18+ (for npx install) or curl (for bash install)
FAQ
Q: Does this work with multiple developers on the same project? A: Yes. Handoff files are gitignored, so each developer has their own session state. No conflicts.
Q: What happens if I forget to /handoff before /clear?
A: If you've enabled auto-handoff (beta), Claude will automatically save the handoff when the context reaches the threshold. Without it, the context is lost for that session — the previous handoff is still there, but you won't have the latest session recorded.
Q: Can I have unlimited workstreams?
A: Yes. The archive/ folder has no limit. Each workstream is a single .md file.
Q: Does it work with Claude Code agents/personas? A: Yes. The handoff captures which agents are active (e.g., @dev, @architect) so Claude knows the context when resuming.
Q: What if _active.md gets too long?
A: The commands automatically summarize older sessions into a "Prior Sessions Summary" when the file exceeds ~300 lines.
Q: Can I edit the handoff files manually? A: Absolutely. They're plain markdown. You can add notes, reorder next steps, or clean up history.
Q: How does the auto-handoff threshold work?
A: The threshold is a percentage of Claude Code's 200K token context window. At 90% (default), the hook triggers at 180K tokens. The hook reads the actual token count from Claude's API usage data — not file size estimates. You can set any value from 1-100 via env var (CLAUDE_CONTEXT_THRESHOLD=80) or the /auto-handoff command.
Q: Can I disable auto-handoff?
A: Yes. Run /auto-handoff and select "Disable", or manually delete .claude/hooks/.auto-handoff-enabled. Without this file, auto-handoff is off.
Q: What if auto-handoff triggers too early/late?
A: Adjust the threshold. If it triggers too early, increase to 95%. If you're running out of context before it triggers, lower to 80% or 75%. Use /auto-handoff to change it interactively.
Q: My context fills up too fast. What can I do?
A: Run /context-doctor to audit your always-on context (CLAUDE.md + rules/). Common fixes: move large rules files to commands/ (on-demand loading), trim generic boilerplate from CLAUDE.md, and compact old handoff sessions. See the Context Optimization section.
Q: What changed in v2.1?
A: v2.1 focuses on context efficiency: leaner rules file (28→10 lines), no auto-read on session start (saves double reading), /resume no longer reads Key Files by default (saves ~50 lines), handoff compaction at 3 sessions (100 line target), and new /context-doctor diagnostic command.
Contributing
- Fork this repo
- Make your changes
- Test by running
./install.shin a test project - Open a PR
License
MIT — built by exímIA Ventures
