Skip to content
Open
180 changes: 180 additions & 0 deletions openspec/changes/add-multi-editor-support/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<context>
Tech stack: TypeScript, Node.js (≥20.19.0), ESM modules
Package manager: pnpm
CLI framework: Commander.js

Cross-platform requirements:
- This tool runs on macOS, Linux, AND Windows
- Always use path.join() or path.resolve() for file paths - never hardcode slashes
- Never assume forward-slash path separators
- Tests must use path.join() for expected path values, not hardcoded strings
- Consider case sensitivity differences in file systems

</context>

<rules>
- Document any platform-specific behavior or limitations
- Prefer Node.js path module over string manipulation for paths
</rules>

## Context

OpenSpec Part 1 establishes the SkillDefinition pattern for Claude Code. However, many developers use other AI code editors like Cursor, Windsurf, and Cline. Each has its own configuration format for AI instructions. We need a unified approach to generate equivalent configurations for all supported editors.

## Goals / Non-Goals

**Goals:**
- Detect existing editor configurations automatically
- Pre-select detected editors during init
- Generate equivalent instruction files for all selected editors
- Use adapter pattern for easy addition of new editors
- Smart recommendations based on project state

**Non-Goals:**
- Supporting every AI editor (focus on popular ones)
- Runtime editor switching (generation-time only)
- Editor-specific features that don't map across editors
- Automatic detection of which editor user is currently using

## Decisions

### 1. Detection Approach

**Decision**: Scan for known directory markers at init time.

```typescript
interface DetectionResult {
editors: {
claudeCode: boolean; // .claude/ exists
cursor: boolean; // .cursor/ exists
windsurf: boolean; // .windsurf/ exists
cline: boolean; // .cline/ exists
};
openspecState: 'uninitialized' | 'old' | 'new' | 'mixed';
}

function detectEditorConfigs(projectPath: string): DetectionResult
```

**Rationale**: Simple, fast, no false positives. Directory existence is a reliable signal.

**Alternative considered**: Parse editor config files to confirm they're actually configured. Rejected - adds complexity, directories are sufficient signal.

### 2. Editor Adapter Interface

**Decision**: Use adapter pattern for editor-specific generation.

```typescript
interface EditorAdapter {
id: string; // "claude-code", "cursor", "windsurf", "cline"
name: string; // "Claude Code", "Cursor", etc.
configDir: string; // ".claude", ".cursor", etc.

generateSkills(skills: SkillDefinition[], outputDir: string): void;
generateCommands(skills: SkillDefinition[], outputDir: string): void;
}

const ADAPTERS: EditorAdapter[] = [
new ClaudeCodeAdapter(),
new CursorAdapter(),
new WindsurfAdapter(),
new ClineAdapter(),
];
```

**Rationale**: Encapsulates editor-specific logic. Adding a new editor = adding one adapter class.

### 3. Editor-Specific Formats

**Claude Code:**
- Skills: `.claude/skills/openspec-*/SKILL.md`
- Commands: `.claude/commands/opsx/*.md`

**Cursor:**
- Rules: `.cursor/rules/openspec-*.mdc` (MDC format)
- All skills combined into rule files with frontmatter

**Windsurf:**
- Rules: `.windsurf/rules/openspec-*.md`
- Similar to Cursor but standard markdown

**Cline:**
- Rules: `.cline/rules/openspec-*.md`
- Standard markdown format

Comment on lines +82 to +85
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

Capitalize “Markdown”.

Use the proper noun capitalization in that sentence.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~103-~103: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ....cline/rules/openspec-*.md - Standard markdown format Rationale: Each editor has ...

(MARKDOWN_NNP)

🤖 Prompt for AI Agents
In `@openspec/changes/add-multi-editor-support/design.md` around lines 101 - 104,
The sentence under "**Cline:**" that reads "- Standard markdown format" should
use the proper noun capitalization by changing "markdown" to "Markdown"; update
the text in the design.md entry (the line containing "Standard markdown format")
to read "Standard Markdown format" so the noun is capitalized correctly.

**Rationale**: Each editor has documented conventions. We follow them.

### 4. Smart Init Flow

**Decision**: Detection → Summary → Selection → Generation

```
$ openspec init

Detecting project configuration...

Found:
Editors: Claude Code, Cursor
OpenSpec: Old system (AGENTS.md exists)

Recommendation: Migrate to new skills-based system

Select editors to configure: (detected editors pre-selected)
[x] Claude Code
[x] Cursor
[ ] Windsurf
[ ] Cline

Generating files for Claude Code...
Created .claude/skills/openspec-*/ (9 skills)
Created .claude/commands/opsx/* (9 commands)

Generating files for Cursor...
Created .cursor/rules/openspec-*.mdc (9 rules)

Done! Run `openspec cleanup` to remove old artifacts.
```
Comment on lines +92 to +117
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 a fenced code language tag.

The block should specify a language (e.g., text) to satisfy markdownlint.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

111-111: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In `@openspec/changes/add-multi-editor-support/design.md` around lines 111 - 136,
The fenced code block in design.md around the sample output from "$ openspec
init" lacks a language tag and triggers markdownlint; update the triple-backtick
opening fence to include a language like "text" (i.e., change ``` to ```text)
for the block that starts with "$ openspec init" so the example output is
properly labeled and lint-cleaned.


**Rationale**: Users see what's detected, can adjust, understand what's happening.

### 5. Content Equivalence

**Decision**: Same SkillDefinition content, different file format per editor.

All editors receive:
- Same skill names (openspec-new-change, etc.)
- Same instruction content
- Same invocation patterns documented

Format differs:
- Claude Code: SKILL.md + pointer commands
- Others: Combined rule files with metadata

**Rationale**: Consistent experience regardless of editor. Skills work the same way.

## Risks / Trade-offs

**[Risk] Editor formats may change**
→ Mitigation: Adapters isolate changes. Only one adapter needs updating per editor.

**[Risk] Some editors may not support skill references**
→ Mitigation: Adapters can include full instructions if needed (no pointer pattern).

**[Risk] Detection may have false positives (empty .cursor/ directory)**
→ Mitigation: Acceptable - pre-selection is a suggestion, user can deselect.

**[Trade-off] More complexity in generation code**
→ Acceptable: Adapter pattern keeps it manageable. Each adapter is self-contained.

## Migration Plan

This is Part 3 of 3:
- **Part 1**: Foundation - SkillDefinition pattern (required first)
- **Part 2**: Migration - Update/cleanup commands (can run in parallel)
- **Part 3 (this change)**: Multi-editor - Detection and adapters

## Open Questions

- Should we support custom adapters (user-defined editors)?
- How do we handle editor-specific features that don't map?
- Should detection also check for editor binaries in PATH?
46 changes: 46 additions & 0 deletions openspec/changes/add-multi-editor-support/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<context>
Tech stack: TypeScript, Node.js (≥20.19.0), ESM modules
Package manager: pnpm
CLI framework: Commander.js

Cross-platform requirements:
- This tool runs on macOS, Linux, AND Windows
- Always use path.join() or path.resolve() for file paths - never hardcode slashes
- Never assume forward-slash path separators
- Tests must use path.join() for expected path values, not hardcoded strings
- Consider case sensitivity differences in file systems

</context>

## Why

After Parts 1 and 2 establish the skills-only architecture and migration path for Claude Code users, we need to expand support to other AI code editors. Many developers use Cursor, Windsurf, or Cline alongside or instead of Claude Code. Each editor has its own configuration format, but they can all benefit from OpenSpec's structured approach.

This is Part 3 of the skills-only migration, focusing on multi-editor support.

## What Changes

- **Smart init detection**: `openspec init` detects existing editor configs and OpenSpec state
- **Editor adapters**: Unified generation for Claude Code, Cursor, Windsurf, and Cline
- **Pre-selection**: Detected editors are pre-selected in the init wizard
- **State awareness**: Init recommends actions based on detected OpenSpec state (uninitialized, old system, new system, mixed)

## Capabilities

### New Capabilities
- `smart-init`: Enhanced initialization with editor detection and state-aware recommendations

### Modified Capabilities
- `skill-generation`: Multi-editor generation with adapter pattern

## Impact

- **Init flow**: Significant enhancement with detection and smart defaults
- **New editor formats**: Support for Cursor, Windsurf, Cline rule formats
- **User experience**: Better onboarding with pre-selected options
- **Future extensibility**: Adapter pattern allows adding more editors

## Dependencies

- Requires Part 1 (add-skill-foundation) to be completed first
Comment on lines +7 to +31
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 direct file/spec references for traceability.

Please add references like path/to/file.ts:42 and specs/.../spec.md where relevant to align with proposal formatting rules. As per coding guidelines, include direct file references for proposals.

🤖 Prompt for AI Agents
In `@openspec/changes/add-multi-editor-support/proposal.md` around lines 21 - 45,
Update the proposal sections ("What Changes", "Capabilities", "Impact",
"Dependencies") to include direct file and spec references for traceability:
insert concrete source-file references and spec links next to each listed
change/capability (for example add entries like `path/to/file.ts:LINE` and
`specs/.../spec.md` adjacent to the Smart init detection item and the editor
adapter bullets), ensure the `smart-init` capability mentions the initialization
entrypoint and config files it touches and ensure the `skill-generation`
modification points to the adapter implementations, and add a short mapping
table under "Dependencies" that lists the required Part 1 artifacts and their
spec files so reviewers can trace proposals to implementation.

- Can run in parallel with Part 2 (add-skill-migration) after Part 1 merges
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<context>
Tech stack: TypeScript, Node.js (≥20.19.0), ESM modules
Package manager: pnpm
CLI framework: Commander.js

Cross-platform requirements:
- This tool runs on macOS, Linux, AND Windows
- Always use path.join() or path.resolve() for file paths - never hardcode slashes
- Never assume forward-slash path separators
- Tests must use path.join() for expected path values, not hardcoded strings
- Consider case sensitivity differences in file systems

</context>

<rules>
- Include scenarios for Windows path handling when dealing with file paths
- Requirements involving paths must specify cross-platform behavior
</rules>

## ADDED Requirements

### Requirement: Multi-editor skill generation via adapters
The system SHALL use an adapter pattern to generate appropriate files for each supported editor.

Supported editors:
- Claude Code: `.claude/skills/` and `.claude/commands/opsx/`
- Cursor: `.cursor/rules/`
- Windsurf: `.windsurf/rules/`
- Cline: `.cline/rules/`

#### Scenario: Generate for Claude Code
- **WHEN** Claude Code is selected during generation
- **THEN** system creates .claude/skills/openspec-*/ directories with SKILL.md
- **AND** system creates .claude/commands/opsx/*.md pointer commands

#### Scenario: Generate for Cursor
- **WHEN** Cursor is selected during generation
- **THEN** system creates .cursor/rules/openspec-*.mdc rule files
- **AND** rule files contain equivalent skill instructions

#### Scenario: Generate for Windsurf
- **WHEN** Windsurf is selected during generation
- **THEN** system creates .windsurf/rules/openspec-*.md rule files
- **AND** rule files contain equivalent skill instructions

#### Scenario: Generate for Cline
- **WHEN** Cline is selected during generation
- **THEN** system creates .cline/rules/openspec-*.md rule files
- **AND** rule files contain equivalent skill instructions

### Requirement: Generate for multiple editors simultaneously
The system SHALL generate files for all selected editors in a single operation.

#### Scenario: Generate for multiple editors
- **WHEN** multiple editors are selected (e.g., Claude Code and Cursor)
- **THEN** system generates files for Claude Code
- **AND** system generates files for Cursor
- **AND** skill content is equivalent across editors

### Requirement: Editor adapters use cross-platform paths
Each editor adapter SHALL use path.join() for all file path construction.

#### Scenario: Multi-editor generation on Windows
- **WHEN** generation runs for multiple editors on Windows
- **THEN** all adapters create files with correct paths
- **AND** all files are accessible and valid

#### Scenario: Multi-editor generation on Unix-like systems
- **WHEN** generation runs for multiple editors on macOS or Linux
- **THEN** all adapters create files with correct paths
- **AND** all files are accessible and valid

### Requirement: Adapters transform content appropriately
Each editor adapter SHALL transform the SkillDefinition content into the editor's expected format.

#### Scenario: Content equivalence across editors
- **WHEN** skills are generated for multiple editors
- **THEN** all editors receive the same skill names
- **AND** all editors receive equivalent instruction content
- **AND** format differs per editor conventions (SKILL.md vs .mdc vs .md)
Loading
Loading