claude-code-handoff 1.5.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -27
- package/cli.js +2 -2
- package/install.sh +8 -8
- package/package.json +1 -1
- package/update.sh +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ Either way, you lose. Auto-compact gives you a degraded Claude that forgets. Man
|
|
|
36
36
|
|
|
37
37
|
## The Solution
|
|
38
38
|
|
|
39
|
-
Instead of relying on lossy compression or starting from zero, **claude-code-handoff** gives Claude **structured persistent memory** —
|
|
39
|
+
Instead of relying on lossy compression or starting from zero, **claude-code-handoff** gives Claude **structured persistent memory** — 6 slash commands that capture exactly what matters and restore it cleanly:
|
|
40
40
|
|
|
41
41
|
| Command | Description |
|
|
42
42
|
|---------|-------------|
|
|
@@ -49,7 +49,7 @@ Instead of relying on lossy compression or starting from zero, **claude-code-han
|
|
|
49
49
|
|
|
50
50
|
The workflow becomes: work until context is full → `/handoff` → `/clear` → `/resume` → continue with full context. No degradation, no amnesia. Just clean handoffs.
|
|
51
51
|
|
|
52
|
-
**
|
|
52
|
+
**Auto-handoff** (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, making it intuitive and portable across different setups.
|
|
53
53
|
|
|
54
54
|
Session state is stored in `.claude/handoffs/` (gitignored) — each developer keeps their own context, no conflicts.
|
|
55
55
|
|
|
@@ -62,7 +62,7 @@ cd your-project
|
|
|
62
62
|
npx claude-code-handoff
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
That's it. Open Claude Code and your
|
|
65
|
+
That's it. Open Claude Code and your 6 commands are ready. Auto-handoff is enabled by default at 90%.
|
|
66
66
|
|
|
67
67
|
---
|
|
68
68
|
|
|
@@ -157,38 +157,88 @@ graph TD
|
|
|
157
157
|
|
|
158
158
|
## Auto-Handoff (Context Monitor)
|
|
159
159
|
|
|
160
|
-
The biggest risk with handoffs is **forgetting to save**. Auto-handoff eliminates this by monitoring your transcript size and forcing
|
|
160
|
+
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.
|
|
161
161
|
|
|
162
162
|
### How It Works
|
|
163
163
|
|
|
164
|
+
A [Claude Code hook](https://docs.anthropic.com/en/docs/claude-code/hooks) runs after every Claude response (Stop event). It checks the transcript file size against a configurable threshold. When the threshold is exceeded, it **blocks** Claude's next action and forces an immediate handoff save.
|
|
165
|
+
|
|
164
166
|
```mermaid
|
|
165
167
|
flowchart TD
|
|
166
168
|
A[Claude responds] --> B[Stop hook fires]
|
|
167
|
-
B --> C
|
|
169
|
+
B --> C["Transcript size > threshold?"]
|
|
168
170
|
C -->|No| D[Continue normally]
|
|
169
|
-
C -->|Yes| E{Already triggered?}
|
|
171
|
+
C -->|Yes| E{Already triggered this session?}
|
|
170
172
|
E -->|Yes| D
|
|
171
|
-
E -->|No| F[Create flag file]
|
|
172
|
-
F --> G["Block: force handoff save"]
|
|
173
|
-
G --> H[Claude
|
|
173
|
+
E -->|No| F[Create flag file in /tmp]
|
|
174
|
+
F --> G["Block Claude: force handoff save"]
|
|
175
|
+
G --> H[Claude writes _active.md]
|
|
174
176
|
H --> I["User: /clear → /resume"]
|
|
175
177
|
```
|
|
176
178
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
### Threshold Configuration
|
|
180
|
+
|
|
181
|
+
The threshold is configured as a **percentage of the estimated maximum context** (~500KB transcript). This makes it intuitive — you think in terms of "how full is my context?" rather than raw byte counts.
|
|
182
|
+
|
|
183
|
+
| Preset | Value | Triggers at | Best for |
|
|
184
|
+
|--------|-------|-------------|----------|
|
|
185
|
+
| **90% (default)** | `THRESHOLD_PERCENT=90` | ~450KB | Maximizing context usage |
|
|
186
|
+
| **80%** | `THRESHOLD_PERCENT=80` | ~400KB | Balance between space and safety |
|
|
187
|
+
| **75%** | `THRESHOLD_PERCENT=75` | ~375KB | Short sessions, early handoff |
|
|
188
|
+
|
|
189
|
+
The calculation is straightforward:
|
|
190
|
+
```
|
|
191
|
+
MAX_CONTEXT_SIZE = 500000 (500KB — estimated max transcript)
|
|
192
|
+
THRESHOLD = MAX_CONTEXT_SIZE × THRESHOLD_PERCENT / 100
|
|
193
|
+
```
|
|
181
194
|
|
|
182
|
-
###
|
|
195
|
+
### Three Ways to Configure
|
|
183
196
|
|
|
197
|
+
**1. Environment variable** (per-session override):
|
|
184
198
|
```bash
|
|
185
|
-
#
|
|
186
|
-
export CLAUDE_CONTEXT_THRESHOLD=80
|
|
199
|
+
# Trigger at 80% instead of the default
|
|
200
|
+
export CLAUDE_CONTEXT_THRESHOLD=80
|
|
201
|
+
```
|
|
187
202
|
|
|
188
|
-
|
|
189
|
-
|
|
203
|
+
**2. Interactive wizard** (`/auto-handoff` command):
|
|
204
|
+
```
|
|
205
|
+
you: /auto-handoff
|
|
206
|
+
claude: Auto-handoff is ENABLED (threshold: 90%). What would you like to do?
|
|
207
|
+
1. Disable
|
|
208
|
+
2. Adjust threshold
|
|
209
|
+
|
|
210
|
+
you: [selects "Adjust threshold"]
|
|
211
|
+
claude: Which threshold do you want?
|
|
212
|
+
1. 90% (Recommended) — Default, maximizes context usage
|
|
213
|
+
2. 80% — Balance between space and safety
|
|
214
|
+
3. 75% — Short sessions, saves handoff earlier
|
|
215
|
+
4. Other — Type a custom value
|
|
190
216
|
```
|
|
191
217
|
|
|
218
|
+
**3. Edit the script directly**:
|
|
219
|
+
```bash
|
|
220
|
+
# In .claude/hooks/context-monitor.sh, change the default:
|
|
221
|
+
THRESHOLD_PERCENT=${CLAUDE_CONTEXT_THRESHOLD:-90} # change 90 to your value
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Safety Mechanisms
|
|
225
|
+
|
|
226
|
+
- **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
|
|
227
|
+
- **Session cleanup**: A `SessionStart` hook automatically cleans up stale flag files older than 24 hours
|
|
228
|
+
- **Disable switch**: Create `.claude/hooks/.auto-handoff-disabled` to completely disable the monitor (or use `/auto-handoff` to toggle)
|
|
229
|
+
- **Non-destructive**: The hook only blocks and instructs — it never modifies files directly. Claude performs the actual handoff save
|
|
230
|
+
|
|
231
|
+
### What Happens When It Triggers
|
|
232
|
+
|
|
233
|
+
When the threshold is hit, Claude receives a block message like:
|
|
234
|
+
|
|
235
|
+
> ⚠️ AUTO-HANDOFF: Context reached 90% of the limit. You MUST save the handoff NOW.
|
|
236
|
+
|
|
237
|
+
Claude will then:
|
|
238
|
+
1. Analyze the full conversation
|
|
239
|
+
2. Write the handoff to `.claude/handoffs/_active.md`
|
|
240
|
+
3. Tell you: "Handoff saved automatically. Use `/clear` then `/resume` to continue."
|
|
241
|
+
|
|
192
242
|
---
|
|
193
243
|
|
|
194
244
|
## Install
|
|
@@ -226,7 +276,7 @@ your-project/
|
|
|
226
276
|
│ ├── save-handoff.md ← /save-handoff (wizard)
|
|
227
277
|
│ ├── switch-context.md ← /switch-context (workstream switch)
|
|
228
278
|
│ ├── delete-handoff.md ← /delete-handoff (remove handoffs)
|
|
229
|
-
│ └── auto-handoff.md
|
|
279
|
+
│ └── auto-handoff.md ← /auto-handoff (on/off + threshold)
|
|
230
280
|
├── rules/
|
|
231
281
|
│ ├── session-continuity.md ← Auto-loaded behavioral rules
|
|
232
282
|
│ └── auto-handoff.md ← Auto-handoff trigger rules
|
|
@@ -298,6 +348,45 @@ claude: Where should this session's handoff be saved?
|
|
|
298
348
|
3. Replace active
|
|
299
349
|
```
|
|
300
350
|
|
|
351
|
+
### Auto-handoff in action
|
|
352
|
+
|
|
353
|
+
```
|
|
354
|
+
you: [working normally on a long session...]
|
|
355
|
+
claude: [responds to your request]
|
|
356
|
+
|
|
357
|
+
── context reaches 90% ──
|
|
358
|
+
|
|
359
|
+
claude: ⚠️ AUTO-HANDOFF: Context reached 90% of the limit.
|
|
360
|
+
Handoff saved automatically.
|
|
361
|
+
Use /clear then /resume to continue.
|
|
362
|
+
|
|
363
|
+
you: /clear
|
|
364
|
+
|
|
365
|
+
── new session ──
|
|
366
|
+
|
|
367
|
+
you: /resume
|
|
368
|
+
claude: ## Resuming session
|
|
369
|
+
[full context restored, continues exactly where you left off]
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Adjusting auto-handoff threshold
|
|
373
|
+
|
|
374
|
+
```
|
|
375
|
+
you: /auto-handoff
|
|
376
|
+
claude: Auto-handoff is ENABLED (threshold: 90%). What would you like to do?
|
|
377
|
+
1. Disable
|
|
378
|
+
2. Adjust threshold
|
|
379
|
+
|
|
380
|
+
you: [selects "Adjust threshold"]
|
|
381
|
+
claude: Which threshold do you want?
|
|
382
|
+
1. 90% (Recommended)
|
|
383
|
+
2. 80%
|
|
384
|
+
3. 75%
|
|
385
|
+
|
|
386
|
+
you: [types "95" via Other]
|
|
387
|
+
claude: ✅ Threshold updated to 95%.
|
|
388
|
+
```
|
|
389
|
+
|
|
301
390
|
---
|
|
302
391
|
|
|
303
392
|
## What Gets Captured
|
|
@@ -399,7 +488,8 @@ The installer adds a `session-continuity.md` rules file that Claude auto-loads o
|
|
|
399
488
|
|
|
400
489
|
- **On session start**: Claude knows `_active.md` exists but doesn't read it unless asked
|
|
401
490
|
- **During work**: Claude proactively reminds you to save after significant milestones
|
|
402
|
-
- **Command awareness**: Claude understands all
|
|
491
|
+
- **Command awareness**: Claude understands all 6 commands natively
|
|
492
|
+
- **Auto-handoff awareness**: When the context monitor triggers, Claude knows exactly what to do — save the handoff immediately without asking
|
|
403
493
|
|
|
404
494
|
---
|
|
405
495
|
|
|
@@ -421,9 +511,10 @@ curl -fsSL https://raw.githubusercontent.com/eximIA-Ventures/claude-code-handoff
|
|
|
421
511
|
|
|
422
512
|
This will:
|
|
423
513
|
- Overwrite command files with the latest versions
|
|
424
|
-
- Update
|
|
425
|
-
-
|
|
426
|
-
-
|
|
514
|
+
- Update rules and hooks to latest
|
|
515
|
+
- Ensure hooks are configured in `settings.json`
|
|
516
|
+
- Remove legacy files if present (`auto-handoff-toggle.md`, Portuguese commands)
|
|
517
|
+
- **Not touch** your `.claude/handoffs/` data or custom threshold settings
|
|
427
518
|
|
|
428
519
|
---
|
|
429
520
|
|
|
@@ -435,16 +526,18 @@ curl -fsSL https://raw.githubusercontent.com/eximIA-Ventures/claude-code-handoff
|
|
|
435
526
|
```
|
|
436
527
|
|
|
437
528
|
The uninstaller:
|
|
438
|
-
- Removes all
|
|
439
|
-
- Removes
|
|
529
|
+
- Removes all 6 command files (including legacy `auto-handoff-toggle.md`)
|
|
530
|
+
- Removes rules and hooks
|
|
531
|
+
- Cleans hooks from `settings.json` (requires `jq`)
|
|
440
532
|
- Preserves handoff data if sessions exist (won't delete your session history)
|
|
441
533
|
- Cleans `.gitignore` entries
|
|
442
534
|
- Leaves `CLAUDE.md` unchanged (remove the section manually if desired)
|
|
443
535
|
|
|
444
536
|
Or remove manually:
|
|
445
537
|
```bash
|
|
446
|
-
rm .claude/commands/{handoff,resume,save-handoff,switch-context,delete-handoff}.md
|
|
447
|
-
rm .claude/rules/session-continuity.md
|
|
538
|
+
rm .claude/commands/{handoff,resume,save-handoff,switch-context,delete-handoff,auto-handoff}.md
|
|
539
|
+
rm .claude/rules/{session-continuity,auto-handoff}.md
|
|
540
|
+
rm .claude/hooks/{context-monitor,session-cleanup}.sh
|
|
448
541
|
rm -rf .claude/handoffs/ # ⚠️ deletes all session history
|
|
449
542
|
```
|
|
450
543
|
|
|
@@ -478,6 +571,15 @@ A: The commands automatically summarize older sessions into a "Prior Sessions Su
|
|
|
478
571
|
**Q: Can I edit the handoff files manually?**
|
|
479
572
|
A: Absolutely. They're plain markdown. You can add notes, reorder next steps, or clean up history.
|
|
480
573
|
|
|
574
|
+
**Q: How does the auto-handoff threshold work?**
|
|
575
|
+
A: The threshold is a percentage of the estimated maximum transcript size (~500KB). At 90% (default), the hook triggers when the transcript reaches ~450KB. You can set any value from 1-100 via env var (`CLAUDE_CONTEXT_THRESHOLD=80`) or the `/auto-handoff` command.
|
|
576
|
+
|
|
577
|
+
**Q: Can I disable auto-handoff?**
|
|
578
|
+
A: Yes. Run `/auto-handoff` and select "Disable", or manually create the file `.claude/hooks/.auto-handoff-disabled`. Delete the file to re-enable.
|
|
579
|
+
|
|
580
|
+
**Q: What if auto-handoff triggers too early/late?**
|
|
581
|
+
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.
|
|
582
|
+
|
|
481
583
|
---
|
|
482
584
|
|
|
483
585
|
## Contributing
|
package/cli.js
CHANGED
|
@@ -67,8 +67,8 @@ fs.chmodSync(path.join(CLAUDE_DIR, 'hooks', 'session-cleanup.sh'), 0o755);
|
|
|
67
67
|
console.log(` ${YELLOW}[5/10]${NC} Configuring hooks in settings.json...`);
|
|
68
68
|
const settingsPath = path.join(CLAUDE_DIR, 'settings.json');
|
|
69
69
|
const hooksConfig = {
|
|
70
|
-
Stop: [{ hooks: [{ type: 'command', command: '$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh', timeout: 10 }] }],
|
|
71
|
-
SessionStart: [{ hooks: [{ type: 'command', command: '$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh', timeout: 5 }] }]
|
|
70
|
+
Stop: [{ hooks: [{ type: 'command', command: '"$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh"', timeout: 10 }] }],
|
|
71
|
+
SessionStart: [{ hooks: [{ type: 'command', command: '"$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh"', timeout: 5 }] }]
|
|
72
72
|
};
|
|
73
73
|
if (fs.existsSync(settingsPath)) {
|
|
74
74
|
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
package/install.sh
CHANGED
|
@@ -82,8 +82,8 @@ if [ -f "$SETTINGS_FILE" ]; then
|
|
|
82
82
|
if command -v jq &>/dev/null; then
|
|
83
83
|
HOOKS_JSON='{
|
|
84
84
|
"hooks": {
|
|
85
|
-
"Stop": [{"hooks": [{"type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh", "timeout": 10}]}],
|
|
86
|
-
"SessionStart": [{"hooks": [{"type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh", "timeout": 5}]}]
|
|
85
|
+
"Stop": [{"hooks": [{"type": "command", "command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh\"", "timeout": 10}]}],
|
|
86
|
+
"SessionStart": [{"hooks": [{"type": "command", "command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh\"", "timeout": 5}]}]
|
|
87
87
|
}
|
|
88
88
|
}'
|
|
89
89
|
jq --argjson hooks "$(echo "$HOOKS_JSON" | jq '.hooks')" '. + {hooks: $hooks}' "$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" && mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE"
|
|
@@ -102,7 +102,7 @@ if [ -f "$SETTINGS_FILE" ]; then
|
|
|
102
102
|
"hooks": [
|
|
103
103
|
{
|
|
104
104
|
"type": "command",
|
|
105
|
-
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh",
|
|
105
|
+
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh\"",
|
|
106
106
|
"timeout": 10
|
|
107
107
|
}
|
|
108
108
|
]
|
|
@@ -113,7 +113,7 @@ if [ -f "$SETTINGS_FILE" ]; then
|
|
|
113
113
|
"hooks": [
|
|
114
114
|
{
|
|
115
115
|
"type": "command",
|
|
116
|
-
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh",
|
|
116
|
+
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh\"",
|
|
117
117
|
"timeout": 5
|
|
118
118
|
}
|
|
119
119
|
]
|
|
@@ -136,7 +136,7 @@ SETTINGSEOF
|
|
|
136
136
|
"hooks": [
|
|
137
137
|
{
|
|
138
138
|
"type": "command",
|
|
139
|
-
"command": "\$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh",
|
|
139
|
+
"command": "\"\$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh\"",
|
|
140
140
|
"timeout": 10
|
|
141
141
|
}
|
|
142
142
|
]
|
|
@@ -147,7 +147,7 @@ SETTINGSEOF
|
|
|
147
147
|
"hooks": [
|
|
148
148
|
{
|
|
149
149
|
"type": "command",
|
|
150
|
-
"command": "\$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh",
|
|
150
|
+
"command": "\"\$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh\"",
|
|
151
151
|
"timeout": 5
|
|
152
152
|
}
|
|
153
153
|
]
|
|
@@ -169,7 +169,7 @@ else
|
|
|
169
169
|
"hooks": [
|
|
170
170
|
{
|
|
171
171
|
"type": "command",
|
|
172
|
-
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh",
|
|
172
|
+
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh\"",
|
|
173
173
|
"timeout": 10
|
|
174
174
|
}
|
|
175
175
|
]
|
|
@@ -180,7 +180,7 @@ else
|
|
|
180
180
|
"hooks": [
|
|
181
181
|
{
|
|
182
182
|
"type": "command",
|
|
183
|
-
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh",
|
|
183
|
+
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh\"",
|
|
184
184
|
"timeout": 5
|
|
185
185
|
}
|
|
186
186
|
]
|
package/package.json
CHANGED
package/update.sh
CHANGED
|
@@ -72,7 +72,7 @@ SETTINGS_FILE="$CLAUDE_DIR/settings.json"
|
|
|
72
72
|
if [ -f "$SETTINGS_FILE" ]; then
|
|
73
73
|
if ! grep -q "context-monitor" "$SETTINGS_FILE" 2>/dev/null; then
|
|
74
74
|
if command -v jq &>/dev/null; then
|
|
75
|
-
HOOKS_JSON='{"Stop":[{"hooks":[{"type":"command","command":"$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh","timeout":10}]}],"SessionStart":[{"hooks":[{"type":"command","command":"$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh","timeout":5}]}]}'
|
|
75
|
+
HOOKS_JSON='{"Stop":[{"hooks":[{"type":"command","command":"\"$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh\"","timeout":10}]}],"SessionStart":[{"hooks":[{"type":"command","command":"\"$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh\"","timeout":5}]}]}'
|
|
76
76
|
jq --argjson hooks "$HOOKS_JSON" '. + {hooks: $hooks}' "$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" && mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE"
|
|
77
77
|
echo -e " Hooks added to settings.json"
|
|
78
78
|
else
|