Compare commits

...
Author SHA1 Message Date
Tabish Bidiwale 83c88be4e5 Merge branch 'main' into proposal/skills-only-migration 2026-01-21 15:40:11 -08:00
Tabish Bidiwale a5ae6435f9 chore(changes): remove accidental rules blocks
Remove the <rules>...</rules> blocks that were accidentally added
to change proposal files. These blocks contained AI instruction hints
that shouldn't be in the markdown documentation.
2026-01-20 22:11:44 -08:00
Tabish Bidiwale e086c06614 chore(changes): remove accidental tech stack context blocks
Remove the <context>...</context> blocks that were accidentally added
to change proposal files. These blocks contained tech stack info that
shouldn't be in the markdown documentation.
2026-01-20 22:10:01 -08:00
Tabish Bidiwale d56325c9ca napkin(skills-only-migration): add simplified migration plan
Two-part approach using smart `update` instead of new commands.
2026-01-20 22:05:44 -08:00
Tabish Bidiwale 87d737a9af proposal(skills-only-migration): remove original, fix gaps in split proposals
Removed the original skills-only-migration proposal since all content has
been distributed to the three focused proposals.

Gaps fixed in add-skill-foundation (Part 1):
- Added "Init handles already-initialized projects gracefully" requirement
- Added scenarios for init on old system and new system projects
- Added CI/non-TTY environment scenario
- Added tasks for existing project detection and handling
- Added integration tests for existing project scenarios

Gaps fixed in add-skill-migration (Part 2):
- Added documentation section with 4 tasks:
  - Migration guide for existing users
  - Cleanup command documentation
  - CLI help text updates
  - Deprecation notice for artifact-experimental-setup

Gaps fixed in add-multi-editor-support (Part 3):
- Added "Detect mixed state" scenario (both old and new artifacts)
- Added test tasks for mixed state handling
2026-01-20 21:35:50 -08:00
Tabish Bidiwale 4b79c2ad48 proposal(skills-only-migration): split into 3 focused changes
Split the large skills-only-migration proposal into three manageable parts:

1. add-skill-foundation: SkillDefinition pattern + Claude Code init
   - Unified SkillDefinition[] array replaces 18 template functions
   - Skills become single source of truth
   - Pointer commands reference skills (~5 lines vs ~70 lines)
   - New projects get skills-only setup

2. add-skill-migration: Update + Cleanup commands
   - Informative update with upgrade messaging
   - New cleanup command with --yes and --dry-run
   - Remove artifact-experimental-setup command
   - Depends on Part 1

3. add-multi-editor-support: Detection + adapters
   - Smart init with editor detection
   - Adapters for Cursor, Windsurf, Cline
   - Pre-selection of detected editors
   - Can run parallel with Part 2 after Part 1
2026-01-20 21:27:39 -08:00
Tabish Bidiwale 00184eb03f proposal(skills-only-migration): consolidate to skills-based architecture
This proposal outlines the migration from the dual old/new system to a
skills-only architecture where:
- Skills are the source of truth for AI instructions
- Commands become lightweight pointers to skills
- Smart init detects editors and OpenSpec state
- New cleanup command for removing old artifacts
- Informative update experience for existing users

Includes:
- proposal.md: Why and what changes
- design.md: Technical decisions and migration plan
- specs/: Detailed requirements for 5 capabilities
- tasks.md: Implementation checklist (50+ tasks)
2026-01-20 19:12:45 -08:00
15 changed files with 1032 additions and 0 deletions
@@ -0,0 +1,161 @@
## 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
**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.
```
**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?
@@ -0,0 +1,32 @@
## 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
- Can run in parallel with Part 2 (add-skill-migration) after Part 1 merges
@@ -0,0 +1,61 @@
## 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)
@@ -0,0 +1,81 @@
## ADDED Requirements
### Requirement: Init detects existing editor configurations
The system SHALL scan for existing editor configuration directories to inform setup recommendations. Detection targets:
- `.claude/` - Claude Code
- `.cursor/` - Cursor
- `.windsurf/` - Windsurf
- `.cline/` - Cline
#### Scenario: Detect Claude Code configuration
- **WHEN** user runs `openspec init` in a project with `.claude/` directory
- **THEN** system detects Claude Code as a configured editor
- **AND** system pre-selects Claude Code in the editor selection
#### Scenario: Detect multiple editor configurations
- **WHEN** user runs `openspec init` in a project with both `.claude/` and `.cursor/` directories
- **THEN** system detects both Claude Code and Cursor as configured editors
- **AND** system pre-selects both in the editor selection
#### Scenario: No editor configurations detected
- **WHEN** user runs `openspec init` in a project with no editor config directories
- **THEN** system shows all available editors without pre-selection
- **AND** system informs user that no existing editor configs were detected
### Requirement: Init detects existing OpenSpec state
The system SHALL detect the current OpenSpec setup state to provide appropriate recommendations:
- Not initialized: No `openspec/` directory
- Old system: `openspec/AGENTS.md` exists
- New system: `.claude/skills/openspec-*` exists
- Mixed: Both old and new artifacts present
#### Scenario: Detect uninitialized project
- **WHEN** user runs `openspec init` in a project without `openspec/` directory
- **THEN** system detects project as uninitialized
- **AND** system offers full initialization
#### Scenario: Detect old system
- **WHEN** user runs `openspec init` in a project with `openspec/AGENTS.md` but no skills
- **THEN** system detects old OpenSpec system
- **AND** system recommends migration to new skills-based system
#### Scenario: Detect new system already in place
- **WHEN** user runs `openspec init` in a project with `.claude/skills/openspec-*`
- **THEN** system detects new system is already set up
- **AND** system informs user that OpenSpec is already configured
#### Scenario: Detect mixed state (both old and new artifacts)
- **WHEN** user runs `openspec init` in a project with both `openspec/AGENTS.md` and `.claude/skills/openspec-*`
- **THEN** system detects mixed state
- **AND** system informs user that both old and new systems exist
- **AND** system recommends running `openspec cleanup` to remove old artifacts
### Requirement: Init shows detection results to user
The system SHALL display detection results before proceeding with setup.
#### Scenario: Display detection summary
- **WHEN** user runs `openspec init` in interactive mode
- **THEN** system displays detected editor configurations
- **AND** system displays detected OpenSpec state
- **AND** system shows recommendations based on detection
### Requirement: Init allows user to override detected selections
The system SHALL allow users to modify the pre-selected editors based on detection.
#### Scenario: User deselects detected editor
- **WHEN** Claude Code is detected and pre-selected
- **AND** user deselects Claude Code during init
- **THEN** system does not generate Claude Code files
#### Scenario: User selects non-detected editor
- **WHEN** Cursor is not detected (no .cursor/ directory)
- **AND** user selects Cursor during init
- **THEN** system generates Cursor files anyway
### Requirement: Init uses detected editors with --yes flag
The system SHALL use detected editors as defaults when running with --yes flag.
#### Scenario: Non-interactive init with detection
- **WHEN** user runs `openspec init --yes` in a project with .claude/ and .cursor/
- **THEN** system initializes for Claude Code and Cursor automatically
- **AND** system does not prompt for editor selection
@@ -0,0 +1,53 @@
## 1. Detection Functions
- [ ] 1.1 Create `detectEditorConfigs()` function to scan for .claude/, .cursor/, .windsurf/, .cline/
- [ ] 1.2 Create `detectOpenSpecState()` function to detect: uninitialized, old system, new system, mixed
- [ ] 1.3 Define `DetectionResult` interface for typed detection output
- [ ] 1.4 Add detection for each editor's configuration markers
- [ ] 1.5 Handle edge cases (empty directories, partial configs)
## 2. Smart Init Enhancement
- [ ] 2.1 Update init wizard to run detection before showing options
- [ ] 2.2 Display detection summary showing what was found
- [ ] 2.3 Pre-select detected editors in the selection UI
- [ ] 2.4 Allow user to override detected selections
- [ ] 2.5 Show state-aware recommendations (e.g., "Old system detected, recommend migration")
- [ ] 2.6 Handle already-initialized projects gracefully (detect and advise)
- [ ] 2.7 Ensure --yes flag uses detected editors as defaults
## 3. Editor Adapters
- [ ] 3.1 Create `EditorAdapter` interface for unified generation
- [ ] 3.2 Implement Claude Code adapter (skills + opsx commands)
- [ ] 3.3 Implement Cursor adapter (rules format in .cursor/rules/)
- [ ] 3.4 Implement Windsurf adapter (rules format in .windsurf/rules/)
- [ ] 3.5 Implement Cline adapter (rules format in .cline/rules/)
- [ ] 3.6 Define content transformation for each adapter (skill content → editor format)
## 4. Multi-Editor Generation
- [ ] 4.1 Update init to accept multiple editor selections
- [ ] 4.2 Generate files for all selected editors
- [ ] 4.3 Handle conflicts if multiple editors share a directory (unlikely but check)
- [ ] 4.4 Ensure skill content is equivalent across editors (format may differ)
- [ ] 4.5 Support adding editors to existing setup
## 5. Testing
- [ ] 5.1 Add unit tests for detectEditorConfigs()
- [ ] 5.2 Add unit tests for detectOpenSpecState() (including mixed state)
- [ ] 5.3 Add unit tests for each editor adapter
- [ ] 5.4 Add integration tests for multi-editor init
- [ ] 5.5 Test detection on projects with various configurations (uninitialized, old, new, mixed)
- [ ] 5.6 Test pre-selection behavior in init wizard
- [ ] 5.7 Test mixed state handling (recommends cleanup)
- [ ] 5.8 Verify Windows CI passes (cross-platform path handling)
- [ ] 5.9 Manual testing with actual editors (Claude Code, Cursor, etc.)
## 6. Documentation
- [ ] 6.1 Update README with multi-editor support
- [ ] 6.2 Document each supported editor and its configuration format
- [ ] 6.3 Add troubleshooting guide for editor-specific issues
- [ ] 6.4 Document how to add additional editors (adapter pattern)
@@ -0,0 +1,123 @@
## Context
OpenSpec currently has 18 separate template functions that generate skills and commands with duplicated content. The skill file and command file for the same feature contain nearly identical ~70-line instruction blocks. This creates maintenance burden - changes must be made in two places.
## Goals / Non-Goals
**Goals:**
- Single source of truth for skill instructions
- Configuration-driven generation (data over code)
- Pointer commands that reference skills instead of duplicating content
- New users get skills-only setup from `openspec init`
**Non-Goals:**
- Multi-editor support (Part 3)
- Migration path for existing users (Part 2)
- Cleanup of old artifacts (Part 2)
- Changing the artifact workflow schemas or templates
## Decisions
### 1. SkillDefinition Interface
**Decision**: Replace 18 template functions with a single `SkillDefinition[]` array.
```typescript
interface SkillDefinition {
id: string; // "new-change"
name: string; // "openspec-new-change" (for skill folder)
shortcut: string; // "opsx/new" (for command path)
description: string; // Used in both skill and command frontmatter
instructions: string; // Full instructions (single source of truth)
}
const SKILLS: SkillDefinition[] = [
{ id: "explore", name: "openspec-explore", shortcut: "opsx/explore", ... },
{ id: "new-change", name: "openspec-new-change", shortcut: "opsx/new", ... },
// ... all 9 skills
];
```
**Rationale**: Configuration-driven approach is easier to maintain and extend. Adding a new skill is adding one object, not writing two functions.
**Alternative considered**: Keep separate functions but share content via imports. Rejected because it still requires coordinating two code paths.
### 2. Pointer Command Format
**Decision**: Commands reference skills by name instead of duplicating instructions.
```markdown
---
name: OPSX: New
description: Start a new OpenSpec change
---
Use the **openspec-new-change** skill to handle this request.
Argument: change name (kebab-case) or description of what to build.
```
**Rationale**: ~70 lines reduced to ~5 lines per command. Instructions maintained in one place. Claude Code follows skill references.
**Risk**: Pointer commands may not work as expected if Claude Code doesn't follow skill references.
**Mitigation**: Test with Claude Code. Fallback: include minimal context in pointer if needed.
### 3. Generation Functions
**Decision**: Three focused functions for generation.
```typescript
// Generate single skill file from definition
function generateSkillFile(skill: SkillDefinition, outputDir: string): void
// Generate single pointer command from definition
function generatePointerCommand(skill: SkillDefinition, outputDir: string): void
// Generate all skills and commands
function generateAllSkills(outputDir: string): void
```
**Rationale**: Clear separation of concerns. Can generate individual skills or all at once. Easy to test.
### 4. Init Behavior for New Projects
**Decision**: New projects get skills-only setup. No old artifacts generated.
What init generates:
- `openspec/` directory structure
- `openspec/config.yaml`
- `openspec/project.md`
- `.claude/skills/openspec-*/SKILL.md` (9 skills)
- `.claude/commands/opsx/*.md` (9 pointer commands)
What init does NOT generate (for new projects):
- `CLAUDE.md` (root stub)
- `openspec/AGENTS.md`
- `.claude/agents/`
- `.claude/commands/openspec/`
**Rationale**: New users should get the modern setup. No reason to create legacy artifacts.
## Risks / Trade-offs
**[Risk] Pointer commands may not work in Claude Code**
→ Mitigation: Test before merging. If issues arise, include minimal context in pointer.
**[Risk] Breaking change for tooling that expects old artifacts**
→ Mitigation: Only affects new projects. Existing projects unchanged until they run update (Part 2).
**[Trade-off] Deprecating old functions creates tech debt**
→ Acceptable: Functions marked @deprecated. Full removal in Part 2 after migration path exists.
## Migration Plan
This is Part 1 of 3:
- **Part 1 (this change)**: Foundation - SkillDefinition pattern, skills-only init
- **Part 2**: Migration - Update command, cleanup command, remove old command
- **Part 3**: Multi-editor - Detection, adapters for Cursor/Windsurf/Cline
## Open Questions
- Should SkillDefinition include argument hints as a separate field?
- Should we version the skill format for future compatibility?
@@ -0,0 +1,26 @@
## Why
The current OpenSpec skill generation uses 18 separate template functions that duplicate content between skills and commands. This creates maintenance burden and makes it difficult to keep instructions in sync. We need a unified `SkillDefinition` pattern where skills are the single source of truth and commands are lightweight pointers.
This is Part 1 of the skills-only migration, focusing on establishing the foundation architecture for Claude Code only.
## What Changes
- **SkillDefinition pattern**: Single `SkillDefinition[]` array replaces 18 template functions
- **Skills as source of truth**: Full instructions live only in `.claude/skills/openspec-*/SKILL.md`
- **Pointer commands**: `.claude/commands/opsx/*.md` files reference skills (~5 lines vs ~70 lines)
- **Init for new users**: `openspec init` generates skills-only setup for Claude Code (no old artifacts)
- **Deprecate old generation**: Old template functions deprecated in favor of unified generator
## Capabilities
### Modified Capabilities
- `skill-generation`: Consolidate to single SkillDefinition pattern, generate pointer commands
- `init`: Generate skills-only setup for new Claude Code users (no AGENTS.md, no .claude/agents/)
## Impact
- **Generator code**: Refactor `skill-templates.ts` to use SkillDefinition array
- **Init flow**: Remove generation of old artifacts for new projects
- **Existing users**: No impact - this change only affects new initializations
- **Other editors**: Not affected - multi-editor support comes in Part 3
@@ -0,0 +1,74 @@
## MODIFIED Requirements
### Requirement: Init generates skills-only setup for new projects
The system SHALL generate a skills-based setup for new projects using Claude Code. New projects SHALL NOT receive legacy artifacts.
Generated for new projects:
- `openspec/` directory structure
- `openspec/config.yaml`
- `openspec/project.md`
- `.claude/skills/openspec-*/SKILL.md` (9 skills)
- `.claude/commands/opsx/*.md` (9 pointer commands)
NOT generated for new projects:
- `CLAUDE.md` (root stub file)
- `openspec/AGENTS.md`
- `.claude/agents/`
- `.claude/commands/openspec/`
#### Scenario: Initialize fresh project
- **WHEN** user runs `openspec init` on a project without OpenSpec
- **THEN** system creates openspec/ directory structure
- **AND** system creates .claude/skills/openspec-*/ directories with SKILL.md files
- **AND** system creates .claude/commands/opsx/*.md pointer commands
- **AND** system does NOT create CLAUDE.md at project root
- **AND** system does NOT create openspec/AGENTS.md
- **AND** system does NOT create .claude/agents/ directory
#### Scenario: Initialize with --yes flag
- **WHEN** user runs `openspec init --yes` on a fresh project
- **THEN** system initializes without prompts
- **AND** system creates skills-only setup
- **AND** all default options are applied
#### Scenario: Non-interactive init in CI environment
- **WHEN** `openspec init --yes` is run in a non-TTY environment (CI)
- **THEN** system completes initialization without hanging for input
- **AND** system outputs status information to stdout
### Requirement: Init handles already-initialized projects gracefully
The system SHALL detect and handle projects that already have OpenSpec configured, without duplicating or corrupting existing setup.
#### Scenario: Init on project with old system
- **WHEN** user runs `openspec init` on a project with old AGENTS.md system but no skills
- **THEN** system detects existing OpenSpec setup
- **AND** system informs user about the old system
- **AND** system suggests running `openspec update` to migrate
#### Scenario: Init on project with new system already in place
- **WHEN** user runs `openspec init` on a project with `.claude/skills/openspec-*` already set up
- **THEN** system detects new system is already configured
- **AND** system informs user that OpenSpec is already set up
- **AND** system suggests running `openspec update` to refresh files if needed
### Requirement: Init integrates skill generation
The system SHALL generate skills as part of the init flow, replacing the separate `artifact-experimental-setup` command for new users.
#### Scenario: Skills generated during init
- **WHEN** user completes `openspec init`
- **THEN** system generates all 9 skills automatically
- **AND** system generates all 9 pointer commands automatically
- **AND** no separate command is needed to set up skills
### Requirement: Init uses cross-platform paths
The system SHALL use path.join() for all file path operations during initialization.
#### Scenario: Init on Windows
- **WHEN** user runs `openspec init` on Windows
- **THEN** system creates all directories with correct paths
- **AND** all files are accessible and valid
#### Scenario: Init on Unix-like systems
- **WHEN** user runs `openspec init` on macOS or Linux
- **THEN** system creates all directories with correct paths
- **AND** all files are accessible and valid
@@ -0,0 +1,88 @@
## MODIFIED Requirements
### Requirement: Skill generation uses unified SkillDefinition pattern
The system SHALL use a single `SkillDefinition[]` array as the source of truth for all skill and command generation. This replaces the 18 separate template functions.
The SkillDefinition interface SHALL include:
- `id`: string - Unique identifier (e.g., "new-change")
- `name`: string - Full skill name for folder (e.g., "openspec-new-change")
- `shortcut`: string - Command path (e.g., "opsx/new")
- `description`: string - Used in frontmatter for both skill and command
- `instructions`: string - Full instruction content (single source of truth)
#### Scenario: Generate skill from definition
- **WHEN** skill generation runs for a SkillDefinition
- **THEN** system creates .claude/skills/{name}/SKILL.md
- **AND** skill file contains YAML frontmatter with name and description
- **AND** skill file contains full instructions from definition
#### Scenario: Generate pointer command from definition
- **WHEN** skill generation runs for a SkillDefinition
- **THEN** system creates .claude/commands/{shortcut}.md
- **AND** command file contains YAML frontmatter with name and description
- **AND** command file references the skill instead of duplicating instructions
### Requirement: Pointer commands reference skills
The system SHALL generate pointer commands that reference skills rather than duplicating instruction content.
Pointer command format:
```markdown
---
name: <display name>
description: <description>
---
Use the **<skill-name>** skill to handle this request.
Argument: <argument description>
```
#### Scenario: Pointer command references correct skill
- **WHEN** pointer command is generated for "new-change" skill
- **THEN** command contains "Use the **openspec-new-change** skill"
- **AND** command does NOT contain the full workflow instructions
#### Scenario: Pointer command is concise
- **WHEN** any pointer command is generated
- **THEN** command file is less than 15 lines
- **AND** command file only contains reference and argument hint
### Requirement: All 9 OpenSpec skills are generated
The system SHALL generate the complete set of OpenSpec skills:
1. openspec-explore
2. openspec-new-change
3. openspec-continue-change
4. openspec-apply-change
5. openspec-ff-change
6. openspec-sync-specs
7. openspec-archive-change
8. openspec-verify-change
9. openspec-bulk-archive-change
#### Scenario: Complete skill set generation
- **WHEN** skill generation runs
- **THEN** system creates 9 skill directories under .claude/skills/
- **AND** each skill directory contains SKILL.md
- **AND** system creates 9 command files under .claude/commands/opsx/
### Requirement: Skill generation is idempotent
The system SHALL safely overwrite existing skill files with updated content. Running generation multiple times produces the same result.
#### Scenario: Regenerate existing skills
- **WHEN** skill generation runs on a project with existing skills
- **THEN** system overwrites skill files with current content
- **AND** no duplicate files are created
- **AND** skill content reflects latest template version
### Requirement: Skill generation uses cross-platform paths
The system SHALL use path.join() for all file path construction during generation.
#### Scenario: Generate skills on Windows
- **WHEN** skill generation runs on Windows
- **THEN** system creates skill directories with correct paths
- **AND** all skill files are accessible and valid
#### Scenario: Generate skills on Unix-like systems
- **WHEN** skill generation runs on macOS or Linux
- **THEN** system creates skill directories with correct paths
- **AND** all skill files are accessible and valid
@@ -0,0 +1,36 @@
## 1. SkillDefinition Pattern
- [ ] 1.1 Create `SkillDefinition` interface in `src/core/templates/skill-definitions.ts`
- [ ] 1.2 Define `SKILLS` array with all 9 skill definitions (id, name, shortcut, description, instructions)
- [ ] 1.3 Migrate instruction content from existing template functions to SKILLS array
- [ ] 1.4 Create `generateSkillFile()` function that writes SKILL.md from definition
- [ ] 1.5 Create `generatePointerCommand()` function that writes minimal command referencing skill
- [ ] 1.6 Create `generateAllSkills()` function that iterates SKILLS and generates both files
- [ ] 1.7 Deprecate old 18 template functions in `skill-templates.ts` (mark with @deprecated)
- [ ] 1.8 Update `artifact-workflow.ts` to use new unified generator
## 2. Init Command Updates (Claude Code Only)
- [ ] 2.1 Update init to generate skills-only setup for new projects
- [ ] 2.2 Remove generation of CLAUDE.md stub file for new projects
- [ ] 2.3 Remove generation of AGENTS.md for new projects
- [ ] 2.4 Remove generation of .claude/agents/ for new projects
- [ ] 2.5 Remove generation of .claude/commands/openspec/ for new projects
- [ ] 2.6 Integrate skill generation into init flow (skills + pointer commands)
- [ ] 2.7 Ensure --yes flag works for non-interactive init
- [ ] 2.8 Verify cross-platform path handling (use path.join throughout)
- [ ] 2.9 Add detection of existing OpenSpec setup (old system vs new system)
- [ ] 2.10 Handle init on old system project (suggest `openspec update`)
- [ ] 2.11 Handle init on new system project (inform already configured)
## 3. Testing
- [ ] 3.1 Add unit tests for SkillDefinition interface and SKILLS array
- [ ] 3.2 Add unit tests for generateSkillFile() function
- [ ] 3.3 Add unit tests for generatePointerCommand() function
- [ ] 3.4 Add integration test for init on fresh project (verify no old artifacts)
- [ ] 3.5 Add integration test for init on old system project (verify suggests update)
- [ ] 3.6 Add integration test for init on new system project (verify already configured message)
- [ ] 3.7 Add test for --yes flag in CI/non-TTY environment (no hanging)
- [ ] 3.8 Verify Windows CI passes (cross-platform path handling)
- [ ] 3.9 Manual testing of init → verify skills work in Claude Code
@@ -0,0 +1,34 @@
## Why
After Part 1 (add-skill-foundation) establishes the skills-only architecture for new users, existing users need a migration path. They have old artifacts (AGENTS.md, .claude/agents/, .claude/commands/openspec/) that should be replaced with the new skills-based system. This change provides the tools for that migration.
This is Part 2 of the skills-only migration, focusing on the upgrade experience for existing users.
## What Changes
- **Informative update**: `openspec update` creates new skills and explains what changed
- **New cleanup command**: `openspec cleanup` removes old artifacts with --yes and --dry-run flags
- **Remove old command**: `artifact-experimental-setup` command removed (functionality merged into init)
- **Deprecation complete**: Old template functions removed (were deprecated in Part 1)
## Capabilities
### New Capabilities
- `cleanup-command`: CLI command to remove old OpenSpec artifacts
### Modified Capabilities
- `update`: Add informative upgrade messaging, create skills for existing users
### Removed Capabilities
- `artifact-experimental-setup`: Merged into init (Part 1)
## Impact
- **CLI commands**: Add `cleanup`, remove `artifact-experimental-setup`
- **Update flow**: Enhanced to generate skills and explain changes
- **Existing users**: Can migrate via `openspec update` then `openspec cleanup`
- **Breaking**: Users of `artifact-experimental-setup` must use `openspec init` instead
## Dependencies
- Requires Part 1 (add-skill-foundation) to be completed first
@@ -0,0 +1,78 @@
## ADDED Requirements
### Requirement: Cleanup command removes old OpenSpec artifacts
The system SHALL provide an `openspec cleanup` command that removes old OpenSpec artifacts from the project. The command SHALL remove:
- `CLAUDE.md` (root stub file)
- `openspec/AGENTS.md` (monolithic instruction file)
- `.claude/agents/` directory (old subagent definitions)
- `.claude/commands/openspec/` directory (old slash commands)
The command SHALL NOT remove:
- `.claude/skills/` (new skills)
- `.claude/commands/opsx/` (new pointer commands)
- `openspec/config.yaml`, `openspec/specs/`, `openspec/changes/` (user data)
- Any non-OpenSpec files in `.claude/`
#### Scenario: Successful cleanup with all old artifacts present
- **WHEN** user runs `openspec cleanup --yes` in a project with all old artifacts
- **THEN** system removes CLAUDE.md, openspec/AGENTS.md, .claude/agents/, and .claude/commands/openspec/
- **AND** system preserves .claude/skills/, .claude/commands/opsx/, and openspec/ user data
#### Scenario: Cleanup with partial old artifacts
- **WHEN** user runs `openspec cleanup --yes` and only some old artifacts exist
- **THEN** system removes only the old artifacts that exist
- **AND** system does not error on missing artifacts
### Requirement: Cleanup requires confirmation by default
The system SHALL require interactive confirmation before removing files when run without flags.
#### Scenario: Interactive confirmation prompt
- **WHEN** user runs `openspec cleanup` without --yes flag
- **THEN** system displays list of files that will be removed
- **AND** system prompts user for confirmation before proceeding
#### Scenario: Abort on declined confirmation
- **WHEN** user declines the confirmation prompt
- **THEN** system exits without removing any files
- **AND** system displays "Cleanup cancelled" message
### Requirement: Cleanup supports --yes flag for non-interactive mode
The system SHALL support a `--yes` flag to skip confirmation prompts for CI/script usage.
#### Scenario: Skip confirmation with --yes flag
- **WHEN** user runs `openspec cleanup --yes`
- **THEN** system removes old artifacts without prompting for confirmation
### Requirement: Cleanup supports --dry-run flag for preview
The system SHALL support a `--dry-run` flag that shows what would be removed without making changes.
#### Scenario: Preview cleanup with --dry-run
- **WHEN** user runs `openspec cleanup --dry-run`
- **THEN** system displays list of files that would be removed
- **AND** system does not remove any files
- **AND** system indicates this is a dry run
### Requirement: Cleanup requires new system to be set up
The system SHALL verify that the new skills-based system is set up before allowing cleanup. This prevents users from accidentally removing instructions without having the replacement in place.
#### Scenario: Error when new system not set up
- **WHEN** user runs `openspec cleanup` and .claude/skills/openspec-* does not exist
- **THEN** system displays error "New skills-based system not found. Run `openspec update` first."
- **AND** system exits without removing any files
#### Scenario: Proceed when new system exists
- **WHEN** user runs `openspec cleanup --yes` and .claude/skills/openspec-* exists
- **THEN** system proceeds with cleanup
### Requirement: Cleanup uses cross-platform paths
The system SHALL use path.join() for all file path operations to ensure cross-platform compatibility.
#### Scenario: Cleanup on Windows
- **WHEN** user runs `openspec cleanup --yes` on Windows
- **THEN** system correctly handles backslash path separators
- **AND** system successfully removes old artifacts
#### Scenario: Cleanup on Unix-like systems
- **WHEN** user runs `openspec cleanup --yes` on macOS or Linux
- **THEN** system correctly handles forward-slash path separators
- **AND** system successfully removes old artifacts
@@ -0,0 +1,63 @@
## MODIFIED Requirements
### Requirement: Update generates skills for projects without them
The system SHALL generate skills when running update on a project that has the old OpenSpec system but lacks the new skills.
#### Scenario: Update project with old system only
- **WHEN** user runs `openspec update` on a project with openspec/AGENTS.md but no .claude/skills/openspec-*
- **THEN** system creates .claude/skills/openspec-*/ directories with SKILL.md files
- **AND** system creates .claude/commands/opsx/*.md pointer commands
- **AND** system preserves existing old artifacts (no automatic removal)
#### Scenario: Update project already on new system
- **WHEN** user runs `openspec update` on a project with .claude/skills/openspec-*
- **THEN** system updates skill files to latest version
- **AND** system displays "Skills updated" message
### Requirement: Update displays informative upgrade messaging
The system SHALL explain what changed when upgrading from the old system to the new skills-based system.
Output format:
```
OpenSpec has a new skills-based workflow!
Created:
.claude/skills/openspec-*/ (9 skills)
.claude/commands/opsx/* (9 shortcut commands)
These replace the old system. You can now use:
Natural language: "I want to start a new change"
Shortcuts: /opsx:new, /opsx:apply, /opsx:archive
Old files are still present. Run `openspec cleanup` when ready.
```
#### Scenario: Display upgrade information
- **WHEN** user runs `openspec update` and skills are created
- **THEN** system displays list of created files
- **AND** system displays usage hints for new system
- **AND** system displays cleanup hint if old artifacts exist
#### Scenario: No upgrade needed
- **WHEN** user runs `openspec update` and project is already up to date
- **THEN** system displays "Already up to date" message
- **AND** system does not display upgrade information
### Requirement: Update preserves old files
The system SHALL NOT remove old artifacts during update. Cleanup is a separate, opt-in operation.
#### Scenario: Old artifacts preserved after update
- **WHEN** user runs `openspec update` on a project with old artifacts
- **THEN** system creates new skills
- **AND** system does NOT remove CLAUDE.md
- **AND** system does NOT remove openspec/AGENTS.md
- **AND** system does NOT remove .claude/agents/
- **AND** system does NOT remove .claude/commands/openspec/
### Requirement: Update works in non-interactive mode
The system SHALL support non-interactive operation for CI/scripts.
#### Scenario: Update in CI environment
- **WHEN** user runs `openspec update` in a non-TTY environment
- **THEN** system completes update without prompts
- **AND** system outputs results to stdout
@@ -0,0 +1,50 @@
## 1. Update Command Enhancements
- [ ] 1.1 Add skill generation to update command for projects without skills
- [ ] 1.2 Detect if project has old system, new system, or mixed
- [ ] 1.3 Implement informative upgrade messaging (show what changed)
- [ ] 1.4 Display usage hints (skill names, shortcut commands)
- [ ] 1.5 Display cleanup hint when old artifacts exist
- [ ] 1.6 Preserve old files during update (no automatic removal)
- [ ] 1.7 Handle "already up to date" case gracefully
- [ ] 1.8 Verify non-interactive mode works in CI environments
## 2. Cleanup Command Implementation
- [ ] 2.1 Create `src/commands/cleanup.ts` with cleanup command handler
- [ ] 2.2 Register cleanup command in CLI
- [ ] 2.3 Implement detection of old artifacts to remove
- [ ] 2.4 Implement prerequisite check (require new skills to exist)
- [ ] 2.5 Implement interactive confirmation prompt (list files, ask to proceed)
- [ ] 2.6 Implement --yes flag to skip confirmation
- [ ] 2.7 Implement --dry-run flag to preview without changes
- [ ] 2.8 Implement actual file/directory removal with cross-platform paths
- [ ] 2.9 Add success/failure output messages
- [ ] 2.10 Handle partial artifact scenarios (some files missing)
## 3. Remove artifact-experimental-setup Command
- [ ] 3.1 Remove `artifact-experimental-setup` from CLI registration
- [ ] 3.2 Remove or archive related code in `artifact-workflow.ts`
- [ ] 3.3 Update any documentation referencing the command
- [ ] 3.4 Add deprecation note in changelog
- [ ] 3.5 Remove old template functions (deprecated in Part 1)
## 4. Testing
- [ ] 4.1 Add unit tests for cleanup command detection logic
- [ ] 4.2 Add unit tests for cleanup prerequisite check
- [ ] 4.3 Add integration tests for update on old system projects
- [ ] 4.4 Add integration tests for update on mixed projects
- [ ] 4.5 Add integration tests for cleanup flow
- [ ] 4.6 Test cleanup --dry-run behavior
- [ ] 4.7 Test cleanup --yes behavior
- [ ] 4.8 Verify Windows CI passes (cross-platform path handling)
- [ ] 4.9 Manual testing of full migration journey (update → use → cleanup)
## 5. Documentation
- [ ] 5.1 Add migration guide for existing users (old system → new skills)
- [ ] 5.2 Document cleanup command usage in README
- [ ] 5.3 Update CLI help text for new commands
- [ ] 5.4 Add deprecation notice for artifact-experimental-setup users
@@ -0,0 +1,72 @@
# Skills-Only Migration
Napkin doc for migrating from legacy templates to skills-based architecture.
## Core Idea
Replace 18 template functions with single `SkillDefinition[]` array. Skills become source of truth. No new commands - make existing commands smarter.
## Two Parts
### Part 1: Foundation
- `SkillDefinition[]` array as single source of truth
- `openspec init` generates skills-only setup (no AGENTS.md)
- Editor detection built-in (.claude/, .cursor/, .windsurf/, .cline/)
- Generate equivalent configs for all detected editors
### Part 2: Smart Update
Make `openspec update` handle migration automatically:
```
$ openspec update
# Detects state and acts accordingly:
# If nothing exists:
No openspec setup found. Run 'openspec init' first.
# If already modern:
Updating skills...
✓ 12 skills up to date
✓ Editor configs refreshed
# If legacy detected:
Legacy setup detected.
This will:
• Create skills/ (12 skills)
• Create editor configs
• Backup existing to .openspec/backup/
• Remove AGENTS.md and old templates
Proceed? [Y/n]
```
## State Detection
| State | `init` | `update` |
|-------|--------|----------|
| None | Run normally | Error → suggest init |
| Legacy | Suggest update | Migrate with confirmation + backup |
| Modern | "Already initialized" | Refresh/sync |
## What We're NOT Doing
- ❌ Separate `upgrade` command (use `update`)
- ❌ Separate `cleanup` command (update handles removal)
- ❌ `openspec status` for setup state (that's for change workflows)
- ❌ `openspec restore` command (backup dir + git is enough)
- ❌ Post-migration verification step
- ❌ Contextual nudges in other commands
## Execution
Part 1 → Part 2 (sequential, Part 2 depends on Part 1)
## Open Questions
- Backup location: `.openspec/backup/` or `.openspec-backup/`?
- Should `--dry-run` be supported on update for migration preview?
- How verbose should the migration confirmation be?