@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 +7 -3
- package/dist/core/config.js +9 -5
- package/dist/core/configurators/iflow.d.ts +8 -0
- package/dist/core/configurators/iflow.js +15 -0
- package/dist/core/configurators/registry.js +3 -0
- package/dist/core/configurators/slash/antigravity.d.ts +9 -0
- package/dist/core/configurators/slash/antigravity.js +23 -0
- package/dist/core/configurators/slash/cline.js +3 -3
- package/dist/core/configurators/slash/gemini.d.ts +9 -0
- package/dist/core/configurators/slash/gemini.js +22 -0
- package/dist/core/configurators/slash/iflow.d.ts +9 -0
- package/dist/core/configurators/slash/iflow.js +37 -0
- package/dist/core/configurators/slash/qwen.d.ts +3 -8
- package/dist/core/configurators/slash/qwen.js +11 -36
- package/dist/core/configurators/slash/registry.js +12 -0
- package/dist/core/configurators/slash/roocode.d.ts +9 -0
- package/dist/core/configurators/slash/roocode.js +23 -0
- package/dist/core/configurators/slash/toml-base.d.ts +10 -0
- package/dist/core/configurators/slash/toml-base.js +53 -0
- package/dist/core/init.js +7 -0
- package/dist/core/templates/slash-command-templates.js +2 -1
- package/package.json +1 -1
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** |
|
|
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 •
|
|
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
|
|
package/dist/core/config.js
CHANGED
|
@@ -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: '
|
|
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 {
|
|
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
|
|
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 {
|
|
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.
|
|
15
|
-
apply: '.qwen/commands/openspec-apply.
|
|
16
|
-
archive: '.qwen/commands/openspec-archive.
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
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
|
-
|
|
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>/\`.
|