claude-code-kanban 2.1.0-rc.3 → 2.1.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/install.js +78 -12
- package/package.json +1 -1
package/install.js
CHANGED
|
@@ -45,7 +45,27 @@ function prompt(question) {
|
|
|
45
45
|
async function runInstall() {
|
|
46
46
|
console.log(`\n ${bold('claude-code-kanban')} — Agent Log hook installer\n`);
|
|
47
47
|
|
|
48
|
-
// 1. Check
|
|
48
|
+
// 1. Check bash
|
|
49
|
+
process.stdout.write(' Checking bash... ');
|
|
50
|
+
try {
|
|
51
|
+
const bashPath = execSync('which bash', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
52
|
+
console.log(green(`✓ found (${bashPath})`));
|
|
53
|
+
} catch {
|
|
54
|
+
const shell = process.env.SHELL || process.env.BASH || '';
|
|
55
|
+
if (shell.includes('bash')) {
|
|
56
|
+
console.log(green(`✓ found via $SHELL (${shell})`));
|
|
57
|
+
} else {
|
|
58
|
+
const currentShell = shell || process.env.ComSpec || 'unknown';
|
|
59
|
+
console.log(yellow(`⚠ bash not found (current shell: ${currentShell})`));
|
|
60
|
+
console.log(` ${dim('Hook scripts use #!/bin/bash and require a bash environment')}`);
|
|
61
|
+
if (!(await prompt(` Continue anyway? [Y/n] `))) {
|
|
62
|
+
console.log(`\n ${dim('Install cancelled.')}\n`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 2. Check jq
|
|
49
69
|
process.stdout.write(' Checking jq... ');
|
|
50
70
|
try {
|
|
51
71
|
const ver = execSync('jq --version', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
@@ -84,15 +104,11 @@ async function runInstall() {
|
|
|
84
104
|
return false;
|
|
85
105
|
}
|
|
86
106
|
|
|
87
|
-
//
|
|
107
|
+
// 3. Hook scripts
|
|
88
108
|
const hookInstalled = await installScript('Hook script', HOOK_SCRIPT_SRC, HOOK_SCRIPT_DEST);
|
|
89
109
|
const ctxInstalled = await installScript('Context spy', CTX_SCRIPT_SRC, CTX_SCRIPT_DEST);
|
|
90
|
-
if (ctxInstalled) {
|
|
91
|
-
console.log(`\n ${yellow('To enable context tracking, pipe it before your statusline:')}`);
|
|
92
|
-
console.log(` ${dim('"statusLine": { "command": "~/.claude/hooks/context-status.sh | <your-statusline>" }')}`);
|
|
93
|
-
}
|
|
94
110
|
|
|
95
|
-
//
|
|
111
|
+
// 4. Settings.json
|
|
96
112
|
console.log(`\n Settings: ${dim(SETTINGS_PATH)}`);
|
|
97
113
|
let settings;
|
|
98
114
|
try {
|
|
@@ -141,6 +157,38 @@ async function runInstall() {
|
|
|
141
157
|
}
|
|
142
158
|
}
|
|
143
159
|
|
|
160
|
+
// 5. StatusLine setup (separate approval)
|
|
161
|
+
const CTX_COMMAND = '~/.claude/hooks/context-status.sh';
|
|
162
|
+
let statusLineUpdated = false;
|
|
163
|
+
if (ctxInstalled) {
|
|
164
|
+
const hasCtx = settings.statusLine?.command?.includes('context-status.sh');
|
|
165
|
+
if (hasCtx) {
|
|
166
|
+
console.log(`\n StatusLine: ${green('✓')} Already configured`);
|
|
167
|
+
statusLineUpdated = true;
|
|
168
|
+
} else if (!settings.statusLine) {
|
|
169
|
+
console.log(`\n StatusLine: ${dim('not configured')}`);
|
|
170
|
+
if (await prompt(` Set up context tracking statusline? [Y/n] `)) {
|
|
171
|
+
settings.statusLine = { command: CTX_COMMAND };
|
|
172
|
+
fs.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + '\n');
|
|
173
|
+
console.log(` ${green('✓')} StatusLine configured`);
|
|
174
|
+
statusLineUpdated = true;
|
|
175
|
+
} else {
|
|
176
|
+
console.log(` ${dim('Skipped')}`);
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
const existing = settings.statusLine.command;
|
|
180
|
+
console.log(`\n StatusLine: ${dim(`current: ${existing}`)}`);
|
|
181
|
+
if (await prompt(` Prepend context spy to existing statusline? [Y/n] `)) {
|
|
182
|
+
settings.statusLine.command = `${CTX_COMMAND} | ${existing}`;
|
|
183
|
+
fs.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + '\n');
|
|
184
|
+
console.log(` ${green('✓')} StatusLine updated`);
|
|
185
|
+
statusLineUpdated = true;
|
|
186
|
+
} else {
|
|
187
|
+
console.log(` ${dim('Skipped')}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
144
192
|
printSummary(hookInstalled, settingsUpdated);
|
|
145
193
|
}
|
|
146
194
|
|
|
@@ -161,20 +209,38 @@ async function runUninstall() {
|
|
|
161
209
|
if (fs.existsSync(SETTINGS_PATH)) {
|
|
162
210
|
try {
|
|
163
211
|
const settings = JSON.parse(fs.readFileSync(SETTINGS_PATH, 'utf8'));
|
|
212
|
+
let removed = 0;
|
|
164
213
|
if (settings.hooks) {
|
|
165
|
-
let removed = 0;
|
|
166
214
|
const eventNames = [...new Set(HOOK_EVENTS.map(e => e.event))];
|
|
167
215
|
for (const event of eventNames) {
|
|
168
216
|
if (!Array.isArray(settings.hooks[event])) continue;
|
|
169
217
|
const before = settings.hooks[event].length;
|
|
170
|
-
settings.hooks[event] = settings.hooks[event].
|
|
171
|
-
!g.hooks?.some(h => h.command === HOOK_COMMAND)
|
|
172
|
-
|
|
218
|
+
settings.hooks[event] = settings.hooks[event].map(g => {
|
|
219
|
+
if (!g.hooks?.some(h => h.command === HOOK_COMMAND)) return g;
|
|
220
|
+
const filtered = g.hooks.filter(h => h.command !== HOOK_COMMAND);
|
|
221
|
+
return filtered.length > 0 ? { ...g, hooks: filtered } : null;
|
|
222
|
+
}).filter(Boolean);
|
|
173
223
|
removed += before - settings.hooks[event].length;
|
|
174
224
|
if (settings.hooks[event].length === 0) delete settings.hooks[event];
|
|
175
225
|
}
|
|
176
226
|
if (Object.keys(settings.hooks).length === 0) delete settings.hooks;
|
|
177
|
-
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Strip context-status.sh from statusLine, restore downstream command if any
|
|
230
|
+
if (settings.statusLine?.command?.includes('context-status.sh')) {
|
|
231
|
+
const cmd = settings.statusLine.command;
|
|
232
|
+
const stripped = cmd.replace(/~\/\.claude\/hooks\/context-status\.sh\s*\|\s*/, '').trim();
|
|
233
|
+
if (stripped && stripped !== cmd) {
|
|
234
|
+
settings.statusLine.command = stripped;
|
|
235
|
+
console.log(` StatusLine: ${green('✓')} Restored to "${stripped}"`);
|
|
236
|
+
} else {
|
|
237
|
+
delete settings.statusLine;
|
|
238
|
+
console.log(` StatusLine: ${green('✓')} Removed`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
fs.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + '\n');
|
|
243
|
+
if (removed > 0) {
|
|
178
244
|
console.log(` Settings: ${green('✓')} Removed ${removed} hook entries`);
|
|
179
245
|
} else {
|
|
180
246
|
console.log(` Settings: ${dim('No hook entries found')}`);
|