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.
Files changed (2) hide show
  1. package/install.js +78 -12
  2. 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 jq
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
- // 2. Hook scripts
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
- // 3. Settings.json
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].filter(g =>
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
- fs.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + '\n');
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')}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-kanban",
3
- "version": "2.1.0-rc.3",
3
+ "version": "2.1.0",
4
4
  "description": "A web-based Kanban board for viewing Claude Code tasks with agent teams support",
5
5
  "main": "server.js",
6
6
  "bin": {