Skip to content

Commit cf8b621

Browse files
authored
feat(cli): merge init and experimental commands (Fission-AI#564)
* feat(cli): add change proposal to merge init and experimental commands This change merges `openspec init` and `openspec experimental` into a single command that uses the skill-based workflow as the default. Key changes: - BREAKING: init generates skills and /opsx:* commands instead of config files - BREAKING: Config files (CLAUDE.md, .cursorrules, etc.) no longer generated - BREAKING: Old slash commands (/openspec:proposal, etc.) no longer generated - BREAKING: openspec/AGENTS.md and project.md no longer generated - Add legacy detection and cleanup with Y/N confirmation - Keep experimental as hidden alias for backward compatibility Artifacts: - proposal.md: Motivation and scope - design.md: Architecture decisions and edge case handling - specs/legacy-cleanup/spec.md: New capability for legacy artifact cleanup - specs/cli-init/spec.md: Modified init spec with skill-based workflow - tasks.md: 37 implementation tasks across 7 groups * docs(change): preserve project.md with migration hint instead of deleting Update merge-init-experimental change artifacts to preserve openspec/project.md during legacy cleanup instead of auto-deleting it. Users will see a migration hint directing them to move content to config.yaml's context field. Changes: - design.md: Add Decision 6 documenting rationale and migration path - spec.md: Add project.md migration hint requirement and scenarios - tasks.md: Add task 1.7 for migration hint output This avoids losing user-written project documentation while guiding them to the new config.yaml approach. * docs(change): resolve open questions about update command and experimental labels
1 parent c157483 commit cf8b621

6 files changed

Lines changed: 626 additions & 0 deletions

File tree

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-23
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
## Context
2+
3+
Currently `openspec init` and `openspec experimental` are separate commands with distinct purposes:
4+
5+
- **init**: Creates `openspec/` directory, generates `AGENTS.md`/`project.md`, configures tool config files (`CLAUDE.md`, etc.), generates old slash commands (`/openspec:proposal`, etc.)
6+
- **experimental**: Generates skills (9 per tool), generates opsx slash commands (`/opsx:new`, etc.), creates `config.yaml`
7+
8+
The skill-based workflow (experimental) is the direction we're going, so we're making it the default by merging into `init`.
9+
10+
## Goals / Non-Goals
11+
12+
**Goals:**
13+
- Single `openspec init` command that sets up the complete skill-based workflow
14+
- Clean migration path for existing users with legacy artifacts
15+
- Remove all code related to config files and old slash commands
16+
- Keep the polished UX from experimental (animated welcome, searchable multi-select)
17+
18+
**Non-Goals:**
19+
- Supporting both workflows simultaneously
20+
- Providing options to use the old workflow
21+
- Backward compatibility for `/openspec:*` commands (breaking change)
22+
23+
## Decisions
24+
25+
### Decision 1: Merge into init, not into experimental
26+
27+
**Choice**: Rewrite `init` to do what `experimental` does, then delete `experimental`.
28+
29+
**Rationale**: `init` is the canonical setup command. Users expect `init` to set up their project. `experimental` was always meant to be temporary.
30+
31+
**Alternatives considered**:
32+
- Keep `experimental` as the main command → confusing name for default behavior
33+
- Create new command → unnecessary, `init` already exists
34+
35+
### Decision 2: Legacy cleanup with Y/N prompt
36+
37+
**Choice**: Detect legacy artifacts, show what was found, prompt `"Legacy files detected. Upgrade and clean up? [Y/n]"`, then remove if confirmed.
38+
39+
**Rationale**: Users should know what's being removed. A single Y/N is simple and decisive. No need for multiple options.
40+
41+
**Alternatives considered**:
42+
- Multiple options (keep/remove/cancel) → overcomplicated
43+
- Silent removal → users might be surprised
44+
- Just warn without removing → leaves cruft
45+
46+
### Decision 3: Surgical removal of legacy content
47+
48+
**Choice**: For files with mixed content (OpenSpec markers + user content), only remove the OpenSpec marker block. For files that are 100% OpenSpec content, delete the entire file.
49+
50+
**Rationale**: Respects user customizations. CLAUDE.md might have other instructions beyond OpenSpec.
51+
52+
**Edge cases**:
53+
- **Config files with mixed content**: Remove only `<!-- OPENSPEC:START -->` to `<!-- OPENSPEC:END -->` block
54+
- **Config files that are 100% OpenSpec**: Delete file entirely (check if content outside markers is empty/whitespace)
55+
- **Old slash command directories** (`.claude/commands/openspec/`): Delete entire directory (ours)
56+
- **`openspec/AGENTS.md`**: Delete (ours)
57+
- **Root `AGENTS.md`**: Only remove OpenSpec marker block, preserve rest
58+
59+
### Decision 6: Preserve project.md with migration hint
60+
61+
**Choice**: Do NOT auto-delete `openspec/project.md`. Preserve it and show a message directing users to manually migrate content to `config.yaml`'s `context:` field.
62+
63+
**Rationale**:
64+
- `project.md` may contain valuable user-written project documentation
65+
- The new workflow uses `config.yaml.context` for the same purpose (auto-injected into artifacts)
66+
- Auto-deleting would lose user content; auto-migrating is complex (needs LLM to compress)
67+
- Users can migrate manually or use `/opsx:explore` to get AI assistance
68+
69+
**Migration path**:
70+
1. During legacy cleanup, detect `openspec/project.md` but do not delete
71+
2. Show in output: "openspec/project.md still exists - migrate content to config.yaml's context: field, then delete"
72+
3. User migrates manually or asks Claude in explore mode: "help me migrate project.md to config.yaml"
73+
4. User deletes project.md when ready
74+
75+
**Why not auto-migrate?**
76+
- `project.md` is verbose (sections, headers, placeholders)
77+
- `config.yaml.context` should be concise and dense
78+
- LLM compression would be ideal but adds complexity and non-determinism to init
79+
- Manual migration lets users decide what's actually important
80+
81+
### Decision 4: Hidden alias for experimental
82+
83+
**Choice**: Keep `openspec experimental` as a hidden command that delegates to `init`.
84+
85+
**Rationale**: Users who learned `experimental` can still use it during transition. Hidden means it won't show in help.
86+
87+
### Decision 5: Reuse existing infrastructure
88+
89+
**Choice**: Reuse skill templates, command adapters, welcome screen, and multi-select from experimental.
90+
91+
**Rationale**: Already built and working. Just needs to be called from init instead of experimental.
92+
93+
## Risks / Trade-offs
94+
95+
| Risk | Mitigation |
96+
|------|------------|
97+
| Users with custom `/openspec:*` commands lose them | Document in release notes; old commands are in git history |
98+
| Mixed-content detection might be imperfect | Conservative approach: if unsure, preserve the file and warn |
99+
| Users confused by missing config files | Clear messaging in init output about what changed |
100+
| `openspec update` might break | Review and update `update` command to work with new structure |
101+
102+
## Architecture
103+
104+
### What init creates (after merge)
105+
106+
```
107+
openspec/
108+
├── config.yaml # Schema settings (from experimental)
109+
├── specs/ # Empty, for user's specs
110+
└── changes/ # Empty, for user's changes
111+
└── archive/
112+
113+
.<tool>/skills/ # 9 skills per selected tool
114+
├── openspec-explore/SKILL.md
115+
├── openspec-new-change/SKILL.md
116+
├── openspec-continue-change/SKILL.md
117+
├── openspec-apply-change/SKILL.md
118+
├── openspec-ff-change/SKILL.md
119+
├── openspec-verify-change/SKILL.md
120+
├── openspec-sync-specs/SKILL.md
121+
├── openspec-archive-change/SKILL.md
122+
└── openspec-bulk-archive-change/SKILL.md
123+
124+
.<tool>/commands/opsx/ # 9 slash commands per selected tool
125+
├── explore.md
126+
├── new.md
127+
├── continue.md
128+
├── apply.md
129+
├── ff.md
130+
├── verify.md
131+
├── sync.md
132+
├── archive.md
133+
└── bulk-archive.md
134+
```
135+
136+
### What init no longer creates
137+
138+
- `CLAUDE.md`, `.cursorrules`, `.windsurfrules`, etc. (config files)
139+
- `openspec/AGENTS.md`
140+
- `openspec/project.md`
141+
- Root `AGENTS.md` stub
142+
- `.claude/commands/openspec/` (old slash commands)
143+
144+
### Legacy detection targets
145+
146+
| Artifact Type | Detection Method | Removal Method |
147+
|--------------|------------------|----------------|
148+
| Config files (CLAUDE.md, etc.) | File exists AND contains OpenSpec markers | Remove marker block; delete file if empty after |
149+
| Old slash command dirs | Directory exists at `.<tool>/commands/openspec/` | Delete entire directory |
150+
| openspec/AGENTS.md | File exists at `openspec/AGENTS.md` | Delete file |
151+
| openspec/project.md | File exists at `openspec/project.md` | **Preserve** - show migration hint only |
152+
| Root AGENTS.md | File exists at `AGENTS.md` AND contains OpenSpec markers | Remove marker block; delete file if empty after |
153+
154+
### Code to remove
155+
156+
- `src/core/configurators/` - entire directory (ToolRegistry, all config generators)
157+
- `src/core/configurators/slash/` - entire directory (SlashCommandRegistry, old command generators)
158+
- `src/core/templates/slash-command-templates.ts` - old `/openspec:*` content
159+
- `src/core/templates/claude-template.ts`
160+
- `src/core/templates/cline-template.ts`
161+
- `src/core/templates/costrict-template.ts`
162+
- `src/core/templates/agents-template.ts`
163+
- `src/core/templates/agents-root-stub.ts`
164+
- `src/core/templates/project-template.ts`
165+
- `src/commands/experimental/` - entire directory (merged into init)
166+
- Related test files
167+
168+
### Code to migrate into init
169+
170+
- Animated welcome screen (`src/ui/welcome-screen.ts`) - keep, call from init
171+
- Searchable multi-select (`src/prompts/searchable-multi-select.ts`) - keep, call from init
172+
- Skill templates (`src/core/templates/skill-templates.ts`) - keep
173+
- Command generation (`src/core/command-generation/`) - keep
174+
- Tool states detection (from `experimental/setup.ts`) - move to init
175+
176+
## Open Questions
177+
178+
1. **What happens to `openspec update`?** - RESOLVED
179+
180+
**Current behavior**: Updates `openspec/AGENTS.md`, config files (`CLAUDE.md`, etc.) via `ToolRegistry`, and old slash commands (`/openspec:*`) via `SlashCommandRegistry`.
181+
182+
**New behavior**: Rewrite to refresh skills and opsx commands instead:
183+
- Detect which tools have skills installed (check for `.claude/skills/openspec-*/`, etc.)
184+
- Refresh all 9 skill files per installed tool using `skill-templates.ts`
185+
- Refresh all 9 opsx command files per installed tool using `command-generation/` adapters
186+
- Remove imports of `ToolRegistry`, `SlashCommandRegistry`, `agentsTemplate`
187+
- Update output messaging to reflect skills/commands instead of config files
188+
189+
**Key principle**: Same as current update - only refresh existing tools, don't add new ones.
190+
191+
2. **Should we keep `openspec schemas` and other experimental subcommands?** - RESOLVED
192+
193+
**Decision**: Yes, keep them. Remove "[Experimental]" label from all subcommands (status, instructions, schemas, etc.). See task 4.3.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## Why
2+
3+
The current setup has two separate commands (`openspec init` and `openspec experimental`) that configure different parts of the OpenSpec workflow. This creates confusion about which command to run, results in partial setups, and maintains two parallel systems (config files + old slash commands vs skills + opsx commands). Making the skill-based workflow the default simplifies onboarding and establishes a single, consistent way to use OpenSpec.
4+
5+
## What Changes
6+
7+
- **BREAKING**: `openspec init` now generates skills and `/opsx:*` commands instead of config files and `/openspec:*` commands
8+
- **BREAKING**: Config files (`CLAUDE.md`, `.cursorrules`, etc.) are no longer generated
9+
- **BREAKING**: Old slash commands (`/openspec:proposal`, `/openspec:apply`, `/openspec:archive`) are no longer generated
10+
- **BREAKING**: `openspec/AGENTS.md` and `openspec/project.md` are no longer generated
11+
- Merge `experimental` command functionality into `init`
12+
- Add legacy detection and auto-cleanup with Y/N confirmation
13+
- Keep `openspec experimental` as hidden alias for backward compatibility
14+
- Use the animated welcome screen from experimental for the unified init
15+
16+
## Capabilities
17+
18+
### New Capabilities
19+
20+
- `legacy-cleanup`: Detect and remove legacy OpenSpec artifacts (config files, old slash commands, AGENTS.md) during init
21+
22+
### Modified Capabilities
23+
24+
- `cli-init`: Complete rewrite - generates skills and opsx commands instead of config files and old slash commands; removes AGENTS.md/project.md generation; adds legacy cleanup; uses experimental's animated welcome screen
25+
26+
## Impact
27+
28+
- **Code removal**: `ToolRegistry`, `SlashCommandRegistry`, config file generators, old slash command templates, AGENTS.md/project.md templates
29+
- **Code migration**: Move skill generation and command adapter logic from `experimental/setup.ts` into `init.ts`
30+
- **Commands affected**: `init` (rewritten), `experimental` (becomes hidden alias), `update` (may need adjustment)
31+
- **User migration**: Existing users running `init` will be prompted to clean up legacy files
32+
- **Breaking for**: Users relying on config files for passive triggering, users using `/openspec:*` commands

0 commit comments

Comments
 (0)