@fission-ai/openspec 0.14.0 → 0.16.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.
package/README.md CHANGED
@@ -94,18 +94,22 @@ These tools have built-in OpenSpec commands. Select the OpenSpec integration whe
94
94
  | **CodeBuddy Code (CLI)** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` (`.codebuddy/commands/`) — see [docs](https://www.codebuddy.ai/cli) |
95
95
  | **CoStrict** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.cospec/openspec/commands/`) — see [docs](https://costrict.ai)|
96
96
  | **Cursor** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` |
97
- | **Cline** | Rules in `.clinerules/` directory (`.clinerules/openspec-*.md`) |
97
+ | **Cline** | Workflows in `.clinerules/workflows/` directory (`.clinerules/workflows/openspec-*.md`) |
98
98
  | **Crush** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.crush/commands/openspec/`) |
99
+ | **RooCode** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.roo/commands/`) |
99
100
  | **Factory Droid** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.factory/commands/`) |
101
+ | **Gemini CLI** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` (`.gemini/commands/openspec/`) |
100
102
  | **OpenCode** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` |
101
103
  | **Kilo Code** | `/openspec-proposal.md`, `/openspec-apply.md`, `/openspec-archive.md` (`.kilocode/workflows/`) |
102
104
  | **Qoder (CLI)** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` (`.qoder/commands/openspec/`) — see [docs](https://qoder.com/cli) |
105
+ | **Antigravity** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.agent/workflows/`) |
103
106
  | **Windsurf** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.windsurf/workflows/`) |
104
107
  | **Codex** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (global: `~/.codex/prompts`, auto-installed) |
105
108
  | **GitHub Copilot** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.github/prompts/`) |
106
109
  | **Amazon Q Developer** | `@openspec-proposal`, `@openspec-apply`, `@openspec-archive` (`.amazonq/prompts/`) |
107
110
  | **Auggie (Augment CLI)** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.augment/commands/`) |
108
111
  | **Qwen Code** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.qwen/commands/`) |
112
+ | **iFlow (iflow-cli)** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.iflow/commands/`) |
109
113
 
110
114
 
111
115
  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`.
@@ -115,7 +119,7 @@ These tools automatically read workflow instructions from `openspec/AGENTS.md`.
115
119
 
116
120
  | Tools |
117
121
  |-------|
118
- | Amp • Jules • Gemini CLI • Others |
122
+ | Amp • Jules • Others |
119
123
 
120
124
  ### Install & Initialize
121
125
 
@@ -232,7 +236,7 @@ Or run the command yourself in terminal:
232
236
  $ openspec archive add-profile-filters --yes # Archive the completed change without prompts
233
237
  ```
234
238
 
235
- **Note:** Tools with native slash commands (Claude Code, CodeBuddy, Cursor, Codex, Qoder) can use the shortcuts shown. All other tools work with natural language requests to "create an OpenSpec proposal", "apply the OpenSpec change", or "archive the change".
239
+ **Note:** Tools with native slash commands (Claude Code, CodeBuddy, Cursor, Codex, Qoder, RooCode) can use the shortcuts shown. All other tools work with natural language requests to "create an OpenSpec proposal", "apply the OpenSpec change", or "archive the change".
236
240
 
237
241
  ## Command Reference
238
242
 
@@ -4,22 +4,26 @@ export const OPENSPEC_MARKERS = {
4
4
  end: '<!-- OPENSPEC:END -->'
5
5
  };
6
6
  export const AI_TOOLS = [
7
+ { name: 'Amazon Q Developer', value: 'amazon-q', available: true, successLabel: 'Amazon Q Developer' },
8
+ { name: 'Antigravity', value: 'antigravity', available: true, successLabel: 'Antigravity' },
7
9
  { name: 'Auggie (Augment CLI)', value: 'auggie', available: true, successLabel: 'Auggie' },
8
10
  { name: 'Claude Code', value: 'claude', available: true, successLabel: 'Claude Code' },
9
11
  { name: 'Cline', value: 'cline', available: true, successLabel: 'Cline' },
12
+ { name: 'Codex', value: 'codex', available: true, successLabel: 'Codex' },
10
13
  { name: 'CodeBuddy Code (CLI)', value: 'codebuddy', available: true, successLabel: 'CodeBuddy Code' },
11
14
  { name: 'CoStrict', value: 'costrict', available: true, successLabel: 'CoStrict' },
12
15
  { name: 'Crush', value: 'crush', available: true, successLabel: 'Crush' },
13
16
  { name: 'Cursor', value: 'cursor', available: true, successLabel: 'Cursor' },
14
17
  { name: 'Factory Droid', value: 'factory', available: true, successLabel: 'Factory Droid' },
15
- { name: 'OpenCode', value: 'opencode', available: true, successLabel: 'OpenCode' },
18
+ { name: 'Gemini CLI', value: 'gemini', available: true, successLabel: 'Gemini CLI' },
19
+ { name: 'GitHub Copilot', value: 'github-copilot', available: true, successLabel: 'GitHub Copilot' },
20
+ { name: 'iFlow', value: 'iflow', available: true, successLabel: 'iFlow' },
16
21
  { name: 'Kilo Code', value: 'kilocode', available: true, successLabel: 'Kilo Code' },
22
+ { name: 'OpenCode', value: 'opencode', available: true, successLabel: 'OpenCode' },
17
23
  { name: 'Qoder (CLI)', value: 'qoder', available: true, successLabel: 'Qoder' },
18
- { name: 'Windsurf', value: 'windsurf', available: true, successLabel: 'Windsurf' },
19
- { name: 'Codex', value: 'codex', available: true, successLabel: 'Codex' },
20
- { name: 'GitHub Copilot', value: 'github-copilot', available: true, successLabel: 'GitHub Copilot' },
21
- { name: 'Amazon Q Developer', value: 'amazon-q', available: true, successLabel: 'Amazon Q Developer' },
22
24
  { name: 'Qwen Code', value: 'qwen', available: true, successLabel: 'Qwen Code' },
25
+ { name: 'RooCode', value: 'roocode', available: true, successLabel: 'RooCode' },
26
+ { name: 'Windsurf', value: 'windsurf', available: true, successLabel: 'Windsurf' },
23
27
  { name: 'AGENTS.md (works with Amp, VS Code, …)', value: 'agents', available: false, successLabel: 'your AGENTS.md-compatible assistant' }
24
28
  ];
25
29
  //# sourceMappingURL=config.js.map
@@ -0,0 +1,8 @@
1
+ import { ToolConfigurator } from "./base.js";
2
+ export declare class IflowConfigurator implements ToolConfigurator {
3
+ name: string;
4
+ configFileName: string;
5
+ isAvailable: boolean;
6
+ configure(projectPath: string, openspecDir: string): Promise<void>;
7
+ }
8
+ //# sourceMappingURL=iflow.d.ts.map
@@ -0,0 +1,15 @@
1
+ import path from "path";
2
+ import { FileSystemUtils } from "../../utils/file-system.js";
3
+ import { TemplateManager } from "../templates/index.js";
4
+ import { OPENSPEC_MARKERS } from "../config.js";
5
+ export class IflowConfigurator {
6
+ name = "iFlow";
7
+ configFileName = "IFLOW.md";
8
+ isAvailable = true;
9
+ async configure(projectPath, openspecDir) {
10
+ const filePath = path.join(projectPath, this.configFileName);
11
+ const content = TemplateManager.getClaudeTemplate();
12
+ await FileSystemUtils.updateFileWithMarkers(filePath, content, OPENSPEC_MARKERS.start, OPENSPEC_MARKERS.end);
13
+ }
14
+ }
15
+ //# sourceMappingURL=iflow.js.map
@@ -3,6 +3,7 @@ import { ClineConfigurator } from './cline.js';
3
3
  import { CodeBuddyConfigurator } from './codebuddy.js';
4
4
  import { CostrictConfigurator } from './costrict.js';
5
5
  import { QoderConfigurator } from './qoder.js';
6
+ import { IflowConfigurator } from './iflow.js';
6
7
  import { AgentsStandardConfigurator } from './agents.js';
7
8
  import { QwenConfigurator } from './qwen.js';
8
9
  export class ToolRegistry {
@@ -13,6 +14,7 @@ export class ToolRegistry {
13
14
  const codeBuddyConfigurator = new CodeBuddyConfigurator();
14
15
  const costrictConfigurator = new CostrictConfigurator();
15
16
  const qoderConfigurator = new QoderConfigurator();
17
+ const iflowConfigurator = new IflowConfigurator();
16
18
  const agentsConfigurator = new AgentsStandardConfigurator();
17
19
  const qwenConfigurator = new QwenConfigurator();
18
20
  // Register with the ID that matches the checkbox value
@@ -21,6 +23,7 @@ export class ToolRegistry {
21
23
  this.tools.set('codebuddy', codeBuddyConfigurator);
22
24
  this.tools.set('costrict', costrictConfigurator);
23
25
  this.tools.set('qoder', qoderConfigurator);
26
+ this.tools.set('iflow', iflowConfigurator);
24
27
  this.tools.set('agents', agentsConfigurator);
25
28
  this.tools.set('qwen', qwenConfigurator);
26
29
  }
@@ -0,0 +1,9 @@
1
+ import { SlashCommandConfigurator } from './base.js';
2
+ import { SlashCommandId } from '../../templates/index.js';
3
+ export declare class AntigravitySlashCommandConfigurator extends SlashCommandConfigurator {
4
+ readonly toolId = "antigravity";
5
+ readonly isAvailable = true;
6
+ protected getRelativePath(id: SlashCommandId): string;
7
+ protected getFrontmatter(id: SlashCommandId): string | undefined;
8
+ }
9
+ //# sourceMappingURL=antigravity.d.ts.map
@@ -0,0 +1,23 @@
1
+ import { SlashCommandConfigurator } from './base.js';
2
+ const FILE_PATHS = {
3
+ proposal: '.agent/workflows/openspec-proposal.md',
4
+ apply: '.agent/workflows/openspec-apply.md',
5
+ archive: '.agent/workflows/openspec-archive.md'
6
+ };
7
+ const DESCRIPTIONS = {
8
+ proposal: 'Scaffold a new OpenSpec change and validate strictly.',
9
+ apply: 'Implement an approved OpenSpec change and keep tasks in sync.',
10
+ archive: 'Archive a deployed OpenSpec change and update specs.'
11
+ };
12
+ export class AntigravitySlashCommandConfigurator extends SlashCommandConfigurator {
13
+ toolId = 'antigravity';
14
+ isAvailable = true;
15
+ getRelativePath(id) {
16
+ return FILE_PATHS[id];
17
+ }
18
+ getFrontmatter(id) {
19
+ const description = DESCRIPTIONS[id];
20
+ return `---\ndescription: ${description}\n---`;
21
+ }
22
+ }
23
+ //# sourceMappingURL=antigravity.js.map
@@ -1,8 +1,8 @@
1
1
  import { SlashCommandConfigurator } from './base.js';
2
2
  const FILE_PATHS = {
3
- proposal: '.clinerules/openspec-proposal.md',
4
- apply: '.clinerules/openspec-apply.md',
5
- archive: '.clinerules/openspec-archive.md'
3
+ proposal: '.clinerules/workflows/openspec-proposal.md',
4
+ apply: '.clinerules/workflows/openspec-apply.md',
5
+ archive: '.clinerules/workflows/openspec-archive.md'
6
6
  };
7
7
  export class ClineSlashCommandConfigurator extends SlashCommandConfigurator {
8
8
  toolId = 'cline';
@@ -0,0 +1,9 @@
1
+ import { TomlSlashCommandConfigurator } from './toml-base.js';
2
+ import { SlashCommandId } from '../../templates/index.js';
3
+ export declare class GeminiSlashCommandConfigurator extends TomlSlashCommandConfigurator {
4
+ readonly toolId = "gemini";
5
+ readonly isAvailable = true;
6
+ protected getRelativePath(id: SlashCommandId): string;
7
+ protected getDescription(id: SlashCommandId): string;
8
+ }
9
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1,22 @@
1
+ import { TomlSlashCommandConfigurator } from './toml-base.js';
2
+ const FILE_PATHS = {
3
+ proposal: '.gemini/commands/openspec/proposal.toml',
4
+ apply: '.gemini/commands/openspec/apply.toml',
5
+ archive: '.gemini/commands/openspec/archive.toml'
6
+ };
7
+ const DESCRIPTIONS = {
8
+ proposal: 'Scaffold a new OpenSpec change and validate strictly.',
9
+ apply: 'Implement an approved OpenSpec change and keep tasks in sync.',
10
+ archive: 'Archive a deployed OpenSpec change and update specs.'
11
+ };
12
+ export class GeminiSlashCommandConfigurator extends TomlSlashCommandConfigurator {
13
+ toolId = 'gemini';
14
+ isAvailable = true;
15
+ getRelativePath(id) {
16
+ return FILE_PATHS[id];
17
+ }
18
+ getDescription(id) {
19
+ return DESCRIPTIONS[id];
20
+ }
21
+ }
22
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1,9 @@
1
+ import { SlashCommandConfigurator } from './base.js';
2
+ import { SlashCommandId } from '../../templates/index.js';
3
+ export declare class IflowSlashCommandConfigurator extends SlashCommandConfigurator {
4
+ readonly toolId = "iflow";
5
+ readonly isAvailable = true;
6
+ protected getRelativePath(id: SlashCommandId): string;
7
+ protected getFrontmatter(id: SlashCommandId): string;
8
+ }
9
+ //# sourceMappingURL=iflow.d.ts.map
@@ -0,0 +1,37 @@
1
+ import { SlashCommandConfigurator } from './base.js';
2
+ const FILE_PATHS = {
3
+ proposal: '.iflow/commands/openspec-proposal.md',
4
+ apply: '.iflow/commands/openspec-apply.md',
5
+ archive: '.iflow/commands/openspec-archive.md'
6
+ };
7
+ const FRONTMATTER = {
8
+ proposal: `---
9
+ name: /openspec-proposal
10
+ id: openspec-proposal
11
+ category: OpenSpec
12
+ description: Scaffold a new OpenSpec change and validate strictly.
13
+ ---`,
14
+ apply: `---
15
+ name: /openspec-apply
16
+ id: openspec-apply
17
+ category: OpenSpec
18
+ description: Implement an approved OpenSpec change and keep tasks in sync.
19
+ ---`,
20
+ archive: `---
21
+ name: /openspec-archive
22
+ id: openspec-archive
23
+ category: OpenSpec
24
+ description: Archive a deployed OpenSpec change and update specs.
25
+ ---`
26
+ };
27
+ export class IflowSlashCommandConfigurator extends SlashCommandConfigurator {
28
+ toolId = 'iflow';
29
+ isAvailable = true;
30
+ getRelativePath(id) {
31
+ return FILE_PATHS[id];
32
+ }
33
+ getFrontmatter(id) {
34
+ return FRONTMATTER[id];
35
+ }
36
+ }
37
+ //# sourceMappingURL=iflow.js.map
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @implements {SlashCommandConfigurator}
7
7
  */
8
- import { SlashCommandConfigurator } from './base.js';
8
+ import { TomlSlashCommandConfigurator } from './toml-base.js';
9
9
  import { SlashCommandId } from '../../templates/index.js';
10
10
  /**
11
11
  * QwenSlashCommandConfigurator class provides integration with Qwen Code
@@ -16,7 +16,7 @@ import { SlashCommandId } from '../../templates/index.js';
16
16
  * - /openspec-apply: Apply an approved OpenSpec change
17
17
  * - /openspec-archive: Archive a deployed OpenSpec change
18
18
  */
19
- export declare class QwenSlashCommandConfigurator extends SlashCommandConfigurator {
19
+ export declare class QwenSlashCommandConfigurator extends TomlSlashCommandConfigurator {
20
20
  /** Unique identifier for the Qwen tool */
21
21
  readonly toolId = "qwen";
22
22
  /** Availability status for the Qwen tool */
@@ -27,11 +27,6 @@ export declare class QwenSlashCommandConfigurator extends SlashCommandConfigurat
27
27
  * @returns {string} The relative path to the command file
28
28
  */
29
29
  protected getRelativePath(id: SlashCommandId): string;
30
- /**
31
- * Returns the YAML frontmatter for a given slash command ID.
32
- * @param {SlashCommandId} id - The slash command identifier
33
- * @returns {string} The YAML frontmatter string
34
- */
35
- protected getFrontmatter(id: SlashCommandId): string;
30
+ protected getDescription(id: SlashCommandId): string;
36
31
  }
37
32
  //# sourceMappingURL=qwen.d.ts.map
@@ -5,40 +5,20 @@
5
5
  *
6
6
  * @implements {SlashCommandConfigurator}
7
7
  */
8
- import { SlashCommandConfigurator } from './base.js';
8
+ import { TomlSlashCommandConfigurator } from './toml-base.js';
9
9
  /**
10
10
  * Mapping of slash command IDs to their corresponding file paths in .qwen/commands directory.
11
11
  * @type {Record<SlashCommandId, string>}
12
12
  */
13
13
  const FILE_PATHS = {
14
- proposal: '.qwen/commands/openspec-proposal.md',
15
- apply: '.qwen/commands/openspec-apply.md',
16
- archive: '.qwen/commands/openspec-archive.md'
14
+ proposal: '.qwen/commands/openspec-proposal.toml',
15
+ apply: '.qwen/commands/openspec-apply.toml',
16
+ archive: '.qwen/commands/openspec-archive.toml'
17
17
  };
18
- /**
19
- * YAML frontmatter definitions for Qwen command files.
20
- * These provide metadata for each slash command to ensure proper recognition by Qwen Code.
21
- * @type {Record<SlashCommandId, string>}
22
- */
23
- const FRONTMATTER = {
24
- proposal: `---
25
- name: /openspec-proposal
26
- id: openspec-proposal
27
- category: OpenSpec
28
- description: Scaffold a new OpenSpec change and validate strictly.
29
- ---`,
30
- apply: `---
31
- name: /openspec-apply
32
- id: openspec-apply
33
- category: OpenSpec
34
- description: Implement an approved OpenSpec change and keep tasks in sync.
35
- ---`,
36
- archive: `---
37
- name: /openspec-archive
38
- id: openspec-archive
39
- category: OpenSpec
40
- description: Archive a deployed OpenSpec change and update specs.
41
- ---`
18
+ const DESCRIPTIONS = {
19
+ proposal: 'Scaffold a new OpenSpec change and validate strictly.',
20
+ apply: 'Implement an approved OpenSpec change and keep tasks in sync.',
21
+ archive: 'Archive a deployed OpenSpec change and update specs.'
42
22
  };
43
23
  /**
44
24
  * QwenSlashCommandConfigurator class provides integration with Qwen Code
@@ -49,7 +29,7 @@ description: Archive a deployed OpenSpec change and update specs.
49
29
  * - /openspec-apply: Apply an approved OpenSpec change
50
30
  * - /openspec-archive: Archive a deployed OpenSpec change
51
31
  */
52
- export class QwenSlashCommandConfigurator extends SlashCommandConfigurator {
32
+ export class QwenSlashCommandConfigurator extends TomlSlashCommandConfigurator {
53
33
  /** Unique identifier for the Qwen tool */
54
34
  toolId = 'qwen';
55
35
  /** Availability status for the Qwen tool */
@@ -62,13 +42,8 @@ export class QwenSlashCommandConfigurator extends SlashCommandConfigurator {
62
42
  getRelativePath(id) {
63
43
  return FILE_PATHS[id];
64
44
  }
65
- /**
66
- * Returns the YAML frontmatter for a given slash command ID.
67
- * @param {SlashCommandId} id - The slash command identifier
68
- * @returns {string} The YAML frontmatter string
69
- */
70
- getFrontmatter(id) {
71
- return FRONTMATTER[id];
45
+ getDescription(id) {
46
+ return DESCRIPTIONS[id];
72
47
  }
73
48
  }
74
49
  //# sourceMappingURL=qwen.js.map
@@ -9,11 +9,15 @@ import { CodexSlashCommandConfigurator } from './codex.js';
9
9
  import { GitHubCopilotSlashCommandConfigurator } from './github-copilot.js';
10
10
  import { AmazonQSlashCommandConfigurator } from './amazon-q.js';
11
11
  import { FactorySlashCommandConfigurator } from './factory.js';
12
+ import { GeminiSlashCommandConfigurator } from './gemini.js';
12
13
  import { AuggieSlashCommandConfigurator } from './auggie.js';
13
14
  import { ClineSlashCommandConfigurator } from './cline.js';
14
15
  import { CrushSlashCommandConfigurator } from './crush.js';
15
16
  import { CostrictSlashCommandConfigurator } from './costrict.js';
16
17
  import { QwenSlashCommandConfigurator } from './qwen.js';
18
+ import { RooCodeSlashCommandConfigurator } from './roocode.js';
19
+ import { AntigravitySlashCommandConfigurator } from './antigravity.js';
20
+ import { IflowSlashCommandConfigurator } from './iflow.js';
17
21
  export class SlashCommandRegistry {
18
22
  static configurators = new Map();
19
23
  static {
@@ -28,11 +32,15 @@ export class SlashCommandRegistry {
28
32
  const githubCopilot = new GitHubCopilotSlashCommandConfigurator();
29
33
  const amazonQ = new AmazonQSlashCommandConfigurator();
30
34
  const factory = new FactorySlashCommandConfigurator();
35
+ const gemini = new GeminiSlashCommandConfigurator();
31
36
  const auggie = new AuggieSlashCommandConfigurator();
32
37
  const cline = new ClineSlashCommandConfigurator();
33
38
  const crush = new CrushSlashCommandConfigurator();
34
39
  const costrict = new CostrictSlashCommandConfigurator();
35
40
  const qwen = new QwenSlashCommandConfigurator();
41
+ const roocode = new RooCodeSlashCommandConfigurator();
42
+ const antigravity = new AntigravitySlashCommandConfigurator();
43
+ const iflow = new IflowSlashCommandConfigurator();
36
44
  this.configurators.set(claude.toolId, claude);
37
45
  this.configurators.set(codeBuddy.toolId, codeBuddy);
38
46
  this.configurators.set(qoder.toolId, qoder);
@@ -44,11 +52,15 @@ export class SlashCommandRegistry {
44
52
  this.configurators.set(githubCopilot.toolId, githubCopilot);
45
53
  this.configurators.set(amazonQ.toolId, amazonQ);
46
54
  this.configurators.set(factory.toolId, factory);
55
+ this.configurators.set(gemini.toolId, gemini);
47
56
  this.configurators.set(auggie.toolId, auggie);
48
57
  this.configurators.set(cline.toolId, cline);
49
58
  this.configurators.set(crush.toolId, crush);
50
59
  this.configurators.set(costrict.toolId, costrict);
51
60
  this.configurators.set(qwen.toolId, qwen);
61
+ this.configurators.set(roocode.toolId, roocode);
62
+ this.configurators.set(antigravity.toolId, antigravity);
63
+ this.configurators.set(iflow.toolId, iflow);
52
64
  }
53
65
  static register(configurator) {
54
66
  this.configurators.set(configurator.toolId, configurator);
@@ -0,0 +1,9 @@
1
+ import { SlashCommandConfigurator } from './base.js';
2
+ import { SlashCommandId } from '../../templates/index.js';
3
+ export declare class RooCodeSlashCommandConfigurator extends SlashCommandConfigurator {
4
+ readonly toolId = "roocode";
5
+ readonly isAvailable = true;
6
+ protected getRelativePath(id: SlashCommandId): string;
7
+ protected getFrontmatter(id: SlashCommandId): string | undefined;
8
+ }
9
+ //# sourceMappingURL=roocode.d.ts.map
@@ -0,0 +1,23 @@
1
+ import { SlashCommandConfigurator } from './base.js';
2
+ const NEW_FILE_PATHS = {
3
+ proposal: '.roo/commands/openspec-proposal.md',
4
+ apply: '.roo/commands/openspec-apply.md',
5
+ archive: '.roo/commands/openspec-archive.md'
6
+ };
7
+ export class RooCodeSlashCommandConfigurator extends SlashCommandConfigurator {
8
+ toolId = 'roocode';
9
+ isAvailable = true;
10
+ getRelativePath(id) {
11
+ return NEW_FILE_PATHS[id];
12
+ }
13
+ getFrontmatter(id) {
14
+ const descriptions = {
15
+ proposal: 'Scaffold a new OpenSpec change and validate strictly.',
16
+ apply: 'Implement an approved OpenSpec change and keep tasks in sync.',
17
+ archive: 'Archive a deployed OpenSpec change and update specs.'
18
+ };
19
+ const description = descriptions[id];
20
+ return `# OpenSpec: ${id.charAt(0).toUpperCase() + id.slice(1)}\n\n${description}`;
21
+ }
22
+ }
23
+ //# sourceMappingURL=roocode.js.map
@@ -0,0 +1,10 @@
1
+ import { SlashCommandConfigurator } from './base.js';
2
+ import { SlashCommandId } from '../../templates/index.js';
3
+ export declare abstract class TomlSlashCommandConfigurator extends SlashCommandConfigurator {
4
+ protected getFrontmatter(_id: SlashCommandId): string | undefined;
5
+ protected abstract getDescription(id: SlashCommandId): string;
6
+ generateAll(projectPath: string, _openspecDir: string): Promise<string[]>;
7
+ private generateTOML;
8
+ protected updateBody(filePath: string, body: string): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=toml-base.d.ts.map
@@ -0,0 +1,53 @@
1
+ import { FileSystemUtils } from '../../../utils/file-system.js';
2
+ import { SlashCommandConfigurator } from './base.js';
3
+ import { OPENSPEC_MARKERS } from '../../config.js';
4
+ export class TomlSlashCommandConfigurator extends SlashCommandConfigurator {
5
+ getFrontmatter(_id) {
6
+ // TOML doesn't use separate frontmatter - it's all in one structure
7
+ return undefined;
8
+ }
9
+ // Override to generate TOML format with markers inside the prompt field
10
+ async generateAll(projectPath, _openspecDir) {
11
+ const createdOrUpdated = [];
12
+ for (const target of this.getTargets()) {
13
+ const body = this.getBody(target.id);
14
+ const filePath = FileSystemUtils.joinPath(projectPath, target.path);
15
+ if (await FileSystemUtils.fileExists(filePath)) {
16
+ await this.updateBody(filePath, body);
17
+ }
18
+ else {
19
+ const tomlContent = this.generateTOML(target.id, body);
20
+ await FileSystemUtils.writeFile(filePath, tomlContent);
21
+ }
22
+ createdOrUpdated.push(target.path);
23
+ }
24
+ return createdOrUpdated;
25
+ }
26
+ generateTOML(id, body) {
27
+ const description = this.getDescription(id);
28
+ // TOML format with triple-quoted string for multi-line prompt
29
+ // Markers are inside the prompt value
30
+ return `description = "${description}"
31
+
32
+ prompt = """
33
+ ${OPENSPEC_MARKERS.start}
34
+ ${body}
35
+ ${OPENSPEC_MARKERS.end}
36
+ """
37
+ `;
38
+ }
39
+ // Override updateBody to handle TOML format
40
+ async updateBody(filePath, body) {
41
+ const content = await FileSystemUtils.readFile(filePath);
42
+ const startIndex = content.indexOf(OPENSPEC_MARKERS.start);
43
+ const endIndex = content.indexOf(OPENSPEC_MARKERS.end);
44
+ if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) {
45
+ throw new Error(`Missing OpenSpec markers in ${filePath}`);
46
+ }
47
+ const before = content.slice(0, startIndex + OPENSPEC_MARKERS.start.length);
48
+ const after = content.slice(endIndex);
49
+ const updatedContent = `${before}\n${body}\n${after}`;
50
+ await FileSystemUtils.writeFile(filePath, updatedContent);
51
+ }
52
+ }
53
+ //# sourceMappingURL=toml-base.js.map
package/dist/core/init.js CHANGED
@@ -567,6 +567,13 @@ export class InitCommand {
567
567
  }
568
568
  console.log();
569
569
  console.log(PALETTE.midGray('Use `openspec update` to refresh shared OpenSpec instructions in the future.'));
570
+ // Show restart instruction if any tools were configured
571
+ if (created.length > 0 || refreshed.length > 0) {
572
+ console.log();
573
+ console.log(PALETTE.white('Important: Restart your IDE'));
574
+ console.log(PALETTE.midGray('Slash commands are loaded at startup. Please restart your coding assistant'));
575
+ console.log(PALETTE.midGray('to ensure the new /openspec commands appear in your command palette.'));
576
+ }
570
577
  // Get the selected tool name(s) for display
571
578
  const toolName = this.formatToolNames(selectedTools);
572
579
  console.log();
@@ -2,7 +2,8 @@ const baseGuardrails = `**Guardrails**
2
2
  - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
3
3
  - Keep changes tightly scoped to the requested outcome.
4
4
  - Refer to \`openspec/AGENTS.md\` (located inside the \`openspec/\` directory—run \`ls openspec\` or \`openspec update\` if you don't see it) if you need additional OpenSpec conventions or clarifications.`;
5
- const proposalGuardrails = `${baseGuardrails}\n- Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.`;
5
+ const proposalGuardrails = `${baseGuardrails}\n- Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.
6
+ - Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.`;
6
7
  const proposalSteps = `**Steps**
7
8
  1. Review \`openspec/project.md\`, run \`openspec list\` and \`openspec list --specs\`, and inspect related code or docs (e.g., via \`rg\`/\`ls\`) to ground the proposal in current behaviour; note any gaps that require clarification.
8
9
  2. Choose a unique verb-led \`change-id\` and scaffold \`proposal.md\`, \`tasks.md\`, and \`design.md\` (when needed) under \`openspec/changes/<id>/\`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fission-ai/openspec",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "description": "AI-native system for spec-driven development",
5
5
  "keywords": [
6
6
  "openspec",