claude-code-handoff 1.8.1 → 2.0.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
@@ -253,7 +253,7 @@ THRESHOLD_PERCENT=${CLAUDE_CONTEXT_THRESHOLD:-90} # change 90 to your value
253
253
 
254
254
  - **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
255
255
  - **Session cleanup**: A `SessionStart` hook automatically cleans up stale flag files older than 24 hours
256
- - **Disable switch**: Create `.claude/hooks/.auto-handoff-disabled` to completely disable the monitor (or use `/auto-handoff` to toggle)
256
+ - **Opt-in design**: Auto-handoff only runs when `.claude/hooks/.auto-handoff-enabled` exists (created by `/auto-handoff`). No file = disabled by default
257
257
  - **Non-destructive**: The hook only blocks and instructs — it never modifies files directly. Claude performs the actual handoff save
258
258
 
259
259
  ### What Happens When It Triggers
@@ -311,7 +311,7 @@ your-project/
311
311
  ├── hooks/
312
312
  │ ├── context-monitor.sh ← Stop hook (monitors context size)
313
313
  │ ├── session-cleanup.sh ← SessionStart hook (cleans old flags)
314
- │ └── .auto-handoff-disabled Disable flag (remove to enable)
314
+ │ └── .auto-handoff-enabled Enable flag (created by /auto-handoff)
315
315
  ├── settings.json ← Hook configuration
316
316
  └── handoffs/ ← Session state (gitignored)
317
317
  ├── _active.md ← Current workstream
@@ -604,7 +604,7 @@ A: Absolutely. They're plain markdown. You can add notes, reorder next steps, or
604
604
  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.
605
605
 
606
606
  **Q: Can I disable auto-handoff?**
607
- A: Yes. Run `/auto-handoff` and select "Disable", or manually create the file `.claude/hooks/.auto-handoff-disabled`. Delete the file to re-enable.
607
+ A: Yes. Run `/auto-handoff` and select "Disable", or manually delete `.claude/hooks/.auto-handoff-enabled`. Without this file, auto-handoff is off.
608
608
 
609
609
  **Q: What if auto-handoff triggers too early/late?**
610
610
  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.
package/cli.js CHANGED
@@ -3,24 +3,35 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
 
6
- const GREEN = '\x1b[32m';
7
- const YELLOW = '\x1b[33m';
8
- const CYAN = '\x1b[36m';
6
+ // Colors (RGB)
7
+ const AMBER = '\x1b[38;2;245;158;11m';
8
+ const GREEN = '\x1b[38;2;16;185;129m';
9
+ const RED = '\x1b[38;2;239;68;68m';
10
+ const CYAN = '\x1b[38;2;34;211;238m';
11
+ const WHITE = '\x1b[37m';
12
+ const GRAY = '\x1b[90m';
13
+ const BOLD = '\x1b[1m';
14
+ const DIM = '\x1b[2m';
9
15
  const NC = '\x1b[0m';
10
16
 
17
+ const ok = (msg) => console.log(` ${GREEN}✓${NC} ${msg}`);
18
+ const fail = (msg) => console.log(` ${RED}✗${NC} ${msg}`);
19
+ const info = (msg) => console.log(` ${GRAY}${msg}${NC}`);
20
+ const head = (msg) => console.log(`\n ${AMBER}${BOLD}${msg}${NC}`);
21
+
11
22
  const PROJECT_DIR = process.cwd();
12
23
  const CLAUDE_DIR = path.join(PROJECT_DIR, '.claude');
13
24
  const SCRIPT_DIR = __dirname;
14
25
 
26
+ // ─── Banner ───────────────────────────────────────────
15
27
  console.log('');
16
- console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
17
- console.log(`${CYAN} claude-code-handoff — Session Continuity${NC}`);
18
- console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
19
- console.log('');
20
- console.log(` Project: ${GREEN}${PROJECT_DIR}${NC}`);
28
+ console.log(` ${AMBER}${BOLD}┌──────────────────────────────────────┐${NC}`);
29
+ console.log(` ${AMBER}${BOLD}│${NC} ${WHITE}${BOLD}claude-code-handoff${NC} ${DIM}v1.9${NC} ${AMBER}${BOLD}│${NC}`);
30
+ console.log(` ${AMBER}${BOLD}│${NC} ${GRAY}Session Continuity for Claude Code${NC} ${AMBER}${BOLD}│${NC}`);
31
+ console.log(` ${AMBER}${BOLD}└──────────────────────────────────────┘${NC}`);
21
32
  console.log('');
33
+ info(`Project: ${WHITE}${PROJECT_DIR}${NC}`);
22
34
 
23
- // Helper
24
35
  function ensureDir(dir) {
25
36
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
26
37
  }
@@ -30,48 +41,62 @@ function copyFile(src, dst) {
30
41
  if (fs.existsSync(srcPath)) {
31
42
  fs.copyFileSync(srcPath, dst);
32
43
  } else {
33
- console.error(` Error: ${src} not found in package`);
44
+ fail(`${src} not found in package`);
34
45
  process.exit(1);
35
46
  }
36
47
  }
37
48
 
38
- // 1. Create directories
39
- console.log(` ${YELLOW}[1/10]${NC} Creating directories...`);
49
+ // ─── Pre-flight ───────────────────────────────────────
50
+ head('Pre-flight');
51
+
52
+ const monitorPath = path.join(CLAUDE_DIR, 'hooks', 'context-monitor.sh');
53
+ let isReinstall = false;
54
+ let savedThreshold = '';
55
+ let savedMaxContext = '';
56
+ if (fs.existsSync(monitorPath)) {
57
+ isReinstall = true;
58
+ const oldContent = fs.readFileSync(monitorPath, 'utf-8');
59
+ const thresholdMatch = oldContent.match(/CLAUDE_CONTEXT_THRESHOLD:-(\d+)/);
60
+ const maxContextMatch = oldContent.match(/CLAUDE_MAX_CONTEXT:-(\d+)/);
61
+ if (thresholdMatch) savedThreshold = thresholdMatch[1];
62
+ if (maxContextMatch) savedMaxContext = maxContextMatch[1];
63
+ }
64
+
65
+ if (isReinstall) {
66
+ info('Existing installation found. Upgrading...');
67
+ } else {
68
+ ok('Fresh install');
69
+ }
70
+
71
+ // ─── Directories ──────────────────────────────────────
72
+ head('Creating directories');
73
+
40
74
  ensureDir(path.join(CLAUDE_DIR, 'commands'));
41
75
  ensureDir(path.join(CLAUDE_DIR, 'rules'));
42
76
  ensureDir(path.join(CLAUDE_DIR, 'hooks'));
43
77
  ensureDir(path.join(CLAUDE_DIR, 'handoffs', 'archive'));
78
+ ok('Directory structure created');
79
+
80
+ // ─── Commands ─────────────────────────────────────────
81
+ head('Installing commands');
44
82
 
45
- // 2. Copy commands
46
- console.log(` ${YELLOW}[2/10]${NC} Installing commands...`);
47
83
  copyFile('commands/resume.md', path.join(CLAUDE_DIR, 'commands', 'resume.md'));
48
84
  copyFile('commands/save-handoff.md', path.join(CLAUDE_DIR, 'commands', 'save-handoff.md'));
49
85
  copyFile('commands/switch-context.md', path.join(CLAUDE_DIR, 'commands', 'switch-context.md'));
50
86
  copyFile('commands/handoff.md', path.join(CLAUDE_DIR, 'commands', 'handoff.md'));
51
87
  copyFile('commands/delete-handoff.md', path.join(CLAUDE_DIR, 'commands', 'delete-handoff.md'));
52
88
  copyFile('commands/auto-handoff.md', path.join(CLAUDE_DIR, 'commands', 'auto-handoff.md'));
89
+ ok('6 slash commands installed');
90
+
91
+ // ─── Rules ────────────────────────────────────────────
92
+ head('Installing rules');
53
93
 
54
- // 3. Copy rules
55
- console.log(` ${YELLOW}[3/10]${NC} Installing rules...`);
56
94
  copyFile('rules/session-continuity.md', path.join(CLAUDE_DIR, 'rules', 'session-continuity.md'));
57
95
  copyFile('rules/auto-handoff.md', path.join(CLAUDE_DIR, 'rules', 'auto-handoff.md'));
96
+ ok('Behavioral rules installed');
58
97
 
59
- // 4. Install hooks
60
- console.log(` ${YELLOW}[4/10]${NC} Installing hooks...`);
61
-
62
- // Detect reinstall: save user's custom settings before overwriting
63
- const monitorPath = path.join(CLAUDE_DIR, 'hooks', 'context-monitor.sh');
64
- let isReinstall = false;
65
- let savedThreshold = '';
66
- let savedMaxContext = '';
67
- if (fs.existsSync(monitorPath)) {
68
- isReinstall = true;
69
- const oldContent = fs.readFileSync(monitorPath, 'utf-8');
70
- const thresholdMatch = oldContent.match(/CLAUDE_CONTEXT_THRESHOLD:-(\d+)/);
71
- const maxContextMatch = oldContent.match(/CLAUDE_MAX_CONTEXT:-(\d+)/);
72
- if (thresholdMatch) savedThreshold = thresholdMatch[1];
73
- if (maxContextMatch) savedMaxContext = maxContextMatch[1];
74
- }
98
+ // ─── Hooks ────────────────────────────────────────────
99
+ head('Installing hooks');
75
100
 
76
101
  copyFile('hooks/context-monitor.sh', monitorPath);
77
102
  copyFile('hooks/session-cleanup.sh', path.join(CLAUDE_DIR, 'hooks', 'session-cleanup.sh'));
@@ -79,25 +104,26 @@ fs.chmodSync(monitorPath, 0o755);
79
104
  fs.chmodSync(path.join(CLAUDE_DIR, 'hooks', 'session-cleanup.sh'), 0o755);
80
105
 
81
106
  if (isReinstall) {
82
- // Restore user's custom settings
83
107
  let content = fs.readFileSync(monitorPath, 'utf-8');
84
108
  if (savedThreshold && savedThreshold !== '90') {
85
109
  content = content.replace('CLAUDE_CONTEXT_THRESHOLD:-90', `CLAUDE_CONTEXT_THRESHOLD:-${savedThreshold}`);
86
- console.log(` Preserved threshold: ${CYAN}${savedThreshold}%${NC}`);
110
+ ok(`Preserved threshold: ${CYAN}${savedThreshold}%${NC}`);
87
111
  }
88
112
  if (savedMaxContext && savedMaxContext !== '200000') {
89
113
  content = content.replace('CLAUDE_MAX_CONTEXT:-200000', `CLAUDE_MAX_CONTEXT:-${savedMaxContext}`);
90
- console.log(` Preserved max context: ${CYAN}${savedMaxContext} tokens${NC}`);
114
+ ok(`Preserved max context: ${CYAN}${savedMaxContext} tokens${NC}`);
91
115
  }
92
116
  fs.writeFileSync(monitorPath, content);
93
- // Don't touch .auto-handoff-disabled — preserve user's on/off choice
94
- } else {
95
- // Fresh install: auto-handoff disabled by default (beta feature)
96
- fs.writeFileSync(path.join(CLAUDE_DIR, 'hooks', '.auto-handoff-disabled'), '');
97
117
  }
98
118
 
99
- // 5. Configure hooks in settings.json
100
- console.log(` ${YELLOW}[5/10]${NC} Configuring hooks in settings.json...`);
119
+ // Clean up legacy disabled flag
120
+ const legacyDisabled = path.join(CLAUDE_DIR, 'hooks', '.auto-handoff-disabled');
121
+ if (fs.existsSync(legacyDisabled)) fs.unlinkSync(legacyDisabled);
122
+ ok('Context monitor + session cleanup hooks');
123
+
124
+ // ─── Settings ─────────────────────────────────────────
125
+ head('Configuring settings.json');
126
+
101
127
  const settingsPath = path.join(CLAUDE_DIR, 'settings.json');
102
128
  const hooksConfig = {
103
129
  Stop: [{ hooks: [{ type: 'command', command: '"$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh"', timeout: 10 }] }],
@@ -108,15 +134,20 @@ if (fs.existsSync(settingsPath)) {
108
134
  if (!JSON.stringify(settings).includes('context-monitor')) {
109
135
  settings.hooks = hooksConfig;
110
136
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
137
+ ok('Hooks added to existing settings.json');
138
+ } else {
139
+ ok('Hooks already configured');
111
140
  }
112
141
  } else {
113
142
  fs.writeFileSync(settingsPath, JSON.stringify({ hooks: hooksConfig }, null, 2) + '\n');
143
+ ok('settings.json created with hooks');
114
144
  }
115
145
 
116
- // 4. Create initial _active.md
146
+ // ─── Handoff ──────────────────────────────────────────
147
+ head('Setting up handoff storage');
148
+
117
149
  const activePath = path.join(CLAUDE_DIR, 'handoffs', '_active.md');
118
150
  if (!fs.existsSync(activePath)) {
119
- console.log(` ${YELLOW}[6/10]${NC} Creating initial handoff...`);
120
151
  fs.writeFileSync(activePath, `# Session Handoff
121
152
 
122
153
  > No active session yet. Use \`/handoff\` or \`/save-handoff\` to save your first session state.
@@ -142,24 +173,31 @@ if (!fs.existsSync(activePath)) {
142
173
  ## Decisions Registry
143
174
  (none)
144
175
  `);
176
+ ok('Initial handoff template created');
145
177
  } else {
146
- console.log(` ${YELLOW}[6/10]${NC} Handoff already exists, keeping it`);
178
+ ok('Existing handoff preserved');
147
179
  }
148
180
 
149
- // 7. Update .gitignore
150
- console.log(` ${YELLOW}[7/10]${NC} Updating .gitignore...`);
181
+ // ─── Gitignore ────────────────────────────────────────
182
+ head('Updating .gitignore');
183
+
151
184
  const gitignorePath = path.join(PROJECT_DIR, '.gitignore');
152
185
  if (fs.existsSync(gitignorePath)) {
153
186
  const content = fs.readFileSync(gitignorePath, 'utf-8');
154
187
  if (!content.includes('.claude/handoffs/')) {
155
188
  fs.appendFileSync(gitignorePath, '\n# claude-code-handoff (personal session state)\n.claude/handoffs/\n');
189
+ ok('Added .claude/handoffs/ to .gitignore');
190
+ } else {
191
+ ok('Already in .gitignore');
156
192
  }
157
193
  } else {
158
194
  fs.writeFileSync(gitignorePath, '# claude-code-handoff (personal session state)\n.claude/handoffs/\n');
195
+ ok('.gitignore created');
159
196
  }
160
197
 
161
- // 8. Update CLAUDE.md
162
- console.log(` ${YELLOW}[8/10]${NC} Updating CLAUDE.md...`);
198
+ // ─── CLAUDE.md ────────────────────────────────────────
199
+ head('Updating CLAUDE.md');
200
+
163
201
  const claudeMdPath = path.join(CLAUDE_DIR, 'CLAUDE.md');
164
202
  const continuityBlock = `## Session Continuity (MANDATORY)
165
203
 
@@ -178,13 +216,26 @@ if (fs.existsSync(claudeMdPath)) {
178
216
  } else {
179
217
  fs.appendFileSync(claudeMdPath, '\n' + continuityBlock + '\n');
180
218
  }
219
+ ok('Session Continuity section added');
220
+ } else {
221
+ ok('Session Continuity already present');
181
222
  }
182
223
  } else {
183
224
  fs.writeFileSync(claudeMdPath, `# Project Rules\n\n${continuityBlock}\n`);
225
+ ok('CLAUDE.md created');
184
226
  }
185
227
 
186
- // 9. Verify
187
- console.log(` ${YELLOW}[9/10]${NC} Verifying installation...`);
228
+ // ─── Legacy cleanup ──────────────────────────────────
229
+ let cleaned = 0;
230
+ for (const f of ['retomar.md', 'salvar-handoff.md', 'trocar-contexto.md', 'auto-handoff-toggle.md']) {
231
+ const fp = path.join(CLAUDE_DIR, 'commands', f);
232
+ if (fs.existsSync(fp)) { fs.unlinkSync(fp); cleaned++; }
233
+ }
234
+ if (cleaned > 0) info(`Removed ${cleaned} legacy command(s)`);
235
+
236
+ // ─── Verify ───────────────────────────────────────────
237
+ head('Verifying');
238
+
188
239
  let installed = 0;
189
240
  for (const f of ['resume.md', 'save-handoff.md', 'switch-context.md', 'handoff.md', 'delete-handoff.md', 'auto-handoff.md']) {
190
241
  if (fs.existsSync(path.join(CLAUDE_DIR, 'commands', f))) installed++;
@@ -193,31 +244,28 @@ let hooksOk = 0;
193
244
  if (fs.existsSync(path.join(CLAUDE_DIR, 'hooks', 'context-monitor.sh'))) hooksOk++;
194
245
  if (fs.existsSync(path.join(CLAUDE_DIR, 'hooks', 'session-cleanup.sh'))) hooksOk++;
195
246
 
196
- console.log('');
197
- console.log(` ${YELLOW}[10/10]${NC} Done!`);
198
- console.log('');
199
247
  if (installed === 6 && hooksOk === 2) {
200
- console.log(`${GREEN} Installed successfully! (${installed}/6 commands, ${hooksOk}/2 hooks)${NC}`);
248
+ ok(`${installed}/6 commands, ${hooksOk}/2 hooks`);
201
249
  } else {
202
- console.log(`${YELLOW} Partial install: ${installed}/6 commands, ${hooksOk}/2 hooks${NC}`);
250
+ fail(`Partial: ${installed}/6 commands, ${hooksOk}/2 hooks`);
203
251
  }
252
+
253
+ // ─── Done ─────────────────────────────────────────────
204
254
  console.log('');
205
- console.log(' Commands available:');
206
- console.log(` ${CYAN}/handoff${NC} Auto-save session (no wizard)`);
207
- console.log(` ${CYAN}/resume${NC} Resume with wizard`);
208
- console.log(` ${CYAN}/save-handoff${NC} Save session state (wizard)`);
209
- console.log(` ${CYAN}/switch-context${NC} Switch workstream`);
210
- console.log(` ${CYAN}/delete-handoff${NC} Delete handoff(s)`);
211
- console.log(` ${CYAN}/auto-handoff${NC} Toggle auto-handoff on/off`);
255
+ console.log(` ${AMBER}${BOLD}════════════════════════════════════════${NC}`);
256
+ console.log(` ${GREEN}${BOLD} Installed successfully!${NC}`);
257
+ console.log(` ${AMBER}${BOLD}════════════════════════════════════════${NC}`);
212
258
  console.log('');
213
- console.log(` Auto-handoff: ${YELLOW}(beta — disabled by default)${NC}`);
214
- console.log(` Use ${CYAN}/auto-handoff${NC} to enable and configure threshold`);
259
+ console.log(` ${WHITE}${BOLD}Commands:${NC}`);
260
+ console.log(` ${CYAN}/handoff${NC} ${GRAY}Auto-save session${NC}`);
261
+ console.log(` ${CYAN}/resume${NC} ${GRAY}Resume with wizard${NC}`);
262
+ console.log(` ${CYAN}/save-handoff${NC} ${GRAY}Save with options${NC}`);
263
+ console.log(` ${CYAN}/switch-context${NC} ${GRAY}Switch workstream${NC}`);
264
+ console.log(` ${CYAN}/delete-handoff${NC} ${GRAY}Delete handoff(s)${NC}`);
265
+ console.log(` ${CYAN}/auto-handoff${NC} ${GRAY}Toggle auto-handoff${NC}`);
215
266
  console.log('');
216
- console.log(' Files:');
217
- console.log(' .claude/commands/ 6 command files');
218
- console.log(' .claude/rules/ session-continuity.md, auto-handoff.md');
219
- console.log(' .claude/hooks/ context-monitor.sh, session-cleanup.sh');
220
- console.log(' .claude/handoffs/ session state (gitignored)');
267
+ console.log(` ${WHITE}${BOLD}Auto-handoff:${NC} ${DIM}beta — disabled by default${NC}`);
268
+ console.log(` ${GRAY}Run ${CYAN}/auto-handoff${GRAY} inside Claude Code to enable${NC}`);
221
269
  console.log('');
222
- console.log(` ${YELLOW}Start Claude Code and use /resume to begin.${NC}`);
270
+ console.log(` ${DIM}Start Claude Code and use ${WHITE}/resume${DIM} to begin.${NC}`);
223
271
  console.log('');
@@ -6,9 +6,9 @@ Toggle the automatic handoff context monitor on/off, configure threshold, and se
6
6
 
7
7
  ### Step 1: Check current state
8
8
 
9
- Check if `.claude/hooks/.auto-handoff-disabled` exists:
10
- - If exists → currently DISABLED
11
- - If not exists → currently ENABLED
9
+ Check if `.claude/hooks/.auto-handoff-enabled` exists:
10
+ - If exists → currently ENABLED
11
+ - If not exists → currently DISABLED (default)
12
12
 
13
13
  Also read from `.claude/hooks/context-monitor.sh`:
14
14
  - `THRESHOLD_PERCENT` value (the default in `THRESHOLD_PERCENT=${CLAUDE_CONTEXT_THRESHOLD:-XX}`)
@@ -30,7 +30,9 @@ Use AskUserQuestion:
30
30
  ### Step 3: Execute
31
31
 
32
32
  #### Toggle (Ativar/Desativar):
33
- - Create or delete `.claude/hooks/.auto-handoff-disabled`
33
+ - Ativar: create `.claude/hooks/.auto-handoff-enabled`
34
+ - Desativar: delete `.claude/hooks/.auto-handoff-enabled`
35
+ - Also delete legacy `.claude/hooks/.auto-handoff-disabled` if it exists
34
36
 
35
37
  #### Ajustar threshold:
36
38
  Ask with AskUserQuestion:
@@ -52,7 +54,7 @@ Ask with AskUserQuestion:
52
54
  - Update the `MAX_CONTEXT_TOKENS` default value in `context-monitor.sh` by changing `MAX_CONTEXT_TOKENS=${CLAUDE_MAX_CONTEXT:-XXXXXX}` to the chosen value
53
55
 
54
56
  #### Ativar com configuração customizada:
55
- Run both "Alterar plano" and "Ajustar threshold" flows above, then delete `.claude/hooks/.auto-handoff-disabled`
57
+ Run both "Alterar plano" and "Ajustar threshold" flows above, then create `.claude/hooks/.auto-handoff-enabled`
56
58
 
57
59
  ### Step 4: Confirm
58
60
 
@@ -3,9 +3,9 @@
3
3
  # Detecta quando o contexto está próximo do limite e força o salvamento do handoff.
4
4
  # Usado como hook "Stop" do Claude Code.
5
5
 
6
- # Check if auto-handoff is disabled
6
+ # Auto-handoff is opt-in: only runs if explicitly enabled
7
7
  SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
- if [ -f "$SCRIPT_DIR/.auto-handoff-disabled" ]; then
8
+ if [ ! -f "$SCRIPT_DIR/.auto-handoff-enabled" ]; then
9
9
  exit 0
10
10
  fi
11
11
 
package/install.sh CHANGED
@@ -1,18 +1,21 @@
1
1
  #!/bin/bash
2
- # claude-code-handoff — Session continuity for Claude Code
3
- # Install: curl -fsSL https://raw.githubusercontent.com/eximIA-Ventures/claude-code-handoff/main/install.sh | bash
4
- #
5
- # Or clone and run:
6
- # git clone https://github.com/eximIA-Ventures/claude-code-handoff.git /tmp/claude-code-handoff
7
- # cd /your/project && /tmp/claude-code-handoff/install.sh
2
+ # ═══════════════════════════════════════════════════════
3
+ # claude-code-handoff Installer
4
+ # Usage: curl -fsSL https://raw.githubusercontent.com/eximIA-Ventures/claude-code-handoff/main/install.sh | bash
5
+ # ═══════════════════════════════════════════════════════
8
6
 
9
7
  set -e
10
8
 
11
- # Colors
12
- GREEN='\033[0;32m'
13
- YELLOW='\033[1;33m'
14
- CYAN='\033[0;36m'
15
- NC='\033[0m'
9
+ # Colors (RGB)
10
+ AMBER='\033[38;2;245;158;11m'
11
+ GREEN='\033[38;2;16;185;129m'
12
+ RED='\033[38;2;239;68;68m'
13
+ CYAN='\033[38;2;34;211;238m'
14
+ WHITE='\033[37m'
15
+ GRAY='\033[90m'
16
+ BOLD='\033[1m'
17
+ DIM='\033[2m'
18
+ RESET='\033[0m'
16
19
 
17
20
  REPO="eximIA-Ventures/claude-code-handoff"
18
21
  BRANCH="main"
@@ -20,13 +23,19 @@ RAW_BASE="https://raw.githubusercontent.com/$REPO/$BRANCH"
20
23
  PROJECT_DIR="$(pwd)"
21
24
  CLAUDE_DIR="$PROJECT_DIR/.claude"
22
25
 
26
+ ok() { echo -e " ${GREEN}✓${RESET} $1"; }
27
+ fail() { echo -e " ${RED}✗${RESET} $1"; }
28
+ info() { echo -e " ${GRAY}$1${RESET}"; }
29
+ head() { echo -e "\n ${AMBER}${BOLD}$1${RESET}"; }
30
+
31
+ # ─── Banner ───────────────────────────────────────────
23
32
  echo ""
24
- echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
25
- echo -e "${CYAN} claude-code-handoff — Session Continuity${NC}"
26
- echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
27
- echo ""
28
- echo -e " Project: ${GREEN}$PROJECT_DIR${NC}"
33
+ echo -e " ${AMBER}${BOLD}┌──────────────────────────────────────┐${RESET}"
34
+ echo -e " ${AMBER}${BOLD}│${RESET} ${WHITE}${BOLD}claude-code-handoff${RESET} ${DIM}v1.9${RESET} ${AMBER}${BOLD}│${RESET}"
35
+ echo -e " ${AMBER}${BOLD}│${RESET} ${GRAY}Session Continuity for Claude Code${RESET} ${AMBER}${BOLD}│${RESET}"
36
+ echo -e " ${AMBER}${BOLD}└──────────────────────────────────────┘${RESET}"
29
37
  echo ""
38
+ info "Project: ${WHITE}$PROJECT_DIR${RESET}"
30
39
 
31
40
  # Detect if running from cloned repo or via curl
32
41
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}" 2>/dev/null)" 2>/dev/null && pwd 2>/dev/null || echo "")"
@@ -34,49 +43,61 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}" 2>/dev/null)" 2>/dev/null && pwd
34
43
  download_file() {
35
44
  local src="$1"
36
45
  local dst="$2"
37
-
38
- # If running from cloned repo, copy locally
39
46
  if [ -n "$SCRIPT_DIR" ] && [ -f "$SCRIPT_DIR/$src" ]; then
40
47
  cp "$SCRIPT_DIR/$src" "$dst"
41
48
  else
42
- # Download from GitHub
43
49
  curl -fsSL "$RAW_BASE/$src" -o "$dst"
44
50
  fi
45
51
  }
46
52
 
47
- # 1. Create directories
48
- echo -e " ${YELLOW}[1/10]${NC} Creating directories..."
53
+ # ─── Pre-flight ───────────────────────────────────────
54
+ head "Pre-flight"
55
+
56
+ # Detect reinstall
57
+ IS_REINSTALL=false
58
+ SAVED_THRESHOLD=""
59
+ SAVED_MAX_CONTEXT=""
60
+ if [ -f "$CLAUDE_DIR/hooks/context-monitor.sh" ]; then
61
+ IS_REINSTALL=true
62
+ SAVED_THRESHOLD=$(grep -oP 'CLAUDE_CONTEXT_THRESHOLD:-\K[0-9]+' "$CLAUDE_DIR/hooks/context-monitor.sh" 2>/dev/null || echo "")
63
+ SAVED_MAX_CONTEXT=$(grep -oP 'CLAUDE_MAX_CONTEXT:-\K[0-9]+' "$CLAUDE_DIR/hooks/context-monitor.sh" 2>/dev/null || echo "")
64
+ fi
65
+
66
+ if [ "$IS_REINSTALL" = true ]; then
67
+ info "Existing installation found. Upgrading..."
68
+ else
69
+ ok "Fresh install"
70
+ fi
71
+
72
+ # ─── Directories ──────────────────────────────────────
73
+ head "Creating directories"
74
+
49
75
  mkdir -p "$CLAUDE_DIR/commands"
50
76
  mkdir -p "$CLAUDE_DIR/rules"
51
77
  mkdir -p "$CLAUDE_DIR/hooks"
52
78
  mkdir -p "$CLAUDE_DIR/handoffs/archive"
79
+ ok "Directory structure created"
80
+
81
+ # ─── Commands ─────────────────────────────────────────
82
+ head "Installing commands"
53
83
 
54
- # 2. Download/copy commands
55
- echo -e " ${YELLOW}[2/10]${NC} Installing commands..."
56
84
  download_file "commands/resume.md" "$CLAUDE_DIR/commands/resume.md"
57
85
  download_file "commands/save-handoff.md" "$CLAUDE_DIR/commands/save-handoff.md"
58
86
  download_file "commands/switch-context.md" "$CLAUDE_DIR/commands/switch-context.md"
59
87
  download_file "commands/handoff.md" "$CLAUDE_DIR/commands/handoff.md"
60
88
  download_file "commands/delete-handoff.md" "$CLAUDE_DIR/commands/delete-handoff.md"
61
89
  download_file "commands/auto-handoff.md" "$CLAUDE_DIR/commands/auto-handoff.md"
90
+ ok "6 slash commands installed"
91
+
92
+ # ─── Rules ────────────────────────────────────────────
93
+ head "Installing rules"
62
94
 
63
- # 3. Download/copy rules
64
- echo -e " ${YELLOW}[3/10]${NC} Installing rules..."
65
95
  download_file "rules/session-continuity.md" "$CLAUDE_DIR/rules/session-continuity.md"
66
96
  download_file "rules/auto-handoff.md" "$CLAUDE_DIR/rules/auto-handoff.md"
97
+ ok "Behavioral rules installed"
67
98
 
68
- # 4. Install hooks (auto-handoff context monitor)
69
- echo -e " ${YELLOW}[4/10]${NC} Installing hooks..."
70
-
71
- # Detect reinstall: save user's custom settings before overwriting
72
- IS_REINSTALL=false
73
- SAVED_THRESHOLD=""
74
- SAVED_MAX_CONTEXT=""
75
- if [ -f "$CLAUDE_DIR/hooks/context-monitor.sh" ]; then
76
- IS_REINSTALL=true
77
- SAVED_THRESHOLD=$(grep -oP 'CLAUDE_CONTEXT_THRESHOLD:-\K[0-9]+' "$CLAUDE_DIR/hooks/context-monitor.sh" 2>/dev/null || echo "")
78
- SAVED_MAX_CONTEXT=$(grep -oP 'CLAUDE_MAX_CONTEXT:-\K[0-9]+' "$CLAUDE_DIR/hooks/context-monitor.sh" 2>/dev/null || echo "")
79
- fi
99
+ # ─── Hooks ────────────────────────────────────────────
100
+ head "Installing hooks"
80
101
 
81
102
  download_file "hooks/context-monitor.sh" "$CLAUDE_DIR/hooks/context-monitor.sh"
82
103
  download_file "hooks/session-cleanup.sh" "$CLAUDE_DIR/hooks/session-cleanup.sh"
@@ -84,30 +105,28 @@ chmod +x "$CLAUDE_DIR/hooks/context-monitor.sh"
84
105
  chmod +x "$CLAUDE_DIR/hooks/session-cleanup.sh"
85
106
 
86
107
  if [ "$IS_REINSTALL" = true ]; then
87
- # Restore user's custom settings
88
108
  if [ -n "$SAVED_THRESHOLD" ] && [ "$SAVED_THRESHOLD" != "90" ]; then
89
109
  sed -i.bak "s/CLAUDE_CONTEXT_THRESHOLD:-90/CLAUDE_CONTEXT_THRESHOLD:-${SAVED_THRESHOLD}/" "$CLAUDE_DIR/hooks/context-monitor.sh"
90
110
  rm -f "$CLAUDE_DIR/hooks/context-monitor.sh.bak"
91
- echo -e " Preserved threshold: ${CYAN}${SAVED_THRESHOLD}%${NC}"
111
+ ok "Preserved threshold: ${CYAN}${SAVED_THRESHOLD}%${RESET}"
92
112
  fi
93
113
  if [ -n "$SAVED_MAX_CONTEXT" ] && [ "$SAVED_MAX_CONTEXT" != "200000" ]; then
94
114
  sed -i.bak "s/CLAUDE_MAX_CONTEXT:-200000/CLAUDE_MAX_CONTEXT:-${SAVED_MAX_CONTEXT}/" "$CLAUDE_DIR/hooks/context-monitor.sh"
95
115
  rm -f "$CLAUDE_DIR/hooks/context-monitor.sh.bak"
96
- echo -e " Preserved max context: ${CYAN}${SAVED_MAX_CONTEXT} tokens${NC}"
116
+ ok "Preserved max context: ${CYAN}${SAVED_MAX_CONTEXT} tokens${RESET}"
97
117
  fi
98
- # Don't touch .auto-handoff-disabled — preserve user's on/off choice
99
- else
100
- # Fresh install: auto-handoff disabled by default (beta feature)
101
- touch "$CLAUDE_DIR/hooks/.auto-handoff-disabled"
102
118
  fi
103
119
 
104
- # 5. Configure hooks in settings.json
105
- echo -e " ${YELLOW}[5/10]${NC} Configuring hooks in settings.json..."
120
+ # Clean up legacy disabled flag
121
+ rm -f "$CLAUDE_DIR/hooks/.auto-handoff-disabled"
122
+ ok "Context monitor + session cleanup hooks"
123
+
124
+ # ─── Settings ─────────────────────────────────────────
125
+ head "Configuring settings.json"
126
+
106
127
  SETTINGS_FILE="$CLAUDE_DIR/settings.json"
107
128
  if [ -f "$SETTINGS_FILE" ]; then
108
- # Check if hooks already configured
109
129
  if ! grep -q "context-monitor" "$SETTINGS_FILE" 2>/dev/null; then
110
- # Merge hooks into existing settings.json using jq if available
111
130
  if command -v jq &>/dev/null; then
112
131
  HOOKS_JSON='{
113
132
  "hooks": {
@@ -116,22 +135,22 @@ if [ -f "$SETTINGS_FILE" ]; then
116
135
  }
117
136
  }'
118
137
  jq --argjson hooks "$(echo "$HOOKS_JSON" | jq '.hooks')" '. + {hooks: $hooks}' "$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" && mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE"
138
+ ok "Hooks added to existing settings.json"
119
139
  else
120
- # Fallback: rewrite settings.json preserving existing keys
121
- echo -e " ${YELLOW} ⚠ jq not found. Adding hooks config manually...${NC}"
122
- # Read existing content, strip trailing brace, append hooks
123
140
  EXISTING=$(cat "$SETTINGS_FILE")
124
- # Remove trailing } and whitespace
125
141
  EXISTING=$(echo "$EXISTING" | sed '$ s/}$//')
126
- cat > "$SETTINGS_FILE" << 'SETTINGSEOF'
142
+ LANG_SETTING=$(echo "$EXISTING" | grep '"language"' | head -1 | sed 's/,$//')
143
+ if [ -n "$LANG_SETTING" ]; then
144
+ cat > "$SETTINGS_FILE" << SETTINGSEOF
127
145
  {
146
+ ${LANG_SETTING},
128
147
  "hooks": {
129
148
  "Stop": [
130
149
  {
131
150
  "hooks": [
132
151
  {
133
152
  "type": "command",
134
- "command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh\"",
153
+ "command": "\"\$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh\"",
135
154
  "timeout": 10
136
155
  }
137
156
  ]
@@ -142,7 +161,7 @@ if [ -f "$SETTINGS_FILE" ]; then
142
161
  "hooks": [
143
162
  {
144
163
  "type": "command",
145
- "command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh\"",
164
+ "command": "\"\$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh\"",
146
165
  "timeout": 5
147
166
  }
148
167
  ]
@@ -151,21 +170,17 @@ if [ -f "$SETTINGS_FILE" ]; then
151
170
  }
152
171
  }
153
172
  SETTINGSEOF
154
- # Merge with original using jq-less approach: just add hooks key
155
- # Since we can't reliably merge JSON without jq, write a complete file
156
- # preserving the language setting if it exists
157
- LANG_SETTING=$(echo "$EXISTING" | grep '"language"' | head -1 | sed 's/,$//')
158
- if [ -n "$LANG_SETTING" ]; then
159
- cat > "$SETTINGS_FILE" << SETTINGSEOF
173
+ ok "Hooks added (preserved language setting)"
174
+ else
175
+ cat > "$SETTINGS_FILE" << 'SETTINGSEOF'
160
176
  {
161
- ${LANG_SETTING},
162
177
  "hooks": {
163
178
  "Stop": [
164
179
  {
165
180
  "hooks": [
166
181
  {
167
182
  "type": "command",
168
- "command": "\"\$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh\"",
183
+ "command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/context-monitor.sh\"",
169
184
  "timeout": 10
170
185
  }
171
186
  ]
@@ -176,7 +191,7 @@ SETTINGSEOF
176
191
  "hooks": [
177
192
  {
178
193
  "type": "command",
179
- "command": "\"\$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh\"",
194
+ "command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/session-cleanup.sh\"",
180
195
  "timeout": 5
181
196
  }
182
197
  ]
@@ -185,11 +200,13 @@ SETTINGSEOF
185
200
  }
186
201
  }
187
202
  SETTINGSEOF
203
+ ok "Hooks config written"
188
204
  fi
189
205
  fi
206
+ else
207
+ ok "Hooks already configured"
190
208
  fi
191
209
  else
192
- # Create new settings.json with hooks
193
210
  cat > "$SETTINGS_FILE" << 'SETTINGSEOF'
194
211
  {
195
212
  "hooks": {
@@ -218,11 +235,13 @@ else
218
235
  }
219
236
  }
220
237
  SETTINGSEOF
238
+ ok "settings.json created with hooks"
221
239
  fi
222
240
 
223
- # 6. Create initial _active.md if not exists
241
+ # ─── Handoff ──────────────────────────────────────────
242
+ head "Setting up handoff storage"
243
+
224
244
  if [ ! -f "$CLAUDE_DIR/handoffs/_active.md" ]; then
225
- echo -e " ${YELLOW}[6/10]${NC} Creating initial handoff..."
226
245
  cat > "$CLAUDE_DIR/handoffs/_active.md" << 'HANDOFF'
227
246
  # Session Handoff
228
247
 
@@ -249,33 +268,34 @@ if [ ! -f "$CLAUDE_DIR/handoffs/_active.md" ]; then
249
268
  ## Decisions Registry
250
269
  (none)
251
270
  HANDOFF
271
+ ok "Initial handoff template created"
252
272
  else
253
- echo -e " ${YELLOW}[6/10]${NC} Handoff already exists, keeping it"
273
+ ok "Existing handoff preserved"
254
274
  fi
255
275
 
256
- # 7. Add to .gitignore
257
- echo -e " ${YELLOW}[7/10]${NC} Updating .gitignore..."
276
+ # ─── Gitignore ────────────────────────────────────────
277
+ head "Updating .gitignore"
278
+
258
279
  GITIGNORE="$PROJECT_DIR/.gitignore"
259
280
  if [ -f "$GITIGNORE" ]; then
260
281
  if ! grep -q ".claude/handoffs/" "$GITIGNORE" 2>/dev/null; then
261
282
  echo "" >> "$GITIGNORE"
262
283
  echo "# claude-code-handoff (personal session state)" >> "$GITIGNORE"
263
284
  echo ".claude/handoffs/" >> "$GITIGNORE"
285
+ ok "Added .claude/handoffs/ to .gitignore"
286
+ else
287
+ ok "Already in .gitignore"
264
288
  fi
265
289
  else
266
290
  echo "# claude-code-handoff (personal session state)" > "$GITIGNORE"
267
291
  echo ".claude/handoffs/" >> "$GITIGNORE"
292
+ ok ".gitignore created"
268
293
  fi
269
294
 
270
- # 8. Add to CLAUDE.md
271
- echo -e " ${YELLOW}[8/10]${NC} Updating CLAUDE.md..."
272
- CLAUDE_MD="$CLAUDE_DIR/CLAUDE.md"
273
- CONTINUITY_BLOCK='## Session Continuity (MANDATORY)
274
-
275
- At the START of every session, read `.claude/handoffs/_active.md` to recover context from prior sessions.
276
- During work, update the handoff proactively after significant milestones.
277
- Use `/handoff` before `/clear`. Use `/resume` to pick up. Use `/switch-context <topic>` to switch workstreams.'
295
+ # ─── CLAUDE.md ────────────────────────────────────────
296
+ head "Updating CLAUDE.md"
278
297
 
298
+ CLAUDE_MD="$CLAUDE_DIR/CLAUDE.md"
279
299
  if [ -f "$CLAUDE_MD" ]; then
280
300
  if ! grep -q "Session Continuity" "$CLAUDE_MD" 2>/dev/null; then
281
301
  TEMP_FILE=$(mktemp)
@@ -295,6 +315,9 @@ if [ -f "$CLAUDE_MD" ]; then
295
315
  { print }
296
316
  ' "$CLAUDE_MD" > "$TEMP_FILE"
297
317
  mv "$TEMP_FILE" "$CLAUDE_MD"
318
+ ok "Session Continuity section added"
319
+ else
320
+ ok "Session Continuity already present"
298
321
  fi
299
322
  else
300
323
  cat > "$CLAUDE_MD" << 'CLAUDEMD'
@@ -306,10 +329,24 @@ At the START of every session, read `.claude/handoffs/_active.md` to recover con
306
329
  During work, update the handoff proactively after significant milestones.
307
330
  Use `/handoff` before `/clear`. Use `/resume` to pick up. Use `/switch-context <topic>` to switch workstreams.
308
331
  CLAUDEMD
332
+ ok "CLAUDE.md created"
309
333
  fi
310
334
 
311
- # 9. Summary
312
- echo -e " ${YELLOW}[9/10]${NC} Verifying installation..."
335
+ # ─── Legacy cleanup ──────────────────────────────────
336
+ CLEANED=0
337
+ for f in retomar.md salvar-handoff.md trocar-contexto.md auto-handoff-toggle.md; do
338
+ if [ -f "$CLAUDE_DIR/commands/$f" ]; then
339
+ rm -f "$CLAUDE_DIR/commands/$f"
340
+ CLEANED=$((CLEANED + 1))
341
+ fi
342
+ done
343
+ if [ "$CLEANED" -gt 0 ]; then
344
+ info "Removed $CLEANED legacy command(s)"
345
+ fi
346
+
347
+ # ─── Verify ───────────────────────────────────────────
348
+ head "Verifying"
349
+
313
350
  INSTALLED=0
314
351
  for f in resume.md save-handoff.md switch-context.md handoff.md delete-handoff.md auto-handoff.md; do
315
352
  [ -f "$CLAUDE_DIR/commands/$f" ] && INSTALLED=$((INSTALLED + 1))
@@ -318,31 +355,28 @@ HOOKS_OK=0
318
355
  [ -f "$CLAUDE_DIR/hooks/context-monitor.sh" ] && HOOKS_OK=$((HOOKS_OK + 1))
319
356
  [ -f "$CLAUDE_DIR/hooks/session-cleanup.sh" ] && HOOKS_OK=$((HOOKS_OK + 1))
320
357
 
321
- echo ""
322
- echo -e " ${YELLOW}[10/10]${NC} Done!"
323
- echo ""
324
358
  if [ "$INSTALLED" -eq 6 ] && [ "$HOOKS_OK" -eq 2 ]; then
325
- echo -e "${GREEN} Installed successfully! ($INSTALLED/6 commands, $HOOKS_OK/2 hooks)${NC}"
359
+ ok "${INSTALLED}/6 commands, ${HOOKS_OK}/2 hooks"
326
360
  else
327
- echo -e "${YELLOW} Partial install: $INSTALLED/6 commands, $HOOKS_OK/2 hooks${NC}"
361
+ fail "Partial: ${INSTALLED}/6 commands, ${HOOKS_OK}/2 hooks"
328
362
  fi
363
+
364
+ # ─── Done ─────────────────────────────────────────────
329
365
  echo ""
330
- echo -e " Commands available:"
331
- echo -e " ${CYAN}/handoff${NC} Auto-save session (no wizard)"
332
- echo -e " ${CYAN}/resume${NC} Resume with wizard"
333
- echo -e " ${CYAN}/save-handoff${NC} Save session state (wizard)"
334
- echo -e " ${CYAN}/switch-context${NC} Switch workstream"
335
- echo -e " ${CYAN}/delete-handoff${NC} Delete handoff(s)"
336
- echo -e " ${CYAN}/auto-handoff${NC} Toggle auto-handoff on/off"
366
+ echo -e " ${AMBER}${BOLD}════════════════════════════════════════${RESET}"
367
+ echo -e " ${GREEN}${BOLD} Installed successfully!${RESET}"
368
+ echo -e " ${AMBER}${BOLD}════════════════════════════════════════${RESET}"
337
369
  echo ""
338
- echo -e " Auto-handoff: ${YELLOW}(beta — disabled by default)${NC}"
339
- echo -e " Use ${CYAN}/auto-handoff${NC} to enable and configure threshold"
370
+ echo -e " ${WHITE}${BOLD}Commands:${RESET}"
371
+ echo -e " ${CYAN}/handoff${RESET} ${GRAY}Auto-save session${RESET}"
372
+ echo -e " ${CYAN}/resume${RESET} ${GRAY}Resume with wizard${RESET}"
373
+ echo -e " ${CYAN}/save-handoff${RESET} ${GRAY}Save with options${RESET}"
374
+ echo -e " ${CYAN}/switch-context${RESET} ${GRAY}Switch workstream${RESET}"
375
+ echo -e " ${CYAN}/delete-handoff${RESET} ${GRAY}Delete handoff(s)${RESET}"
376
+ echo -e " ${CYAN}/auto-handoff${RESET} ${GRAY}Toggle auto-handoff${RESET}"
340
377
  echo ""
341
- echo -e " Files:"
342
- echo -e " .claude/commands/ 6 command files"
343
- echo -e " .claude/rules/ session-continuity.md, auto-handoff.md"
344
- echo -e " .claude/hooks/ context-monitor.sh, session-cleanup.sh"
345
- echo -e " .claude/handoffs/ session state (gitignored)"
378
+ echo -e " ${WHITE}${BOLD}Auto-handoff:${RESET} ${DIM}beta — disabled by default${RESET}"
379
+ echo -e " ${GRAY}Run ${CYAN}/auto-handoff${GRAY} inside Claude Code to enable${RESET}"
346
380
  echo ""
347
- echo -e " ${YELLOW}Start Claude Code and use /resume to begin.${NC}"
381
+ echo -e " ${DIM}Start Claude Code and use ${WHITE}/resume${DIM} to begin.${RESET}"
348
382
  echo ""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-handoff",
3
- "version": "1.8.1",
3
+ "version": "2.0.0",
4
4
  "description": "Session continuity for Claude Code — 6 slash commands to save, resume, delete, and switch workstreams across /clear",
5
5
  "bin": {
6
6
  "claude-code-handoff": "./cli.js"
package/uninstall.sh CHANGED
@@ -50,6 +50,7 @@ rm -f "$CLAUDE_DIR/rules/auto-handoff.md"
50
50
  echo -e " ${YELLOW}[3/6]${NC} Removing hooks..."
51
51
  rm -f "$CLAUDE_DIR/hooks/context-monitor.sh"
52
52
  rm -f "$CLAUDE_DIR/hooks/session-cleanup.sh"
53
+ rm -f "$CLAUDE_DIR/hooks/.auto-handoff-enabled"
53
54
  rm -f "$CLAUDE_DIR/hooks/.auto-handoff-disabled"
54
55
  rmdir "$CLAUDE_DIR/hooks" 2>/dev/null || true
55
56