-
Notifications
You must be signed in to change notification settings - Fork 4.5k
feat(cli): merge init and experimental commands #564
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| schema: spec-driven | ||
| created: 2026-01-23 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| ## Context | ||
|
|
||
| Currently `openspec init` and `openspec experimental` are separate commands with distinct purposes: | ||
|
|
||
| - **init**: Creates `openspec/` directory, generates `AGENTS.md`/`project.md`, configures tool config files (`CLAUDE.md`, etc.), generates old slash commands (`/openspec:proposal`, etc.) | ||
| - **experimental**: Generates skills (9 per tool), generates opsx slash commands (`/opsx:new`, etc.), creates `config.yaml` | ||
|
|
||
| The skill-based workflow (experimental) is the direction we're going, so we're making it the default by merging into `init`. | ||
|
|
||
| ## Goals / Non-Goals | ||
|
|
||
| **Goals:** | ||
| - Single `openspec init` command that sets up the complete skill-based workflow | ||
| - Clean migration path for existing users with legacy artifacts | ||
| - Remove all code related to config files and old slash commands | ||
| - Keep the polished UX from experimental (animated welcome, searchable multi-select) | ||
|
|
||
| **Non-Goals:** | ||
| - Supporting both workflows simultaneously | ||
| - Providing options to use the old workflow | ||
| - Backward compatibility for `/openspec:*` commands (breaking change) | ||
|
|
||
| ## Decisions | ||
|
|
||
| ### Decision 1: Merge into init, not into experimental | ||
|
|
||
| **Choice**: Rewrite `init` to do what `experimental` does, then delete `experimental`. | ||
|
|
||
| **Rationale**: `init` is the canonical setup command. Users expect `init` to set up their project. `experimental` was always meant to be temporary. | ||
|
|
||
| **Alternatives considered**: | ||
| - Keep `experimental` as the main command → confusing name for default behavior | ||
| - Create new command → unnecessary, `init` already exists | ||
|
|
||
| ### Decision 2: Legacy cleanup with Y/N prompt | ||
|
|
||
| **Choice**: Detect legacy artifacts, show what was found, prompt `"Legacy files detected. Upgrade and clean up? [Y/n]"`, then remove if confirmed. | ||
|
|
||
| **Rationale**: Users should know what's being removed. A single Y/N is simple and decisive. No need for multiple options. | ||
|
|
||
| **Alternatives considered**: | ||
| - Multiple options (keep/remove/cancel) → overcomplicated | ||
| - Silent removal → users might be surprised | ||
| - Just warn without removing → leaves cruft | ||
|
|
||
| ### Decision 3: Surgical removal of legacy content | ||
|
|
||
| **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. | ||
|
|
||
| **Rationale**: Respects user customizations. CLAUDE.md might have other instructions beyond OpenSpec. | ||
|
|
||
| **Edge cases**: | ||
| - **Config files with mixed content**: Remove only `<!-- OPENSPEC:START -->` to `<!-- OPENSPEC:END -->` block | ||
| - **Config files that are 100% OpenSpec**: Delete file entirely (check if content outside markers is empty/whitespace) | ||
| - **Old slash command directories** (`.claude/commands/openspec/`): Delete entire directory (ours) | ||
| - **`openspec/AGENTS.md` and `project.md`**: Delete (ours) | ||
| - **Root `AGENTS.md`**: Only remove OpenSpec marker block, preserve rest | ||
|
|
||
| ### Decision 4: Hidden alias for experimental | ||
|
|
||
| **Choice**: Keep `openspec experimental` as a hidden command that delegates to `init`. | ||
|
|
||
| **Rationale**: Users who learned `experimental` can still use it during transition. Hidden means it won't show in help. | ||
|
|
||
| ### Decision 5: Reuse existing infrastructure | ||
|
|
||
| **Choice**: Reuse skill templates, command adapters, welcome screen, and multi-select from experimental. | ||
|
|
||
| **Rationale**: Already built and working. Just needs to be called from init instead of experimental. | ||
|
|
||
| ## Risks / Trade-offs | ||
|
|
||
| | Risk | Mitigation | | ||
| |------|------------| | ||
| | Users with custom `/openspec:*` commands lose them | Document in release notes; old commands are in git history | | ||
| | Mixed-content detection might be imperfect | Conservative approach: if unsure, preserve the file and warn | | ||
| | Users confused by missing config files | Clear messaging in init output about what changed | | ||
| | `openspec update` might break | Review and update `update` command to work with new structure | | ||
|
|
||
| ## Architecture | ||
|
|
||
| ### What init creates (after merge) | ||
|
|
||
| ``` | ||
| openspec/ | ||
| ├── config.yaml # Schema settings (from experimental) | ||
| ├── specs/ # Empty, for user's specs | ||
| └── changes/ # Empty, for user's changes | ||
| └── archive/ | ||
|
|
||
| .<tool>/skills/ # 9 skills per selected tool | ||
| ├── openspec-explore/SKILL.md | ||
| ├── openspec-new-change/SKILL.md | ||
| ├── openspec-continue-change/SKILL.md | ||
| ├── openspec-apply-change/SKILL.md | ||
| ├── openspec-ff-change/SKILL.md | ||
| ├── openspec-verify-change/SKILL.md | ||
| ├── openspec-sync-specs/SKILL.md | ||
| ├── openspec-archive-change/SKILL.md | ||
| └── openspec-bulk-archive-change/SKILL.md | ||
|
|
||
| .<tool>/commands/opsx/ # 9 slash commands per selected tool | ||
| ├── explore.md | ||
| ├── new.md | ||
| ├── continue.md | ||
| ├── apply.md | ||
| ├── ff.md | ||
| ├── verify.md | ||
| ├── sync.md | ||
| ├── archive.md | ||
| └── bulk-archive.md | ||
| ``` | ||
|
|
||
| ### What init no longer creates | ||
|
|
||
| - `CLAUDE.md`, `.cursorrules`, `.windsurfrules`, etc. (config files) | ||
| - `openspec/AGENTS.md` | ||
| - `openspec/project.md` | ||
| - Root `AGENTS.md` stub | ||
| - `.claude/commands/openspec/` (old slash commands) | ||
|
|
||
| ### Legacy detection targets | ||
|
|
||
| | Artifact Type | Detection Method | Removal Method | | ||
| |--------------|------------------|----------------| | ||
| | Config files (CLAUDE.md, etc.) | File exists AND contains OpenSpec markers | Remove marker block; delete file if empty after | | ||
| | Old slash command dirs | Directory exists at `.<tool>/commands/openspec/` | Delete entire directory | | ||
| | openspec/AGENTS.md | File exists at `openspec/AGENTS.md` | Delete file | | ||
| | openspec/project.md | File exists at `openspec/project.md` | Delete file | | ||
| | Root AGENTS.md | File exists at `AGENTS.md` AND contains OpenSpec markers | Remove marker block; delete file if empty after | | ||
|
|
||
| ### Code to remove | ||
|
|
||
| - `src/core/configurators/` - entire directory (ToolRegistry, all config generators) | ||
| - `src/core/configurators/slash/` - entire directory (SlashCommandRegistry, old command generators) | ||
| - `src/core/templates/slash-command-templates.ts` - old `/openspec:*` content | ||
| - `src/core/templates/claude-template.ts` | ||
| - `src/core/templates/cline-template.ts` | ||
| - `src/core/templates/costrict-template.ts` | ||
| - `src/core/templates/agents-template.ts` | ||
| - `src/core/templates/agents-root-stub.ts` | ||
| - `src/core/templates/project-template.ts` | ||
| - `src/commands/experimental/` - entire directory (merged into init) | ||
| - Related test files | ||
|
|
||
| ### Code to migrate into init | ||
|
|
||
| - Animated welcome screen (`src/ui/welcome-screen.ts`) - keep, call from init | ||
| - Searchable multi-select (`src/prompts/searchable-multi-select.ts`) - keep, call from init | ||
| - Skill templates (`src/core/templates/skill-templates.ts`) - keep | ||
| - Command generation (`src/core/command-generation/`) - keep | ||
| - Tool states detection (from `experimental/setup.ts`) - move to init | ||
|
|
||
| ## Open Questions | ||
|
|
||
| 1. **What happens to `openspec update`?** - Currently updates config files and AGENTS.md. Needs to be updated to refresh skills/commands instead. | ||
|
|
||
| 2. **Should we keep `openspec schemas` and other experimental subcommands?** - These are useful for the workflow. Probably keep them but remove "[Experimental]" label. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Resolve this open question before starting implementation. The Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! Prompt To Fix With AIThis is a comment left during a code review.
Path: openspec/changes/merge-init-experimental/design.md
Line: 156:158
Comment:
**style:** Resolve this open question before starting implementation. The `update` command currently refreshes config files and `AGENTS.md`, which this proposal removes. Tasks 5.1-5.3 address the implementation, but deciding the approach now will prevent rework and ensure the architecture is sound.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| ## Why | ||
|
|
||
| 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. | ||
|
|
||
| ## What Changes | ||
|
|
||
| - **BREAKING**: `openspec init` now generates skills and `/opsx:*` commands instead of config files and `/openspec:*` commands | ||
| - **BREAKING**: Config files (`CLAUDE.md`, `.cursorrules`, etc.) are no longer generated | ||
| - **BREAKING**: Old slash commands (`/openspec:proposal`, `/openspec:apply`, `/openspec:archive`) are no longer generated | ||
| - **BREAKING**: `openspec/AGENTS.md` and `openspec/project.md` are no longer generated | ||
| - Merge `experimental` command functionality into `init` | ||
| - Add legacy detection and auto-cleanup with Y/N confirmation | ||
| - Keep `openspec experimental` as hidden alias for backward compatibility | ||
| - Use the animated welcome screen from experimental for the unified init | ||
|
|
||
| ## Capabilities | ||
|
|
||
| ### New Capabilities | ||
|
|
||
| - `legacy-cleanup`: Detect and remove legacy OpenSpec artifacts (config files, old slash commands, AGENTS.md) during init | ||
|
|
||
| ### Modified Capabilities | ||
|
|
||
| - `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 | ||
|
|
||
| ## Impact | ||
|
|
||
| - **Code removal**: `ToolRegistry`, `SlashCommandRegistry`, config file generators, old slash command templates, AGENTS.md/project.md templates | ||
| - **Code migration**: Move skill generation and command adapter logic from `experimental/setup.ts` into `init.ts` | ||
| - **Commands affected**: `init` (rewritten), `experimental` (becomes hidden alias), `update` (may need adjustment) | ||
| - **User migration**: Existing users running `init` will be prompted to clean up legacy files | ||
| - **Breaking for**: Users relying on config files for passive triggering, users using `/openspec:*` commands |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,176 @@ | ||
| ## MODIFIED Requirements | ||
|
|
||
| ### Requirement: Directory Creation | ||
|
|
||
| The command SHALL create the OpenSpec directory structure with config file. | ||
|
|
||
| #### Scenario: Creating OpenSpec structure | ||
|
|
||
| - **WHEN** `openspec init` is executed | ||
| - **THEN** create the following directory structure: | ||
| ``` | ||
| openspec/ | ||
| ├── config.yaml | ||
| ├── specs/ | ||
| └── changes/ | ||
| └── archive/ | ||
| ``` | ||
|
|
||
| ### Requirement: AI Tool Configuration | ||
|
|
||
| The command SHALL configure AI coding assistants with skills and slash commands using a searchable multi-select experience. | ||
|
|
||
| #### Scenario: Prompting for AI tool selection | ||
|
|
||
| - **WHEN** run interactively | ||
| - **THEN** display animated welcome screen with OpenSpec logo | ||
| - **AND** present a searchable multi-select that shows all available tools | ||
| - **AND** mark already configured tools with "(configured ✓)" indicator | ||
| - **AND** pre-select configured tools for easy refresh | ||
| - **AND** sort configured tools to appear first in the list | ||
| - **AND** allow filtering by typing to search | ||
|
|
||
| #### Scenario: Selecting tools to configure | ||
|
|
||
| - **WHEN** user selects tools and confirms | ||
| - **THEN** generate skills in `.<tool>/skills/` directory for each selected tool | ||
| - **AND** generate slash commands in `.<tool>/commands/opsx/` directory for each selected tool | ||
| - **AND** create `openspec/config.yaml` with default schema setting | ||
|
|
||
| ### Requirement: Skill Generation | ||
|
|
||
| The command SHALL generate Agent Skills for selected AI tools. | ||
|
|
||
| #### Scenario: Generating skills for a tool | ||
|
|
||
| - **WHEN** a tool is selected during initialization | ||
| - **THEN** create 9 skill directories under `.<tool>/skills/`: | ||
| - `openspec-explore/SKILL.md` | ||
| - `openspec-new-change/SKILL.md` | ||
| - `openspec-continue-change/SKILL.md` | ||
| - `openspec-apply-change/SKILL.md` | ||
| - `openspec-ff-change/SKILL.md` | ||
| - `openspec-verify-change/SKILL.md` | ||
| - `openspec-sync-specs/SKILL.md` | ||
| - `openspec-archive-change/SKILL.md` | ||
| - `openspec-bulk-archive-change/SKILL.md` | ||
| - **AND** each SKILL.md SHALL contain YAML frontmatter with name and description | ||
| - **AND** each SKILL.md SHALL contain the skill instructions | ||
|
|
||
| ### Requirement: Slash Command Generation | ||
|
|
||
| The command SHALL generate opsx slash commands for selected AI tools. | ||
|
|
||
| #### Scenario: Generating slash commands for a tool | ||
|
|
||
| - **WHEN** a tool is selected during initialization | ||
| - **THEN** create 9 slash command files using the tool's command adapter: | ||
| - `/opsx:explore` | ||
| - `/opsx:new` | ||
| - `/opsx:continue` | ||
| - `/opsx:apply` | ||
| - `/opsx:ff` | ||
| - `/opsx:verify` | ||
| - `/opsx:sync` | ||
| - `/opsx:archive` | ||
| - `/opsx:bulk-archive` | ||
| - **AND** use tool-specific path conventions (e.g., `.claude/commands/opsx/` for Claude) | ||
| - **AND** include tool-specific frontmatter format | ||
|
|
||
| ### Requirement: Success Output | ||
|
|
||
| The command SHALL provide clear, actionable next steps upon successful initialization. | ||
|
|
||
| #### Scenario: Displaying success message | ||
|
|
||
| - **WHEN** initialization completes successfully | ||
| - **THEN** display categorized summary: | ||
| - "Created: <tools>" for newly configured tools | ||
| - "Refreshed: <tools>" for already-configured tools that were updated | ||
| - Count of skills and commands generated | ||
| - **AND** display getting started section with: | ||
| - `/opsx:new` - Start a new change | ||
| - `/opsx:continue` - Create the next artifact | ||
| - `/opsx:apply` - Implement tasks | ||
| - **AND** display links to documentation and feedback | ||
|
|
||
| #### Scenario: Displaying restart instruction | ||
|
|
||
| - **WHEN** initialization completes successfully and tools were created or refreshed | ||
| - **THEN** display instruction to restart IDE for slash commands to take effect | ||
|
|
||
| ### Requirement: Config File Generation | ||
|
|
||
| The command SHALL create an OpenSpec config file with schema settings. | ||
|
|
||
| #### Scenario: Creating config.yaml | ||
|
|
||
| - **WHEN** initialization completes | ||
| - **AND** config.yaml does not exist | ||
| - **THEN** create `openspec/config.yaml` with default schema setting | ||
| - **AND** display config location in output | ||
|
|
||
| #### Scenario: Preserving existing config.yaml | ||
|
|
||
| - **WHEN** initialization runs in extend mode | ||
| - **AND** `openspec/config.yaml` already exists | ||
| - **THEN** preserve the existing config file | ||
| - **AND** display "(exists)" indicator in output | ||
|
|
||
| ### Requirement: Non-Interactive Mode | ||
|
|
||
| The command SHALL support non-interactive operation through command-line options. | ||
|
|
||
| #### Scenario: Select all tools non-interactively | ||
|
|
||
| - **WHEN** run with `--tools all` | ||
| - **THEN** automatically select every available AI tool without prompting | ||
| - **AND** proceed with skill and command generation | ||
|
|
||
| #### Scenario: Select specific tools non-interactively | ||
|
|
||
| - **WHEN** run with `--tools claude,cursor` | ||
| - **THEN** parse the comma-separated tool IDs | ||
| - **AND** generate skills and commands for specified tools only | ||
|
|
||
| #### Scenario: Skip tool configuration non-interactively | ||
|
|
||
| - **WHEN** run with `--tools none` | ||
| - **THEN** create only the openspec directory structure and config.yaml | ||
| - **AND** skip skill and command generation | ||
|
|
||
| ### Requirement: Experimental Command Alias | ||
|
|
||
| The command SHALL maintain backward compatibility with the experimental command. | ||
|
|
||
| #### Scenario: Running openspec experimental | ||
|
|
||
| - **WHEN** user runs `openspec experimental` | ||
| - **THEN** delegate to `openspec init` | ||
| - **AND** the command SHALL be hidden from help output | ||
|
|
||
| ## REMOVED Requirements | ||
|
|
||
| ### Requirement: File Generation | ||
|
|
||
| **Reason**: AGENTS.md and project.md are no longer generated. Skills contain all necessary instructions. | ||
|
|
||
| **Migration**: Skills in `.<tool>/skills/` provide all OpenSpec workflow instructions. No manual file needed. | ||
|
|
||
| ### Requirement: AI Tool Configuration Details | ||
|
|
||
| **Reason**: Config files (CLAUDE.md, .cursorrules, etc.) are replaced by skills. | ||
|
|
||
| **Migration**: Use skills in `.<tool>/skills/` instead of config files. Skills provide richer, tool-specific instructions. | ||
|
|
||
| ### Requirement: Slash Command Configuration | ||
|
|
||
| **Reason**: Old `/openspec:*` slash commands are replaced by `/opsx:*` commands with richer functionality. | ||
|
|
||
| **Migration**: Use `/opsx:new`, `/opsx:continue`, `/opsx:apply` instead of `/openspec:proposal`, `/openspec:apply`, `/openspec:archive`. | ||
|
|
||
| ### Requirement: Root instruction stub | ||
|
|
||
| **Reason**: Root AGENTS.md stub is no longer needed. Skills provide tool-specific instructions. | ||
|
|
||
| **Migration**: Skills are loaded automatically by supporting tools. No root stub needed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add language specifier to fenced code block.
The fenced code block lacks a language identifier. Add
textorplaintextto resolve the markdownlint warning.📝 Proposed fix
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
106-106: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents