@shepai/cli 1.17.0 → 1.19.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 (119) hide show
  1. package/dist/eslint.config.mjs +8 -1
  2. package/dist/src/application/ports/output/agents/agent-executor.interface.d.ts +4 -0
  3. package/dist/src/application/ports/output/agents/agent-executor.interface.d.ts.map +1 -1
  4. package/dist/src/domain/factories/settings-defaults.factory.js +2 -2
  5. package/dist/src/domain/generated/output.d.ts +8 -1
  6. package/dist/src/domain/generated/output.d.ts.map +1 -1
  7. package/dist/src/domain/generated/output.js +8 -0
  8. package/dist/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
  9. package/dist/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts.map +1 -1
  10. package/dist/src/infrastructure/services/agents/common/executors/claude-code-executor.service.js +4 -0
  11. package/dist/src/infrastructure/services/agents/feature-agent/nodes/implement.node.d.ts.map +1 -1
  12. package/dist/src/infrastructure/services/agents/feature-agent/nodes/implement.node.js +13 -3
  13. package/dist/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +35 -1
  14. package/dist/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
  15. package/dist/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +96 -1
  16. package/dist/src/infrastructure/services/ide-launchers/antigravity.launcher.d.ts +10 -0
  17. package/dist/src/infrastructure/services/ide-launchers/antigravity.launcher.d.ts.map +1 -0
  18. package/dist/src/infrastructure/services/ide-launchers/antigravity.launcher.js +21 -0
  19. package/dist/src/infrastructure/services/ide-launchers/cursor.launcher.d.ts +10 -0
  20. package/dist/src/infrastructure/services/ide-launchers/cursor.launcher.d.ts.map +1 -0
  21. package/dist/src/infrastructure/services/ide-launchers/cursor.launcher.js +21 -0
  22. package/dist/src/infrastructure/services/ide-launchers/ide-launcher.interface.d.ts +31 -0
  23. package/dist/src/infrastructure/services/ide-launchers/ide-launcher.interface.d.ts.map +1 -0
  24. package/dist/src/infrastructure/services/ide-launchers/ide-launcher.interface.js +8 -0
  25. package/dist/src/infrastructure/services/ide-launchers/ide-launcher.registry.d.ts +9 -0
  26. package/dist/src/infrastructure/services/ide-launchers/ide-launcher.registry.d.ts.map +1 -0
  27. package/dist/src/infrastructure/services/ide-launchers/ide-launcher.registry.js +24 -0
  28. package/dist/src/infrastructure/services/ide-launchers/vscode.launcher.d.ts +10 -0
  29. package/dist/src/infrastructure/services/ide-launchers/vscode.launcher.d.ts.map +1 -0
  30. package/dist/src/infrastructure/services/ide-launchers/vscode.launcher.js +21 -0
  31. package/dist/src/infrastructure/services/ide-launchers/windsurf.launcher.d.ts +10 -0
  32. package/dist/src/infrastructure/services/ide-launchers/windsurf.launcher.d.ts.map +1 -0
  33. package/dist/src/infrastructure/services/ide-launchers/windsurf.launcher.js +21 -0
  34. package/dist/src/infrastructure/services/ide-launchers/zed.launcher.d.ts +10 -0
  35. package/dist/src/infrastructure/services/ide-launchers/zed.launcher.d.ts.map +1 -0
  36. package/dist/src/infrastructure/services/ide-launchers/zed.launcher.js +21 -0
  37. package/dist/src/presentation/cli/commands/ide-open.command.d.ts +10 -0
  38. package/dist/src/presentation/cli/commands/ide-open.command.d.ts.map +1 -0
  39. package/dist/src/presentation/cli/commands/ide-open.command.js +77 -0
  40. package/dist/src/presentation/cli/commands/settings/ide.command.d.ts +15 -0
  41. package/dist/src/presentation/cli/commands/settings/ide.command.d.ts.map +1 -0
  42. package/dist/src/presentation/cli/commands/settings/ide.command.js +76 -0
  43. package/dist/src/presentation/cli/commands/settings/index.d.ts.map +1 -1
  44. package/dist/src/presentation/cli/commands/settings/index.js +3 -1
  45. package/dist/src/presentation/cli/index.js +2 -0
  46. package/dist/src/presentation/tui/prompts/ide-select.prompt.d.ts +45 -0
  47. package/dist/src/presentation/tui/prompts/ide-select.prompt.d.ts.map +1 -0
  48. package/dist/src/presentation/tui/prompts/ide-select.prompt.js +44 -0
  49. package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.js +1 -1
  50. package/dist/src/presentation/web/components/ui/alert.js +1 -1
  51. package/dist/src/presentation/web/components/ui/badge.js +4 -4
  52. package/dist/src/presentation/web/components/ui/button.js +3 -3
  53. package/dist/src/presentation/web/components/ui/sidebar.js +2 -2
  54. package/dist/tsconfig.build.tsbuildinfo +1 -1
  55. package/package.json +1 -1
  56. package/web/.next/BUILD_ID +1 -1
  57. package/web/.next/build-manifest.json +2 -2
  58. package/web/.next/cache/.previewinfo +1 -1
  59. package/web/.next/cache/.rscinfo +1 -1
  60. package/web/.next/cache/.tsbuildinfo +1 -1
  61. package/web/.next/cache/config.json +3 -3
  62. package/web/.next/fallback-build-manifest.json +2 -2
  63. package/web/.next/prerender-manifest.json +3 -3
  64. package/web/.next/required-server-files.js +1 -1
  65. package/web/.next/required-server-files.json +1 -1
  66. package/web/.next/server/app/_global-error.html +2 -2
  67. package/web/.next/server/app/_global-error.rsc +1 -1
  68. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  69. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  70. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  71. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  72. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  73. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  74. package/web/.next/server/app/_not-found.html +2 -2
  75. package/web/.next/server/app/_not-found.rsc +8 -8
  76. package/web/.next/server/app/_not-found.segments/_full.segment.rsc +8 -8
  77. package/web/.next/server/app/_not-found.segments/_head.segment.rsc +3 -3
  78. package/web/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  79. package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  80. package/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  81. package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  82. package/web/.next/server/app/index.html +2 -2
  83. package/web/.next/server/app/index.rsc +3 -3
  84. package/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  85. package/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
  86. package/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  87. package/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
  88. package/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  89. package/web/.next/server/app/page_client-reference-manifest.js +1 -1
  90. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  91. package/web/.next/server/app/version.html +2 -2
  92. package/web/.next/server/app/version.rsc +3 -3
  93. package/web/.next/server/app/version.segments/_full.segment.rsc +3 -3
  94. package/web/.next/server/app/version.segments/_head.segment.rsc +1 -1
  95. package/web/.next/server/app/version.segments/_index.segment.rsc +2 -2
  96. package/web/.next/server/app/version.segments/_tree.segment.rsc +1 -1
  97. package/web/.next/server/app/version.segments/version/__PAGE__.segment.rsc +2 -2
  98. package/web/.next/server/app/version.segments/version.segment.rsc +1 -1
  99. package/web/.next/server/chunks/ssr/_0f02ab66._.js +1 -1
  100. package/web/.next/server/chunks/ssr/_0f02ab66._.js.map +1 -1
  101. package/web/.next/server/chunks/ssr/_19be0743._.js +1 -1
  102. package/web/.next/server/chunks/ssr/_4582f3c3._.js +1 -1
  103. package/web/.next/server/chunks/ssr/_4582f3c3._.js.map +1 -1
  104. package/web/.next/server/chunks/ssr/_a0c04017._.js +1 -1
  105. package/web/.next/server/chunks/ssr/_a0c04017._.js.map +1 -1
  106. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_version_version-page-client_tsx_fe9db753._.js +1 -1
  107. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_version_version-page-client_tsx_fe9db753._.js.map +1 -1
  108. package/web/.next/server/pages/404.html +2 -2
  109. package/web/.next/server/pages/500.html +2 -2
  110. package/web/.next/server/server-reference-manifest.js +1 -1
  111. package/web/.next/server/server-reference-manifest.json +1 -1
  112. package/web/.next/static/chunks/{5130d7093ad39f4a.js → 26d260496abf3ed8.js} +1 -1
  113. package/web/.next/static/chunks/{ef1296dbe67d5aae.js → 8353f5690707d9a5.js} +1 -1
  114. package/web/.next/static/chunks/{523c5cfe0570712c.js → f74cb59a5a6c94f1.js} +1 -1
  115. package/web/.next/trace +1 -1
  116. package/web/.next/trace-build +1 -1
  117. /package/web/.next/static/{Wgd1DC_QfVhpAi62LjpwI → nw4IT0rr_mE5Tx22X9OgO}/_buildManifest.js +0 -0
  118. /package/web/.next/static/{Wgd1DC_QfVhpAi62LjpwI → nw4IT0rr_mE5Tx22X9OgO}/_clientMiddlewareManifest.json +0 -0
  119. /package/web/.next/static/{Wgd1DC_QfVhpAi62LjpwI → nw4IT0rr_mE5Tx22X9OgO}/_ssgManifest.js +0 -0
@@ -0,0 +1,21 @@
1
+ import { spawn, execFile } from 'node:child_process';
2
+ import { EditorType } from '../../../domain/generated/output.js';
3
+ export class VsCodeLauncher {
4
+ name = 'VS Code';
5
+ editorId = EditorType.VsCode;
6
+ binary = 'code';
7
+ async launch(path) {
8
+ const child = spawn(this.binary, [path], {
9
+ detached: true,
10
+ stdio: 'ignore',
11
+ });
12
+ child.unref();
13
+ }
14
+ checkAvailable() {
15
+ return new Promise((resolve) => {
16
+ execFile('which', [this.binary], (err) => {
17
+ resolve(!err);
18
+ });
19
+ });
20
+ }
21
+ }
@@ -0,0 +1,10 @@
1
+ import { EditorType } from '../../../domain/generated/output.js';
2
+ import type { IdeLauncher } from './ide-launcher.interface';
3
+ export declare class WindsurfLauncher implements IdeLauncher {
4
+ readonly name = "Windsurf";
5
+ readonly editorId = EditorType.Windsurf;
6
+ readonly binary = "windsurf";
7
+ launch(path: string): Promise<void>;
8
+ checkAvailable(): Promise<boolean>;
9
+ }
10
+ //# sourceMappingURL=windsurf.launcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windsurf.launcher.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/ide-launchers/windsurf.launcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,qBAAa,gBAAiB,YAAW,WAAW;IAClD,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,QAAQ,uBAAuB;IACxC,QAAQ,CAAC,MAAM,cAAc;IAEvB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CAOnC"}
@@ -0,0 +1,21 @@
1
+ import { spawn, execFile } from 'node:child_process';
2
+ import { EditorType } from '../../../domain/generated/output.js';
3
+ export class WindsurfLauncher {
4
+ name = 'Windsurf';
5
+ editorId = EditorType.Windsurf;
6
+ binary = 'windsurf';
7
+ async launch(path) {
8
+ const child = spawn(this.binary, [path], {
9
+ detached: true,
10
+ stdio: 'ignore',
11
+ });
12
+ child.unref();
13
+ }
14
+ checkAvailable() {
15
+ return new Promise((resolve) => {
16
+ execFile('which', [this.binary], (err) => {
17
+ resolve(!err);
18
+ });
19
+ });
20
+ }
21
+ }
@@ -0,0 +1,10 @@
1
+ import { EditorType } from '../../../domain/generated/output.js';
2
+ import type { IdeLauncher } from './ide-launcher.interface';
3
+ export declare class ZedLauncher implements IdeLauncher {
4
+ readonly name = "Zed";
5
+ readonly editorId = EditorType.Zed;
6
+ readonly binary = "zed";
7
+ launch(path: string): Promise<void>;
8
+ checkAvailable(): Promise<boolean>;
9
+ }
10
+ //# sourceMappingURL=zed.launcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zed.launcher.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/ide-launchers/zed.launcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,qBAAa,WAAY,YAAW,WAAW;IAC7C,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,QAAQ,kBAAkB;IACnC,QAAQ,CAAC,MAAM,SAAS;IAElB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CAOnC"}
@@ -0,0 +1,21 @@
1
+ import { spawn, execFile } from 'node:child_process';
2
+ import { EditorType } from '../../../domain/generated/output.js';
3
+ export class ZedLauncher {
4
+ name = 'Zed';
5
+ editorId = EditorType.Zed;
6
+ binary = 'zed';
7
+ async launch(path) {
8
+ const child = spawn(this.binary, [path], {
9
+ detached: true,
10
+ stdio: 'ignore',
11
+ });
12
+ child.unref();
13
+ }
14
+ checkAvailable() {
15
+ return new Promise((resolve) => {
16
+ execFile('which', [this.binary], (err) => {
17
+ resolve(!err);
18
+ });
19
+ });
20
+ }
21
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * IDE Open Command
3
+ *
4
+ * Opens a feature worktree in the configured IDE.
5
+ *
6
+ * Usage: shep ide <feat-id> [--vscode|--cursor|--windsurf|--zed|--antigravity]
7
+ */
8
+ import { Command } from 'commander';
9
+ export declare function createIdeOpenCommand(): Command;
10
+ //# sourceMappingURL=ide-open.command.d.ts.map
@@ -0,0 +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;AA+CpC,wBAAgB,oBAAoB,IAAI,OAAO,CAwC9C"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * IDE Open Command
3
+ *
4
+ * Opens a feature worktree in the configured IDE.
5
+ *
6
+ * Usage: shep ide <feat-id> [--vscode|--cursor|--windsurf|--zed|--antigravity]
7
+ */
8
+ import { Command } from 'commander';
9
+ import { createHash } from 'node:crypto';
10
+ import { join } from 'node:path';
11
+ import { EditorType } from '../../../domain/generated/output.js';
12
+ import { container } from '../../../infrastructure/di/container.js';
13
+ import { ShowFeatureUseCase } from '../../../application/use-cases/features/show-feature.use-case.js';
14
+ import { getSettings } from '../../../infrastructure/services/settings.service.js';
15
+ import { createLauncherRegistry } from '../../../infrastructure/services/ide-launchers/ide-launcher.registry.js';
16
+ import { SHEP_HOME_DIR } from '../../../infrastructure/services/filesystem/shep-directory.service.js';
17
+ import { messages } from '../ui/index.js';
18
+ function computeWorktreePath(repoPath, branch) {
19
+ const repoHash = createHash('sha256').update(repoPath).digest('hex').slice(0, 16);
20
+ const slug = branch.replace(/\//g, '-');
21
+ return join(SHEP_HOME_DIR, 'repos', repoHash, 'wt', slug);
22
+ }
23
+ /** IDE flag names mapped to their EditorType values. */
24
+ const IDE_FLAG_MAP = {
25
+ vscode: EditorType.VsCode,
26
+ cursor: EditorType.Cursor,
27
+ windsurf: EditorType.Windsurf,
28
+ zed: EditorType.Zed,
29
+ antigravity: EditorType.Antigravity,
30
+ };
31
+ /**
32
+ * Determine which editor to use based on CLI flags and settings.
33
+ * Flag takes precedence over settings.
34
+ */
35
+ function resolveEditorId(options) {
36
+ for (const [flag, editorType] of Object.entries(IDE_FLAG_MAP)) {
37
+ if (options[flag]) {
38
+ return editorType;
39
+ }
40
+ }
41
+ return getSettings().environment.defaultEditor;
42
+ }
43
+ export function createIdeOpenCommand() {
44
+ return new Command('ide')
45
+ .description('Open a feature worktree in your IDE')
46
+ .argument('<feat-id>', 'Feature ID or prefix')
47
+ .option('--vscode', 'Open in VS Code')
48
+ .option('--cursor', 'Open in Cursor')
49
+ .option('--windsurf', 'Open in Windsurf')
50
+ .option('--zed', 'Open in Zed')
51
+ .option('--antigravity', 'Open in Antigravity')
52
+ .action(async (featId, options) => {
53
+ try {
54
+ // Resolve the editor
55
+ const editorId = resolveEditorId(options);
56
+ const registry = createLauncherRegistry();
57
+ const launcher = registry.get(editorId);
58
+ if (!launcher) {
59
+ messages.error(`Unknown editor "${editorId}". Supported: ${[...registry.keys()].join(', ')}`, new Error(`Unknown editor: ${editorId}`));
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+ // Resolve the feature
64
+ const useCase = container.resolve(ShowFeatureUseCase);
65
+ const feature = await useCase.execute(featId);
66
+ // Compute worktree path and launch
67
+ const worktreePath = computeWorktreePath(feature.repositoryPath, feature.branch);
68
+ await launcher.launch(worktreePath);
69
+ messages.success(`Opened ${launcher.name} at ${worktreePath}`);
70
+ }
71
+ catch (error) {
72
+ const err = error instanceof Error ? error : new Error(String(error));
73
+ messages.error('Failed to open IDE', err);
74
+ process.exitCode = 1;
75
+ }
76
+ });
77
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * IDE Configuration Command
3
+ *
4
+ * Configures the preferred IDE/editor used by Shep.
5
+ *
6
+ * Usage:
7
+ * shep settings ide # Interactive selection
8
+ * shep settings ide --editor cursor # Non-interactive
9
+ */
10
+ import { Command } from 'commander';
11
+ /**
12
+ * Create the IDE configuration command.
13
+ */
14
+ export declare function createIdeCommand(): Command;
15
+ //# sourceMappingURL=ide.command.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * IDE Configuration Command
3
+ *
4
+ * Configures the preferred IDE/editor used by Shep.
5
+ *
6
+ * Usage:
7
+ * shep settings ide # Interactive selection
8
+ * shep settings ide --editor cursor # Non-interactive
9
+ */
10
+ import { Command } from 'commander';
11
+ import { select } from '@inquirer/prompts';
12
+ import { EditorType } from '../../../../domain/generated/output.js';
13
+ import { container } from '../../../../infrastructure/di/container.js';
14
+ import { UpdateSettingsUseCase } from '../../../../application/use-cases/settings/update-settings.use-case.js';
15
+ import { createIdeSelectConfig } from '../../../tui/prompts/ide-select.prompt.js';
16
+ import { getSettings, resetSettings, initializeSettings, } from '../../../../infrastructure/services/settings.service.js';
17
+ import { createLauncherRegistry } from '../../../../infrastructure/services/ide-launchers/ide-launcher.registry.js';
18
+ import { messages } from '../../ui/index.js';
19
+ /** Valid EditorType values for input validation. */
20
+ const VALID_EDITORS = new Set(Object.values(EditorType));
21
+ /**
22
+ * Create the IDE configuration command.
23
+ */
24
+ export function createIdeCommand() {
25
+ return new Command('ide')
26
+ .description('Configure preferred IDE/editor')
27
+ .option('--editor <name>', 'IDE/editor name (e.g., vscode, cursor, windsurf, zed, antigravity)')
28
+ .addHelpText('after', `
29
+ Examples:
30
+ $ shep settings ide Interactive selection
31
+ $ shep settings ide --editor cursor Non-interactive
32
+ $ shep settings ide --editor antigravity Set Google Antigravity`)
33
+ .action(async (options) => {
34
+ try {
35
+ let editorValue;
36
+ if (options.editor !== undefined) {
37
+ if (!VALID_EDITORS.has(options.editor)) {
38
+ messages.error(`Unknown editor "${options.editor}". Valid: ${[...VALID_EDITORS].join(', ')}`, new Error(`Unknown editor: ${options.editor}`));
39
+ process.exitCode = 1;
40
+ return;
41
+ }
42
+ editorValue = options.editor;
43
+ }
44
+ else {
45
+ editorValue = await select(createIdeSelectConfig());
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
+ }
55
+ }
56
+ // Persist settings
57
+ const settings = getSettings();
58
+ settings.environment.defaultEditor = editorValue;
59
+ const useCase = container.resolve(UpdateSettingsUseCase);
60
+ const updatedSettings = await useCase.execute(settings);
61
+ // Refresh in-memory singleton
62
+ resetSettings();
63
+ initializeSettings(updatedSettings);
64
+ messages.success(`Default editor set to: ${editorValue}`);
65
+ }
66
+ catch (error) {
67
+ const err = error instanceof Error ? error : new Error(String(error));
68
+ if (err.message.includes('force closed') || err.message.includes('User force closed')) {
69
+ messages.info('Configuration cancelled.');
70
+ return;
71
+ }
72
+ messages.error('Failed to configure IDE', err);
73
+ process.exitCode = 1;
74
+ }
75
+ });
76
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/settings/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAM/C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/settings/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAO/C"}
@@ -12,6 +12,7 @@ import { Command } from 'commander';
12
12
  import { createShowCommand } from './show.command.js';
13
13
  import { createInitCommand } from './init.command.js';
14
14
  import { createAgentCommand } from './agent.command.js';
15
+ import { createIdeCommand } from './ide.command.js';
15
16
  /**
16
17
  * Create the settings command group
17
18
  */
@@ -20,5 +21,6 @@ export function createSettingsCommand() {
20
21
  .description('Manage Shep global settings')
21
22
  .addCommand(createShowCommand())
22
23
  .addCommand(createInitCommand())
23
- .addCommand(createAgentCommand());
24
+ .addCommand(createAgentCommand())
25
+ .addCommand(createIdeCommand());
24
26
  }
@@ -30,6 +30,7 @@ import { createUiCommand } from './commands/ui.command.js';
30
30
  import { createRunCommand } from './commands/run.command.js';
31
31
  import { createAgentCommand } from './commands/agent/index.js';
32
32
  import { createFeatCommand } from './commands/feat/index.js';
33
+ import { createIdeOpenCommand } from './commands/ide-open.command.js';
33
34
  import { messages } from './ui/index.js';
34
35
  // DI container and settings
35
36
  import { initializeContainer, container } from '../../infrastructure/di/container.js';
@@ -78,6 +79,7 @@ async function bootstrap() {
78
79
  program.addCommand(createRunCommand());
79
80
  program.addCommand(createAgentCommand());
80
81
  program.addCommand(createFeatCommand());
82
+ program.addCommand(createIdeOpenCommand());
81
83
  // Parse arguments (parseAsync needed for async command actions like init)
82
84
  await program.parseAsync();
83
85
  }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * IDE Select Prompt Configuration
3
+ *
4
+ * Configuration for the @inquirer/select prompt that lets users
5
+ * choose their preferred IDE/editor.
6
+ */
7
+ import { EditorType } from '../../../domain/generated/output.js';
8
+ /**
9
+ * Creates the @inquirer/select configuration for selecting a preferred IDE.
10
+ */
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: {
35
+ readonly prefix: {
36
+ readonly idle: string;
37
+ readonly done: string;
38
+ };
39
+ readonly style: {
40
+ readonly highlight: import("picocolors/types.js").Formatter;
41
+ readonly answer: import("picocolors/types.js").Formatter;
42
+ };
43
+ };
44
+ };
45
+ //# sourceMappingURL=ide-select.prompt.d.ts.map
@@ -0,0 +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,qCAAqC,CAAC;AAGjE;;GAEG;AACH,wBAAgB,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCpC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * IDE Select Prompt Configuration
3
+ *
4
+ * Configuration for the @inquirer/select prompt that lets users
5
+ * choose their preferred IDE/editor.
6
+ */
7
+ import { EditorType } from '../../../domain/generated/output.js';
8
+ import { shepTheme } from '../themes/shep.theme.js';
9
+ /**
10
+ * Creates the @inquirer/select configuration for selecting a preferred IDE.
11
+ */
12
+ export function createIdeSelectConfig() {
13
+ return {
14
+ 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
+ ],
42
+ theme: shepTheme,
43
+ };
44
+ }
@@ -7,5 +7,5 @@ import { useSidebar } from '../../ui/sidebar';
7
7
  import { cn } from '../../../lib/utils';
8
8
  export function SidebarSectionHeader({ label, onFolderClick, onMenuClick, className, }) {
9
9
  const { state, isMobile } = useSidebar();
10
- return (_jsx(SidebarGroup, { "data-testid": "sidebar-section-header", className: cn('px-2 py-1', className), children: _jsxs("div", { className: "text-sidebar-foreground flex h-7 w-full shrink-0 items-center px-2 text-sm font-medium", children: [_jsx("span", { className: "min-w-0 flex-1 truncate", children: label }), _jsxs("span", { className: "text-sidebar-foreground/70 flex shrink-0 items-center gap-0.5", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: onFolderClick, className: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground ring-sidebar-ring flex size-7 items-center justify-center rounded-md p-0 outline-hidden transition-colors focus-visible:ring-2 [&>svg]:size-4", "aria-label": "Open features folder", children: _jsx(Folder, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "right", align: "center", hidden: state !== 'collapsed' || isMobile, children: "Open features folder" })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: onMenuClick, className: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground ring-sidebar-ring flex size-7 items-center justify-center rounded-md p-0 outline-hidden transition-colors focus-visible:ring-2 [&>svg]:size-4", "aria-label": "Features options", children: _jsx(GripHorizontal, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "right", align: "center", hidden: state !== 'collapsed' || isMobile, children: "Features options" })] })] })] }) }));
10
+ return (_jsx(SidebarGroup, { "data-testid": "sidebar-section-header", className: cn('px-2 py-1', className), children: _jsxs("div", { className: "text-sidebar-foreground flex h-7 w-full shrink-0 items-center px-2 text-sm font-medium", children: [_jsx("span", { className: "min-w-0 flex-1 truncate", children: label }), _jsxs("span", { className: "text-sidebar-foreground/70 flex shrink-0 items-center gap-0.5", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: onFolderClick, className: "ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground flex size-7 items-center justify-center rounded-md p-0 outline-hidden transition-colors focus-visible:ring-2 [&>svg]:size-4", "aria-label": "Open features folder", children: _jsx(Folder, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "right", align: "center", hidden: state !== 'collapsed' || isMobile, children: "Open features folder" })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: onMenuClick, className: "ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground flex size-7 items-center justify-center rounded-md p-0 outline-hidden transition-colors focus-visible:ring-2 [&>svg]:size-4", "aria-label": "Features options", children: _jsx(GripHorizontal, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "right", align: "center", hidden: state !== 'collapsed' || isMobile, children: "Features options" })] })] })] }) }));
11
11
  }
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import * as React from 'react';
3
3
  import { cva } from 'class-variance-authority';
4
4
  import { cn } from '../../lib/utils';
5
- const alertVariants = cva('[&>svg]:text-foreground relative w-full rounded-lg border px-4 py-3 text-sm [&>svg]:absolute [&>svg]:top-4 [&>svg]:left-4 [&>svg+div]:translate-y-[-3px] [&>svg~*]:pl-7', {
5
+ const alertVariants = cva('relative w-full rounded-lg border px-4 py-3 text-sm [&>svg]:absolute [&>svg]:top-4 [&>svg]:left-4 [&>svg]:text-foreground [&>svg+div]:translate-y-[-3px] [&>svg~*]:pl-7', {
6
6
  variants: {
7
7
  variant: {
8
8
  default: 'bg-background text-foreground',
@@ -1,12 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cva } from 'class-variance-authority';
3
3
  import { cn } from '../../lib/utils';
4
- const badgeVariants = cva('focus:ring-ring inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:ring-2 focus:ring-offset-2 focus:outline-none', {
4
+ const badgeVariants = cva('inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-none', {
5
5
  variants: {
6
6
  variant: {
7
- default: 'bg-primary text-primary-foreground hover:bg-primary/80 border-transparent shadow',
8
- secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent',
9
- destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent shadow',
7
+ default: 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
8
+ secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
9
+ destructive: 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
10
10
  outline: 'text-foreground',
11
11
  },
12
12
  },
@@ -2,12 +2,12 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cva } from 'class-variance-authority';
3
3
  import { Slot } from 'radix-ui';
4
4
  import { cn } from '../../lib/utils';
5
- const buttonVariants = cva("focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
5
+ const buttonVariants = cva("inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
6
6
  variants: {
7
7
  variant: {
8
8
  default: 'bg-primary text-primary-foreground hover:bg-primary/90',
9
- destructive: 'bg-destructive hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white',
10
- outline: 'bg-background hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border shadow-xs',
9
+ destructive: 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40',
10
+ outline: 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50',
11
11
  secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
12
12
  ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
13
13
  link: 'text-primary underline-offset-4 hover:underline',
@@ -148,11 +148,11 @@ function SidebarMenu({ className, ...props }) {
148
148
  function SidebarMenuItem({ className, ...props }) {
149
149
  return (_jsx("li", { "data-slot": "sidebar-menu-item", "data-sidebar": "menu-item", className: cn('group/menu-item relative', className), ...props }));
150
150
  }
151
- const sidebarMenuButtonVariants = cva('peer/menu-button ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:font-medium [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0', {
151
+ const sidebarMenuButtonVariants = cva('peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0', {
152
152
  variants: {
153
153
  variant: {
154
154
  default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
155
- outline: 'bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',
155
+ outline: 'bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',
156
156
  },
157
157
  size: {
158
158
  default: 'h-8 text-sm',