Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-01-22
144 changes: 144 additions & 0 deletions openspec/changes/multi-provider-skill-generation/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
## Context

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`.

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.
Comment on lines +3 to +5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use direct file references for mentioned code artifacts.
Please update references like config.ts and SlashCommandConfigurator to the file.ts:line format (e.g., src/core/config.ts:42) for clarity. As per coding guidelines, use direct file references in these design docs.

🤖 Prompt for AI Agents
In `@openspec/changes/multi-provider-skill-generation/design.md` around lines 3 -
5, Update the design doc to use explicit file:line references for the code
artifacts instead of generic names: replace mentions of config.ts, AI_TOOLS,
SlashCommandConfigurator, and artifact-experimental-setup with the precise
file.ts:line locations that host those symbols in the repo (pointing to the
actual source file and line for the AI_TOOLS array, the config.ts module, the
SlashCommandConfigurator class, and the artifact-experimental-setup command
implementation), ensuring each reference follows the file.ts:line format used by
the codebase and keeping the symbol names (AI_TOOLS, SlashCommandConfigurator,
artifact-experimental-setup) so readers can correlate doc text with code.


Each AI tool has:
- Different skill directory conventions (`.claude/skills/`, `.cursor/skills/`, etc.)
- Different command file paths (`.claude/commands/opsx/`, `.cursor/commands/`, etc.)
- Different frontmatter formats (YAML keys, structure varies by tool)

## Goals / Non-Goals

**Goals:**
- Support skill generation for any AI tool following the Agent Skills spec
- Support command generation with tool-specific formatting via adapters
- Require explicit tool selection (no defaults)
- Create a generic, extensible command generation system

**Non-Goals:**
- Global path installation (deferred to future work)
- Multi-tool generation in single command (future enhancement)
- Unifying with existing SlashCommandConfigurator (separate systems for now)

## Decisions

### 1. Add `skillsDir` to `AIToolOption` interface

**Decision**: Add single `skillsDir` field to existing interface. No `commandsDir` or `globalSkillsDir`.

```typescript
interface AIToolOption {
name: string;
value: string;
available: boolean;
successLabel?: string;
skillsDir?: string; // e.g., '.claude' - /skills suffix per Agent Skills spec
}
```

**Rationale**:
- Skills follow Agent Skills spec: `<toolDir>/skills/` - suffix is standard
- Commands need per-tool formatting, handled by adapters (not a simple path)
- Global paths deferred - can extend interface later

### 2. Strategy/Adapter pattern for command generation

**Decision**: Create generic command generation with tool-specific adapters.

```text
┌─────────────────────────────────────────────────────────────────┐
│ CommandContent │
│ (tool-agnostic: id, name, description, category, tags, body) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ generateCommand(content, adapter) │
└─────────────────────────────────────────────────────────────────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Claude │ │ Cursor │ │ Windsurf │
│ Adapter │ │ Adapter │ │ Adapter │
└──────────┘ └──────────┘ └──────────┘
```

**Interfaces:**

```typescript
// Tool-agnostic command data
interface CommandContent {
id: string; // e.g., 'explore', 'new', 'apply'
name: string; // e.g., 'OpenSpec Explore'
description: string; // e.g., 'Enter explore mode...'
category: string; // e.g., 'OpenSpec'
tags: string[]; // e.g., ['openspec', 'explore']
body: string; // The command instructions
}

// Per-tool formatting strategy
interface ToolCommandAdapter {
toolId: string;
getFilePath(commandId: string): string;
formatFile(content: CommandContent): string;
}
```

**Rationale**:
- Separates "what to generate" from "how to format it"
- Each tool's frontmatter quirks encapsulated in its adapter
- Easy to add new tools by implementing adapter interface
- Body content shared across all tools

**Alternative considered**: Extend existing SlashCommandConfigurator
- Rejected: Tightly coupled to old 3 commands, significant refactor needed

### 3. Adapter registry pattern

**Decision**: Create `CommandAdapterRegistry` similar to existing `SlashCommandRegistry`.

```typescript
class CommandAdapterRegistry {
private static adapters: Map<string, ToolCommandAdapter> = new Map();

static get(toolId: string): ToolCommandAdapter | undefined;
static getAll(): ToolCommandAdapter[];
}
```

**Rationale**:
- Consistent with existing codebase patterns
- Easy lookup by tool ID
- Centralized registration

### 4. Required tool flag

**Decision**: Require `--tool` flag - error if omitted.

**Rationale**:
- Explicit tool selection avoids assumptions
- Consistent with project convention of not providing defaults
- Users must consciously choose their target tool

## Risks / Trade-offs

**[Risk] Adapter maintenance burden** → Each new tool needs an adapter. Mitigated by simple interface - most adapters are ~20 lines.

**[Risk] Frontmatter format drift** → Tools may change their formats. Mitigated by encapsulating format in adapter - single place to update.

**[Trade-off] Two command systems** → Old SlashCommandConfigurator and new CommandAdapterRegistry coexist. Acceptable for now - can unify later if needed.

**[Trade-off] skillsDir optional** → Tools without skillsDir configured will error. Acceptable - we add paths as tools are tested.

## Implementation Approach

1. Add `skillsDir` to `AIToolOption` and populate for known tools
2. Create `CommandContent` and `ToolCommandAdapter` interfaces
3. Implement adapters for Claude, Cursor, Windsurf (start with 3)
4. Create `CommandAdapterRegistry`
5. Create `generateCommand()` function
6. Update `artifact-experimental-setup` to use new system
7. Add `--tool` flag with validation
36 changes: 36 additions & 0 deletions openspec/changes/multi-provider-skill-generation/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Why

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.

## What Changes

- Add `skillsDir` path configuration to the existing `AIToolOption` interface in `config.ts`
- Add required `--tool <tool-id>` flag to the `artifact-experimental-setup` command
- Create a generic command generation system using Strategy/Adapter pattern:
- `CommandContent`: tool-agnostic command data (id, name, description, body)
- `ToolCommandAdapter`: per-tool formatting (file paths, frontmatter format)
- `CommandGenerator`: orchestrates generation using content + adapter
- Require explicit tool selection (no default) for clarity

## Capabilities

### New Capabilities

- `ai-tool-paths`: Configuration mapping AI tool IDs to their project-local skill directory paths
- `command-generation`: Generic command generation system with tool adapters for formatting differences

### Modified Capabilities

- `cli-artifact-workflow`: Adding `--tool` flag to setup command for provider selection

## Impact

- **Files Modified**:
- `src/core/config.ts` - Extend `AIToolOption` interface with `skillsDir` field
- `src/commands/artifact-workflow.ts` - Add `--tool` flag, use provider paths and adapters
- **New Files**:
- `src/core/command-generation/types.ts` - CommandContent, ToolCommandAdapter interfaces
- `src/core/command-generation/generator.ts` - Generic command generator
- `src/core/command-generation/adapters/*.ts` - Per-tool adapters
Comment on lines +28 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add line-numbered file references.

The proposal references files without line numbers; please use direct references like src/core/config.ts:19 to meet the documentation format requirement.

As per coding guidelines, use file.ts:line references in proposal/design/tasks.

🤖 Prompt for AI Agents
In `@openspec/changes/multi-provider-skill-generation/proposal.md` around lines 28
- 34, Update the proposal to include explicit line-numbered file references for
each referenced file entry; specifically, add file:line style references next to
the entries that mention AIToolOption, the artifact-workflow --tool flag,
CommandContent, ToolCommandAdapter, the generic command generator, and the
per-tool adapters so reviewers can jump directly to the exact lines in the
implementation; ensure each list item shows the target file and a plausible
example line number for the declaration of AIToolOption, the --tool flag
handling, the CommandContent/ToolCommandAdapter interfaces, the generator
implementation, and adapter files.

- **Backward Compatibility**: Existing workflows unaffected - this is a new command setup feature
- **User-Facing**: Required `--tool` flag on `artifact-experimental-setup` command for explicit tool selection
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# ai-tool-paths Specification

## Purpose

Define the path configuration for AI coding tool skill directories, enabling skill generation to target different tools following the Agent Skills spec.

## Requirements

## ADDED Requirements

### Requirement: AIToolOption skillsDir field

The `AIToolOption` interface SHALL include an optional `skillsDir` field for skill generation path configuration.

#### Scenario: Interface includes skillsDir field

- **WHEN** a tool entry is defined in `AI_TOOLS` that supports skill generation
- **THEN** it SHALL include a `skillsDir` field specifying the project-local base directory (e.g., `.claude`)

#### Scenario: Skills path follows Agent Skills spec

- **WHEN** generating skills for a tool with `skillsDir: '.claude'`
- **THEN** skills SHALL be written to `<projectRoot>/<skillsDir>/skills/`
- **AND** the `/skills` suffix is appended per Agent Skills specification

### Requirement: Path configuration for supported tools

The `AI_TOOLS` array SHALL include `skillsDir` for tools that support the Agent Skills specification.

#### Scenario: Claude Code paths defined

- **WHEN** looking up the `claude` tool
- **THEN** `skillsDir` SHALL be `.claude`

#### Scenario: Cursor paths defined

- **WHEN** looking up the `cursor` tool
- **THEN** `skillsDir` SHALL be `.cursor`

#### Scenario: Windsurf paths defined

- **WHEN** looking up the `windsurf` tool
- **THEN** `skillsDir` SHALL be `.windsurf`

#### Scenario: Tools without skillsDir

- **WHEN** a tool has no `skillsDir` defined
- **THEN** skill generation SHALL error with message indicating the tool is not supported

### Requirement: Cross-platform path handling

The system SHALL handle paths correctly across operating systems.

#### Scenario: Path construction on Windows

- **WHEN** constructing skill paths on Windows
- **THEN** the system SHALL use `path.join()` for all path construction
- **AND** SHALL NOT hardcode forward slashes

#### Scenario: Path construction on Unix

- **WHEN** constructing skill paths on macOS or Linux
- **THEN** the system SHALL use `path.join()` for consistency
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# cli-artifact-workflow Delta Specification

## Purpose

Add `--tool` flag to the `artifact-experimental-setup` command for multi-provider support.

## ADDED Requirements

### Requirement: Tool selection flag

The `artifact-experimental-setup` command SHALL accept a `--tool <tool-id>` flag to specify the target AI tool.

#### Scenario: Specify tool via flag

- **WHEN** user runs `openspec artifact-experimental-setup --tool cursor`
- **THEN** skill files are generated in `.cursor/skills/`
- **AND** command files are generated using Cursor's frontmatter format

#### Scenario: Missing tool flag

- **WHEN** user runs `openspec artifact-experimental-setup` without `--tool`
- **THEN** the system displays an error requiring the `--tool` flag
- **AND** lists valid tool IDs in the error message

#### Scenario: Unknown tool ID

- **WHEN** user runs `openspec artifact-experimental-setup --tool unknown-tool`
- **AND** the tool ID is not in `AI_TOOLS`
- **THEN** the system displays an error listing valid tool IDs

#### Scenario: Tool without skillsDir

- **WHEN** user specifies a tool that has no `skillsDir` configured
- **THEN** the system displays an error indicating skill generation is not supported for that tool

#### Scenario: Tool without command adapter

- **WHEN** user specifies a tool that has `skillsDir` but no command adapter registered
- **THEN** skill files are generated successfully
- **AND** command generation is skipped with informational message

### Requirement: Output messaging

The setup command SHALL display clear output about what was generated.

#### Scenario: Show target tool in output

- **WHEN** setup command runs successfully
- **THEN** output includes the target tool name (e.g., "Setting up for Cursor...")

#### Scenario: Show generated paths

- **WHEN** setup command completes
- **THEN** output lists all generated skill file paths
- **AND** lists all generated command file paths (if applicable)

#### Scenario: Show skipped commands message

- **WHEN** command generation is skipped due to missing adapter
- **THEN** output includes message: "Command generation skipped - no adapter for <tool>"
Loading
Loading