claude-code-handoff 1.5.1 → 1.6.0

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 CHANGED
@@ -161,7 +161,7 @@ The biggest risk with handoffs is **forgetting to save**. You're deep in a task,
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.
164
+ A [Claude Code hook](https://docs.anthropic.com/en/docs/claude-code/hooks) 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.
165
165
 
166
166
  ```mermaid
167
167
  flowchart TD
@@ -178,18 +178,21 @@ flowchart TD
178
178
 
179
179
  ### Threshold Configuration
180
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.
181
+ The threshold is configured as a **percentage of the 200K token 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.
182
182
 
183
183
  | Preset | Value | Triggers at | Best for |
184
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 |
185
+ | **90% (default)** | `THRESHOLD_PERCENT=90` | 180K tokens | Maximizing context usage |
186
+ | **80%** | `THRESHOLD_PERCENT=80` | 160K tokens | Balance between space and safety |
187
+ | **75%** | `THRESHOLD_PERCENT=75` | 150K tokens | Short sessions, early handoff |
188
188
 
189
- The calculation is straightforward:
189
+ The calculation uses real data:
190
190
  ```
191
- MAX_CONTEXT_SIZE = 500000 (500KB estimated max transcript)
192
- THRESHOLD = MAX_CONTEXT_SIZE × THRESHOLD_PERCENT / 100
191
+ MAX_CONTEXT_TOKENS = 200000 (Claude Code's context window)
192
+ THRESHOLD = MAX_CONTEXT_TOKENS × THRESHOLD_PERCENT / 100
193
+
194
+ # The hook reads input_tokens from the last assistant message in the JSONL
195
+ # This is the ACTUAL context size — not an estimate
193
196
  ```
194
197
 
195
198
  ### Three Ways to Configure
@@ -572,7 +575,7 @@ A: The commands automatically summarize older sessions into a "Prior Sessions Su
572
575
  A: Absolutely. They're plain markdown. You can add notes, reorder next steps, or clean up history.
573
576
 
574
577
  **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.
578
+ 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.
576
579
 
577
580
  **Q: Can I disable auto-handoff?**
578
581
  A: Yes. Run `/auto-handoff` and select "Disable", or manually create the file `.claude/hooks/.auto-handoff-disabled`. Delete the file to re-enable.
@@ -9,11 +9,11 @@ if [ -f "$SCRIPT_DIR/.auto-handoff-disabled" ]; then
9
9
  exit 0
10
10
  fi
11
11
 
12
- # Contexto máximo estimado (bytes). 500KB ~ transcript máximo típico
13
- MAX_CONTEXT_SIZE=500000
12
+ # Contexto máximo do Claude Code (tokens)
13
+ MAX_CONTEXT_TOKENS=200000
14
14
  # Threshold configurável (% do contexto). 90% padrão — maximiza uso do contexto
15
15
  THRESHOLD_PERCENT=${CLAUDE_CONTEXT_THRESHOLD:-90}
16
- THRESHOLD=$((MAX_CONTEXT_SIZE * THRESHOLD_PERCENT / 100))
16
+ THRESHOLD_TOKENS=$((MAX_CONTEXT_TOKENS * THRESHOLD_PERCENT / 100))
17
17
 
18
18
  INPUT=$(cat)
19
19
  TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path // empty')
@@ -28,11 +28,52 @@ if [ -z "$SESSION_ID" ]; then
28
28
  exit 0
29
29
  fi
30
30
 
31
- # Verifica tamanho do transcript
32
- SIZE=$(wc -c < "$TRANSCRIPT_PATH" 2>/dev/null || echo 0)
33
- SIZE=$(echo "$SIZE" | tr -d ' ')
31
+ # Extrai o input_tokens da última mensagem do assistente no JSONL.
32
+ # Isso reflete o tamanho REAL do contexto que o Claude está usando.
33
+ # Campos: input_tokens + cache_read_input_tokens + cache_creation_input_tokens = total input
34
+ CURRENT_TOKENS=0
35
+ if command -v python3 &>/dev/null; then
36
+ CURRENT_TOKENS=$(python3 -c "
37
+ import json, sys
38
+ last = 0
39
+ with open('$TRANSCRIPT_PATH') as f:
40
+ for line in f:
41
+ try:
42
+ e = json.loads(line)
43
+ if e.get('type') == 'assistant':
44
+ u = e.get('message', {}).get('usage', {})
45
+ t = u.get('input_tokens', 0) + u.get('cache_read_input_tokens', 0) + u.get('cache_creation_input_tokens', 0)
46
+ if t > 0:
47
+ last = t
48
+ except:
49
+ pass
50
+ print(last)
51
+ " 2>/dev/null)
52
+ elif command -v node &>/dev/null; then
53
+ CURRENT_TOKENS=$(node -e "
54
+ const fs = require('fs');
55
+ const lines = fs.readFileSync('$TRANSCRIPT_PATH', 'utf-8').trim().split('\n');
56
+ let last = 0;
57
+ for (const line of lines) {
58
+ try {
59
+ const e = JSON.parse(line);
60
+ if (e.type === 'assistant' && e.message?.usage) {
61
+ const u = e.message.usage;
62
+ const t = (u.input_tokens || 0) + (u.cache_read_input_tokens || 0) + (u.cache_creation_input_tokens || 0);
63
+ if (t > 0) last = t;
64
+ }
65
+ } catch {}
66
+ }
67
+ console.log(last);
68
+ " 2>/dev/null)
69
+ fi
70
+
71
+ CURRENT_TOKENS=$(echo "$CURRENT_TOKENS" | tr -d ' \n')
72
+ if [ -z "$CURRENT_TOKENS" ] || [ "$CURRENT_TOKENS" -eq 0 ] 2>/dev/null; then
73
+ exit 0
74
+ fi
34
75
 
35
- if [ "$SIZE" -lt "$THRESHOLD" ]; then
76
+ if [ "$CURRENT_TOKENS" -lt "$THRESHOLD_TOKENS" ]; then
36
77
  exit 0
37
78
  fi
38
79
 
@@ -43,10 +84,13 @@ if [ -f "$FLAG" ]; then
43
84
  fi
44
85
  touch "$FLAG"
45
86
 
87
+ # Calcula % atual
88
+ CURRENT_PERCENT=$((CURRENT_TOKENS * 100 / MAX_CONTEXT_TOKENS))
89
+
46
90
  # Bloqueia e força handoff
47
91
  cat <<HOOKEOF
48
92
  {
49
93
  "decision": "block",
50
- "reason": "⚠️ AUTO-HANDOFF: O contexto atingiu ${THRESHOLD_PERCENT}% do limite. Você DEVE salvar o handoff AGORA.\n\nSiga estes passos IMEDIATAMENTE:\n1. Analise a conversa inteira e extraia: o que foi feito, próximos passos, arquivos-chave, decisões\n2. Escreva o handoff em .claude/handoffs/_active.md seguindo o template padrão\n3. Diga ao usuário: 'Handoff salvo automaticamente. Use /clear e depois /resume para continuar.'\n\nNÃO continue com outro trabalho até o handoff estar salvo."
94
+ "reason": "⚠️ AUTO-HANDOFF: O contexto atingiu ${CURRENT_PERCENT}% do limite (${CURRENT_TOKENS}/${MAX_CONTEXT_TOKENS} tokens). Você DEVE salvar o handoff AGORA.\n\nSiga estes passos IMEDIATAMENTE:\n1. Analise a conversa inteira e extraia: o que foi feito, próximos passos, arquivos-chave, decisões\n2. Escreva o handoff em .claude/handoffs/_active.md seguindo o template padrão\n3. Diga ao usuário: 'Handoff salvo automaticamente. Use /clear e depois /resume para continuar.'\n\nNÃO continue com outro trabalho até o handoff estar salvo."
51
95
  }
52
96
  HOOKEOF
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-handoff",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "description": "Session continuity for Claude Code — 5 slash commands to save, resume, delete, and switch workstreams across /clear",
5
5
  "bin": {
6
6
  "claude-code-handoff": "./cli.js"