Skip to content

Commit d485281

Browse files
authored
feat(cli): add multi-provider skill generation support (Fission-AI#556)
* feat(cli): add multi-provider skill generation support Add --tool flag to artifact-experimental-setup command to generate skills and commands for different AI tools (Claude, Cursor, Windsurf). - Add skillsDir field to AIToolOption interface - Create command-generation module with tool-specific adapters - Each adapter handles tool-specific file paths and frontmatter formats - Add CommandAdapterRegistry for adapter lookup - Update artifact-experimental-setup to use dynamic paths * feat(config): add skillsDir for all supported AI tools Add skillsDir mappings for tools that were missing: - Amazon Q Developer (.amazonq) - Antigravity (.agent) - Auggie (.augment) - Cline (.cline) - CodeBuddy Code (.codebuddy) - Continue (.continue) - CoStrict (.cospec) - Crush (.crush) - iFlow (.iflow) - Qoder (.qoder) - Qwen Code (.qwen) Fix RooCode path: .roocode → .roo * feat(adapters): add command adapters for all supported AI tools Add 18 new command adapters covering all supported AI tools in the multi-provider skill generation system. Each adapter implements the correct file path and frontmatter format for its respective tool. New adapters: amazon-q, antigravity, auggie, cline, codex, codebuddy, continue, costrict, crush, factory, gemini, github-copilot, iflow, kilocode, opencode, qoder, qwen, roocode. * fix(adapters): address PR review feedback - Change .requiredOption to .option for custom error handling with tool list - Add YAML escaping for special characters in all command adapters - Normalize path separators in tests for cross-platform compatibility - Update docs: --tool flag is required, not optional with default - Add missing Windsurf adapter scenario to spec - Fix spec headers and language specifiers
1 parent 54bd3f1 commit d485281

40 files changed

Lines changed: 2458 additions & 95 deletions
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-01-22
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
## Context
2+
3+
The `artifact-experimental-setup` command generates skill files and opsx slash commands for AI coding assistants. Currently it hardcodes paths to `.claude/skills` and `.claude/commands/opsx`.
4+
5+
The existing `AI_TOOLS` array in `config.ts` lists 22 AI tools but lacks path information. There's also an existing `SlashCommandConfigurator` system for the old workflow commands, but it's tightly coupled to the old 3 commands (proposal, apply, archive) and can't be easily extended for the 9 opsx commands.
6+
7+
Each AI tool has:
8+
- Different skill directory conventions (`.claude/skills/`, `.cursor/skills/`, etc.)
9+
- Different command file paths (`.claude/commands/opsx/`, `.cursor/commands/`, etc.)
10+
- Different frontmatter formats (YAML keys, structure varies by tool)
11+
12+
## Goals / Non-Goals
13+
14+
**Goals:**
15+
- Support skill generation for any AI tool following the Agent Skills spec
16+
- Support command generation with tool-specific formatting via adapters
17+
- Require explicit tool selection (no defaults)
18+
- Create a generic, extensible command generation system
19+
20+
**Non-Goals:**
21+
- Global path installation (deferred to future work)
22+
- Multi-tool generation in single command (future enhancement)
23+
- Unifying with existing SlashCommandConfigurator (separate systems for now)
24+
25+
## Decisions
26+
27+
### 1. Add `skillsDir` to `AIToolOption` interface
28+
29+
**Decision**: Add single `skillsDir` field to existing interface. No `commandsDir` or `globalSkillsDir`.
30+
31+
```typescript
32+
interface AIToolOption {
33+
name: string;
34+
value: string;
35+
available: boolean;
36+
successLabel?: string;
37+
skillsDir?: string; // e.g., '.claude' - /skills suffix per Agent Skills spec
38+
}
39+
```
40+
41+
**Rationale**:
42+
- Skills follow Agent Skills spec: `<toolDir>/skills/` - suffix is standard
43+
- Commands need per-tool formatting, handled by adapters (not a simple path)
44+
- Global paths deferred - can extend interface later
45+
46+
### 2. Strategy/Adapter pattern for command generation
47+
48+
**Decision**: Create generic command generation with tool-specific adapters.
49+
50+
```text
51+
┌─────────────────────────────────────────────────────────────────┐
52+
│ CommandContent │
53+
│ (tool-agnostic: id, name, description, category, tags, body) │
54+
└─────────────────────────────────────────────────────────────────┘
55+
56+
57+
┌─────────────────────────────────────────────────────────────────┐
58+
│ generateCommand(content, adapter) │
59+
└─────────────────────────────────────────────────────────────────┘
60+
61+
┌───────────────┼───────────────┐
62+
▼ ▼ ▼
63+
┌──────────┐ ┌──────────┐ ┌──────────┐
64+
│ Claude │ │ Cursor │ │ Windsurf │
65+
│ Adapter │ │ Adapter │ │ Adapter │
66+
└──────────┘ └──────────┘ └──────────┘
67+
```
68+
69+
**Interfaces:**
70+
71+
```typescript
72+
// Tool-agnostic command data
73+
interface CommandContent {
74+
id: string; // e.g., 'explore', 'new', 'apply'
75+
name: string; // e.g., 'OpenSpec Explore'
76+
description: string; // e.g., 'Enter explore mode...'
77+
category: string; // e.g., 'OpenSpec'
78+
tags: string[]; // e.g., ['openspec', 'explore']
79+
body: string; // The command instructions
80+
}
81+
82+
// Per-tool formatting strategy
83+
interface ToolCommandAdapter {
84+
toolId: string;
85+
getFilePath(commandId: string): string;
86+
formatFile(content: CommandContent): string;
87+
}
88+
```
89+
90+
**Rationale**:
91+
- Separates "what to generate" from "how to format it"
92+
- Each tool's frontmatter quirks encapsulated in its adapter
93+
- Easy to add new tools by implementing adapter interface
94+
- Body content shared across all tools
95+
96+
**Alternative considered**: Extend existing SlashCommandConfigurator
97+
- Rejected: Tightly coupled to old 3 commands, significant refactor needed
98+
99+
### 3. Adapter registry pattern
100+
101+
**Decision**: Create `CommandAdapterRegistry` similar to existing `SlashCommandRegistry`.
102+
103+
```typescript
104+
class CommandAdapterRegistry {
105+
private static adapters: Map<string, ToolCommandAdapter> = new Map();
106+
107+
static get(toolId: string): ToolCommandAdapter | undefined;
108+
static getAll(): ToolCommandAdapter[];
109+
}
110+
```
111+
112+
**Rationale**:
113+
- Consistent with existing codebase patterns
114+
- Easy lookup by tool ID
115+
- Centralized registration
116+
117+
### 4. Required tool flag
118+
119+
**Decision**: Require `--tool` flag - error if omitted.
120+
121+
**Rationale**:
122+
- Explicit tool selection avoids assumptions
123+
- Consistent with project convention of not providing defaults
124+
- Users must consciously choose their target tool
125+
126+
## Risks / Trade-offs
127+
128+
**[Risk] Adapter maintenance burden** → Each new tool needs an adapter. Mitigated by simple interface - most adapters are ~20 lines.
129+
130+
**[Risk] Frontmatter format drift** → Tools may change their formats. Mitigated by encapsulating format in adapter - single place to update.
131+
132+
**[Trade-off] Two command systems** → Old SlashCommandConfigurator and new CommandAdapterRegistry coexist. Acceptable for now - can unify later if needed.
133+
134+
**[Trade-off] skillsDir optional** → Tools without skillsDir configured will error. Acceptable - we add paths as tools are tested.
135+
136+
## Implementation Approach
137+
138+
1. Add `skillsDir` to `AIToolOption` and populate for known tools
139+
2. Create `CommandContent` and `ToolCommandAdapter` interfaces
140+
3. Implement adapters for Claude, Cursor, Windsurf (start with 3)
141+
4. Create `CommandAdapterRegistry`
142+
5. Create `generateCommand()` function
143+
6. Update `artifact-experimental-setup` to use new system
144+
7. Add `--tool` flag with validation
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
## Why
2+
3+
The `artifact-experimental-setup` command currently hardcodes skill output paths to `.claude/skills` and `.claude/commands/opsx`. This prevents users of other AI coding tools (Cursor, Windsurf, Codex, etc.) from using OpenSpec's skill generation. We need to support the diverse ecosystem of AI coding assistants, each with their own conventions for skill/instruction file locations and command frontmatter formats.
4+
5+
## What Changes
6+
7+
- Add `skillsDir` path configuration to the existing `AIToolOption` interface in `config.ts`
8+
- Add required `--tool <tool-id>` flag to the `artifact-experimental-setup` command
9+
- Create a generic command generation system using Strategy/Adapter pattern:
10+
- `CommandContent`: tool-agnostic command data (id, name, description, body)
11+
- `ToolCommandAdapter`: per-tool formatting (file paths, frontmatter format)
12+
- `CommandGenerator`: orchestrates generation using content + adapter
13+
- Require explicit tool selection (no default) for clarity
14+
15+
## Capabilities
16+
17+
### New Capabilities
18+
19+
- `ai-tool-paths`: Configuration mapping AI tool IDs to their project-local skill directory paths
20+
- `command-generation`: Generic command generation system with tool adapters for formatting differences
21+
22+
### Modified Capabilities
23+
24+
- `cli-artifact-workflow`: Adding `--tool` flag to setup command for provider selection
25+
26+
## Impact
27+
28+
- **Files Modified**:
29+
- `src/core/config.ts` - Extend `AIToolOption` interface with `skillsDir` field
30+
- `src/commands/artifact-workflow.ts` - Add `--tool` flag, use provider paths and adapters
31+
- **New Files**:
32+
- `src/core/command-generation/types.ts` - CommandContent, ToolCommandAdapter interfaces
33+
- `src/core/command-generation/generator.ts` - Generic command generator
34+
- `src/core/command-generation/adapters/*.ts` - Per-tool adapters
35+
- **Backward Compatibility**: Existing workflows unaffected - this is a new command setup feature
36+
- **User-Facing**: Required `--tool` flag on `artifact-experimental-setup` command for explicit tool selection
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# ai-tool-paths Specification
2+
3+
## Purpose
4+
5+
Define the path configuration for AI coding tool skill directories, enabling skill generation to target different tools following the Agent Skills spec.
6+
7+
## Requirements
8+
9+
## ADDED Requirements
10+
11+
### Requirement: AIToolOption skillsDir field
12+
13+
The `AIToolOption` interface SHALL include an optional `skillsDir` field for skill generation path configuration.
14+
15+
#### Scenario: Interface includes skillsDir field
16+
17+
- **WHEN** a tool entry is defined in `AI_TOOLS` that supports skill generation
18+
- **THEN** it SHALL include a `skillsDir` field specifying the project-local base directory (e.g., `.claude`)
19+
20+
#### Scenario: Skills path follows Agent Skills spec
21+
22+
- **WHEN** generating skills for a tool with `skillsDir: '.claude'`
23+
- **THEN** skills SHALL be written to `<projectRoot>/<skillsDir>/skills/`
24+
- **AND** the `/skills` suffix is appended per Agent Skills specification
25+
26+
### Requirement: Path configuration for supported tools
27+
28+
The `AI_TOOLS` array SHALL include `skillsDir` for tools that support the Agent Skills specification.
29+
30+
#### Scenario: Claude Code paths defined
31+
32+
- **WHEN** looking up the `claude` tool
33+
- **THEN** `skillsDir` SHALL be `.claude`
34+
35+
#### Scenario: Cursor paths defined
36+
37+
- **WHEN** looking up the `cursor` tool
38+
- **THEN** `skillsDir` SHALL be `.cursor`
39+
40+
#### Scenario: Windsurf paths defined
41+
42+
- **WHEN** looking up the `windsurf` tool
43+
- **THEN** `skillsDir` SHALL be `.windsurf`
44+
45+
#### Scenario: Tools without skillsDir
46+
47+
- **WHEN** a tool has no `skillsDir` defined
48+
- **THEN** skill generation SHALL error with message indicating the tool is not supported
49+
50+
### Requirement: Cross-platform path handling
51+
52+
The system SHALL handle paths correctly across operating systems.
53+
54+
#### Scenario: Path construction on Windows
55+
56+
- **WHEN** constructing skill paths on Windows
57+
- **THEN** the system SHALL use `path.join()` for all path construction
58+
- **AND** SHALL NOT hardcode forward slashes
59+
60+
#### Scenario: Path construction on Unix
61+
62+
- **WHEN** constructing skill paths on macOS or Linux
63+
- **THEN** the system SHALL use `path.join()` for consistency
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# cli-artifact-workflow Delta Specification
2+
3+
## Purpose
4+
5+
Add `--tool` flag to the `artifact-experimental-setup` command for multi-provider support.
6+
7+
## ADDED Requirements
8+
9+
### Requirement: Tool selection flag
10+
11+
The `artifact-experimental-setup` command SHALL accept a `--tool <tool-id>` flag to specify the target AI tool.
12+
13+
#### Scenario: Specify tool via flag
14+
15+
- **WHEN** user runs `openspec artifact-experimental-setup --tool cursor`
16+
- **THEN** skill files are generated in `.cursor/skills/`
17+
- **AND** command files are generated using Cursor's frontmatter format
18+
19+
#### Scenario: Missing tool flag
20+
21+
- **WHEN** user runs `openspec artifact-experimental-setup` without `--tool`
22+
- **THEN** the system displays an error requiring the `--tool` flag
23+
- **AND** lists valid tool IDs in the error message
24+
25+
#### Scenario: Unknown tool ID
26+
27+
- **WHEN** user runs `openspec artifact-experimental-setup --tool unknown-tool`
28+
- **AND** the tool ID is not in `AI_TOOLS`
29+
- **THEN** the system displays an error listing valid tool IDs
30+
31+
#### Scenario: Tool without skillsDir
32+
33+
- **WHEN** user specifies a tool that has no `skillsDir` configured
34+
- **THEN** the system displays an error indicating skill generation is not supported for that tool
35+
36+
#### Scenario: Tool without command adapter
37+
38+
- **WHEN** user specifies a tool that has `skillsDir` but no command adapter registered
39+
- **THEN** skill files are generated successfully
40+
- **AND** command generation is skipped with informational message
41+
42+
### Requirement: Output messaging
43+
44+
The setup command SHALL display clear output about what was generated.
45+
46+
#### Scenario: Show target tool in output
47+
48+
- **WHEN** setup command runs successfully
49+
- **THEN** output includes the target tool name (e.g., "Setting up for Cursor...")
50+
51+
#### Scenario: Show generated paths
52+
53+
- **WHEN** setup command completes
54+
- **THEN** output lists all generated skill file paths
55+
- **AND** lists all generated command file paths (if applicable)
56+
57+
#### Scenario: Show skipped commands message
58+
59+
- **WHEN** command generation is skipped due to missing adapter
60+
- **THEN** output includes message: "Command generation skipped - no adapter for <tool>"

0 commit comments

Comments
 (0)