kanban 0.1.4 → 0.1.5

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 (92) hide show
  1. package/README.md +19 -0
  2. package/dist/cli.js +102 -11
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config/runtime-config.d.ts +3 -3
  5. package/dist/config/runtime-config.d.ts.map +1 -1
  6. package/dist/config/runtime-config.js +17 -18
  7. package/dist/config/runtime-config.js.map +1 -1
  8. package/dist/config/shortcut-utils.d.ts.map +1 -1
  9. package/dist/config/shortcut-utils.js +1 -2
  10. package/dist/config/shortcut-utils.js.map +1 -1
  11. package/dist/core/agent-catalog.d.ts.map +1 -1
  12. package/dist/core/agent-catalog.js +8 -0
  13. package/dist/core/agent-catalog.js.map +1 -1
  14. package/dist/core/api-contract.d.ts +27 -50
  15. package/dist/core/api-contract.d.ts.map +1 -1
  16. package/dist/core/api-contract.js +5 -23
  17. package/dist/core/api-contract.js.map +1 -1
  18. package/dist/core/api-validation.d.ts +2 -2
  19. package/dist/core/api-validation.d.ts.map +1 -1
  20. package/dist/core/api-validation.js +4 -4
  21. package/dist/core/api-validation.js.map +1 -1
  22. package/dist/core/runtime-endpoint.d.ts +6 -3
  23. package/dist/core/runtime-endpoint.d.ts.map +1 -1
  24. package/dist/core/runtime-endpoint.js +19 -7
  25. package/dist/core/runtime-endpoint.js.map +1 -1
  26. package/dist/mcp/server.d.ts.map +1 -1
  27. package/dist/mcp/server.js +2 -3
  28. package/dist/mcp/server.js.map +1 -1
  29. package/dist/server/runtime-server.d.ts +2 -2
  30. package/dist/server/runtime-server.d.ts.map +1 -1
  31. package/dist/server/runtime-server.js +7 -6
  32. package/dist/server/runtime-server.js.map +1 -1
  33. package/dist/server/runtime-state-hub.d.ts.map +1 -1
  34. package/dist/server/runtime-state-hub.js +0 -68
  35. package/dist/server/runtime-state-hub.js.map +1 -1
  36. package/dist/terminal/agent-registry.js +5 -5
  37. package/dist/terminal/agent-registry.js.map +1 -1
  38. package/dist/terminal/agent-session-adapters.d.ts +3 -0
  39. package/dist/terminal/agent-session-adapters.d.ts.map +1 -1
  40. package/dist/terminal/agent-session-adapters.js +63 -1
  41. package/dist/terminal/agent-session-adapters.js.map +1 -1
  42. package/dist/terminal/claude-workspace-trust.d.ts +0 -2
  43. package/dist/terminal/claude-workspace-trust.d.ts.map +1 -1
  44. package/dist/terminal/claude-workspace-trust.js +0 -5
  45. package/dist/terminal/claude-workspace-trust.js.map +1 -1
  46. package/dist/terminal/pty-session.d.ts +35 -0
  47. package/dist/terminal/pty-session.d.ts.map +1 -0
  48. package/dist/terminal/pty-session.js +88 -0
  49. package/dist/terminal/pty-session.js.map +1 -0
  50. package/dist/terminal/session-manager.d.ts +5 -8
  51. package/dist/terminal/session-manager.d.ts.map +1 -1
  52. package/dist/terminal/session-manager.js +182 -275
  53. package/dist/terminal/session-manager.js.map +1 -1
  54. package/dist/terminal/slash-commands.d.ts.map +1 -1
  55. package/dist/terminal/slash-commands.js +17 -0
  56. package/dist/terminal/slash-commands.js.map +1 -1
  57. package/dist/terminal/terminal-session-service.d.ts +15 -0
  58. package/dist/terminal/terminal-session-service.d.ts.map +1 -0
  59. package/dist/terminal/terminal-session-service.js +2 -0
  60. package/dist/terminal/terminal-session-service.js.map +1 -0
  61. package/dist/terminal/ws-server.d.ts +5 -4
  62. package/dist/terminal/ws-server.d.ts.map +1 -1
  63. package/dist/terminal/ws-server.js +171 -44
  64. package/dist/terminal/ws-server.js.map +1 -1
  65. package/dist/trpc/app-router.d.ts +19 -29
  66. package/dist/trpc/app-router.d.ts.map +1 -1
  67. package/dist/trpc/app-router.js +5 -5
  68. package/dist/trpc/app-router.js.map +1 -1
  69. package/dist/trpc/runtime-api.d.ts +2 -2
  70. package/dist/trpc/runtime-api.d.ts.map +1 -1
  71. package/dist/trpc/runtime-api.js +5 -4
  72. package/dist/trpc/runtime-api.js.map +1 -1
  73. package/dist/trpc/workspace-api.js +2 -2
  74. package/dist/trpc/workspace-api.js.map +1 -1
  75. package/dist/web-ui/assets/{allPaths-hQZnjS_p.js → allPaths-CdLm57A0.js} +1 -1
  76. package/dist/web-ui/assets/allPathsLoader-FKnSZCTb.js +2 -0
  77. package/dist/web-ui/assets/index-BDb_xXnu.css +32 -0
  78. package/dist/web-ui/assets/index-CL-DaDRu.js +296 -0
  79. package/dist/web-ui/assets/{splitPathsBySizeLoader-CWXI7LLN.js → splitPathsBySizeLoader-BBFjPIdp.js} +1 -1
  80. package/dist/web-ui/index.html +2 -2
  81. package/dist/workspace/task-worktree.d.ts +1 -1
  82. package/dist/workspace/task-worktree.d.ts.map +1 -1
  83. package/dist/workspace/task-worktree.js +112 -13
  84. package/dist/workspace/task-worktree.js.map +1 -1
  85. package/package.json +2 -1
  86. package/dist/terminal/activity-preview.d.ts +0 -8
  87. package/dist/terminal/activity-preview.d.ts.map +0 -1
  88. package/dist/terminal/activity-preview.js +0 -495
  89. package/dist/terminal/activity-preview.js.map +0 -1
  90. package/dist/web-ui/assets/allPathsLoader-BZV0v7Fb.js +0 -2
  91. package/dist/web-ui/assets/index-Cb9WHKOt.css +0 -32
  92. package/dist/web-ui/assets/index-CwJtdBqQ.js +0 -159
package/README.md CHANGED
@@ -48,6 +48,25 @@ Use MCP to let the agent add and start tasks on the kanban board itself, decompo
48
48
  claude mcp add --transport stdio --scope user kanban -- kanban mcp
49
49
  ```
50
50
 
51
+ <details>
52
+ <summary>Using Cline?</summary>
53
+
54
+ Add this to your `~/.cline/data/settings/cline_mcp_settings.json`:
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "kanban": {
60
+ "command": "kanban",
61
+ "args": ["mcp"],
62
+ "transportType": "stdio"
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ </details>
69
+
51
70
  With the MCP tools, your agent can:
52
71
 
53
72
  - `list_tasks`: see what's on the board, including task links and auto-review settings
package/dist/cli.js CHANGED
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { spawn, spawnSync } from "node:child_process";
3
3
  import { stat } from "node:fs/promises";
4
+ import { createServer as createNetServer } from "node:net";
4
5
  import packageJson from "../package.json" with { type: "json" };
5
6
  import { isHooksSubcommand, runHooksSubcommand } from "./commands/hooks.js";
6
7
  import { isMcpSubcommand, runMcpSubcommand } from "./commands/mcp.js";
7
8
  import { loadRuntimeConfig, updateRuntimeConfig } from "./config/runtime-config.js";
8
9
  import { createGitProcessEnv } from "./core/git-process-env.js";
9
10
  import { resolveProjectInputPath } from "./projects/project-path.js";
10
- import { buildKanbanRuntimeUrl, KANBAN_RUNTIME_ORIGIN, } from "./core/runtime-endpoint.js";
11
+ import { buildKanbanRuntimeUrl, DEFAULT_KANBAN_RUNTIME_PORT, getKanbanRuntimePort, getKanbanRuntimeOrigin, parseRuntimePort, setKanbanRuntimePort, } from "./core/runtime-endpoint.js";
11
12
  import { openInBrowser } from "./server/browser.js";
12
13
  import { createRuntimeStateHub } from "./server/runtime-state-hub.js";
13
14
  import { createRuntimeServer } from "./server/runtime-server.js";
@@ -16,7 +17,7 @@ import { resolveInteractiveShellCommand } from "./server/shell.js";
16
17
  import { loadWorkspaceContext, } from "./state/workspace-state.js";
17
18
  import { collectProjectWorktreeTaskIdsForRemoval, createWorkspaceRegistry, } from "./server/workspace-registry.js";
18
19
  import { autoUpdateOnStartup } from "./update/auto-update.js";
19
- const CLI_AGENT_IDS = ["claude", "codex", "gemini", "opencode", "cline"];
20
+ const CLI_AGENT_IDS = ["claude", "codex", "gemini", "opencode", "droid", "cline"];
20
21
  const KANBAN_VERSION = typeof packageJson.version === "string" ? packageJson.version : "0.1.0";
21
22
  function parseCliAgentId(value) {
22
23
  const normalized = value.trim().toLowerCase();
@@ -24,16 +25,33 @@ function parseCliAgentId(value) {
24
25
  normalized === "codex" ||
25
26
  normalized === "gemini" ||
26
27
  normalized === "opencode" ||
28
+ normalized === "droid" ||
27
29
  normalized === "cline") {
28
30
  return normalized;
29
31
  }
30
32
  throw new Error(`Invalid agent: ${value}. Expected one of: ${CLI_AGENT_IDS.join(", ")}`);
31
33
  }
34
+ function parseCliPortValue(rawValue) {
35
+ const normalized = rawValue.trim().toLowerCase();
36
+ if (!normalized) {
37
+ throw new Error("Missing value for --port.");
38
+ }
39
+ if (normalized === "auto") {
40
+ return { mode: "auto" };
41
+ }
42
+ try {
43
+ return { mode: "fixed", value: parseRuntimePort(normalized) };
44
+ }
45
+ catch {
46
+ throw new Error(`Invalid port value: ${rawValue}. Expected an integer from 1-65535 or "auto".`);
47
+ }
48
+ }
32
49
  function parseCliOptions(argv) {
33
50
  let help = false;
34
51
  let version = false;
35
52
  let noOpen = false;
36
53
  let agent = null;
54
+ let port = null;
37
55
  for (let index = 0; index < argv.length; index += 1) {
38
56
  const arg = argv[index];
39
57
  if (arg === "--help" || arg === "-h") {
@@ -63,21 +81,71 @@ function parseCliOptions(argv) {
63
81
  throw new Error("Missing value for --agent.");
64
82
  }
65
83
  agent = parseCliAgentId(value);
84
+ continue;
85
+ }
86
+ if (arg === "--port") {
87
+ const value = argv[index + 1];
88
+ if (!value) {
89
+ throw new Error("Missing value for --port.");
90
+ }
91
+ port = parseCliPortValue(value);
92
+ index += 1;
93
+ continue;
94
+ }
95
+ if (arg.startsWith("--port=")) {
96
+ const value = arg.slice("--port=".length);
97
+ if (!value) {
98
+ throw new Error("Missing value for --port.");
99
+ }
100
+ port = parseCliPortValue(value);
66
101
  }
67
102
  }
68
- return { help, version, noOpen, agent };
103
+ return { help, version, noOpen, agent, port };
69
104
  }
70
105
  function printHelp() {
71
106
  console.log("kanban");
72
107
  console.log("Local orchestration board for coding agents.");
73
108
  console.log("");
74
109
  console.log("Usage:");
75
- console.log(" kanban [--agent <id>] [--no-open] [--help] [--version]");
110
+ console.log(" kanban [--agent <id>] [--port <number|auto>] [--no-open] [--help] [--version]");
76
111
  console.log(" kanban mcp");
77
112
  console.log("");
78
- console.log(`Runtime URL: ${KANBAN_RUNTIME_ORIGIN}`);
113
+ console.log(`Runtime URL: ${getKanbanRuntimeOrigin()}`);
79
114
  console.log(`Agent IDs: ${CLI_AGENT_IDS.join(", ")}`);
80
115
  }
116
+ async function isPortAvailable(port) {
117
+ return await new Promise((resolve) => {
118
+ const probe = createNetServer();
119
+ probe.once("error", () => {
120
+ resolve(false);
121
+ });
122
+ probe.listen(port, "127.0.0.1", () => {
123
+ probe.close(() => {
124
+ resolve(true);
125
+ });
126
+ });
127
+ });
128
+ }
129
+ async function findAvailableRuntimePort(startPort) {
130
+ for (let candidate = startPort; candidate <= 65535; candidate += 1) {
131
+ if (await isPortAvailable(candidate)) {
132
+ return candidate;
133
+ }
134
+ }
135
+ throw new Error("No available runtime port found.");
136
+ }
137
+ async function applyRuntimePortOption(portOption) {
138
+ if (!portOption) {
139
+ return null;
140
+ }
141
+ if (portOption.mode === "fixed") {
142
+ setKanbanRuntimePort(portOption.value);
143
+ return portOption.value;
144
+ }
145
+ const autoPort = await findAvailableRuntimePort(DEFAULT_KANBAN_RUNTIME_PORT);
146
+ setKanbanRuntimePort(autoPort);
147
+ return autoPort;
148
+ }
81
149
  async function persistCliAgentSelection(cwd, selectedAgentId) {
82
150
  const currentRuntimeConfig = await loadRuntimeConfig(cwd);
83
151
  if (currentRuntimeConfig.selectedAgentId === selectedAgentId) {
@@ -174,8 +242,8 @@ async function tryOpenExistingServer(noOpen) {
174
242
  }
175
243
  const projectUrl = workspaceId
176
244
  ? buildKanbanRuntimeUrl(`/${encodeURIComponent(workspaceId)}`)
177
- : KANBAN_RUNTIME_ORIGIN;
178
- console.log(`Kanban already running at ${KANBAN_RUNTIME_ORIGIN}`);
245
+ : getKanbanRuntimeOrigin();
246
+ console.log(`Kanban already running at ${getKanbanRuntimeOrigin()}`);
179
247
  if (!noOpen) {
180
248
  try {
181
249
  openInBrowser(projectUrl);
@@ -188,7 +256,7 @@ async function tryOpenExistingServer(noOpen) {
188
256
  console.log(`Project URL: ${projectUrl}`);
189
257
  return true;
190
258
  }
191
- async function runShortcutCommand(command, cwd) {
259
+ async function runScopedCommand(command, cwd) {
192
260
  const startedAt = Date.now();
193
261
  const outputLimitBytes = 64 * 1024;
194
262
  return await new Promise((resolve, reject) => {
@@ -270,7 +338,7 @@ async function startServer() {
270
338
  },
271
339
  ensureTerminalManagerForWorkspace: workspaceRegistry.ensureTerminalManagerForWorkspace,
272
340
  resolveInteractiveShellCommand,
273
- runShortcutCommand,
341
+ runCommand: runScopedCommand,
274
342
  resolveProjectInputPath,
275
343
  assertPathIsDirectory,
276
344
  hasGitRepository,
@@ -296,6 +364,25 @@ async function startServer() {
296
364
  shutdown,
297
365
  };
298
366
  }
367
+ async function startServerWithAutoPortRetry(options) {
368
+ if (options.port?.mode !== "auto") {
369
+ return await startServer();
370
+ }
371
+ while (true) {
372
+ try {
373
+ return await startServer();
374
+ }
375
+ catch (error) {
376
+ if (!isAddressInUseError(error)) {
377
+ throw error;
378
+ }
379
+ const currentPort = getKanbanRuntimePort();
380
+ const retryPort = await findAvailableRuntimePort(currentPort + 1);
381
+ setKanbanRuntimePort(retryPort);
382
+ console.warn(`Runtime port ${currentPort} became busy during startup, retrying on ${retryPort}.`);
383
+ }
384
+ }
385
+ }
299
386
  async function run() {
300
387
  const argv = process.argv.slice(2);
301
388
  if (isMcpSubcommand(argv)) {
@@ -315,6 +402,10 @@ async function run() {
315
402
  console.log(KANBAN_VERSION);
316
403
  return;
317
404
  }
405
+ const selectedPort = await applyRuntimePortOption(options.port);
406
+ if (selectedPort !== null) {
407
+ console.log(`Using runtime port ${selectedPort}.`);
408
+ }
318
409
  autoUpdateOnStartup({
319
410
  currentVersion: KANBAN_VERSION,
320
411
  });
@@ -326,10 +417,10 @@ async function run() {
326
417
  }
327
418
  let runtime;
328
419
  try {
329
- runtime = await startServer();
420
+ runtime = await startServerWithAutoPortRetry(options);
330
421
  }
331
422
  catch (error) {
332
- if (isAddressInUseError(error) && (await tryOpenExistingServer(options.noOpen))) {
423
+ if (options.port?.mode !== "auto" && isAddressInUseError(error) && (await tryOpenExistingServer(options.noOpen))) {
333
424
  return;
334
425
  }
335
426
  throw error;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { stat } from \"node:fs/promises\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nimport { isHooksSubcommand, runHooksSubcommand } from \"./commands/hooks.js\";\nimport { isMcpSubcommand, runMcpSubcommand } from \"./commands/mcp.js\";\nimport type {\n\tRuntimeAgentId,\n\tRuntimeShortcutRunResponse,\n} from \"./core/api-contract.js\";\nimport { loadRuntimeConfig, updateRuntimeConfig } from \"./config/runtime-config.js\";\nimport { createGitProcessEnv } from \"./core/git-process-env.js\";\nimport { resolveProjectInputPath } from \"./projects/project-path.js\";\nimport {\n\tbuildKanbanRuntimeUrl,\n\tKANBAN_RUNTIME_ORIGIN,\n} from \"./core/runtime-endpoint.js\";\nimport { openInBrowser } from \"./server/browser.js\";\nimport { createRuntimeStateHub } from \"./server/runtime-state-hub.js\";\nimport { createRuntimeServer } from \"./server/runtime-server.js\";\nimport { shutdownRuntimeServer } from \"./server/shutdown-coordinator.js\";\nimport { resolveInteractiveShellCommand } from \"./server/shell.js\";\nimport {\n\tloadWorkspaceContext,\n} from \"./state/workspace-state.js\";\nimport {\n\tcollectProjectWorktreeTaskIdsForRemoval,\n\tcreateWorkspaceRegistry,\n} from \"./server/workspace-registry.js\";\nimport type { TerminalSessionManager } from \"./terminal/session-manager.js\";\nimport { autoUpdateOnStartup } from \"./update/auto-update.js\";\n\ninterface CliOptions {\n\thelp: boolean;\n\tversion: boolean;\n\tnoOpen: boolean;\n\tagent: RuntimeAgentId | null;\n}\n\nconst CLI_AGENT_IDS: readonly RuntimeAgentId[] = [\"claude\", \"codex\", \"gemini\", \"opencode\", \"cline\"];\nconst KANBAN_VERSION = typeof packageJson.version === \"string\" ? packageJson.version : \"0.1.0\";\n\nfunction parseCliAgentId(value: string): RuntimeAgentId {\n\tconst normalized = value.trim().toLowerCase();\n\tif (\n\t\tnormalized === \"claude\" ||\n\t\tnormalized === \"codex\" ||\n\t\tnormalized === \"gemini\" ||\n\t\tnormalized === \"opencode\" ||\n\t\tnormalized === \"cline\"\n\t) {\n\t\treturn normalized;\n\t}\n\tthrow new Error(`Invalid agent: ${value}. Expected one of: ${CLI_AGENT_IDS.join(\", \")}`);\n}\n\nfunction parseCliOptions(argv: string[]): CliOptions {\n\tlet help = false;\n\tlet version = false;\n\tlet noOpen = false;\n\tlet agent: RuntimeAgentId | null = null;\n\n\tfor (let index = 0; index < argv.length; index += 1) {\n\t\tconst arg = argv[index];\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\thelp = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--version\" || arg === \"-v\") {\n\t\t\tversion = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--no-open\") {\n\t\t\tnoOpen = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--agent\") {\n\t\t\tconst value = argv[index + 1];\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --agent.\");\n\t\t\t}\n\t\t\tagent = parseCliAgentId(value);\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--agent=\")) {\n\t\t\tconst value = arg.slice(\"--agent=\".length);\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --agent.\");\n\t\t\t}\n\t\t\tagent = parseCliAgentId(value);\n\t\t}\n\t}\n\n\treturn { help, version, noOpen, agent };\n}\n\nfunction printHelp(): void {\n\tconsole.log(\"kanban\");\n\tconsole.log(\"Local orchestration board for coding agents.\");\n\tconsole.log(\"\");\n\tconsole.log(\"Usage:\");\n\tconsole.log(\" kanban [--agent <id>] [--no-open] [--help] [--version]\");\n\tconsole.log(\" kanban mcp\");\n\tconsole.log(\"\");\n\tconsole.log(`Runtime URL: ${KANBAN_RUNTIME_ORIGIN}`);\n\tconsole.log(`Agent IDs: ${CLI_AGENT_IDS.join(\", \")}`);\n}\n\nasync function persistCliAgentSelection(cwd: string, selectedAgentId: RuntimeAgentId): Promise<boolean> {\n\tconst currentRuntimeConfig = await loadRuntimeConfig(cwd);\n\tif (currentRuntimeConfig.selectedAgentId === selectedAgentId) {\n\t\treturn false;\n\t}\n\tawait updateRuntimeConfig(cwd, { selectedAgentId });\n\treturn true;\n}\n\nasync function assertPathIsDirectory(path: string): Promise<void> {\n\tconst info = await stat(path);\n\tif (!info.isDirectory()) {\n\t\tthrow new Error(`Project path is not a directory: ${path}`);\n\t}\n}\n\nasync function pathIsDirectory(path: string): Promise<boolean> {\n\ttry {\n\t\tconst info = await stat(path);\n\t\treturn info.isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction hasGitRepository(path: string): boolean {\n\tconst result = spawnSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n\t\tcwd: path,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\tenv: createGitProcessEnv(),\n\t});\n\treturn result.status === 0 && result.stdout.trim() === \"true\";\n}\n\nfunction pickDirectoryPathFromSystemDialog(): string | null {\n\tif (process.platform === \"darwin\") {\n\t\tconst result = spawnSync(\n\t\t\t\"osascript\",\n\t\t\t[\"-e\", 'POSIX path of (choose folder with prompt \"Select a project folder\")'],\n\t\t\t{\n\t\t\t\tencoding: \"utf8\",\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t},\n\t\t);\n\t\tif (result.status !== 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst selected = typeof result.stdout === \"string\" ? result.stdout.trim() : \"\";\n\t\treturn selected || null;\n\t}\n\n\tif (process.platform === \"linux\") {\n\t\tconst result = spawnSync(\"zenity\", [\"--file-selection\", \"--directory\", \"--title=Select project folder\"], {\n\t\t\tencoding: \"utf8\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tif (result.status !== 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst selected = typeof result.stdout === \"string\" ? result.stdout.trim() : \"\";\n\t\treturn selected || null;\n\t}\n\n\treturn null;\n}\n\n\nfunction isAddressInUseError(error: unknown): error is NodeJS.ErrnoException {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error as NodeJS.ErrnoException).code === \"EADDRINUSE\"\n\t);\n}\n\nasync function canReachKanbanServer(workspaceId: string | null): Promise<boolean> {\n\ttry {\n\t\tconst headers: Record<string, string> = {};\n\t\tif (workspaceId) {\n\t\t\theaders[\"x-kanban-workspace-id\"] = workspaceId;\n\t\t}\n\t\tconst response = await fetch(buildKanbanRuntimeUrl(\"/api/trpc/projects.list\"), {\n\t\t\tmethod: \"GET\",\n\t\t\theaders,\n\t\t\tsignal: AbortSignal.timeout(1_500),\n\t\t});\n\t\tif (response.status === 404) {\n\t\t\treturn false;\n\t\t}\n\t\tconst payload = (await response.json().catch(() => null)) as {\n\t\t\tresult?: { data?: unknown };\n\t\t\terror?: unknown;\n\t\t} | null;\n\t\treturn Boolean(payload && (payload.result || payload.error));\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function tryOpenExistingServer(noOpen: boolean): Promise<boolean> {\n\tlet workspaceId: string | null = null;\n\tif (hasGitRepository(process.cwd())) {\n\t\tconst context = await loadWorkspaceContext(process.cwd());\n\t\tworkspaceId = context.workspaceId;\n\t}\n\tconst running = await canReachKanbanServer(workspaceId);\n\tif (!running) {\n\t\treturn false;\n\t}\n\tconst projectUrl = workspaceId\n\t\t? buildKanbanRuntimeUrl(`/${encodeURIComponent(workspaceId)}`)\n\t\t: KANBAN_RUNTIME_ORIGIN;\n\tconsole.log(`Kanban already running at ${KANBAN_RUNTIME_ORIGIN}`);\n\tif (!noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(projectUrl);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(`Project URL: ${projectUrl}`);\n\treturn true;\n}\n\nasync function runShortcutCommand(command: string, cwd: string): Promise<RuntimeShortcutRunResponse> {\n\tconst startedAt = Date.now();\n\tconst outputLimitBytes = 64 * 1024;\n\n\treturn await new Promise<RuntimeShortcutRunResponse>((resolve, reject) => {\n\t\tconst child = spawn(command, {\n\t\t\tcwd,\n\t\t\tshell: true,\n\t\t\tenv: process.env,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\n\t\tif (!child.stdout || !child.stderr) {\n\t\t\treject(new Error(\"Shortcut process did not expose stdout/stderr.\"));\n\t\t\treturn;\n\t\t}\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\n\t\tconst appendOutput = (current: string, chunk: string): string => {\n\t\t\tconst next = current + chunk;\n\t\t\tif (next.length <= outputLimitBytes) {\n\t\t\t\treturn next;\n\t\t\t}\n\t\t\treturn next.slice(0, outputLimitBytes);\n\t\t};\n\n\t\tchild.stdout.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstdout = appendOutput(stdout, String(chunk));\n\t\t});\n\n\t\tchild.stderr.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstderr = appendOutput(stderr, String(chunk));\n\t\t});\n\n\t\tchild.on(\"error\", (error) => {\n\t\t\treject(error);\n\t\t});\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tchild.kill(\"SIGTERM\");\n\t\t}, 60_000);\n\n\t\tchild.on(\"close\", (code) => {\n\t\t\tclearTimeout(timeout);\n\t\t\tconst exitCode = typeof code === \"number\" ? code : 1;\n\t\t\tconst combinedOutput = [stdout.trim(), stderr.trim()].filter(Boolean).join(\"\\n\");\n\t\t\tresolve({\n\t\t\t\texitCode,\n\t\t\t\tstdout: stdout.trim(),\n\t\t\t\tstderr: stderr.trim(),\n\t\t\t\tcombinedOutput,\n\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function startServer(): Promise<{ url: string; close: () => Promise<void>; shutdown: () => Promise<void> }> {\n\tlet runtimeStateHub: ReturnType<typeof createRuntimeStateHub> | undefined;\n\tconst workspaceRegistry = await createWorkspaceRegistry({\n\t\tcwd: process.cwd(),\n\t\tloadRuntimeConfig,\n\t\thasGitRepository,\n\t\tpathIsDirectory,\n\t\tonTerminalManagerReady: (workspaceId, manager) => {\n\t\t\truntimeStateHub?.trackTerminalManager(workspaceId, manager);\n\t\t},\n\t});\n\truntimeStateHub = createRuntimeStateHub({\n\t\tworkspaceRegistry,\n\t});\n\tconst runtimeHub = runtimeStateHub;\n\tfor (const { workspaceId, terminalManager } of workspaceRegistry.listManagedWorkspaces()) {\n\t\truntimeHub.trackTerminalManager(workspaceId, terminalManager);\n\t}\n\n\tconst disposeTrackedWorkspace = (\n\t\tworkspaceId: string,\n\t\toptions?: {\n\t\t\tstopTerminalSessions?: boolean;\n\t\t},\n\t): { terminalManager: TerminalSessionManager | null; workspacePath: string | null } => {\n\t\tconst disposed = workspaceRegistry.disposeWorkspace(workspaceId, {\n\t\t\tstopTerminalSessions: options?.stopTerminalSessions,\n\t\t});\n\t\truntimeHub.disposeWorkspace(workspaceId);\n\t\treturn disposed;\n\t};\n\n\tconst runtimeServer = await createRuntimeServer({\n\t\tworkspaceRegistry,\n\t\truntimeStateHub: runtimeHub,\n\t\twarn: (message) => {\n\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t},\n\t\tensureTerminalManagerForWorkspace: workspaceRegistry.ensureTerminalManagerForWorkspace,\n\t\tresolveInteractiveShellCommand,\n\t\trunShortcutCommand,\n\t\tresolveProjectInputPath,\n\t\tassertPathIsDirectory,\n\t\thasGitRepository,\n\t\tdisposeWorkspace: disposeTrackedWorkspace,\n\t\tcollectProjectWorktreeTaskIdsForRemoval,\n\t\tpickDirectoryPathFromSystemDialog,\n\t});\n\n\tconst close = async () => {\n\t\tawait runtimeServer.close();\n\t};\n\n\tconst shutdown = async () => {\n\t\tawait shutdownRuntimeServer({\n\t\t\tworkspaceRegistry,\n\t\t\twarn: (message) => {\n\t\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t\t},\n\t\t\tcloseRuntimeServer: close,\n\t\t});\n\t};\n\n\treturn {\n\t\turl: runtimeServer.url,\n\t\tclose,\n\t\tshutdown,\n\t};\n}\n\nasync function run(): Promise<void> {\n\tconst argv = process.argv.slice(2);\n\tif (isMcpSubcommand(argv)) {\n\t\tawait runMcpSubcommand(argv);\n\t\treturn;\n\t}\n\tif (isHooksSubcommand(argv)) {\n\t\tawait runHooksSubcommand(argv);\n\t\treturn;\n\t}\n\n\tconst options = parseCliOptions(argv);\n\n\tif (options.help) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\tif (options.version) {\n\t\tconsole.log(KANBAN_VERSION);\n\t\treturn;\n\t}\n\n\tautoUpdateOnStartup({\n\t\tcurrentVersion: KANBAN_VERSION,\n\t});\n\n\tif (options.agent) {\n\t\tconst didChange = await persistCliAgentSelection(process.cwd(), options.agent);\n\t\tif (didChange) {\n\t\t\tconsole.log(`Default agent set to ${options.agent}.`);\n\t\t}\n\t}\n\n\tlet runtime: Awaited<ReturnType<typeof startServer>>;\n\ttry {\n\t\truntime = await startServer();\n\t} catch (error) {\n\t\tif (isAddressInUseError(error) && (await tryOpenExistingServer(options.noOpen))) {\n\t\t\treturn;\n\t\t}\n\t\tthrow error;\n\t}\n\tconsole.log(`Kanban running at ${runtime.url}`);\n\tif (!options.noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(runtime.url);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(\"Press Ctrl+C to stop.\");\n\n\tlet isShuttingDown = false;\n\tconst shutdown = async (signal: \"SIGINT\" | \"SIGTERM\") => {\n\t\tif (isShuttingDown) {\n\t\t\tprocess.exit(130);\n\t\t\treturn;\n\t\t}\n\t\tisShuttingDown = true;\n\t\tconst forceExitTimer = setTimeout(() => {\n\t\t\tconsole.error(`Forced exit after ${signal} timeout.`);\n\t\t\tprocess.exit(130);\n\t\t}, 3000);\n\t\tforceExitTimer.unref();\n\t\ttry {\n\t\t\tawait runtime.shutdown();\n\t\t\tclearTimeout(forceExitTimer);\n\t\t\tprocess.exit(130);\n\t\t} catch (error) {\n\t\t\tclearTimeout(forceExitTimer);\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(`Shutdown failed: ${message}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t};\n\tprocess.on(\"SIGINT\", () => {\n\t\tvoid shutdown(\"SIGINT\");\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tvoid shutdown(\"SIGTERM\");\n\t});\n}\n\nrun().catch((error) => {\n\tconst message = error instanceof Error ? error.message : String(error);\n\tconsole.error(`Failed to start Kanban: ${message}`);\n\tprocess.exit(1);\n});\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { stat } from \"node:fs/promises\";\nimport { createServer as createNetServer } from \"node:net\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nimport { isHooksSubcommand, runHooksSubcommand } from \"./commands/hooks.js\";\nimport { isMcpSubcommand, runMcpSubcommand } from \"./commands/mcp.js\";\nimport type {\n\tRuntimeAgentId,\n\tRuntimeCommandRunResponse,\n} from \"./core/api-contract.js\";\nimport { loadRuntimeConfig, updateRuntimeConfig } from \"./config/runtime-config.js\";\nimport { createGitProcessEnv } from \"./core/git-process-env.js\";\nimport { resolveProjectInputPath } from \"./projects/project-path.js\";\nimport {\n\tbuildKanbanRuntimeUrl,\n\tDEFAULT_KANBAN_RUNTIME_PORT,\n\tgetKanbanRuntimePort,\n\tgetKanbanRuntimeOrigin,\n\tparseRuntimePort,\n\tsetKanbanRuntimePort,\n} from \"./core/runtime-endpoint.js\";\nimport { openInBrowser } from \"./server/browser.js\";\nimport { createRuntimeStateHub } from \"./server/runtime-state-hub.js\";\nimport { createRuntimeServer } from \"./server/runtime-server.js\";\nimport { shutdownRuntimeServer } from \"./server/shutdown-coordinator.js\";\nimport { resolveInteractiveShellCommand } from \"./server/shell.js\";\nimport {\n\tloadWorkspaceContext,\n} from \"./state/workspace-state.js\";\nimport {\n\tcollectProjectWorktreeTaskIdsForRemoval,\n\tcreateWorkspaceRegistry,\n} from \"./server/workspace-registry.js\";\nimport type { TerminalSessionManager } from \"./terminal/session-manager.js\";\nimport { autoUpdateOnStartup } from \"./update/auto-update.js\";\n\ninterface CliOptions {\n\thelp: boolean;\n\tversion: boolean;\n\tnoOpen: boolean;\n\tagent: RuntimeAgentId | null;\n\tport: { mode: \"fixed\"; value: number } | { mode: \"auto\" } | null;\n}\n\nconst CLI_AGENT_IDS: readonly RuntimeAgentId[] = [\"claude\", \"codex\", \"gemini\", \"opencode\", \"droid\", \"cline\"];\nconst KANBAN_VERSION = typeof packageJson.version === \"string\" ? packageJson.version : \"0.1.0\";\n\nfunction parseCliAgentId(value: string): RuntimeAgentId {\n\tconst normalized = value.trim().toLowerCase();\n\tif (\n\t\tnormalized === \"claude\" ||\n\t\tnormalized === \"codex\" ||\n\t\tnormalized === \"gemini\" ||\n\t\tnormalized === \"opencode\" ||\n\t\tnormalized === \"droid\" ||\n\t\tnormalized === \"cline\"\n\t) {\n\t\treturn normalized;\n\t}\n\tthrow new Error(`Invalid agent: ${value}. Expected one of: ${CLI_AGENT_IDS.join(\", \")}`);\n}\n\nfunction parseCliPortValue(rawValue: string): { mode: \"fixed\"; value: number } | { mode: \"auto\" } {\n\tconst normalized = rawValue.trim().toLowerCase();\n\tif (!normalized) {\n\t\tthrow new Error(\"Missing value for --port.\");\n\t}\n\tif (normalized === \"auto\") {\n\t\treturn { mode: \"auto\" };\n\t}\n\ttry {\n\t\treturn { mode: \"fixed\", value: parseRuntimePort(normalized) };\n\t} catch {\n\t\tthrow new Error(`Invalid port value: ${rawValue}. Expected an integer from 1-65535 or \"auto\".`);\n\t}\n}\n\nfunction parseCliOptions(argv: string[]): CliOptions {\n\tlet help = false;\n\tlet version = false;\n\tlet noOpen = false;\n\tlet agent: RuntimeAgentId | null = null;\n\tlet port: { mode: \"fixed\"; value: number } | { mode: \"auto\" } | null = null;\n\n\tfor (let index = 0; index < argv.length; index += 1) {\n\t\tconst arg = argv[index];\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\thelp = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--version\" || arg === \"-v\") {\n\t\t\tversion = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--no-open\") {\n\t\t\tnoOpen = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--agent\") {\n\t\t\tconst value = argv[index + 1];\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --agent.\");\n\t\t\t}\n\t\t\tagent = parseCliAgentId(value);\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--agent=\")) {\n\t\t\tconst value = arg.slice(\"--agent=\".length);\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --agent.\");\n\t\t\t}\n\t\t\tagent = parseCliAgentId(value);\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--port\") {\n\t\t\tconst value = argv[index + 1];\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --port.\");\n\t\t\t}\n\t\t\tport = parseCliPortValue(value);\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--port=\")) {\n\t\t\tconst value = arg.slice(\"--port=\".length);\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --port.\");\n\t\t\t}\n\t\t\tport = parseCliPortValue(value);\n\t\t}\n\t}\n\n\treturn { help, version, noOpen, agent, port };\n}\n\nfunction printHelp(): void {\n\tconsole.log(\"kanban\");\n\tconsole.log(\"Local orchestration board for coding agents.\");\n\tconsole.log(\"\");\n\tconsole.log(\"Usage:\");\n\tconsole.log(\" kanban [--agent <id>] [--port <number|auto>] [--no-open] [--help] [--version]\");\n\tconsole.log(\" kanban mcp\");\n\tconsole.log(\"\");\n\tconsole.log(`Runtime URL: ${getKanbanRuntimeOrigin()}`);\n\tconsole.log(`Agent IDs: ${CLI_AGENT_IDS.join(\", \")}`);\n}\n\nasync function isPortAvailable(port: number): Promise<boolean> {\n\treturn await new Promise<boolean>((resolve) => {\n\t\tconst probe = createNetServer();\n\t\tprobe.once(\"error\", () => {\n\t\t\tresolve(false);\n\t\t});\n\t\tprobe.listen(port, \"127.0.0.1\", () => {\n\t\t\tprobe.close(() => {\n\t\t\t\tresolve(true);\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function findAvailableRuntimePort(startPort: number): Promise<number> {\n\tfor (let candidate = startPort; candidate <= 65535; candidate += 1) {\n\t\tif (await isPortAvailable(candidate)) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\tthrow new Error(\"No available runtime port found.\");\n}\n\nasync function applyRuntimePortOption(portOption: CliOptions[\"port\"]): Promise<number | null> {\n\tif (!portOption) {\n\t\treturn null;\n\t}\n\tif (portOption.mode === \"fixed\") {\n\t\tsetKanbanRuntimePort(portOption.value);\n\t\treturn portOption.value;\n\t}\n\tconst autoPort = await findAvailableRuntimePort(DEFAULT_KANBAN_RUNTIME_PORT);\n\tsetKanbanRuntimePort(autoPort);\n\treturn autoPort;\n}\n\nasync function persistCliAgentSelection(cwd: string, selectedAgentId: RuntimeAgentId): Promise<boolean> {\n\tconst currentRuntimeConfig = await loadRuntimeConfig(cwd);\n\tif (currentRuntimeConfig.selectedAgentId === selectedAgentId) {\n\t\treturn false;\n\t}\n\tawait updateRuntimeConfig(cwd, { selectedAgentId });\n\treturn true;\n}\n\nasync function assertPathIsDirectory(path: string): Promise<void> {\n\tconst info = await stat(path);\n\tif (!info.isDirectory()) {\n\t\tthrow new Error(`Project path is not a directory: ${path}`);\n\t}\n}\n\nasync function pathIsDirectory(path: string): Promise<boolean> {\n\ttry {\n\t\tconst info = await stat(path);\n\t\treturn info.isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction hasGitRepository(path: string): boolean {\n\tconst result = spawnSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n\t\tcwd: path,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\tenv: createGitProcessEnv(),\n\t});\n\treturn result.status === 0 && result.stdout.trim() === \"true\";\n}\n\nfunction pickDirectoryPathFromSystemDialog(): string | null {\n\tif (process.platform === \"darwin\") {\n\t\tconst result = spawnSync(\n\t\t\t\"osascript\",\n\t\t\t[\"-e\", 'POSIX path of (choose folder with prompt \"Select a project folder\")'],\n\t\t\t{\n\t\t\t\tencoding: \"utf8\",\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t},\n\t\t);\n\t\tif (result.status !== 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst selected = typeof result.stdout === \"string\" ? result.stdout.trim() : \"\";\n\t\treturn selected || null;\n\t}\n\n\tif (process.platform === \"linux\") {\n\t\tconst result = spawnSync(\"zenity\", [\"--file-selection\", \"--directory\", \"--title=Select project folder\"], {\n\t\t\tencoding: \"utf8\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tif (result.status !== 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst selected = typeof result.stdout === \"string\" ? result.stdout.trim() : \"\";\n\t\treturn selected || null;\n\t}\n\n\treturn null;\n}\n\n\nfunction isAddressInUseError(error: unknown): error is NodeJS.ErrnoException {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error as NodeJS.ErrnoException).code === \"EADDRINUSE\"\n\t);\n}\n\nasync function canReachKanbanServer(workspaceId: string | null): Promise<boolean> {\n\ttry {\n\t\tconst headers: Record<string, string> = {};\n\t\tif (workspaceId) {\n\t\t\theaders[\"x-kanban-workspace-id\"] = workspaceId;\n\t\t}\n\t\tconst response = await fetch(buildKanbanRuntimeUrl(\"/api/trpc/projects.list\"), {\n\t\t\tmethod: \"GET\",\n\t\t\theaders,\n\t\t\tsignal: AbortSignal.timeout(1_500),\n\t\t});\n\t\tif (response.status === 404) {\n\t\t\treturn false;\n\t\t}\n\t\tconst payload = (await response.json().catch(() => null)) as {\n\t\t\tresult?: { data?: unknown };\n\t\t\terror?: unknown;\n\t\t} | null;\n\t\treturn Boolean(payload && (payload.result || payload.error));\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function tryOpenExistingServer(noOpen: boolean): Promise<boolean> {\n\tlet workspaceId: string | null = null;\n\tif (hasGitRepository(process.cwd())) {\n\t\tconst context = await loadWorkspaceContext(process.cwd());\n\t\tworkspaceId = context.workspaceId;\n\t}\n\tconst running = await canReachKanbanServer(workspaceId);\n\tif (!running) {\n\t\treturn false;\n\t}\n\tconst projectUrl = workspaceId\n\t\t? buildKanbanRuntimeUrl(`/${encodeURIComponent(workspaceId)}`)\n\t\t: getKanbanRuntimeOrigin();\n\tconsole.log(`Kanban already running at ${getKanbanRuntimeOrigin()}`);\n\tif (!noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(projectUrl);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(`Project URL: ${projectUrl}`);\n\treturn true;\n}\n\nasync function runScopedCommand(command: string, cwd: string): Promise<RuntimeCommandRunResponse> {\n\tconst startedAt = Date.now();\n\tconst outputLimitBytes = 64 * 1024;\n\n\treturn await new Promise<RuntimeCommandRunResponse>((resolve, reject) => {\n\t\tconst child = spawn(command, {\n\t\t\tcwd,\n\t\t\tshell: true,\n\t\t\tenv: process.env,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\n\t\tif (!child.stdout || !child.stderr) {\n\t\t\treject(new Error(\"Shortcut process did not expose stdout/stderr.\"));\n\t\t\treturn;\n\t\t}\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\n\t\tconst appendOutput = (current: string, chunk: string): string => {\n\t\t\tconst next = current + chunk;\n\t\t\tif (next.length <= outputLimitBytes) {\n\t\t\t\treturn next;\n\t\t\t}\n\t\t\treturn next.slice(0, outputLimitBytes);\n\t\t};\n\n\t\tchild.stdout.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstdout = appendOutput(stdout, String(chunk));\n\t\t});\n\n\t\tchild.stderr.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstderr = appendOutput(stderr, String(chunk));\n\t\t});\n\n\t\tchild.on(\"error\", (error) => {\n\t\t\treject(error);\n\t\t});\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tchild.kill(\"SIGTERM\");\n\t\t}, 60_000);\n\n\t\tchild.on(\"close\", (code) => {\n\t\t\tclearTimeout(timeout);\n\t\t\tconst exitCode = typeof code === \"number\" ? code : 1;\n\t\t\tconst combinedOutput = [stdout.trim(), stderr.trim()].filter(Boolean).join(\"\\n\");\n\t\t\tresolve({\n\t\t\t\texitCode,\n\t\t\t\tstdout: stdout.trim(),\n\t\t\t\tstderr: stderr.trim(),\n\t\t\t\tcombinedOutput,\n\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function startServer(): Promise<{ url: string; close: () => Promise<void>; shutdown: () => Promise<void> }> {\n\tlet runtimeStateHub: ReturnType<typeof createRuntimeStateHub> | undefined;\n\tconst workspaceRegistry = await createWorkspaceRegistry({\n\t\tcwd: process.cwd(),\n\t\tloadRuntimeConfig,\n\t\thasGitRepository,\n\t\tpathIsDirectory,\n\t\tonTerminalManagerReady: (workspaceId, manager) => {\n\t\t\truntimeStateHub?.trackTerminalManager(workspaceId, manager);\n\t\t},\n\t});\n\truntimeStateHub = createRuntimeStateHub({\n\t\tworkspaceRegistry,\n\t});\n\tconst runtimeHub = runtimeStateHub;\n\tfor (const { workspaceId, terminalManager } of workspaceRegistry.listManagedWorkspaces()) {\n\t\truntimeHub.trackTerminalManager(workspaceId, terminalManager);\n\t}\n\n\tconst disposeTrackedWorkspace = (\n\t\tworkspaceId: string,\n\t\toptions?: {\n\t\t\tstopTerminalSessions?: boolean;\n\t\t},\n\t): { terminalManager: TerminalSessionManager | null; workspacePath: string | null } => {\n\t\tconst disposed = workspaceRegistry.disposeWorkspace(workspaceId, {\n\t\t\tstopTerminalSessions: options?.stopTerminalSessions,\n\t\t});\n\t\truntimeHub.disposeWorkspace(workspaceId);\n\t\treturn disposed;\n\t};\n\n\tconst runtimeServer = await createRuntimeServer({\n\t\tworkspaceRegistry,\n\t\truntimeStateHub: runtimeHub,\n\t\twarn: (message) => {\n\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t},\n\t\tensureTerminalManagerForWorkspace: workspaceRegistry.ensureTerminalManagerForWorkspace,\n\t\tresolveInteractiveShellCommand,\n\t\trunCommand: runScopedCommand,\n\t\tresolveProjectInputPath,\n\t\tassertPathIsDirectory,\n\t\thasGitRepository,\n\t\tdisposeWorkspace: disposeTrackedWorkspace,\n\t\tcollectProjectWorktreeTaskIdsForRemoval,\n\t\tpickDirectoryPathFromSystemDialog,\n\t});\n\n\tconst close = async () => {\n\t\tawait runtimeServer.close();\n\t};\n\n\tconst shutdown = async () => {\n\t\tawait shutdownRuntimeServer({\n\t\t\tworkspaceRegistry,\n\t\t\twarn: (message) => {\n\t\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t\t},\n\t\t\tcloseRuntimeServer: close,\n\t\t});\n\t};\n\n\treturn {\n\t\turl: runtimeServer.url,\n\t\tclose,\n\t\tshutdown,\n\t};\n}\n\nasync function startServerWithAutoPortRetry(options: CliOptions): Promise<Awaited<ReturnType<typeof startServer>>> {\n\tif (options.port?.mode !== \"auto\") {\n\t\treturn await startServer();\n\t}\n\n\twhile (true) {\n\t\ttry {\n\t\t\treturn await startServer();\n\t\t} catch (error) {\n\t\t\tif (!isAddressInUseError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tconst currentPort = getKanbanRuntimePort();\n\t\t\tconst retryPort = await findAvailableRuntimePort(currentPort + 1);\n\t\t\tsetKanbanRuntimePort(retryPort);\n\t\t\tconsole.warn(`Runtime port ${currentPort} became busy during startup, retrying on ${retryPort}.`);\n\t\t}\n\t}\n}\n\nasync function run(): Promise<void> {\n\tconst argv = process.argv.slice(2);\n\tif (isMcpSubcommand(argv)) {\n\t\tawait runMcpSubcommand(argv);\n\t\treturn;\n\t}\n\tif (isHooksSubcommand(argv)) {\n\t\tawait runHooksSubcommand(argv);\n\t\treturn;\n\t}\n\n\tconst options = parseCliOptions(argv);\n\n\tif (options.help) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\tif (options.version) {\n\t\tconsole.log(KANBAN_VERSION);\n\t\treturn;\n\t}\n\n\tconst selectedPort = await applyRuntimePortOption(options.port);\n\tif (selectedPort !== null) {\n\t\tconsole.log(`Using runtime port ${selectedPort}.`);\n\t}\n\n\tautoUpdateOnStartup({\n\t\tcurrentVersion: KANBAN_VERSION,\n\t});\n\n\tif (options.agent) {\n\t\tconst didChange = await persistCliAgentSelection(process.cwd(), options.agent);\n\t\tif (didChange) {\n\t\t\tconsole.log(`Default agent set to ${options.agent}.`);\n\t\t}\n\t}\n\n\tlet runtime: Awaited<ReturnType<typeof startServer>>;\n\ttry {\n\t\truntime = await startServerWithAutoPortRetry(options);\n\t} catch (error) {\n\t\tif (options.port?.mode !== \"auto\" && isAddressInUseError(error) && (await tryOpenExistingServer(options.noOpen))) {\n\t\t\treturn;\n\t\t}\n\t\tthrow error;\n\t}\n\tconsole.log(`Kanban running at ${runtime.url}`);\n\tif (!options.noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(runtime.url);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(\"Press Ctrl+C to stop.\");\n\n\tlet isShuttingDown = false;\n\tconst shutdown = async (signal: \"SIGINT\" | \"SIGTERM\") => {\n\t\tif (isShuttingDown) {\n\t\t\tprocess.exit(130);\n\t\t\treturn;\n\t\t}\n\t\tisShuttingDown = true;\n\t\tconst forceExitTimer = setTimeout(() => {\n\t\t\tconsole.error(`Forced exit after ${signal} timeout.`);\n\t\t\tprocess.exit(130);\n\t\t}, 3000);\n\t\tforceExitTimer.unref();\n\t\ttry {\n\t\t\tawait runtime.shutdown();\n\t\t\tclearTimeout(forceExitTimer);\n\t\t\tprocess.exit(130);\n\t\t} catch (error) {\n\t\t\tclearTimeout(forceExitTimer);\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(`Shutdown failed: ${message}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t};\n\tprocess.on(\"SIGINT\", () => {\n\t\tvoid shutdown(\"SIGINT\");\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tvoid shutdown(\"SIGTERM\");\n\t});\n}\n\nrun().catch((error) => {\n\tconst message = error instanceof Error ? error.message : String(error);\n\tconsole.error(`Failed to start Kanban: ${message}`);\n\tprocess.exit(1);\n});\n"]}
@@ -3,7 +3,7 @@ export interface RuntimeConfigState {
3
3
  globalConfigPath: string;
4
4
  projectConfigPath: string;
5
5
  selectedAgentId: RuntimeAgentId;
6
- selectedShortcutId: string | null;
6
+ selectedShortcutLabel: string | null;
7
7
  agentAutonomousModeEnabled: boolean;
8
8
  readyForReviewNotificationsEnabled: boolean;
9
9
  shortcuts: RuntimeProjectShortcut[];
@@ -14,7 +14,7 @@ export interface RuntimeConfigState {
14
14
  }
15
15
  export interface RuntimeConfigUpdateInput {
16
16
  selectedAgentId?: RuntimeAgentId;
17
- selectedShortcutId?: string | null;
17
+ selectedShortcutLabel?: string | null;
18
18
  agentAutonomousModeEnabled?: boolean;
19
19
  readyForReviewNotificationsEnabled?: boolean;
20
20
  shortcuts?: RuntimeProjectShortcut[];
@@ -27,7 +27,7 @@ export declare function getRuntimeProjectConfigPath(cwd: string): string;
27
27
  export declare function loadRuntimeConfig(cwd: string): Promise<RuntimeConfigState>;
28
28
  export declare function saveRuntimeConfig(cwd: string, config: {
29
29
  selectedAgentId: RuntimeAgentId;
30
- selectedShortcutId: string | null;
30
+ selectedShortcutLabel: string | null;
31
31
  agentAutonomousModeEnabled: boolean;
32
32
  readyForReviewNotificationsEnabled: boolean;
33
33
  shortcuts: RuntimeProjectShortcut[];
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-config.d.ts","sourceRoot":"","sources":["../../src/config/runtime-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAiBtF,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,cAAc,CAAC;IAChC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,0BAA0B,EAAE,OAAO,CAAC;IACpC,kCAAkC,EAAE,OAAO,CAAC;IAC5C,SAAS,EAAE,sBAAsB,EAAE,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,2BAA2B,EAAE,MAAM,CAAC;IACpC,2BAA2B,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,wBAAwB;IACxC,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,kCAAkC,CAAC,EAAE,OAAO,CAAC;IAC7C,SAAS,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACrC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAoDD,wBAAgB,oCAAoC,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,GAAG,IAAI,CAQ/G;AAyFD,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/D;AAwID,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuBhF;AAED,wBAAsB,iBAAiB,CACtC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE;IACP,eAAe,EAAE,cAAc,CAAC;IAChC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,0BAA0B,EAAE,OAAO,CAAC;IACpC,kCAAkC,EAAE,OAAO,CAAC;IAC5C,SAAS,EAAE,sBAAsB,EAAE,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC7B,GACC,OAAO,CAAC,kBAAkB,CAAC,CA+B7B;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA4BrH"}
1
+ {"version":3,"file":"runtime-config.d.ts","sourceRoot":"","sources":["../../src/config/runtime-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAiBtF,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,cAAc,CAAC;IAChC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,0BAA0B,EAAE,OAAO,CAAC;IACpC,kCAAkC,EAAE,OAAO,CAAC;IAC5C,SAAS,EAAE,sBAAsB,EAAE,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,2BAA2B,EAAE,MAAM,CAAC;IACpC,2BAA2B,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,wBAAwB;IACxC,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,kCAAkC,CAAC,EAAE,OAAO,CAAC;IAC7C,SAAS,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACrC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAoDD,wBAAgB,oCAAoC,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,GAAG,IAAI,CAQ/G;AAwFD,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/D;AAwID,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuBhF;AAED,wBAAsB,iBAAiB,CACtC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE;IACP,eAAe,EAAE,cAAc,CAAC;IAChC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,0BAA0B,EAAE,OAAO,CAAC;IACpC,kCAAkC,EAAE,OAAO,CAAC;IAC5C,SAAS,EAAE,sBAAsB,EAAE,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC7B,GACC,OAAO,CAAC,kBAAkB,CAAC,CA+B7B;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA4BrH"}
@@ -8,7 +8,7 @@ const CONFIG_FILENAME = "config.json";
8
8
  const PROJECT_CONFIG_DIR = ".kanban";
9
9
  const PROJECT_CONFIG_FILENAME = "config.json";
10
10
  const DEFAULT_AGENT_ID = "claude";
11
- const AUTO_SELECT_AGENT_PRIORITY = ["claude", "codex", "opencode", "gemini", "cline"];
11
+ const AUTO_SELECT_AGENT_PRIORITY = ["claude", "codex", "opencode", "droid", "gemini", "cline"];
12
12
  const DEFAULT_AGENT_AUTONOMOUS_MODE_ENABLED = true;
13
13
  const DEFAULT_READY_FOR_REVIEW_NOTIFICATIONS_ENABLED = true;
14
14
  const DEFAULT_COMMIT_PROMPT_TEMPLATE = `You are in a worktree on a detached HEAD. When you are finished with the task, commit the working changes onto {{base_ref}}.
@@ -69,6 +69,7 @@ function normalizeAgentId(agentId) {
69
69
  agentId === "codex" ||
70
70
  agentId === "gemini" ||
71
71
  agentId === "opencode" ||
72
+ agentId === "droid" ||
72
73
  agentId === "cline") {
73
74
  return agentId;
74
75
  }
@@ -81,15 +82,13 @@ function normalizeShortcut(shortcut) {
81
82
  if (!shortcut || typeof shortcut !== "object") {
82
83
  return null;
83
84
  }
84
- const id = typeof shortcut.id === "string" ? shortcut.id.trim() : "";
85
85
  const label = typeof shortcut.label === "string" ? shortcut.label.trim() : "";
86
86
  const command = typeof shortcut.command === "string" ? shortcut.command.trim() : "";
87
87
  const icon = typeof shortcut.icon === "string" ? shortcut.icon.trim() : "";
88
- if (!id || !label || !command) {
88
+ if (!label || !command) {
89
89
  return null;
90
90
  }
91
91
  return {
92
- id,
93
92
  label,
94
93
  command,
95
94
  icon: icon || undefined,
@@ -121,7 +120,7 @@ function normalizeBoolean(value, fallback) {
121
120
  }
122
121
  return fallback;
123
122
  }
124
- function normalizeShortcutId(value) {
123
+ function normalizeShortcutLabel(value) {
125
124
  if (typeof value !== "string") {
126
125
  return null;
127
126
  }
@@ -145,7 +144,7 @@ function toRuntimeConfigState({ globalConfigPath, projectConfigPath, globalConfi
145
144
  globalConfigPath,
146
145
  projectConfigPath,
147
146
  selectedAgentId: normalizeAgentId(globalConfig?.selectedAgentId),
148
- selectedShortcutId: normalizeShortcutId(globalConfig?.selectedShortcutId),
147
+ selectedShortcutLabel: normalizeShortcutLabel(globalConfig?.selectedShortcutLabel),
149
148
  agentAutonomousModeEnabled: normalizeBoolean(globalConfig?.agentAutonomousModeEnabled, DEFAULT_AGENT_AUTONOMOUS_MODE_ENABLED),
150
149
  readyForReviewNotificationsEnabled: normalizeBoolean(globalConfig?.readyForReviewNotificationsEnabled, DEFAULT_READY_FOR_REVIEW_NOTIFICATIONS_ENABLED),
151
150
  shortcuts: normalizeShortcuts(projectConfig?.shortcuts),
@@ -170,9 +169,9 @@ async function writeRuntimeGlobalConfigFile(configPath, config) {
170
169
  const existingSelectedAgentId = hasOwnKey(existing, "selectedAgentId")
171
170
  ? normalizeAgentId(existing?.selectedAgentId)
172
171
  : undefined;
173
- const selectedShortcutId = config.selectedShortcutId === undefined ? undefined : normalizeShortcutId(config.selectedShortcutId);
174
- const existingSelectedShortcutId = hasOwnKey(existing, "selectedShortcutId")
175
- ? normalizeShortcutId(existing?.selectedShortcutId)
172
+ const selectedShortcutLabel = config.selectedShortcutLabel === undefined ? undefined : normalizeShortcutLabel(config.selectedShortcutLabel);
173
+ const existingSelectedShortcutLabel = hasOwnKey(existing, "selectedShortcutLabel")
174
+ ? normalizeShortcutLabel(existing?.selectedShortcutLabel)
176
175
  : undefined;
177
176
  const agentAutonomousModeEnabled = config.agentAutonomousModeEnabled === undefined
178
177
  ? DEFAULT_AGENT_AUTONOMOUS_MODE_ENABLED
@@ -195,13 +194,13 @@ async function writeRuntimeGlobalConfigFile(configPath, config) {
195
194
  else if (existingSelectedAgentId !== undefined) {
196
195
  payload.selectedAgentId = existingSelectedAgentId;
197
196
  }
198
- if (selectedShortcutId !== undefined) {
199
- if (selectedShortcutId) {
200
- payload.selectedShortcutId = selectedShortcutId;
197
+ if (selectedShortcutLabel !== undefined) {
198
+ if (selectedShortcutLabel) {
199
+ payload.selectedShortcutLabel = selectedShortcutLabel;
201
200
  }
202
201
  }
203
- else if (existingSelectedShortcutId) {
204
- payload.selectedShortcutId = existingSelectedShortcutId;
202
+ else if (existingSelectedShortcutLabel) {
203
+ payload.selectedShortcutLabel = existingSelectedShortcutLabel;
205
204
  }
206
205
  if (hasOwnKey(existing, "agentAutonomousModeEnabled") ||
207
206
  agentAutonomousModeEnabled !== DEFAULT_AGENT_AUTONOMOUS_MODE_ENABLED) {
@@ -259,7 +258,7 @@ export async function saveRuntimeConfig(cwd, config) {
259
258
  const projectConfigPath = getRuntimeProjectConfigPath(cwd);
260
259
  await writeRuntimeGlobalConfigFile(globalConfigPath, {
261
260
  selectedAgentId: config.selectedAgentId,
262
- selectedShortcutId: config.selectedShortcutId,
261
+ selectedShortcutLabel: config.selectedShortcutLabel,
263
262
  agentAutonomousModeEnabled: config.agentAutonomousModeEnabled,
264
263
  readyForReviewNotificationsEnabled: config.readyForReviewNotificationsEnabled,
265
264
  commitPromptTemplate: config.commitPromptTemplate,
@@ -270,7 +269,7 @@ export async function saveRuntimeConfig(cwd, config) {
270
269
  globalConfigPath,
271
270
  projectConfigPath,
272
271
  selectedAgentId: normalizeAgentId(config.selectedAgentId),
273
- selectedShortcutId: normalizeShortcutId(config.selectedShortcutId),
272
+ selectedShortcutLabel: normalizeShortcutLabel(config.selectedShortcutLabel),
274
273
  agentAutonomousModeEnabled: normalizeBoolean(config.agentAutonomousModeEnabled, DEFAULT_AGENT_AUTONOMOUS_MODE_ENABLED),
275
274
  readyForReviewNotificationsEnabled: normalizeBoolean(config.readyForReviewNotificationsEnabled, DEFAULT_READY_FOR_REVIEW_NOTIFICATIONS_ENABLED),
276
275
  shortcuts: normalizeShortcuts(config.shortcuts),
@@ -284,7 +283,7 @@ export async function updateRuntimeConfig(cwd, updates) {
284
283
  const current = await loadRuntimeConfig(cwd);
285
284
  const nextConfig = {
286
285
  selectedAgentId: updates.selectedAgentId ?? current.selectedAgentId,
287
- selectedShortcutId: updates.selectedShortcutId === undefined ? current.selectedShortcutId : updates.selectedShortcutId,
286
+ selectedShortcutLabel: updates.selectedShortcutLabel === undefined ? current.selectedShortcutLabel : updates.selectedShortcutLabel,
288
287
  agentAutonomousModeEnabled: updates.agentAutonomousModeEnabled ?? current.agentAutonomousModeEnabled,
289
288
  readyForReviewNotificationsEnabled: updates.readyForReviewNotificationsEnabled ?? current.readyForReviewNotificationsEnabled,
290
289
  shortcuts: updates.shortcuts ?? current.shortcuts,
@@ -292,7 +291,7 @@ export async function updateRuntimeConfig(cwd, updates) {
292
291
  openPrPromptTemplate: updates.openPrPromptTemplate ?? current.openPrPromptTemplate,
293
292
  };
294
293
  const hasChanges = nextConfig.selectedAgentId !== current.selectedAgentId ||
295
- nextConfig.selectedShortcutId !== current.selectedShortcutId ||
294
+ nextConfig.selectedShortcutLabel !== current.selectedShortcutLabel ||
296
295
  nextConfig.agentAutonomousModeEnabled !== current.agentAutonomousModeEnabled ||
297
296
  nextConfig.readyForReviewNotificationsEnabled !== current.readyForReviewNotificationsEnabled ||
298
297
  nextConfig.commitPromptTemplate !== current.commitPromptTemplate ||