@shepai/cli 1.36.0 → 1.37.1

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 (137) hide show
  1. package/dist/packages/core/src/application/ports/output/services/ide-launcher-service.interface.d.ts +64 -0
  2. package/dist/packages/core/src/application/ports/output/services/ide-launcher-service.interface.d.ts.map +1 -0
  3. package/dist/packages/core/src/application/ports/output/services/ide-launcher-service.interface.js +7 -0
  4. package/dist/packages/core/src/application/ports/output/services/index.d.ts +1 -0
  5. package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
  6. package/dist/packages/core/src/application/use-cases/ide/launch-ide.use-case.d.ts +20 -0
  7. package/dist/packages/core/src/application/use-cases/ide/launch-ide.use-case.d.ts.map +1 -0
  8. package/dist/packages/core/src/application/use-cases/ide/launch-ide.use-case.js +54 -0
  9. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  10. package/dist/packages/core/src/infrastructure/di/container.js +7 -0
  11. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
  12. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +1 -3
  13. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.d.ts.map +1 -1
  14. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.js +2 -1
  15. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts.map +1 -1
  16. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.js +4 -1
  17. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
  18. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +2 -1
  19. package/dist/packages/core/src/infrastructure/services/ide-launchers/json-driven-ide-launcher.service.d.ts +23 -0
  20. package/dist/packages/core/src/infrastructure/services/ide-launchers/json-driven-ide-launcher.service.d.ts.map +1 -0
  21. package/dist/packages/core/src/infrastructure/services/ide-launchers/json-driven-ide-launcher.service.js +114 -0
  22. package/dist/packages/core/src/infrastructure/services/tool-installer/tool-metadata.d.ts +20 -4
  23. package/dist/packages/core/src/infrastructure/services/tool-installer/tool-metadata.d.ts.map +1 -1
  24. package/dist/packages/core/src/infrastructure/services/tool-installer/tool-metadata.js +9 -1
  25. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/antigravity.json +5 -2
  26. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/claude-code.json +8 -2
  27. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/cursor-cli.json +8 -2
  28. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/cursor.json +2 -2
  29. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/vscode.json +2 -2
  30. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/windsurf.json +2 -2
  31. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/zed.json +2 -2
  32. package/dist/src/presentation/cli/commands/feat/show.command.d.ts.map +1 -1
  33. package/dist/src/presentation/cli/commands/feat/show.command.js +21 -2
  34. package/dist/src/presentation/cli/commands/ide-open.command.d.ts +3 -1
  35. package/dist/src/presentation/cli/commands/ide-open.command.d.ts.map +1 -1
  36. package/dist/src/presentation/cli/commands/ide-open.command.js +27 -28
  37. package/dist/src/presentation/cli/commands/install.command.js +3 -3
  38. package/dist/src/presentation/cli/commands/settings/ide.command.d.ts +1 -0
  39. package/dist/src/presentation/cli/commands/settings/ide.command.d.ts.map +1 -1
  40. package/dist/src/presentation/cli/commands/settings/ide.command.js +10 -13
  41. package/dist/src/presentation/tui/prompts/ide-select.prompt.d.ts +9 -25
  42. package/dist/src/presentation/tui/prompts/ide-select.prompt.d.ts.map +1 -1
  43. package/dist/src/presentation/tui/prompts/ide-select.prompt.js +9 -29
  44. package/dist/src/presentation/web/app/api/ide/open/route.d.ts.map +1 -1
  45. package/dist/src/presentation/web/app/api/ide/open/route.js +3 -2
  46. package/dist/tsconfig.build.tsbuildinfo +1 -1
  47. package/package.json +1 -1
  48. package/web/.next/BUILD_ID +1 -1
  49. package/web/.next/build-manifest.json +2 -2
  50. package/web/.next/cache/.previewinfo +1 -1
  51. package/web/.next/cache/.rscinfo +1 -1
  52. package/web/.next/cache/.tsbuildinfo +1 -1
  53. package/web/.next/cache/config.json +3 -3
  54. package/web/.next/fallback-build-manifest.json +2 -2
  55. package/web/.next/prerender-manifest.json +3 -3
  56. package/web/.next/required-server-files.js +1 -1
  57. package/web/.next/required-server-files.json +1 -1
  58. package/web/.next/server/app/_global-error.html +2 -2
  59. package/web/.next/server/app/_global-error.rsc +1 -1
  60. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  61. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  62. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  63. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  64. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  65. package/web/.next/server/app/api/ide/open/route.js +1 -2
  66. package/web/.next/server/app/api/ide/open/route.js.nft.json +1 -1
  67. package/web/.next/server/app/api/shell/open/route.js +1 -1
  68. package/web/.next/server/app/api/shell/open/route.js.nft.json +1 -1
  69. package/web/.next/server/chunks/[root-of-the-server]__04ae3a77._.js +3 -0
  70. package/web/.next/server/chunks/[root-of-the-server]__04ae3a77._.js.map +1 -0
  71. package/web/.next/server/chunks/[root-of-the-server]__f32c280c._.js +3 -0
  72. package/web/.next/server/chunks/[root-of-the-server]__f32c280c._.js.map +1 -0
  73. package/web/.next/server/chunks/ssr/[root-of-the-server]__f12b60be._.js +1 -1
  74. package/web/.next/server/pages/500.html +2 -2
  75. package/web/.next/server/server-reference-manifest.js +1 -1
  76. package/web/.next/server/server-reference-manifest.json +1 -1
  77. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  78. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  79. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  80. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  81. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  82. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  83. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  84. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  85. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  86. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  87. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  88. package/web/.next/standalone/src/presentation/web/.next/server/app/api/ide/open/route.js +1 -2
  89. package/web/.next/standalone/src/presentation/web/.next/server/app/api/ide/open/route.js.nft.json +1 -1
  90. package/web/.next/standalone/src/presentation/web/.next/server/app/api/shell/open/route.js +1 -1
  91. package/web/.next/standalone/src/presentation/web/.next/server/app/api/shell/open/route.js.nft.json +1 -1
  92. package/web/.next/standalone/src/presentation/web/.next/server/chunks/[root-of-the-server]__04ae3a77._.js +3 -0
  93. package/web/.next/standalone/src/presentation/web/.next/server/chunks/[root-of-the-server]__f32c280c._.js +3 -0
  94. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__f12b60be._.js +1 -1
  95. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  96. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  97. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +1 -1
  98. package/web/.next/standalone/src/presentation/web/app/api/ide/open/route.ts +4 -2
  99. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  100. package/web/.next/trace +1 -1
  101. package/web/.next/trace-build +1 -1
  102. package/dist/packages/core/src/infrastructure/services/ide-launchers/antigravity.launcher.d.ts +0 -10
  103. package/dist/packages/core/src/infrastructure/services/ide-launchers/antigravity.launcher.d.ts.map +0 -1
  104. package/dist/packages/core/src/infrastructure/services/ide-launchers/antigravity.launcher.js +0 -21
  105. package/dist/packages/core/src/infrastructure/services/ide-launchers/cursor.launcher.d.ts +0 -10
  106. package/dist/packages/core/src/infrastructure/services/ide-launchers/cursor.launcher.d.ts.map +0 -1
  107. package/dist/packages/core/src/infrastructure/services/ide-launchers/cursor.launcher.js +0 -21
  108. package/dist/packages/core/src/infrastructure/services/ide-launchers/ide-launcher.interface.d.ts +0 -31
  109. package/dist/packages/core/src/infrastructure/services/ide-launchers/ide-launcher.interface.d.ts.map +0 -1
  110. package/dist/packages/core/src/infrastructure/services/ide-launchers/ide-launcher.interface.js +0 -8
  111. package/dist/packages/core/src/infrastructure/services/ide-launchers/ide-launcher.registry.d.ts +0 -9
  112. package/dist/packages/core/src/infrastructure/services/ide-launchers/ide-launcher.registry.d.ts.map +0 -1
  113. package/dist/packages/core/src/infrastructure/services/ide-launchers/ide-launcher.registry.js +0 -24
  114. package/dist/packages/core/src/infrastructure/services/ide-launchers/launch-ide.d.ts +0 -30
  115. package/dist/packages/core/src/infrastructure/services/ide-launchers/launch-ide.d.ts.map +0 -1
  116. package/dist/packages/core/src/infrastructure/services/ide-launchers/launch-ide.js +0 -43
  117. package/dist/packages/core/src/infrastructure/services/ide-launchers/vscode.launcher.d.ts +0 -10
  118. package/dist/packages/core/src/infrastructure/services/ide-launchers/vscode.launcher.d.ts.map +0 -1
  119. package/dist/packages/core/src/infrastructure/services/ide-launchers/vscode.launcher.js +0 -21
  120. package/dist/packages/core/src/infrastructure/services/ide-launchers/windsurf.launcher.d.ts +0 -10
  121. package/dist/packages/core/src/infrastructure/services/ide-launchers/windsurf.launcher.d.ts.map +0 -1
  122. package/dist/packages/core/src/infrastructure/services/ide-launchers/windsurf.launcher.js +0 -21
  123. package/dist/packages/core/src/infrastructure/services/ide-launchers/zed.launcher.d.ts +0 -10
  124. package/dist/packages/core/src/infrastructure/services/ide-launchers/zed.launcher.d.ts.map +0 -1
  125. package/dist/packages/core/src/infrastructure/services/ide-launchers/zed.launcher.js +0 -21
  126. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_12059e3e.js +0 -3
  127. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_12059e3e.js.map +0 -1
  128. package/web/.next/server/chunks/[root-of-the-server]__0af905fe._.js +0 -3
  129. package/web/.next/server/chunks/[root-of-the-server]__0af905fe._.js.map +0 -1
  130. package/web/.next/server/chunks/[root-of-the-server]__72567d8d._.js +0 -3
  131. package/web/.next/server/chunks/[root-of-the-server]__72567d8d._.js.map +0 -1
  132. package/web/.next/standalone/src/presentation/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_12059e3e.js +0 -3
  133. package/web/.next/standalone/src/presentation/web/.next/server/chunks/[root-of-the-server]__0af905fe._.js +0 -3
  134. package/web/.next/standalone/src/presentation/web/.next/server/chunks/[root-of-the-server]__72567d8d._.js +0 -3
  135. /package/web/.next/static/{TkrzrZBiArd9QW2xebsyW → UemLwbVtqCGOm4FHNOp05}/_buildManifest.js +0 -0
  136. /package/web/.next/static/{TkrzrZBiArd9QW2xebsyW → UemLwbVtqCGOm4FHNOp05}/_clientMiddlewareManifest.json +0 -0
  137. /package/web/.next/static/{TkrzrZBiArd9QW2xebsyW → UemLwbVtqCGOm4FHNOp05}/_ssgManifest.js +0 -0
@@ -2,7 +2,7 @@
2
2
  "name": "Visual Studio Code",
3
3
  "summary": "Lightweight but powerful source code editor",
4
4
  "description": "Microsoft Visual Studio Code is a free, open-source code editor with built-in support for debugging, version control, and extensions for enhanced development workflows.",
5
- "category": "ide",
5
+ "tags": ["ide"],
6
6
  "binary": "code",
7
7
  "packageManager": "apt",
8
8
  "commands": {
@@ -13,5 +13,5 @@
13
13
  "documentationUrl": "https://code.visualstudio.com/docs/setup/linux",
14
14
  "verifyCommand": "code --version --no-sandbox --user-data-dir=/tmp/vscode-test",
15
15
  "autoInstall": true,
16
- "openDirectory": "code ."
16
+ "openDirectory": "code {dir}"
17
17
  }
@@ -2,7 +2,7 @@
2
2
  "name": "Windsurf",
3
3
  "summary": "AI-powered code editor by Codeium",
4
4
  "description": "Windsurf is an AI-powered code editor by Codeium that provides intelligent code assistance and automation features for modern development.",
5
- "category": "ide",
5
+ "tags": ["ide"],
6
6
  "binary": "windsurf",
7
7
  "packageManager": "apt",
8
8
  "commands": {
@@ -13,5 +13,5 @@
13
13
  "documentationUrl": "https://docs.windsurf.com/windsurf/getting-started",
14
14
  "verifyCommand": "windsurf --version --no-sandbox --user-data-dir=/tmp/windsurf-test",
15
15
  "autoInstall": true,
16
- "openDirectory": "windsurf ."
16
+ "openDirectory": "windsurf {dir}"
17
17
  }
@@ -2,7 +2,7 @@
2
2
  "name": "Zed",
3
3
  "summary": "High-performance code editor written in Rust",
4
4
  "description": "Zed is a high-performance code editor written in Rust, designed for speed and collaboration with modern developer workflows.",
5
- "category": "ide",
5
+ "tags": ["ide"],
6
6
  "binary": "zed",
7
7
  "packageManager": "curl",
8
8
  "commands": {
@@ -13,5 +13,5 @@
13
13
  "documentationUrl": "https://zed.dev/docs/installation",
14
14
  "verifyCommand": "zed --version",
15
15
  "autoInstall": true,
16
- "openDirectory": "zed ."
16
+ "openDirectory": "zed {dir}"
17
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"show.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/show.command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmFpC,wBAAgB,iBAAiB,IAAI,OAAO,CAiO3C"}
1
+ {"version":3,"file":"show.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/show.command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmFpC,wBAAgB,iBAAiB,IAAI,OAAO,CAwP3C"}
@@ -131,7 +131,9 @@ export function createShowCommand() {
131
131
  if (t.completedAt && t.durationMs != null) {
132
132
  const ms = Number(t.durationMs);
133
133
  const secs = (ms / 1000).toFixed(1);
134
- const barLen = maxDurationMs > 0 ? Math.max(1, Math.round((ms / maxDurationMs) * MAX_BAR)) : 1;
134
+ const barLen = maxDurationMs > 0
135
+ ? Math.min(MAX_BAR, Math.max(1, Math.round((ms / maxDurationMs) * MAX_BAR)))
136
+ : 1;
135
137
  const bar = `${colors.success('\u2588'.repeat(barLen))}${colors.muted('\u2591'.repeat(MAX_BAR - barLen))}`;
136
138
  lines.push(`${label} ${bar} ${secs}s`);
137
139
  }
@@ -151,13 +153,30 @@ export function createShowCommand() {
151
153
  }
152
154
  // Show approval wait time under gated phases
153
155
  if (t.approvalWaitMs != null && Number(t.approvalWaitMs) > 0) {
156
+ // Completed approval wait - show final duration
154
157
  const waitMs = Number(t.approvalWaitMs);
155
158
  const waitSecs = (waitMs / 1000).toFixed(1);
156
159
  const waitLabel = ' \u21b3 approval'.padEnd(16);
157
- const waitBarLen = maxDurationMs > 0 ? Math.max(1, Math.round((waitMs / maxDurationMs) * MAX_BAR)) : 1;
160
+ const waitBarLen = maxDurationMs > 0
161
+ ? Math.min(MAX_BAR, Math.max(1, Math.round((waitMs / maxDurationMs) * MAX_BAR)))
162
+ : 1;
158
163
  const waitBar = `${colors.warning('\u2588'.repeat(waitBarLen))}${colors.muted('\u2591'.repeat(MAX_BAR - waitBarLen))}`;
159
164
  lines.push(`${waitLabel} ${waitBar} ${waitSecs}s`);
160
165
  }
166
+ else if (isLast && isWaiting && t.waitingApprovalAt) {
167
+ // Live approval wait - show elapsed time
168
+ const waitStart = t.waitingApprovalAt instanceof Date
169
+ ? t.waitingApprovalAt.getTime()
170
+ : Number(t.waitingApprovalAt);
171
+ const waitElapsedMs = Math.max(0, Date.now() - waitStart);
172
+ const waitSecs = (waitElapsedMs / 1000).toFixed(1);
173
+ const waitLabel = ' \u21b3 approval'.padEnd(16);
174
+ const waitBarLen = maxDurationMs > 0
175
+ ? Math.min(MAX_BAR, Math.max(1, Math.round((waitElapsedMs / maxDurationMs) * MAX_BAR)))
176
+ : 1;
177
+ const waitBar = `${colors.warning('\u2588'.repeat(waitBarLen))}${colors.muted('\u2591'.repeat(MAX_BAR - waitBarLen))}`;
178
+ lines.push(`${waitLabel} ${waitBar} ${waitSecs}s (waiting)`);
179
+ }
161
180
  }
162
181
  // Summary totals
163
182
  const totalExecMs = timings.reduce((sum, t) => sum + (t.durationMs != null ? Number(t.durationMs) : 0), 0);
@@ -2,8 +2,10 @@
2
2
  * IDE Open Command
3
3
  *
4
4
  * Opens a feature worktree in the configured IDE.
5
+ * IDE flags (e.g. --vscode, --cursor) are derived dynamically from
6
+ * the JSON tool metadata files in packages/core.
5
7
  *
6
- * Usage: shep ide <feat-id> [--vscode|--cursor|--windsurf|--zed|--antigravity]
8
+ * Usage: shep ide <feat-id> [--<ide-name>]
7
9
  */
8
10
  import { Command } from 'commander';
9
11
  export declare function createIdeOpenCommand(): Command;
@@ -1 +1 @@
1
- {"version":3,"file":"ide-open.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/ide-open.command.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsCpC,wBAAgB,oBAAoB,IAAI,OAAO,CAkC9C"}
1
+ {"version":3,"file":"ide-open.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/ide-open.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBpC,wBAAgB,oBAAoB,IAAI,OAAO,CAwC9C"}
@@ -2,51 +2,49 @@
2
2
  * IDE Open Command
3
3
  *
4
4
  * Opens a feature worktree in the configured IDE.
5
+ * IDE flags (e.g. --vscode, --cursor) are derived dynamically from
6
+ * the JSON tool metadata files in packages/core.
5
7
  *
6
- * Usage: shep ide <feat-id> [--vscode|--cursor|--windsurf|--zed|--antigravity]
8
+ * Usage: shep ide <feat-id> [--<ide-name>]
7
9
  */
8
10
  import { Command } from 'commander';
9
- import { EditorType } from '../../../../packages/core/src/domain/generated/output.js';
10
11
  import { container } from '../../../../packages/core/src/infrastructure/di/container.js';
11
12
  import { ShowFeatureUseCase } from '../../../../packages/core/src/application/use-cases/features/show-feature.use-case.js';
13
+ import { LaunchIdeUseCase } from '../../../../packages/core/src/application/use-cases/ide/launch-ide.use-case.js';
12
14
  import { getSettings } from '../../../../packages/core/src/infrastructure/services/settings.service.js';
13
- import { launchIde } from '../../../../packages/core/src/infrastructure/services/ide-launchers/launch-ide.js';
15
+ import { getIdeEntries } from '../../../../packages/core/src/infrastructure/services/tool-installer/tool-metadata.js';
14
16
  import { messages } from '../ui/index.js';
15
- /** IDE flag names mapped to their EditorType values. */
16
- const IDE_FLAG_MAP = {
17
- vscode: EditorType.VsCode,
18
- cursor: EditorType.Cursor,
19
- windsurf: EditorType.Windsurf,
20
- zed: EditorType.Zed,
21
- antigravity: EditorType.Antigravity,
22
- };
17
+ /** Commander converts --kebab-case flags to camelCase option keys. */
18
+ function toCamelCase(s) {
19
+ return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
20
+ }
23
21
  /**
24
22
  * Determine which editor to use based on CLI flags and settings.
25
23
  * Flag takes precedence over settings.
26
24
  */
27
- function resolveEditorId(options) {
28
- for (const [flag, editorType] of Object.entries(IDE_FLAG_MAP)) {
29
- if (options[flag]) {
30
- return editorType;
31
- }
25
+ function resolveEditorId(options, ideIds) {
26
+ for (const id of ideIds) {
27
+ if (options[toCamelCase(id)])
28
+ return id;
32
29
  }
33
30
  return getSettings().environment.defaultEditor;
34
31
  }
35
32
  export function createIdeOpenCommand() {
36
- return new Command('ide')
33
+ const cmd = new Command('ide')
37
34
  .description('Open a feature worktree in your IDE')
38
- .argument('<feat-id>', 'Feature ID or prefix')
39
- .option('--vscode', 'Open in VS Code')
40
- .option('--cursor', 'Open in Cursor')
41
- .option('--windsurf', 'Open in Windsurf')
42
- .option('--zed', 'Open in Zed')
43
- .option('--antigravity', 'Open in Antigravity')
44
- .action(async (featId, options) => {
35
+ .argument('<feat-id>', 'Feature ID or prefix');
36
+ const ideEntries = getIdeEntries();
37
+ const ideIds = ideEntries.map(([id]) => id);
38
+ for (const [id, meta] of ideEntries) {
39
+ cmd.option(`--${id}`, `Open in ${meta.name}`);
40
+ }
41
+ cmd.action(async (featId, options) => {
45
42
  try {
46
- const editorId = resolveEditorId(options);
47
- const useCase = container.resolve(ShowFeatureUseCase);
48
- const feature = await useCase.execute(featId);
49
- const result = await launchIde({
43
+ const editorId = resolveEditorId(options, ideIds);
44
+ const showFeature = container.resolve(ShowFeatureUseCase);
45
+ const feature = await showFeature.execute(featId);
46
+ const launchIde = container.resolve(LaunchIdeUseCase);
47
+ const result = await launchIde.execute({
50
48
  editorId,
51
49
  repositoryPath: feature.repositoryPath,
52
50
  branch: feature.branch,
@@ -64,4 +62,5 @@ export function createIdeOpenCommand() {
64
62
  process.exitCode = 1;
65
63
  }
66
64
  });
65
+ return cmd;
67
66
  }
@@ -17,8 +17,8 @@ import { TOOL_METADATA } from '../../../../packages/core/src/infrastructure/serv
17
17
  import { messages, fmt, colors } from '../ui/index.js';
18
18
  function printToolsList() {
19
19
  const tools = Object.entries(TOOL_METADATA);
20
- const ides = tools.filter(([, meta]) => meta.category === 'ide');
21
- const cliAgents = tools.filter(([, meta]) => meta.category === 'cli-agent');
20
+ const ides = tools.filter(([, meta]) => meta.tags.includes('ide'));
21
+ const cliAgents = tools.filter(([, meta]) => meta.tags.includes('cli-agent'));
22
22
  console.log(fmt.heading('IDEs:'));
23
23
  for (const [key, meta] of ides) {
24
24
  console.log(` ${colors.accent(key.padEnd(16))}${meta.name} - ${colors.muted(meta.summary)}`);
@@ -101,7 +101,7 @@ function printInstallInstructions(metadata) {
101
101
  console.log(`${fmt.label('Name:')} ${metadata.name}`);
102
102
  console.log(`${fmt.label('Summary:')} ${metadata.summary}`);
103
103
  console.log(`${fmt.label('Description:')} ${metadata.description}`);
104
- console.log(`${fmt.label('Category:')} ${metadata.category}`);
104
+ console.log(`${fmt.label('Tags:')} ${metadata.tags.join(', ')}`);
105
105
  console.log();
106
106
  const binaryDisplay = typeof metadata.binary === 'string'
107
107
  ? metadata.binary
@@ -2,6 +2,7 @@
2
2
  * IDE Configuration Command
3
3
  *
4
4
  * Configures the preferred IDE/editor used by Shep.
5
+ * Valid editors are derived dynamically from JSON tool metadata.
5
6
  *
6
7
  * Usage:
7
8
  * shep settings ide # Interactive selection
@@ -1 +1 @@
1
- {"version":3,"file":"ide.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/settings/ide.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAkE1C"}
1
+ {"version":3,"file":"ide.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/settings/ide.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CA+D1C"}
@@ -2,6 +2,7 @@
2
2
  * IDE Configuration Command
3
3
  *
4
4
  * Configures the preferred IDE/editor used by Shep.
5
+ * Valid editors are derived dynamically from JSON tool metadata.
5
6
  *
6
7
  * Usage:
7
8
  * shep settings ide # Interactive selection
@@ -9,22 +10,21 @@
9
10
  */
10
11
  import { Command } from 'commander';
11
12
  import { select } from '@inquirer/prompts';
12
- import { EditorType } from '../../../../../packages/core/src/domain/generated/output.js';
13
13
  import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
14
14
  import { UpdateSettingsUseCase } from '../../../../../packages/core/src/application/use-cases/settings/update-settings.use-case.js';
15
15
  import { createIdeSelectConfig } from '../../../tui/prompts/ide-select.prompt.js';
16
16
  import { getSettings, resetSettings, initializeSettings, } from '../../../../../packages/core/src/infrastructure/services/settings.service.js';
17
- import { createLauncherRegistry } from '../../../../../packages/core/src/infrastructure/services/ide-launchers/ide-launcher.registry.js';
17
+ import { getIdeEntries } from '../../../../../packages/core/src/infrastructure/services/tool-installer/tool-metadata.js';
18
18
  import { messages } from '../../ui/index.js';
19
- /** Valid EditorType values for input validation. */
20
- const VALID_EDITORS = new Set(Object.values(EditorType));
19
+ /** Valid IDE tool IDs derived from JSON metadata. */
20
+ const VALID_EDITORS = new Set(getIdeEntries().map(([id]) => id));
21
21
  /**
22
22
  * Create the IDE configuration command.
23
23
  */
24
24
  export function createIdeCommand() {
25
25
  return new Command('ide')
26
26
  .description('Configure preferred IDE/editor')
27
- .option('--editor <name>', 'IDE/editor name (e.g., vscode, cursor, windsurf, zed, antigravity)')
27
+ .option('--editor <name>', `IDE/editor name (${[...VALID_EDITORS].join(', ')})`)
28
28
  .addHelpText('after', `
29
29
  Examples:
30
30
  $ shep settings ide Interactive selection
@@ -44,14 +44,11 @@ Examples:
44
44
  else {
45
45
  editorValue = await select(createIdeSelectConfig());
46
46
  }
47
- // PATH check via launcher registry (non-blocking warning)
48
- const registry = createLauncherRegistry();
49
- const launcher = registry.get(editorValue);
50
- if (launcher) {
51
- const available = await launcher.checkAvailable();
52
- if (!available) {
53
- messages.warning(`'${launcher.binary}' not found in PATH. The editor will still be saved.`);
54
- }
47
+ // PATH check via IDE launcher service (non-blocking warning)
48
+ const ideLauncher = container.resolve('IIdeLauncherService');
49
+ const available = await ideLauncher.checkAvailability(editorValue);
50
+ if (!available) {
51
+ messages.warning(`Editor '${editorValue}' not found in PATH. The editor will still be saved.`);
55
52
  }
56
53
  // Persist settings
57
54
  const settings = getSettings();
@@ -2,36 +2,20 @@
2
2
  * IDE Select Prompt Configuration
3
3
  *
4
4
  * Configuration for the @inquirer/select prompt that lets users
5
- * choose their preferred IDE/editor.
5
+ * choose their preferred IDE/editor. Choices are derived dynamically
6
+ * from JSON tool metadata (any tool with openDirectory).
6
7
  */
7
- import { EditorType } from '../../../../packages/core/src/domain/generated/output.js';
8
8
  /**
9
9
  * Creates the @inquirer/select configuration for selecting a preferred IDE.
10
10
  */
11
11
  export declare function createIdeSelectConfig(): {
12
- readonly message: "Select your preferred IDE";
13
- readonly choices: readonly [{
14
- readonly name: "VS Code";
15
- readonly value: EditorType.VsCode;
16
- readonly description: "Visual Studio Code";
17
- }, {
18
- readonly name: "Cursor";
19
- readonly value: EditorType.Cursor;
20
- readonly description: "Cursor AI editor";
21
- }, {
22
- readonly name: "Windsurf";
23
- readonly value: EditorType.Windsurf;
24
- readonly description: "Windsurf editor";
25
- }, {
26
- readonly name: "Zed";
27
- readonly value: EditorType.Zed;
28
- readonly description: "Zed editor";
29
- }, {
30
- readonly name: "Antigravity";
31
- readonly value: EditorType.Antigravity;
32
- readonly description: "Google Antigravity IDE";
33
- }];
34
- readonly theme: {
12
+ message: string;
13
+ choices: {
14
+ name: string;
15
+ value: string;
16
+ description: string;
17
+ }[];
18
+ theme: {
35
19
  readonly prefix: {
36
20
  readonly idle: string;
37
21
  readonly done: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ide-select.prompt.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/prompts/ide-select.prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAG1D;;GAEG;AACH,wBAAgB,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCpC"}
1
+ {"version":3,"file":"ide-select.prompt.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/prompts/ide-select.prompt.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH;;GAEG;AACH,wBAAgB,qBAAqB;;;;;;;;;;;;;;;;;EAYpC"}
@@ -2,43 +2,23 @@
2
2
  * IDE Select Prompt Configuration
3
3
  *
4
4
  * Configuration for the @inquirer/select prompt that lets users
5
- * choose their preferred IDE/editor.
5
+ * choose their preferred IDE/editor. Choices are derived dynamically
6
+ * from JSON tool metadata (any tool with openDirectory).
6
7
  */
7
- import { EditorType } from '../../../../packages/core/src/domain/generated/output.js';
8
+ import { getIdeEntries } from '../../../../packages/core/src/infrastructure/services/tool-installer/tool-metadata.js';
8
9
  import { shepTheme } from '../themes/shep.theme.js';
9
10
  /**
10
11
  * Creates the @inquirer/select configuration for selecting a preferred IDE.
11
12
  */
12
13
  export function createIdeSelectConfig() {
14
+ const choices = getIdeEntries().map(([id, meta]) => ({
15
+ name: meta.name,
16
+ value: id,
17
+ description: meta.summary,
18
+ }));
13
19
  return {
14
20
  message: 'Select your preferred IDE',
15
- choices: [
16
- {
17
- name: 'VS Code',
18
- value: EditorType.VsCode,
19
- description: 'Visual Studio Code',
20
- },
21
- {
22
- name: 'Cursor',
23
- value: EditorType.Cursor,
24
- description: 'Cursor AI editor',
25
- },
26
- {
27
- name: 'Windsurf',
28
- value: EditorType.Windsurf,
29
- description: 'Windsurf editor',
30
- },
31
- {
32
- name: 'Zed',
33
- value: EditorType.Zed,
34
- description: 'Zed editor',
35
- },
36
- {
37
- name: 'Antigravity',
38
- value: EditorType.Antigravity,
39
- description: 'Google Antigravity IDE',
40
- },
41
- ],
21
+ choices,
42
22
  theme: shepTheme,
43
23
  };
44
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../../src/presentation/web/app/api/ide/open/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,wBAAsB,IAAI,CAAC,OAAO,EAAE,OAAO;;;;;;IAoC1C"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../../src/presentation/web/app/api/ide/open/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,wBAAsB,IAAI,CAAC,OAAO,EAAE,OAAO;;;;;;IAqC1C"}
@@ -1,6 +1,6 @@
1
1
  import { NextResponse } from 'next/server';
2
2
  import { getSettings } from '../../../../../../../packages/core/src/infrastructure/services/settings.service.js';
3
- import { launchIde } from '../../../../../../../packages/core/src/infrastructure/services/ide-launchers/launch-ide.js';
3
+ import { resolve } from '../../../../lib/server-container.js';
4
4
  import { validateToolbarInput } from '../../validate-toolbar-input.js';
5
5
  export async function POST(request) {
6
6
  let body;
@@ -17,7 +17,8 @@ export async function POST(request) {
17
17
  const { repositoryPath, branch } = validation;
18
18
  const settings = getSettings();
19
19
  const editor = settings.environment.defaultEditor;
20
- const result = await launchIde({
20
+ const useCase = resolve('LaunchIdeUseCase');
21
+ const result = await useCase.execute({
21
22
  editorId: editor,
22
23
  repositoryPath,
23
24
  branch,