@fission-ai/openspec 0.15.0 → 0.17.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 (56) hide show
  1. package/README.md +21 -12
  2. package/dist/cli/index.js +67 -2
  3. package/dist/commands/change.js +4 -3
  4. package/dist/commands/completion.d.ts +72 -0
  5. package/dist/commands/completion.js +221 -0
  6. package/dist/commands/config.d.ts +8 -0
  7. package/dist/commands/config.js +198 -0
  8. package/dist/commands/show.js +3 -2
  9. package/dist/commands/spec.js +4 -3
  10. package/dist/commands/validate.js +21 -2
  11. package/dist/core/archive.js +4 -1
  12. package/dist/core/completions/command-registry.d.ts +7 -0
  13. package/dist/core/completions/command-registry.js +362 -0
  14. package/dist/core/completions/completion-provider.d.ts +60 -0
  15. package/dist/core/completions/completion-provider.js +102 -0
  16. package/dist/core/completions/factory.d.ts +51 -0
  17. package/dist/core/completions/factory.js +57 -0
  18. package/dist/core/completions/generators/zsh-generator.d.ts +58 -0
  19. package/dist/core/completions/generators/zsh-generator.js +319 -0
  20. package/dist/core/completions/installers/zsh-installer.d.ts +136 -0
  21. package/dist/core/completions/installers/zsh-installer.js +449 -0
  22. package/dist/core/completions/types.d.ts +78 -0
  23. package/dist/core/completions/types.js +2 -0
  24. package/dist/core/config-schema.d.ts +76 -0
  25. package/dist/core/config-schema.js +200 -0
  26. package/dist/core/config.js +8 -6
  27. package/dist/core/configurators/iflow.d.ts +8 -0
  28. package/dist/core/configurators/iflow.js +15 -0
  29. package/dist/core/configurators/registry.js +3 -0
  30. package/dist/core/configurators/slash/antigravity.d.ts +9 -0
  31. package/dist/core/configurators/slash/antigravity.js +23 -0
  32. package/dist/core/configurators/slash/gemini.d.ts +3 -6
  33. package/dist/core/configurators/slash/gemini.js +4 -50
  34. package/dist/core/configurators/slash/iflow.d.ts +9 -0
  35. package/dist/core/configurators/slash/iflow.js +37 -0
  36. package/dist/core/configurators/slash/opencode.js +0 -3
  37. package/dist/core/configurators/slash/qwen.d.ts +3 -8
  38. package/dist/core/configurators/slash/qwen.js +11 -36
  39. package/dist/core/configurators/slash/registry.js +6 -0
  40. package/dist/core/configurators/slash/toml-base.d.ts +10 -0
  41. package/dist/core/configurators/slash/toml-base.js +53 -0
  42. package/dist/core/global-config.d.ts +29 -0
  43. package/dist/core/global-config.js +87 -0
  44. package/dist/core/index.d.ts +1 -1
  45. package/dist/core/index.js +2 -1
  46. package/dist/core/init.js +7 -0
  47. package/dist/core/templates/slash-command-templates.js +2 -1
  48. package/dist/utils/file-system.js +19 -3
  49. package/dist/utils/interactive.d.ts +12 -1
  50. package/dist/utils/interactive.js +7 -2
  51. package/dist/utils/item-discovery.d.ts +1 -0
  52. package/dist/utils/item-discovery.js +23 -0
  53. package/dist/utils/shell-detection.d.ts +20 -0
  54. package/dist/utils/shell-detection.js +41 -0
  55. package/package.json +4 -1
  56. package/scripts/postinstall.js +147 -0
package/README.md CHANGED
@@ -85,40 +85,49 @@ See the full comparison in [How OpenSpec Compares](#how-openspec-compares).
85
85
 
86
86
  ### Supported AI Tools
87
87
 
88
- #### Native Slash Commands
88
+ <details>
89
+ <summary><strong>Native Slash Commands</strong> (click to expand)</summary>
90
+
89
91
  These tools have built-in OpenSpec commands. Select the OpenSpec integration when prompted.
90
92
 
91
93
  | Tool | Commands |
92
94
  |------|----------|
95
+ | **Amazon Q Developer** | `@openspec-proposal`, `@openspec-apply`, `@openspec-archive` (`.amazonq/prompts/`) |
96
+ | **Antigravity** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.agent/workflows/`) |
97
+ | **Auggie (Augment CLI)** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.augment/commands/`) |
93
98
  | **Claude Code** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` |
99
+ | **Cline** | Workflows in `.clinerules/workflows/` directory (`.clinerules/workflows/openspec-*.md`) |
94
100
  | **CodeBuddy Code (CLI)** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` (`.codebuddy/commands/`) — see [docs](https://www.codebuddy.ai/cli) |
101
+ | **Codex** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (global: `~/.codex/prompts`, auto-installed) |
95
102
  | **CoStrict** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.cospec/openspec/commands/`) — see [docs](https://costrict.ai)|
96
- | **Cursor** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` |
97
- | **Cline** | Workflows in `.clinerules/workflows/` directory (`.clinerules/workflows/openspec-*.md`) |
98
103
  | **Crush** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.crush/commands/openspec/`) |
99
- | **RooCode** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.roo/commands/`) |
104
+ | **Cursor** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` |
100
105
  | **Factory Droid** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.factory/commands/`) |
101
106
  | **Gemini CLI** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` (`.gemini/commands/openspec/`) |
102
- | **OpenCode** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` |
107
+ | **GitHub Copilot** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.github/prompts/`) |
108
+ | **iFlow (iflow-cli)** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.iflow/commands/`) |
103
109
  | **Kilo Code** | `/openspec-proposal.md`, `/openspec-apply.md`, `/openspec-archive.md` (`.kilocode/workflows/`) |
110
+ | **OpenCode** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` |
104
111
  | **Qoder (CLI)** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` (`.qoder/commands/openspec/`) — see [docs](https://qoder.com/cli) |
105
- | **Windsurf** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.windsurf/workflows/`) |
106
- | **Codex** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (global: `~/.codex/prompts`, auto-installed) |
107
- | **GitHub Copilot** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.github/prompts/`) |
108
- | **Amazon Q Developer** | `@openspec-proposal`, `@openspec-apply`, `@openspec-archive` (`.amazonq/prompts/`) |
109
- | **Auggie (Augment CLI)** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.augment/commands/`) |
110
112
  | **Qwen Code** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.qwen/commands/`) |
111
-
113
+ | **RooCode** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.roo/commands/`) |
114
+ | **Windsurf** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.windsurf/workflows/`) |
112
115
 
113
116
  Kilo Code discovers team workflows automatically. Save the generated files under `.kilocode/workflows/` and trigger them from the command palette with `/openspec-proposal.md`, `/openspec-apply.md`, or `/openspec-archive.md`.
114
117
 
115
- #### AGENTS.md Compatible
118
+ </details>
119
+
120
+ <details>
121
+ <summary><strong>AGENTS.md Compatible</strong> (click to expand)</summary>
122
+
116
123
  These tools automatically read workflow instructions from `openspec/AGENTS.md`. Ask them to follow the OpenSpec workflow if they need a reminder. Learn more about the [AGENTS.md convention](https://agents.md/).
117
124
 
118
125
  | Tools |
119
126
  |-------|
120
127
  | Amp • Jules • Others |
121
128
 
129
+ </details>
130
+
122
131
  ### Install & Initialize
123
132
 
124
133
  #### Prerequisites
package/dist/cli/index.js CHANGED
@@ -3,7 +3,6 @@ import { createRequire } from 'module';
3
3
  import ora from 'ora';
4
4
  import path from 'path';
5
5
  import { promises as fs } from 'fs';
6
- import { InitCommand } from '../core/init.js';
7
6
  import { AI_TOOLS } from '../core/config.js';
8
7
  import { UpdateCommand } from '../core/update.js';
9
8
  import { ListCommand } from '../core/list.js';
@@ -13,6 +12,8 @@ import { registerSpecCommand } from '../commands/spec.js';
13
12
  import { ChangeCommand } from '../commands/change.js';
14
13
  import { ValidateCommand } from '../commands/validate.js';
15
14
  import { ShowCommand } from '../commands/show.js';
15
+ import { CompletionCommand } from '../commands/completion.js';
16
+ import { registerConfigCommand } from '../commands/config.js';
16
17
  const program = new Command();
17
18
  const require = createRequire(import.meta.url);
18
19
  const { version } = require('../../package.json');
@@ -25,7 +26,7 @@ program.option('--no-color', 'Disable color output');
25
26
  // Apply global flags before any command runs
26
27
  program.hook('preAction', (thisCommand) => {
27
28
  const opts = thisCommand.opts();
28
- if (opts.noColor) {
29
+ if (opts.color === false) {
29
30
  process.env.NO_COLOR = '1';
30
31
  }
31
32
  });
@@ -57,6 +58,7 @@ program
57
58
  throw new Error(`Cannot access path "${targetPath}": ${error.message}`);
58
59
  }
59
60
  }
61
+ const { InitCommand } = await import('../core/init.js');
60
62
  const initCommand = new InitCommand({
61
63
  tools: options?.tools,
62
64
  });
@@ -192,6 +194,7 @@ program
192
194
  }
193
195
  });
194
196
  registerSpecCommand(program);
197
+ registerConfigCommand(program);
195
198
  // Top-level validate command
196
199
  program
197
200
  .command('validate [item-name]')
@@ -242,5 +245,67 @@ program
242
245
  process.exit(1);
243
246
  }
244
247
  });
248
+ // Completion command with subcommands
249
+ const completionCmd = program
250
+ .command('completion')
251
+ .description('Manage shell completions for OpenSpec CLI');
252
+ completionCmd
253
+ .command('generate [shell]')
254
+ .description('Generate completion script for a shell (outputs to stdout)')
255
+ .action(async (shell) => {
256
+ try {
257
+ const completionCommand = new CompletionCommand();
258
+ await completionCommand.generate({ shell });
259
+ }
260
+ catch (error) {
261
+ console.log();
262
+ ora().fail(`Error: ${error.message}`);
263
+ process.exit(1);
264
+ }
265
+ });
266
+ completionCmd
267
+ .command('install [shell]')
268
+ .description('Install completion script for a shell')
269
+ .option('--verbose', 'Show detailed installation output')
270
+ .action(async (shell, options) => {
271
+ try {
272
+ const completionCommand = new CompletionCommand();
273
+ await completionCommand.install({ shell, verbose: options?.verbose });
274
+ }
275
+ catch (error) {
276
+ console.log();
277
+ ora().fail(`Error: ${error.message}`);
278
+ process.exit(1);
279
+ }
280
+ });
281
+ completionCmd
282
+ .command('uninstall [shell]')
283
+ .description('Uninstall completion script for a shell')
284
+ .option('-y, --yes', 'Skip confirmation prompts')
285
+ .action(async (shell, options) => {
286
+ try {
287
+ const completionCommand = new CompletionCommand();
288
+ await completionCommand.uninstall({ shell, yes: options?.yes });
289
+ }
290
+ catch (error) {
291
+ console.log();
292
+ ora().fail(`Error: ${error.message}`);
293
+ process.exit(1);
294
+ }
295
+ });
296
+ // Hidden command for machine-readable completion data
297
+ program
298
+ .command('__complete <type>', { hidden: true })
299
+ .description('Output completion data in machine-readable format (internal use)')
300
+ .action(async (type) => {
301
+ try {
302
+ const completionCommand = new CompletionCommand();
303
+ await completionCommand.complete({ type });
304
+ }
305
+ catch (error) {
306
+ // Silently fail for graceful shell completion experience
307
+ process.exitCode = 1;
308
+ }
309
+ });
245
310
  program.parse();
246
311
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,5 @@
1
1
  import { promises as fs } from 'fs';
2
2
  import path from 'path';
3
- import { select } from '@inquirer/prompts';
4
3
  import { JsonConverter } from '../core/converters/json-converter.js';
5
4
  import { Validator } from '../core/validation/validator.js';
6
5
  import { ChangeParser } from '../core/parsers/change-parser.js';
@@ -24,9 +23,10 @@ export class ChangeCommand {
24
23
  async show(changeName, options) {
25
24
  const changesPath = path.join(process.cwd(), 'openspec', 'changes');
26
25
  if (!changeName) {
27
- const canPrompt = isInteractive(options?.noInteractive);
26
+ const canPrompt = isInteractive(options);
28
27
  const changes = await this.getActiveChanges(changesPath);
29
28
  if (canPrompt && changes.length > 0) {
29
+ const { select } = await import('@inquirer/prompts');
30
30
  const selected = await select({
31
31
  message: 'Select a change to show',
32
32
  choices: changes.map(id => ({ name: id, value: id })),
@@ -172,9 +172,10 @@ export class ChangeCommand {
172
172
  async validate(changeName, options) {
173
173
  const changesPath = path.join(process.cwd(), 'openspec', 'changes');
174
174
  if (!changeName) {
175
- const canPrompt = isInteractive(options?.noInteractive);
175
+ const canPrompt = isInteractive(options);
176
176
  const changes = await getActiveChangeIds();
177
177
  if (canPrompt && changes.length > 0) {
178
+ const { select } = await import('@inquirer/prompts');
178
179
  const selected = await select({
179
180
  message: 'Select a change to validate',
180
181
  choices: changes.map(id => ({ name: id, value: id })),
@@ -0,0 +1,72 @@
1
+ interface GenerateOptions {
2
+ shell?: string;
3
+ }
4
+ interface InstallOptions {
5
+ shell?: string;
6
+ verbose?: boolean;
7
+ }
8
+ interface UninstallOptions {
9
+ shell?: string;
10
+ yes?: boolean;
11
+ }
12
+ interface CompleteOptions {
13
+ type: string;
14
+ }
15
+ /**
16
+ * Command for managing shell completions for OpenSpec CLI
17
+ */
18
+ export declare class CompletionCommand {
19
+ private completionProvider;
20
+ constructor();
21
+ /**
22
+ * Resolve shell parameter or exit with error
23
+ *
24
+ * @param shell - The shell parameter (may be undefined)
25
+ * @param operationName - Name of the operation (for error messages)
26
+ * @returns Resolved shell or null if should exit
27
+ */
28
+ private resolveShellOrExit;
29
+ /**
30
+ * Generate completion script and output to stdout
31
+ *
32
+ * @param options - Options for generation (shell type)
33
+ */
34
+ generate(options?: GenerateOptions): Promise<void>;
35
+ /**
36
+ * Install completion script to the appropriate location
37
+ *
38
+ * @param options - Options for installation (shell type, verbose output)
39
+ */
40
+ install(options?: InstallOptions): Promise<void>;
41
+ /**
42
+ * Uninstall completion script from the installation location
43
+ *
44
+ * @param options - Options for uninstallation (shell type, yes flag)
45
+ */
46
+ uninstall(options?: UninstallOptions): Promise<void>;
47
+ /**
48
+ * Generate completion script for a specific shell
49
+ */
50
+ private generateForShell;
51
+ /**
52
+ * Install completion script for a specific shell
53
+ */
54
+ private installForShell;
55
+ /**
56
+ * Uninstall completion script for a specific shell
57
+ */
58
+ private uninstallForShell;
59
+ /**
60
+ * Output machine-readable completion data for shell consumption
61
+ * Format: tab-separated "id\tdescription" per line
62
+ *
63
+ * @param options - Options specifying completion type
64
+ */
65
+ complete(options: CompleteOptions): Promise<void>;
66
+ /**
67
+ * Normalize shell parameter to lowercase
68
+ */
69
+ private normalizeShell;
70
+ }
71
+ export {};
72
+ //# sourceMappingURL=completion.d.ts.map
@@ -0,0 +1,221 @@
1
+ import ora from 'ora';
2
+ import { CompletionFactory } from '../core/completions/factory.js';
3
+ import { COMMAND_REGISTRY } from '../core/completions/command-registry.js';
4
+ import { detectShell } from '../utils/shell-detection.js';
5
+ import { CompletionProvider } from '../core/completions/completion-provider.js';
6
+ import { getArchivedChangeIds } from '../utils/item-discovery.js';
7
+ /**
8
+ * Command for managing shell completions for OpenSpec CLI
9
+ */
10
+ export class CompletionCommand {
11
+ completionProvider;
12
+ constructor() {
13
+ this.completionProvider = new CompletionProvider();
14
+ }
15
+ /**
16
+ * Resolve shell parameter or exit with error
17
+ *
18
+ * @param shell - The shell parameter (may be undefined)
19
+ * @param operationName - Name of the operation (for error messages)
20
+ * @returns Resolved shell or null if should exit
21
+ */
22
+ resolveShellOrExit(shell, operationName) {
23
+ const normalizedShell = this.normalizeShell(shell);
24
+ if (!normalizedShell) {
25
+ const detectionResult = detectShell();
26
+ if (detectionResult.shell && CompletionFactory.isSupported(detectionResult.shell)) {
27
+ return detectionResult.shell;
28
+ }
29
+ // Shell was detected but not supported
30
+ if (detectionResult.detected && !detectionResult.shell) {
31
+ console.error(`Error: Shell '${detectionResult.detected}' is not supported yet. Currently supported: ${CompletionFactory.getSupportedShells().join(', ')}`);
32
+ process.exitCode = 1;
33
+ return null;
34
+ }
35
+ // No shell specified and cannot auto-detect
36
+ console.error('Error: Could not auto-detect shell. Please specify shell explicitly.');
37
+ console.error(`Usage: openspec completion ${operationName} [shell]`);
38
+ console.error(`Currently supported: ${CompletionFactory.getSupportedShells().join(', ')}`);
39
+ process.exitCode = 1;
40
+ return null;
41
+ }
42
+ if (!CompletionFactory.isSupported(normalizedShell)) {
43
+ console.error(`Error: Shell '${normalizedShell}' is not supported yet. Currently supported: ${CompletionFactory.getSupportedShells().join(', ')}`);
44
+ process.exitCode = 1;
45
+ return null;
46
+ }
47
+ return normalizedShell;
48
+ }
49
+ /**
50
+ * Generate completion script and output to stdout
51
+ *
52
+ * @param options - Options for generation (shell type)
53
+ */
54
+ async generate(options = {}) {
55
+ const shell = this.resolveShellOrExit(options.shell, 'generate');
56
+ if (!shell)
57
+ return;
58
+ await this.generateForShell(shell);
59
+ }
60
+ /**
61
+ * Install completion script to the appropriate location
62
+ *
63
+ * @param options - Options for installation (shell type, verbose output)
64
+ */
65
+ async install(options = {}) {
66
+ const shell = this.resolveShellOrExit(options.shell, 'install');
67
+ if (!shell)
68
+ return;
69
+ await this.installForShell(shell, options.verbose || false);
70
+ }
71
+ /**
72
+ * Uninstall completion script from the installation location
73
+ *
74
+ * @param options - Options for uninstallation (shell type, yes flag)
75
+ */
76
+ async uninstall(options = {}) {
77
+ const shell = this.resolveShellOrExit(options.shell, 'uninstall');
78
+ if (!shell)
79
+ return;
80
+ await this.uninstallForShell(shell, options.yes || false);
81
+ }
82
+ /**
83
+ * Generate completion script for a specific shell
84
+ */
85
+ async generateForShell(shell) {
86
+ const generator = CompletionFactory.createGenerator(shell);
87
+ const script = generator.generate(COMMAND_REGISTRY);
88
+ console.log(script);
89
+ }
90
+ /**
91
+ * Install completion script for a specific shell
92
+ */
93
+ async installForShell(shell, verbose) {
94
+ const generator = CompletionFactory.createGenerator(shell);
95
+ const installer = CompletionFactory.createInstaller(shell);
96
+ const spinner = ora(`Installing ${shell} completion script...`).start();
97
+ try {
98
+ // Generate the completion script
99
+ const script = generator.generate(COMMAND_REGISTRY);
100
+ // Install it
101
+ const result = await installer.install(script);
102
+ spinner.stop();
103
+ if (result.success) {
104
+ console.log(`✓ ${result.message}`);
105
+ if (verbose && result.installedPath) {
106
+ console.log(` Installed to: ${result.installedPath}`);
107
+ if (result.backupPath) {
108
+ console.log(` Backup created: ${result.backupPath}`);
109
+ }
110
+ if (result.zshrcConfigured) {
111
+ console.log(` ~/.zshrc configured automatically`);
112
+ }
113
+ }
114
+ // Print instructions (only shown if .zshrc wasn't auto-configured)
115
+ if (result.instructions && result.instructions.length > 0) {
116
+ console.log('');
117
+ for (const instruction of result.instructions) {
118
+ console.log(instruction);
119
+ }
120
+ }
121
+ else if (result.zshrcConfigured) {
122
+ console.log('');
123
+ console.log('Restart your shell or run: exec zsh');
124
+ }
125
+ }
126
+ else {
127
+ console.error(`✗ ${result.message}`);
128
+ process.exitCode = 1;
129
+ }
130
+ }
131
+ catch (error) {
132
+ spinner.stop();
133
+ console.error(`✗ Failed to install completion script: ${error instanceof Error ? error.message : String(error)}`);
134
+ process.exitCode = 1;
135
+ }
136
+ }
137
+ /**
138
+ * Uninstall completion script for a specific shell
139
+ */
140
+ async uninstallForShell(shell, skipConfirmation) {
141
+ const installer = CompletionFactory.createInstaller(shell);
142
+ // Prompt for confirmation unless --yes flag is provided
143
+ if (!skipConfirmation) {
144
+ const { confirm } = await import('@inquirer/prompts');
145
+ const confirmed = await confirm({
146
+ message: 'Remove OpenSpec configuration from ~/.zshrc?',
147
+ default: false,
148
+ });
149
+ if (!confirmed) {
150
+ console.log('Uninstall cancelled.');
151
+ return;
152
+ }
153
+ }
154
+ const spinner = ora(`Uninstalling ${shell} completion script...`).start();
155
+ try {
156
+ const result = await installer.uninstall();
157
+ spinner.stop();
158
+ if (result.success) {
159
+ console.log(`✓ ${result.message}`);
160
+ }
161
+ else {
162
+ console.error(`✗ ${result.message}`);
163
+ process.exitCode = 1;
164
+ }
165
+ }
166
+ catch (error) {
167
+ spinner.stop();
168
+ console.error(`✗ Failed to uninstall completion script: ${error instanceof Error ? error.message : String(error)}`);
169
+ process.exitCode = 1;
170
+ }
171
+ }
172
+ /**
173
+ * Output machine-readable completion data for shell consumption
174
+ * Format: tab-separated "id\tdescription" per line
175
+ *
176
+ * @param options - Options specifying completion type
177
+ */
178
+ async complete(options) {
179
+ const type = options.type.toLowerCase();
180
+ try {
181
+ switch (type) {
182
+ case 'changes': {
183
+ const changeIds = await this.completionProvider.getChangeIds();
184
+ for (const id of changeIds) {
185
+ console.log(`${id}\tactive change`);
186
+ }
187
+ break;
188
+ }
189
+ case 'specs': {
190
+ const specIds = await this.completionProvider.getSpecIds();
191
+ for (const id of specIds) {
192
+ console.log(`${id}\tspecification`);
193
+ }
194
+ break;
195
+ }
196
+ case 'archived-changes': {
197
+ const archivedIds = await getArchivedChangeIds();
198
+ for (const id of archivedIds) {
199
+ console.log(`${id}\tarchived change`);
200
+ }
201
+ break;
202
+ }
203
+ default:
204
+ // Invalid type - silently exit with no output for graceful shell completion failure
205
+ process.exitCode = 1;
206
+ break;
207
+ }
208
+ }
209
+ catch {
210
+ // Silently fail for graceful shell completion experience
211
+ process.exitCode = 1;
212
+ }
213
+ }
214
+ /**
215
+ * Normalize shell parameter to lowercase
216
+ */
217
+ normalizeShell(shell) {
218
+ return shell?.toLowerCase();
219
+ }
220
+ }
221
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1,8 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Register the config command and all its subcommands.
4
+ *
5
+ * @param program - The Commander program instance
6
+ */
7
+ export declare function registerConfigCommand(program: Command): void;
8
+ //# sourceMappingURL=config.d.ts.map