# Concepts (/docs/core-concepts) This guide explains the core ideas behind OpenSpec and how they fit together. For practical usage, see [Getting Started](/docs/getting-started) and [Workflows](/docs/the-workflow). ## Philosophy [#philosophy] OpenSpec is built around four principles: ``` fluid not rigid — no phase gates, work on what makes sense iterative not waterfall — learn as you build, refine as you go easy not complex — lightweight setup, minimal ceremony brownfield-first — works with existing codebases, not just greenfield ``` ### Why These Principles Matter [#why-these-principles-matter] **Fluid not rigid.** Traditional spec systems lock you into phases: first you plan, then you implement, then you're done. OpenSpec is more flexible — you can create artifacts in any order that makes sense for your work. **Iterative not waterfall.** Requirements change. Understanding deepens. What seemed like a good approach at the start might not hold up after you see the codebase. OpenSpec embraces this reality. **Easy not complex.** Some spec frameworks require extensive setup, rigid formats, or heavyweight processes. OpenSpec stays out of your way. Initialize in seconds, start working immediately, customize only if you need to. **Brownfield-first.** Most software work isn't building from scratch — it's modifying existing systems. OpenSpec's delta-based approach makes it easy to specify changes to existing behavior, not just describe new systems. ## The Big Picture [#the-big-picture] OpenSpec organizes your work into two main areas: ``` ┌────────────────────────────────────────────────────────────────────┐ │ openspec/ │ │ │ │ ┌─────────────────────┐ ┌───────────────────────────────┐ │ │ │ specs/ │ │ changes/ │ │ │ │ │ │ │ │ │ │ Source of truth │◄─────│ Proposed modifications │ │ │ │ How your system │ merge│ Each change = one folder │ │ │ │ currently works │ │ Contains artifacts + deltas │ │ │ │ │ │ │ │ │ └─────────────────────┘ └───────────────────────────────┘ │ │ │ └────────────────────────────────────────────────────────────────────┘ ``` **Specs** are the source of truth — they describe how your system currently behaves. **Changes** are proposed modifications — they live in separate folders until you're ready to merge them. This separation is key. You can work on multiple changes in parallel without conflicts. You can review a change before it affects the main specs. And when you archive a change, its deltas merge cleanly into the source of truth. ## Specs [#specs] Specs describe your system's behavior using structured requirements and scenarios. ### Structure [#structure] ``` openspec/specs/ ├── auth/ │ └── spec.md # Authentication behavior ├── payments/ │ └── spec.md # Payment processing ├── notifications/ │ └── spec.md # Notification system └── ui/ └── spec.md # UI behavior and themes ``` Organize specs by domain — logical groupings that make sense for your system. Common patterns: * **By feature area**: `auth/`, `payments/`, `search/` * **By component**: `api/`, `frontend/`, `workers/` * **By bounded context**: `ordering/`, `fulfillment/`, `inventory/` ### Spec Format [#spec-format] A spec contains requirements, and each requirement has scenarios: ```markdown # Auth Specification ## Purpose Authentication and session management for the application. ## Requirements ### Requirement: User Authentication The system SHALL issue a JWT token upon successful login. #### Scenario: Valid credentials - GIVEN a user with valid credentials - WHEN the user submits login form - THEN a JWT token is returned - AND the user is redirected to dashboard #### Scenario: Invalid credentials - GIVEN invalid credentials - WHEN the user submits login form - THEN an error message is displayed - AND no token is issued ### Requirement: Session Expiration The system MUST expire sessions after 30 minutes of inactivity. #### Scenario: Idle timeout - GIVEN an authenticated session - WHEN 30 minutes pass without activity - THEN the session is invalidated - AND the user must re-authenticate ``` **Key elements:** | Element | Purpose | | ------------------ | ------------------------------------------------- | | `## Purpose` | High-level description of this spec's domain | | `### Requirement:` | A specific behavior the system must have | | `#### Scenario:` | A concrete example of the requirement in action | | SHALL/MUST/SHOULD | RFC 2119 keywords indicating requirement strength | ### Why Structure Specs This Way [#why-structure-specs-this-way] **Requirements are the "what"** — they state what the system should do without specifying implementation. **Scenarios are the "when"** — they provide concrete examples that can be verified. Good scenarios: * Are testable (you could write an automated test for them) * Cover both happy path and edge cases * Use Given/When/Then or similar structured format **RFC 2119 keywords** (SHALL, MUST, SHOULD, MAY) communicate intent: * **MUST/SHALL** — absolute requirement * **SHOULD** — recommended, but exceptions exist * **MAY** — optional ### What a Spec Is (and Is Not) [#what-a-spec-is-and-is-not] A spec is a **behavior contract**, not an implementation plan. Good spec content: * Observable behavior users or downstream systems rely on * Inputs, outputs, and error conditions * External constraints (security, privacy, reliability, compatibility) * Scenarios that can be tested or explicitly validated Avoid in specs: * Internal class/function names * Library or framework choices * Step-by-step implementation details * Detailed execution plans (those belong in `design.md` or `tasks.md`) Quick test: * If implementation can change without changing externally visible behavior, it likely does not belong in the spec. ### Keep It Lightweight: Progressive Rigor [#keep-it-lightweight-progressive-rigor] OpenSpec aims to avoid bureaucracy. Use the lightest level that still makes the change verifiable. **Lite spec (default):** * Short behavior-first requirements * Clear scope and non-goals * A few concrete acceptance checks **Full spec (for higher risk):** * Cross-team or cross-repo changes * API/contract changes, migrations, security/privacy concerns * Changes where ambiguity is likely to cause expensive rework Most changes should stay in Lite mode. ### Human + Agent Collaboration [#human--agent-collaboration] In many teams, humans explore and agents draft artifacts. The intended loop is: 1. Human provides intent, context, and constraints. 2. Agent converts this into behavior-first requirements and scenarios. 3. Agent keeps implementation detail in `design.md` and `tasks.md`, not `spec.md`. 4. Validation confirms structure and clarity before implementation. This keeps specs readable for humans and consistent for agents. ## Changes [#changes] A change is a proposed modification to your system, packaged as a folder with everything needed to understand and implement it. ### Change Structure [#change-structure] ``` openspec/changes/add-dark-mode/ ├── proposal.md # Why and what ├── design.md # How (technical approach) ├── tasks.md # Implementation checklist ├── .openspec.yaml # Change metadata (optional) └── specs/ # Delta specs └── ui/ └── spec.md # What's changing in ui/spec.md ``` Each change is self-contained. It has: * **Artifacts** — documents that capture intent, design, and tasks * **Delta specs** — specifications for what's being added, modified, or removed * **Metadata** — optional configuration for this specific change ### Why Changes Are Folders [#why-changes-are-folders] Packaging a change as a folder has several benefits: 1. **Everything together.** Proposal, design, tasks, and specs live in one place. No hunting through different locations. 2. **Parallel work.** Multiple changes can exist simultaneously without conflicting. Work on `add-dark-mode` while `fix-auth-bug` is also in progress. 3. **Clean history.** When archived, changes move to `changes/archive/` with their full context preserved. You can look back and understand not just what changed, but why. 4. **Review-friendly.** A change folder is easy to review — open it, read the proposal, check the design, see the spec deltas. ## Artifacts [#artifacts] Artifacts are the documents within a change that guide the work. ### The Artifact Flow [#the-artifact-flow] ``` proposal ──────► specs ──────► design ──────► tasks ──────► implement │ │ │ │ why what how steps + scope changes approach to take ``` Artifacts build on each other. Each artifact provides context for the next. ### Artifact Types [#artifact-types] #### Proposal (`proposal.md`) [#proposal-proposalmd] The proposal captures **intent**, **scope**, and **approach** at a high level. ```markdown # Proposal: Add Dark Mode ## Intent Users have requested a dark mode option to reduce eye strain during nighttime usage and match system preferences. ## Scope In scope: - Theme toggle in settings - System preference detection - Persist preference in localStorage Out of scope: - Custom color themes (future work) - Per-page theme overrides ## Approach Use CSS custom properties for theming with a React context for state management. Detect system preference on first load, allow manual override. ``` **When to update the proposal:** * Scope changes (narrowing or expanding) * Intent clarifies (better understanding of the problem) * Approach fundamentally shifts #### Specs (delta specs in `specs/`) [#specs-delta-specs-in-specs] Delta specs describe **what's changing** relative to the current specs. See [Delta Specs](#delta-specs) below. #### Design (`design.md`) [#design-designmd] The design captures **technical approach** and **architecture decisions**. ````markdown # Design: Add Dark Mode ## Technical Approach Theme state managed via React Context to avoid prop drilling. CSS custom properties enable runtime switching without class toggling. ## Architecture Decisions ### Decision: Context over Redux Using React Context for theme state because: - Simple binary state (light/dark) - No complex state transitions - Avoids adding Redux dependency ### Decision: CSS Custom Properties Using CSS variables instead of CSS-in-JS because: - Works with existing stylesheet - No runtime overhead - Browser-native solution ## Data Flow ``` ThemeProvider (context) │ ▼ ThemeToggle ◄──► localStorage │ ▼ CSS Variables (applied to :root) ``` ## File Changes - `src/contexts/ThemeContext.tsx` (new) - `src/components/ThemeToggle.tsx` (new) - `src/styles/globals.css` (modified) ```` **When to update the design:** * Implementation reveals the approach won't work * Better solution discovered * Dependencies or constraints change #### Tasks (`tasks.md`) [#tasks-tasksmd] Tasks are the **implementation checklist** — concrete steps with checkboxes. ```markdown # Tasks ## 1. Theme Infrastructure - [ ] 1.1 Create ThemeContext with light/dark state - [ ] 1.2 Add CSS custom properties for colors - [ ] 1.3 Implement localStorage persistence - [ ] 1.4 Add system preference detection ## 2. UI Components - [ ] 2.1 Create ThemeToggle component - [ ] 2.2 Add toggle to settings page - [ ] 2.3 Update Header to include quick toggle ## 3. Styling - [ ] 3.1 Define dark theme color palette - [ ] 3.2 Update components to use CSS variables - [ ] 3.3 Test contrast ratios for accessibility ``` **Task best practices:** * Group related tasks under headings * Use hierarchical numbering (1.1, 1.2, etc.) * Keep tasks small enough to complete in one session * Check tasks off as you complete them ## Delta Specs [#delta-specs] Delta specs are the key concept that makes OpenSpec work for brownfield development. They describe **what's changing** rather than restating the entire spec. ### The Format [#the-format] ```markdown # Delta for Auth ## ADDED Requirements ### Requirement: Two-Factor Authentication The system MUST support TOTP-based two-factor authentication. #### Scenario: 2FA enrollment - GIVEN a user without 2FA enabled - WHEN the user enables 2FA in settings - THEN a QR code is displayed for authenticator app setup - AND the user must verify with a code before activation #### Scenario: 2FA login - GIVEN a user with 2FA enabled - WHEN the user submits valid credentials - THEN an OTP challenge is presented - AND login completes only after valid OTP ## MODIFIED Requirements ### Requirement: Session Expiration The system MUST expire sessions after 15 minutes of inactivity. (Previously: 30 minutes) #### Scenario: Idle timeout - GIVEN an authenticated session - WHEN 15 minutes pass without activity - THEN the session is invalidated ## REMOVED Requirements ### Requirement: Remember Me (Deprecated in favor of 2FA. Users should re-authenticate each session.) ``` ### Delta Sections [#delta-sections] | Section | Meaning | What Happens on Archive | | -------------------------- | ------------------- | ----------------------------- | | `## ADDED Requirements` | New behavior | Appended to main spec | | `## MODIFIED Requirements` | Changed behavior | Replaces existing requirement | | `## REMOVED Requirements` | Deprecated behavior | Deleted from main spec | ### Why Deltas Instead of Full Specs [#why-deltas-instead-of-full-specs] **Clarity.** A delta shows exactly what's changing. Reading a full spec, you'd have to diff it mentally against the current version. **Conflict avoidance.** Two changes can touch the same spec file without conflicting, as long as they modify different requirements. **Review efficiency.** Reviewers see the change, not the unchanged context. Focus on what matters. **Brownfield fit.** Most work modifies existing behavior. Deltas make modifications first-class, not an afterthought. ## Schemas [#schemas] Schemas define the artifact types and their dependencies for a workflow. ### How Schemas Work [#how-schemas-work] ```yaml # openspec/schemas/spec-driven/schema.yaml name: spec-driven artifacts: - id: proposal generates: proposal.md requires: [] # No dependencies, can create first - id: specs generates: specs/**/*.md requires: [proposal] # Needs proposal before creating - id: design generates: design.md requires: [proposal] # Can create in parallel with specs - id: tasks generates: tasks.md requires: [specs, design] # Needs both specs and design first ``` **Artifacts form a dependency graph:** ``` proposal (root node) │ ┌─────────────┴─────────────┐ │ │ ▼ ▼ specs design (requires: (requires: proposal) proposal) │ │ └─────────────┬─────────────┘ │ ▼ tasks (requires: specs, design) ``` **Dependencies are enablers, not gates.** They show what's possible to create, not what you must create next. You can skip design if you don't need it. You can create specs before or after design — both depend only on proposal. ### Built-in Schemas [#built-in-schemas] **spec-driven** (default) The standard workflow for spec-driven development: ``` proposal → specs → design → tasks → implement ``` Best for: Most feature work where you want to agree on specs before implementation. ### Custom Schemas [#custom-schemas] Create custom schemas for your team's workflow: ```bash # Create from scratch openspec schema init research-first # Or fork an existing one openspec schema fork spec-driven research-first ``` **Example custom schema:** ```yaml # openspec/schemas/research-first/schema.yaml name: research-first artifacts: - id: research generates: research.md requires: [] # Do research first - id: proposal generates: proposal.md requires: [research] # Proposal informed by research - id: tasks generates: tasks.md requires: [proposal] # Skip specs/design, go straight to tasks ``` See [Customization](/docs/customization) for full details on creating and using custom schemas. ## Archive [#archive] Archiving completes a change by merging its delta specs into the main specs and preserving the change for history. ### What Happens When You Archive [#what-happens-when-you-archive] ``` Before archive: openspec/ ├── specs/ │ └── auth/ │ └── spec.md ◄────────────────┐ └── changes/ │ └── add-2fa/ │ ├── proposal.md │ ├── design.md │ merge ├── tasks.md │ └── specs/ │ └── auth/ │ └── spec.md ─────────┘ After archive: openspec/ ├── specs/ │ └── auth/ │ └── spec.md # Now includes 2FA requirements └── changes/ └── archive/ └── 2025-01-24-add-2fa/ # Preserved for history ├── proposal.md ├── design.md ├── tasks.md └── specs/ └── auth/ └── spec.md ``` ### The Archive Process [#the-archive-process] 1. **Merge deltas.** Each delta spec section (ADDED/MODIFIED/REMOVED) is applied to the corresponding main spec. 2. **Move to archive.** The change folder moves to `changes/archive/` with a date prefix for chronological ordering. 3. **Preserve context.** All artifacts remain intact in the archive. You can always look back to understand why a change was made. ### Why Archive Matters [#why-archive-matters] **Clean state.** Active changes (`changes/`) shows only work in progress. Completed work moves out of the way. **Audit trail.** The archive preserves the full context of every change — not just what changed, but the proposal explaining why, the design explaining how, and the tasks showing the work done. **Spec evolution.** Specs grow organically as changes are archived. Each archive merges its deltas, building up a comprehensive specification over time. ## How It All Fits Together [#how-it-all-fits-together] ``` ┌──────────────────────────────────────────────────────────────────────────────┐ │ OPENSPEC FLOW │ │ │ │ ┌────────────────┐ │ │ │ 1. START │ /opsx:propose (core) or /opsx:new (expanded) │ │ │ CHANGE │ │ │ └───────┬────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────┐ │ │ │ 2. CREATE │ /opsx:ff or /opsx:continue (expanded workflow) │ │ │ ARTIFACTS │ Creates proposal → specs → design → tasks │ │ │ │ (based on schema dependencies) │ │ └───────┬────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────┐ │ │ │ 3. IMPLEMENT │ /opsx:apply │ │ │ TASKS │ Work through tasks, checking them off │ │ │ │◄──── Update artifacts as you learn │ │ └───────┬────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────┐ │ │ │ 4. VERIFY │ /opsx:verify (optional) │ │ │ WORK │ Check implementation matches specs │ │ └───────┬────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │ │ │ 5. ARCHIVE │────►│ Delta specs merge into main specs │ │ │ │ CHANGE │ │ Change folder moves to archive/ │ │ │ └────────────────┘ │ Specs are now the updated source of truth │ │ │ └──────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ ``` **The virtuous cycle:** 1. Specs describe current behavior 2. Changes propose modifications (as deltas) 3. Implementation makes the changes real 4. Archive merges deltas into specs 5. Specs now describe the new behavior 6. Next change builds on updated specs ## Glossary [#glossary] | Term | Definition | | ------------------- | --------------------------------------------------------------------------------- | | **Artifact** | A document within a change (proposal, design, tasks, or delta specs) | | **Archive** | The process of completing a change and merging its deltas into main specs | | **Change** | A proposed modification to the system, packaged as a folder with artifacts | | **Delta spec** | A spec that describes changes (ADDED/MODIFIED/REMOVED) relative to current specs | | **Domain** | A logical grouping for specs (e.g., `auth/`, `payments/`) | | **Requirement** | A specific behavior the system must have | | **Scenario** | A concrete example of a requirement, typically in Given/When/Then format | | **Schema** | A definition of artifact types and their dependencies | | **Spec** | A specification describing system behavior, containing requirements and scenarios | | **Source of truth** | The `openspec/specs/` directory, containing the current agreed-upon behavior | ## Next Steps [#next-steps] * [Getting Started](/docs/getting-started) - Practical first steps * [Workflows](/docs/the-workflow) - Common patterns and when to use each * [Commands](/docs/reference/slash-commands) - Full command reference * [Customization](/docs/customization) - Create custom schemas and configure your project # Customization (/docs/customization) OpenSpec provides three levels of customization: | Level | What it does | Best for | | -------------------- | ---------------------------------- | --------------------------- | | **Project Config** | Set defaults, inject context/rules | Most teams | | **Custom Schemas** | Define your own workflow artifacts | Teams with unique processes | | **Global Overrides** | Share schemas across all projects | Power users | *** ## Project Configuration [#project-configuration] The `openspec/config.yaml` file is the easiest way to customize OpenSpec for your team. It lets you: * **Set a default schema** - Skip `--schema` on every command * **Inject project context** - AI sees your tech stack, conventions, etc. * **Add per-artifact rules** - Custom rules for specific artifacts ### Quick Setup [#quick-setup] ```bash openspec init ``` This walks you through creating a config interactively. Or create one manually: ```yaml # openspec/config.yaml schema: spec-driven context: | Tech stack: TypeScript, React, Node.js, PostgreSQL API style: RESTful, documented in docs/api.md Testing: Jest + React Testing Library We value backwards compatibility for all public APIs rules: proposal: - Include rollback plan - Identify affected teams specs: - Use Given/When/Then format - Reference existing patterns before inventing new ones ``` ### How It Works [#how-it-works] **Default schema:** ```bash # Without config openspec new change my-feature --schema spec-driven # With config - schema is automatic openspec new change my-feature ``` **Context and rules injection:** When generating any artifact, your context and rules are injected into the AI prompt: ```xml Tech stack: TypeScript, React, Node.js, PostgreSQL ... - Include rollback plan - Identify affected teams ``` * **Context** appears in ALL artifacts * **Rules** ONLY appear for the matching artifact ### Schema Resolution Order [#schema-resolution-order] When OpenSpec needs a schema, it checks in this order: 1. CLI flag: `--schema ` 2. Change metadata (`.openspec.yaml` in the change folder) 3. Project config (`openspec/config.yaml`) 4. Default (`spec-driven`) *** ## Custom Schemas [#custom-schemas] When project config isn't enough, create your own schema with a completely custom workflow. Custom schemas live in your project's `openspec/schemas/` directory and are version-controlled with your code. ```text your-project/ ├── openspec/ │ ├── config.yaml # Project config │ ├── schemas/ # Custom schemas live here │ │ └── my-workflow/ │ │ ├── schema.yaml │ │ └── templates/ │ └── changes/ # Your changes └── src/ ``` ### Fork an Existing Schema [#fork-an-existing-schema] The fastest way to customize is to fork a built-in schema: ```bash openspec schema fork spec-driven my-workflow ``` This copies the entire `spec-driven` schema to `openspec/schemas/my-workflow/` where you can edit it freely. **What you get:** ```text openspec/schemas/my-workflow/ ├── schema.yaml # Workflow definition └── templates/ ├── proposal.md # Template for proposal artifact ├── spec.md # Template for specs ├── design.md # Template for design └── tasks.md # Template for tasks ``` Now edit `schema.yaml` to change the workflow, or edit templates to change what AI generates. ### Create a Schema from Scratch [#create-a-schema-from-scratch] For a completely fresh workflow: ```bash # Interactive openspec schema init research-first # Non-interactive openspec schema init rapid \ --description "Rapid iteration workflow" \ --artifacts "proposal,tasks" \ --default ``` ### Schema Structure [#schema-structure] A schema defines the artifacts in your workflow and how they depend on each other: ```yaml # openspec/schemas/my-workflow/schema.yaml name: my-workflow version: 1 description: My team's custom workflow artifacts: - id: proposal generates: proposal.md description: Initial proposal document template: proposal.md instruction: | Create a proposal that explains WHY this change is needed. Focus on the problem, not the solution. requires: [] - id: design generates: design.md description: Technical design template: design.md instruction: | Create a design document explaining HOW to implement. requires: - proposal # Can't create design until proposal exists - id: tasks generates: tasks.md description: Implementation checklist template: tasks.md requires: - design apply: requires: [tasks] tracks: tasks.md ``` **Key fields:** | Field | Purpose | | ------------- | ----------------------------------------------------- | | `id` | Unique identifier, used in commands and rules | | `generates` | Output filename (supports globs like `specs/**/*.md`) | | `template` | Template file in `templates/` directory | | `instruction` | AI instructions for creating this artifact | | `requires` | Dependencies - which artifacts must exist first | ### Templates [#templates] Templates are markdown files that guide the AI. They're injected into the prompt when creating that artifact. ```markdown ## Why ## What Changes ## Impact ``` Templates can include: * Section headers the AI should fill in * HTML comments with guidance for the AI * Example formats showing expected structure ### Validate Your Schema [#validate-your-schema] Before using a custom schema, validate it: ```bash openspec schema validate my-workflow ``` This checks: * `schema.yaml` syntax is correct * All referenced templates exist * No circular dependencies * Artifact IDs are valid ### Use Your Custom Schema [#use-your-custom-schema] Once created, use your schema with: ```bash # Specify on command openspec new change feature --schema my-workflow # Or set as default in config.yaml schema: my-workflow ``` ### Debug Schema Resolution [#debug-schema-resolution] Not sure which schema is being used? Check with: ```bash # See where a specific schema resolves from openspec schema which my-workflow # List all available schemas openspec schema which --all ``` Output shows whether it's from your project, user directory, or the package: ```text Schema: my-workflow Source: project Path: /path/to/project/openspec/schemas/my-workflow ``` *** > **Note:** OpenSpec also supports user-level schemas at `~/.local/share/openspec/schemas/` for sharing across projects, but project-level schemas in `openspec/schemas/` are recommended since they're version-controlled with your code. *** ## Examples [#examples] ### Rapid Iteration Workflow [#rapid-iteration-workflow] A minimal workflow for quick iterations: ```yaml # openspec/schemas/rapid/schema.yaml name: rapid version: 1 description: Fast iteration with minimal overhead artifacts: - id: proposal generates: proposal.md description: Quick proposal template: proposal.md instruction: | Create a brief proposal for this change. Focus on what and why, skip detailed specs. requires: [] - id: tasks generates: tasks.md description: Implementation checklist template: tasks.md requires: [proposal] apply: requires: [tasks] tracks: tasks.md ``` ### Adding a Review Artifact [#adding-a-review-artifact] Fork the default and add a review step: ```bash openspec schema fork spec-driven with-review ``` Then edit `schema.yaml` to add: ```yaml - id: review generates: review.md description: Pre-implementation review checklist template: review.md instruction: | Create a review checklist based on the design. Include security, performance, and testing considerations. requires: - design - id: tasks # ... existing tasks config ... requires: - specs - design - review # Now tasks require review too ``` *** ## Community Schemas [#community-schemas] OpenSpec also supports community-maintained schemas distributed via standalone repositories. These provide opinionated workflows that integrate OpenSpec with other tools or systems, similar to how [github/spec-kit's community extension catalog](https://github.com/github/spec-kit/tree/main/extensions) works for spec-kit. Community schemas are not vendored into OpenSpec core — they live in their own repositories with their own release cadence. To use one, copy the schema bundle into your project's `openspec/schemas//` directory (each repo's README has install instructions). | Schema | Maintainer | Repository | Description | | -------------------- | ---------- | ------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `superpowers-bridge` | @JiangWay | [JiangWay/openspec-schemas](https://github.com/JiangWay/openspec-schemas/tree/main/superpowers-bridge) | Integrates OpenSpec's artifact governance with [obra/superpowers](https://github.com/obra/superpowers) execution skills (brainstorming, writing-plans, TDD via subagents, code review, finishing). Adds an evidence-first `retrospective` artifact filling a gap Superpowers does not natively cover. | > Want to contribute a community schema? Open an issue with a link to your repository, or submit a PR adding a row to this table. *** ## See Also [#see-also] * [CLI Reference: Schema Commands](/docs/reference/cli#schema-commands) - Full command documentation # Editing & Iterating on a Change (/docs/editing-changes) **Every artifact in a change is just a Markdown file you can edit at any time.** There is no locked "planning phase," no approval gate, no special edit mode to enter. Want to change the proposal after you've started building? Open `proposal.md` and change it. Realized the design is wrong mid-implementation? Fix `design.md` and keep going. That's the whole answer, and it's by design. This page is for the moment you think "wait, can I go back and change that?" Yes. Here's how, for each common case. ## Two ways to edit anything [#two-ways-to-edit-anything] You always have both: 1. **Edit the file directly.** Artifacts are plain Markdown in `openspec/changes//`. Open `proposal.md`, `design.md`, `tasks.md`, or a delta spec under `specs/` in your editor and change it. Nothing else is required. 2. **Ask your AI to revise it.** In chat, just say what you want: "Update the proposal to drop the caching idea and add a rate-limit section," or "the design should use a queue, not polling." The AI edits the artifact for you, using the rest of the change as context. Use whichever fits the moment. Small wording tweak? Edit the file. Substantive rethink? Let the AI revise with full context. ## "How do I update the proposal (or specs) after I've started?" [#how-do-i-update-the-proposal-or-specs-after-ive-started] Just update it. Same change, refined. If you're using the expanded commands, the natural flow is: edit the artifact, then run `/opsx:continue` to pick up from the new state, or `/opsx:apply` to keep implementing against the updated plan. If you're on the default `core` commands, edit the artifact and run `/opsx:apply`; it reads the current files, so it builds against whatever the artifacts now say. The mental model: artifacts are the live plan, not a signed contract. The AI always works from their current contents, so editing them steers the work. ```text You: I want to change the approach in this change. You: [edit design.md, or tell the AI:] Update design.md to use a background job instead of a synchronous call. AI: Updated design.md. The task list still fits; want me to continue applying? You: /opsx:apply ``` This answers a very common question: there's no separate "update proposal" command because you don't need one. The file is the source of truth, and editing it (by hand or via the AI) is the update. ## "How do I go back to review after implementing?" [#how-do-i-go-back-to-review-after-implementing] You don't have to "go back," because you never left. The workflow is fluid: review, edit, and implementation aren't sequential phases you're trapped in. Concretely, after some `/opsx:apply` work: * Want to re-examine the plan? Open the artifacts and read them, or run `openspec show ` in your terminal for a consolidated view. * Found something to change? Edit the artifact (or ask the AI to), then continue. * Want a structured check that the code matches the plan? Run `/opsx:verify` (expanded command). It reports completeness, correctness, and coherence without blocking anything. See [Workflows: Verify](/docs/the-workflow#verify-check-your-work). There's no "review phase" to return to, because review is something you can do at any point, including after implementation. ## "I edited the code by hand. How do I reconcile that with OpenSpec?" [#i-edited-the-code-by-hand-how-do-i-reconcile-that-with-openspec] This happens constantly and it's fine. You tweaked something in your editor, and now the code and the artifacts disagree. Bring them back in sync in whichever direction is true: * **The code is now correct, the spec is stale.** Update the delta spec (and tasks, if relevant) to describe the behavior you actually shipped. The spec should match reality before you archive, because archiving merges the spec into your source of truth. * **The spec is correct, the code drifted.** Keep building or fixing until the code matches the spec. A fast way to surface mismatches is `/opsx:verify`: it reads your artifacts and your code and tells you where they diverge. Treat its output as a to-do list for reconciliation, then archive once they agree. The principle: at archive time, your specs become the truth of record. So before you archive, make the specs honest about what the code does. Manual edits are welcome; just don't let them quietly desync the spec. ## Refining a proposal you're not happy with [#refining-a-proposal-youre-not-happy-with] If a generated proposal misses the mark, you have three good moves: * **Iterate in place.** Tell the AI what's off ("the scope is too broad, drop the admin features") and let it revise. Cheapest and usually right. * **Explore first, then re-propose.** If the problem is that the idea itself is unclear, step back to `/opsx:explore`, think it through, and let a sharper proposal come out of that. See [Explore First](/docs/explore). * **Start fresh.** If the intent has fundamentally changed, a new change can be clearer than patching the old one. That last move has its own decision guide, next. ## When to update vs. start a new change [#when-to-update-vs-start-a-new-change] Short version: **update when it's the same work refined; start new when the intent fundamentally changed or the scope exploded into different work.** * Same goal, better approach? Update. * Scope narrowing (ship the MVP now, more later)? Update, then archive, then a new change for phase two. * The problem itself changed ("add dark mode" became "build a full theming system")? New change. There's a full flowchart and worked examples in [Workflows: When to Update vs Start Fresh](/docs/the-workflow#when-to-update-vs-start-fresh) and a deeper treatment in [OPSX: When to Update vs. Start Fresh](/docs/opsx#when-to-update-vs-start-fresh). ## A note on tasks [#a-note-on-tasks] `tasks.md` is a living checklist, not a frozen plan. As you implement, you can add tasks you discover, remove ones that turned out unnecessary, or reorder them. The AI checks items off as it completes them during `/opsx:apply`, and it resumes from the first unchecked task if you come back later. Editing the list mid-flight is expected. ## Where to go next [#where-to-go-next] * [Workflows](/docs/the-workflow) - patterns, plus the update-vs-new decision guide * [Reviewing a Change](/docs/reviewing-changes) - the two-minute pass on a plan before you build it * [Explore First](/docs/explore) - the place to step back to when an idea needs rethinking * [Commands](/docs/reference/slash-commands) - `/opsx:continue`, `/opsx:apply`, and `/opsx:verify` in detail * [Concepts: Artifacts](/docs/core-concepts#artifacts) - what each artifact is for # Examples & Recipes (/docs/examples) Real changes, start to finish. Each recipe shows the commands you'd type and what you'd see back, so you can match your situation to a pattern and copy it. These use the default **core** commands (`propose`, `explore`, `apply`, `sync`, `archive`); where the expanded set helps, it's noted. A reminder before you start: slash commands like `/opsx:propose` go in your **AI assistant's chat**, and `openspec` commands go in your **terminal**. If that's new, read [How Commands Work](/docs/how-commands-work) first. In the transcripts below, `You:` and `AI:` are the chat, and lines starting with `$` are the terminal. > **Not sure what you're building yet?** Most of these recipes are sharper if you start with `/opsx:explore` to think it through first. [Recipe 3](#recipe-3-exploring-before-you-commit) shows it in action, and the [Explore First](/docs/explore) guide makes the full case. ## Recipe 1: A small feature, the fast path [#recipe-1-a-small-feature-the-fast-path] **When to use it:** you know what you want, and it's a contained piece of work. This is the most common recipe. The whole thing is three commands. Propose, build, archive. ```text You: /opsx:propose add-logout-button AI: Created openspec/changes/add-logout-button/ ✓ proposal.md — why and what ✓ specs/ — the new requirement and its scenarios ✓ design.md — technical approach ✓ tasks.md — implementation checklist Ready for implementation. Run /opsx:apply. ``` Now read the plan. Open the proposal and the delta spec. This is the moment OpenSpec is built for: catching a wrong assumption while it's still one paragraph, not 400 lines of code. Edit any artifact directly if something's off, then continue. ```text You: /opsx:apply AI: Working through tasks... ✓ 1.1 Add logout button to header ✓ 1.2 Clear session on click ✓ 1.3 Add confirmation dialog All tasks complete! You: /opsx:archive AI: Archiving add-logout-button... ✓ Merged specs into openspec/specs/auth/spec.md ✓ Moved to openspec/changes/archive/2026-06-22-add-logout-button/ Done. Ready for the next change. ``` That's it. The logout behavior is now part of your specs, and the change is filed away with its full context. ## Recipe 2: A bug fix [#recipe-2-a-bug-fix] **When to use it:** something is broken and you want the fix recorded as a deliberate change to behavior, not a mystery commit. Bug fixes work exactly like features. The difference is in how you frame the proposal: describe the *correct* behavior, not just "fix the bug." ```text You: /opsx:propose fix-login-redirect-loop AI: Created openspec/changes/fix-login-redirect-loop/ The proposal captures the current broken behavior and the intended behavior. The delta spec MODIFIES the redirect requirement so it's now precise and testable. Ready for implementation. ``` Because the fix lands as a `MODIFIED` requirement with a fresh scenario, the next person (or the next AI session) sees not just that you fixed it, but what "correct" means. Then `/opsx:apply` and `/opsx:archive` as usual. Tip: for a fix, a good scenario is the regression test in prose. "GIVEN a logged-out user, WHEN they submit valid credentials, THEN they land on the dashboard and are not redirected again." Write that, and the implementation has a clear target. ## Recipe 3: Exploring before you commit [#recipe-3-exploring-before-you-commit] **When to use it:** you have a problem but not yet a plan. You're not sure what to build, or which approach is right. Start with `/opsx:explore`. It's a thinking partner with no structure and no artifacts created. It reads your codebase and helps you decide. ```text You: /opsx:explore AI: What would you like to explore? You: Page loads feel slow but I don't know where the time goes. AI: Let me look... I found three likely culprits: 1. Large unoptimized images on the product list 2. Synchronous data fetching that blocks render 3. Re-renders triggered by context changes Which should we tackle first? You: The data fetching one. You: /opsx:propose optimize-product-list-fetching AI: Created the change, with a proposal informed by what we just found. Ready for implementation. ``` Exploration clarifies your thinking *before* you spend a change on it. When the insight crystallizes, propose, and the AI carries the context forward. ## Recipe 4: Juggling two changes at once [#recipe-4-juggling-two-changes-at-once] **When to use it:** you're mid-feature and an urgent fix jumps the queue. Changes are independent folders, so parallel work doesn't conflict. Start the fix, ship it, then return to the feature right where you left off. ```text You: I'm partway through add-dark-mode, but I need to fix a login bug now. You: /opsx:propose fix-login-redirect AI: Created openspec/changes/fix-login-redirect/. Ready for implementation. You: /opsx:apply AI: Implemented the fix. All tasks complete. You: /opsx:archive AI: ✓ Archived fix-login-redirect. You: Back to dark mode. You: /opsx:apply add-dark-mode AI: Resuming add-dark-mode. Picking up at task 2.3: Update Header... ``` Naming the change in `/opsx:apply add-dark-mode` is how you point the AI at a specific change when more than one is active. Because tasks track completion in `tasks.md`, the AI knows exactly where you stopped. When several changes are done at once, the expanded `/opsx:bulk-archive` files them together and resolves spec conflicts by checking what's actually implemented. See [Workflows](/docs/the-workflow#parallel-changes). ## Recipe 5: A refactor with no behavior change [#recipe-5-a-refactor-with-no-behavior-change] **When to use it:** you're restructuring code, and externally visible behavior should stay identical. This is the interesting case, because a pure refactor has *nothing to add to your specs*. The behavior contract doesn't change; only the implementation does. So the work lives in the design and tasks, and the spec delta is empty or absent. ```text You: /opsx:propose refactor-payment-module AI: Created the change. The proposal states the goal (split the payment module, no behavior change) and the design captures the new structure. No spec changes, since behavior is identical. Ready for implementation. ``` When you archive a change that doesn't touch specs, you can tell the terminal command to skip the spec step: ```bash $ openspec archive refactor-payment-module --skip-specs ``` The same flag is handy for tooling, CI, and docs-only changes. The principle: specs describe behavior, so if behavior didn't change, the spec shouldn't either. See [Concepts](/docs/core-concepts#what-a-spec-is-and-is-not). ## Recipe 6: Step-by-step control (expanded commands) [#recipe-6-step-by-step-control-expanded-commands] **When to use it:** a complex or risky change where you want to review each artifact before moving on. The core `/opsx:propose` drafts everything at once. When you'd rather go one step at a time, turn on the expanded commands: ```bash $ openspec config profile # select the expanded workflows $ openspec update # apply them to this project ``` Now you can scaffold and build incrementally: ```text You: /opsx:new add-2fa AI: Created openspec/changes/add-2fa/. Ready to create: proposal. You: /opsx:continue AI: Created proposal.md. Now available: specs, design. You: /opsx:continue AI: Created specs/auth/spec.md. Now available: design. ``` Review each artifact as it lands, edit freely, and continue when you're happy. When you want the rest drafted in one go, `/opsx:ff` fast-forwards through the remaining planning artifacts. Before archiving, `/opsx:verify` checks that the implementation actually matches the specs. See [Workflows](/docs/the-workflow#opsxff-vs-opsxcontinue). ## Recipe 7: Learning the whole loop hands-on [#recipe-7-learning-the-whole-loop-hands-on] **When to use it:** you've installed OpenSpec and want to *feel* the workflow on your own code, not a toy example. Turn on the expanded commands (see Recipe 6), then: ```text You: /opsx:onboard AI: Welcome to OpenSpec! I'll walk you through a complete change using your actual codebase. Let me scan for a small, safe improvement we can make together... ``` `/opsx:onboard` finds a real (small) improvement, creates a change for it, implements it, and archives it, narrating every step. It takes 15 to 30 minutes and leaves you with a real change you can keep or discard. It's the gentlest way to learn. See [Commands](/docs/reference/slash-commands#opsxonboard). ## Checking your work from the terminal [#checking-your-work-from-the-terminal] Any time, from your terminal, you can inspect the state of things: ```bash $ openspec list # active changes $ openspec show add-dark-mode # one change in detail $ openspec validate add-dark-mode # check structure $ openspec view # interactive dashboard ``` These are read-and-inspect tools. The proposing and building still happen through slash commands in chat. Full details in the [CLI reference](/docs/reference/cli). ## Where to go next [#where-to-go-next] * [Explore First](/docs/explore): the recommended way to start when you're unsure * [Workflows](/docs/the-workflow): the patterns above, with decision guidance on when to use each * [Commands](/docs/reference/slash-commands): every slash command in detail * [Getting Started](/docs/getting-started): the canonical first-change walkthrough * [Concepts](/docs/core-concepts): why the pieces fit together the way they do # Using OpenSpec in an Existing Project (/docs/existing-projects) **You do not document your whole codebase to start. You write specs only for what you're about to change.** That's the single most important thing to know about adopting OpenSpec on an existing project, and it's why OpenSpec is built brownfield-first. A common worry sounds like this: "My app is 80,000 lines old. Do I have to write specs for all of it before OpenSpec is useful?" No. You'd hate that, and so would we. OpenSpec grows your specs one change at a time. Your first change documents the slice it touches, the next change documents its slice, and over months your specs fill in naturally around the work you actually do. This guide shows how to start on day one without boiling the ocean. ## The thirty-second version [#the-thirty-second-version] ```bash $ cd your-existing-project $ openspec init # adds openspec/ and your AI tool's commands ``` Then, in your AI chat: ```text /opsx:explore # optional: have the AI read the area you'll touch /opsx:propose /opsx:apply /opsx:archive ``` Your specs now describe exactly the part of the system that change touched, and nothing more. That's correct. You're done worrying about the other 80,000 lines. ## Why delta-first is the whole trick [#why-delta-first-is-the-whole-trick] OpenSpec changes are written as **deltas**: `ADDED`, `MODIFIED`, `REMOVED`. A delta describes what's changing relative to current behavior, not the entire system. This is exactly what brownfield work needs. You're rarely building from nothing. You're adding a field, fixing a redirect, tightening a timeout. A delta lets you specify that one change precisely without first writing a 40-page spec of everything around it. So your `openspec/specs/` directory doesn't start full and complete. It starts nearly empty and accumulates. Each archived change merges its delta in. The spec for `auth/` becomes thorough only after you've made several auth changes, which is exactly when you want it thorough. If you want the deeper mechanics, see [Concepts: Delta Specs](/docs/core-concepts#delta-specs). ## Your first change on a real codebase [#your-first-change-on-a-real-codebase] Pick something small and real. Not a toy, not a rewrite. A change you were going to make this week anyway. Small first changes teach you the workflow with low stakes. **Step 1: Let the AI read the relevant area.** This is where `/opsx:explore` earns its keep on an unfamiliar or large codebase. Point it at the part you're about to touch and let it map how things work before proposing anything. ```text You: /opsx:explore AI: What would you like to explore? You: I need to add rate limiting to our public API, but I'm not sure how requests currently flow through the middleware. AI: Let me trace it... [reads the router, middleware stack, and config] Requests hit Express, pass through auth middleware, then your controllers. There's no rate-limiting layer today. The cleanest insertion point is a middleware right after auth. Want me to scope it? ``` Notice the AI now understands your actual structure, so the proposal it writes will fit your code, not a generic template. On a big codebase, this single habit saves the most pain. See [Explore First](/docs/explore). **Step 2: Propose the change.** The proposal and its delta spec capture just this change. ```text You: /opsx:propose add-api-rate-limiting ``` **Step 3: Build and archive** with `/opsx:apply` and `/opsx:archive`, same as any change. After archiving, you have a real spec for your rate-limiting behavior, born from a change you needed anyway. ## Prefer a guided tour? Use onboard [#prefer-a-guided-tour-use-onboard] If you'd rather watch the whole loop happen on your own code with narration, the expanded command `/opsx:onboard` does exactly that: it scans your codebase for a small, safe improvement, then walks you through proposing, building, and archiving it, explaining each step. Turn on the expanded commands first: ```bash $ openspec config profile # select the expanded workflows $ openspec update # apply them to this project ``` Then in chat: ```text /opsx:onboard ``` It's the gentlest possible introduction on a real project, and it leaves you with a genuine (small) change you can keep or discard. See [Commands: `/opsx:onboard`](/docs/reference/slash-commands#opsxonboard). ## "But I already have requirements docs" [#but-i-already-have-requirements-docs] Maybe you have a PRD, an SRS, a formal spec, even TLA+ models. Good. You don't import them wholesale, and you don't throw them away either. Treat existing docs as **source material for exploration**, not as specs to convert. When you start a change, paste or point the AI at the relevant section, and let it shape a focused OpenSpec delta from it. The delta captures the behavior you're changing now, in OpenSpec's testable requirement-and-scenario form. Your original documents stay where they are as background. The honest reason: OpenSpec specs are deliberately behavior-first and scoped to changes. A 40-page PRD is a different artifact with a different job. Forcing a one-time bulk conversion tends to produce a large, stale spec nobody trusts. Letting specs grow from real changes keeps them accurate. ```text You: /opsx:explore You: Here's the section of our PRD about checkout. I'm implementing the "guest checkout" requirement next. [paste the relevant requirement] AI: [reads it, asks clarifying questions, then helps scope a change] You: /opsx:propose add-guest-checkout ``` ## Organizing specs in a big codebase [#organizing-specs-in-a-big-codebase] Specs live under `openspec/specs/`, grouped by **domain**: a logical area that matches how your team thinks about the system. You don't have to design the whole taxonomy up front. Create a domain folder when your first change in that area needs one. Common ways to slice domains: * **By feature area:** `auth/`, `payments/`, `search/` * **By component:** `api/`, `frontend/`, `workers/` * **By bounded context:** `ordering/`, `fulfillment/`, `inventory/` Pick whatever makes a newcomer nod. You can refine later. See [Concepts: Specs](/docs/core-concepts#specs). ## Monorepos and work that spans repos [#monorepos-and-work-that-spans-repos] For a monorepo, the simplest model is one `openspec/` directory at the repo root, with domains that map to your packages or services. That covers most teams. If your work genuinely spans **multiple repositories** (or several packages you treat as separate), OpenSpec has a beta **stores** feature: planning lives in its own standalone repo that any of your code repos can reference, so the plan does not have to live inside one repo's `openspec/` folder. It's beta, so treat its commands and state as evolving. Start with the [Stores User Guide](/docs/stores) for the mental model and the smallest useful path. ## A few honest cautions [#a-few-honest-cautions] * **Resist the urge to back-fill everything.** Writing specs for code you aren't changing feels productive and usually isn't. Those specs go stale, because nothing forces them to track reality. Let real changes drive your specs. * **Keep early changes small.** Your first few changes are as much about learning the rhythm as shipping. A tight scope makes the loop fast and the lessons cheap. * **Commit `openspec/` to git.** Your specs and archive belong in version control alongside the code they describe. * **Give the AI context.** On a large codebase with strong conventions, fill in `openspec/config.yaml`'s `context:` so every proposal respects your stack and patterns. See [Customization](/docs/customization#project-configuration). ## Where to go next [#where-to-go-next] * [Explore First](/docs/explore) - the key habit for understanding code before you change it * [Getting Started](/docs/getting-started) - the full first-change walkthrough * [Editing & Iterating on a Change](/docs/editing-changes) - adjusting a change as you learn * [Concepts: Delta Specs](/docs/core-concepts#delta-specs) - why deltas make brownfield work clean * [Customization](/docs/customization) - teach OpenSpec your project's conventions # Explore First (/docs/explore) **`/opsx:explore` is your thinking partner. Reach for it whenever you have a problem but not yet a plan.** It investigates your codebase, weighs options with you, and clarifies what you actually want, all before a single artifact or line of code is created. When the picture is clear, it hands off to `/opsx:propose`. If you take one habit from these docs, take this one: **when you're not sure, explore before you propose.** Here's why that matters. AI coding assistants are eager. Ask vaguely and they'll confidently build *something*, just maybe not the thing you needed. Explore is the cure. It's a no-stakes conversation where you and the AI figure out the right move together, so that by the time you propose, you're proposing the right thing. ## When to explore [#when-to-explore] Explore is the right first step more often than people expect. Use it when any of these is true: * You know the *problem* but not the *solution*. ("Pages feel slow." "Auth is a mess." "We keep getting duplicate orders.") * You're choosing between approaches and want the tradeoffs laid out against your actual code. * You're new to a codebase and need to understand how something works before you change it. * The requirements are fuzzy and you want to sharpen them before committing. * You suspect the work is bigger or smaller than it looks and want to scope it honestly. Skip explore only when you already know exactly what you want and how. In that case go straight to [`/opsx:propose`](/docs/reference/slash-commands#opsxpropose). ## What it does (and doesn't) [#what-it-does-and-doesnt] Explore is a **conversation**, not a generator. **It does:** * Read and search your codebase to answer real questions. * Compare options and name the tradeoffs of each. * Draw diagrams to make a design legible. * Help you narrow a vague idea into a concrete, buildable scope. * Transition to `/opsx:propose` when you're ready. **It does not:** * Create a change folder. * Write any artifacts (no proposal, specs, design, or tasks). * Write or modify code. That's the point. Exploring costs you nothing and commits you to nothing. You can explore three dead ends, learn something from each, and only then propose the path that survived. ## It's already installed [#its-already-installed] Good news: `/opsx:explore` ships in the default **core** profile, right alongside `propose`, `apply`, `sync`, and `archive`. You don't need to enable anything. If OpenSpec is set up in your project, explore is ready in your AI chat. (As with all `/opsx:*` commands, you type it in your assistant's chat, not the terminal. See [How Commands Work](/docs/how-commands-work).) ## A full example [#a-full-example] Watch how a vague worry becomes a sharp, buildable change. ```text You: /opsx:explore AI: What would you like to explore? You: Our checkout sometimes creates duplicate orders. I don't know why and I don't know how to fix it safely. AI: Let me dig into the checkout path... [reads the order service, the payment webhook handler, and the client submit logic] Here's what I found. There are two ways a duplicate can happen: 1. The client can submit twice (double-click, retry on slow network). Nothing debounces it. 2. The payment webhook can fire more than once, and the handler creates an order each time. There's no idempotency key. Cause #2 is the dangerous one: it can charge and fulfill twice. Three ways to fix it, roughly in order of robustness: - Idempotency key on the order-creation endpoint (handles both causes) - Dedup on the webhook by payment-intent id (handles #2 only) - Client-side debounce (handles #1 only, papers over the real bug) Given your code already stores the payment-intent id, the idempotency-key approach is a small change with the biggest payoff. Want me to scope that? You: Yes, let's do the idempotency key. You: /opsx:propose add-order-idempotency-key AI: Created openspec/changes/add-order-idempotency-key/, with a proposal and delta spec grounded in what we just found. Ready for implementation. ``` Notice what happened. The starting point was "something is wrong and I'm scared to touch it." Twenty seconds of exploration turned that into a named root cause, three ranked options, a recommendation tied to the existing code, and a precise change. The proposal that follows is sharp because the thinking happened first. ## Handing off to propose [#handing-off-to-propose] Explore doesn't archive into anything. When you're ready, you simply start a change, and the AI carries the context from your conversation into the artifacts. ```text explore ──► propose ──► apply ──► archive (think) (agree) (build) (record) ``` You can say it in plain language ("let's turn this into a change") or run `/opsx:propose ` directly. Either way, the exploration you just did becomes the foundation of the proposal, not throwaway chat. If you use the expanded command set, explore can hand off to `/opsx:new` instead, for step-by-step artifact creation. See [Workflows](/docs/the-workflow). ## Tips for a good exploration [#tips-for-a-good-exploration] * **Bring the problem, not the solution.** "Logins feel slow" gives the AI room to investigate. "Add a Redis cache" pre-commits you to an answer you haven't tested yet. * **Ask for the tradeoffs out loud.** "What are the downsides of each option?" gets you a more honest comparison. * **Let it read first.** The best explorations start with the AI actually looking at your code, not guessing. Point it at the relevant area if it helps. * **It's okay to bail.** If exploration reveals the idea isn't worth it, that's a win. You learned it cheaply. * **Explore again mid-change.** Stuck during `/opsx:apply`? You can step back and explore a sub-problem, then return. ## The honest tradeoffs [#the-honest-tradeoffs] **What you gain:** explore catches wrong turns at the cheapest possible moment, before any artifact exists. It's especially powerful in unfamiliar code, where the AI's ability to read and summarize the system saves you an afternoon of spelunking. **What it costs:** a little patience. Explore is a conversation, so it's slower than firing off `/opsx:propose` and hoping. For work you genuinely understand already, that extra step is pure overhead, and you should skip it. The rule of thumb: the fuzzier the task, the more explore pays off. The clearer the task, the more you can skip straight to proposing. ## Where to go next [#where-to-go-next] * [Commands: `/opsx:explore`](/docs/reference/slash-commands#opsxexplore): the precise reference * [Workflows](/docs/the-workflow): explore as part of the everyday loop * [Examples & Recipes](/docs/examples#recipe-3-exploring-before-you-commit): explore in a full walkthrough * [Getting Started](/docs/getting-started): the first-change guide, exploration included # FAQ (/docs/faq) Quick answers to the questions people ask most. If your question is really a "something is broken" question, [Troubleshooting](/docs/troubleshooting) is the better page. If you want a term defined, see the [Glossary](/docs/glossary). ## The basics [#the-basics] ### What is OpenSpec, in one sentence? [#what-is-openspec-in-one-sentence] A lightweight layer that gets you and your AI coding assistant to agree on what to build, in writing, before any code is written. ### Why would I want that? [#why-would-i-want-that] Because AI assistants are confident even when they're wrong. When the requirements live only in a chat thread, the AI fills gaps with guesses, and you find out after the code exists. OpenSpec moves the agreement earlier, where mistakes are cheap to fix. See [Core Concepts at a Glance](/docs/overview) for the full case. ### Do I have to use it for everything? [#do-i-have-to-use-it-for-everything] No. Use it where agreement matters, which is most non-trivial work. For a one-character typo fix, the ceremony probably isn't worth it, and that's fine. ### Can I use it on a big existing codebase, or only new projects? [#can-i-use-it-on-a-big-existing-codebase-or-only-new-projects] Existing codebases are the main event. OpenSpec is brownfield-first: you do not document your whole app up front. You write specs only for what each change touches, and your specs fill in over time around the work you actually do. There's a dedicated guide: [Using OpenSpec in an Existing Project](/docs/existing-projects). ### Is it tied to one AI tool? [#is-it-tied-to-one-ai-tool] No. OpenSpec works with 25+ assistants, including Claude Code, Cursor, Windsurf, GitHub Copilot, Gemini CLI, Codex, and more. The full list and per-tool details are in [Supported Tools](/docs/reference/supported-tools). ## Running commands [#running-commands] ### Where do I type `/opsx:propose`? [#where-do-i-type-opsxpropose] In your AI assistant's chat, not your terminal. This is the single most common point of confusion, so it has its own page: [How Commands Work](/docs/how-commands-work). Short version: `openspec ...` runs in the terminal, `/opsx:...` runs in chat. ### How do I "start interactive mode"? [#how-do-i-start-interactive-mode] There isn't a separate mode to start. You open your AI assistant like normal and type a slash command into its chat. The slash command is how you "enter" OpenSpec. (The one genuinely interactive terminal feature is `openspec view`, a dashboard for browsing specs and changes.) Full explanation in [How Commands Work](/docs/how-commands-work). ### I typed a slash command and nothing happened. Why? [#i-typed-a-slash-command-and-nothing-happened-why] Most likely you typed it in the terminal instead of your AI chat, or the commands aren't installed yet. Run `openspec update` in your project, restart your assistant, then try typing `/opsx` in chat and watch for autocomplete. [Troubleshooting](/docs/troubleshooting#commands-dont-show-up) has the full checklist. ### Why is the syntax `/opsx:propose` in one tool and `/opsx-propose` in another? [#why-is-the-syntax-opsxpropose-in-one-tool-and-opsx-propose-in-another] Each AI tool surfaces custom commands a little differently. The intent is identical; only the punctuation changes. Type a slash in your chat and the autocomplete shows you the form your tool expects. The per-tool table is in [How Commands Work](/docs/how-commands-work#slash-command-syntax-by-tool). ### What's the difference between a skill and a command? [#whats-the-difference-between-a-skill-and-a-command] Both are files OpenSpec writes so your assistant can run the workflow. Skills (`.../skills/openspec-*/SKILL.md`) are the newer cross-tool standard; commands (`.../commands/opsx-*`) are the older per-tool slash files. You don't need to pick. You just type the slash command, and OpenSpec installs whichever your tool uses. ## The workflow [#the-workflow] ### Where should I start if I'm not sure what to build? [#where-should-i-start-if-im-not-sure-what-to-build] With `/opsx:explore`. It's a no-stakes thinking partner that reads your codebase, lays out options, and turns a fuzzy problem into a concrete plan, all before any change or code exists. It's in the default profile, so it's always available. When the plan is clear, it hands off to `/opsx:propose`. This is the single best habit to form, because it stops an eager AI from confidently building the wrong thing. See [Explore First](/docs/explore). ### What's the simplest possible flow? [#whats-the-simplest-possible-flow] ```text /opsx:explore (optional) then /opsx:propose then /opsx:apply then /opsx:archive ``` Explore to think it through, propose to draft the plan, apply to build it, archive to file it away. Skip explore when you already know exactly what you want. ### What's the difference between `/opsx:propose` and `/opsx:new`? [#whats-the-difference-between-opsxpropose-and-opsxnew] `/opsx:propose` is the default one-step command: it creates the change and drafts all the planning artifacts at once. `/opsx:new` is part of the expanded command set and only scaffolds an empty change, leaving you to create artifacts one at a time with `/opsx:continue` (or all at once with `/opsx:ff`). Use propose unless you want step-by-step control. See [Commands](/docs/reference/slash-commands). ### What are `core` and expanded profiles? [#what-are-core-and-expanded-profiles] A profile decides which slash commands get installed. **Core** (the default) gives you `propose`, `explore`, `apply`, `sync`, `archive`. The **expanded** set adds `new`, `continue`, `ff`, `verify`, `bulk-archive`, and `onboard` for finer control. Switch with `openspec config profile`, then apply with `openspec update`. ### Do I need to run `/opsx:sync`? [#do-i-need-to-run-opsxsync] Usually not. Sync merges a change's delta specs into your main specs, and `/opsx:archive` will offer to do it for you. Run sync manually only when you want the specs merged before archiving, for example on a long-running change. See [Commands](/docs/reference/slash-commands#opsxsync). ### How do I edit a proposal, spec, or task after I've started? [#how-do-i-edit-a-proposal-spec-or-task-after-ive-started] Just edit the file. Every artifact is plain Markdown in `openspec/changes//`, and there's no locked phase or special edit mode. Change it by hand, or ask your AI to revise it ("update the design to use a queue"), then keep going. The AI always works from the current file contents. Full guide: [Editing & Iterating on a Change](/docs/editing-changes). ### Can I go back and change the plan after implementing some of it? [#can-i-go-back-and-change-the-plan-after-implementing-some-of-it] Yes, at any time. The workflow is fluid, so review and editing aren't phases you get locked out of. Edit the artifact, then continue. If you want a structured check that the code still matches the plan, run `/opsx:verify`. See [Editing & Iterating on a Change](/docs/editing-changes#how-do-i-go-back-to-review-after-implementing). ### I edited the code by hand. How do I reconcile it with the spec? [#i-edited-the-code-by-hand-how-do-i-reconcile-it-with-the-spec] Bring them back in sync before you archive, since archiving makes your specs the record of truth. If the code is now correct, update the delta spec to match what you shipped; if the spec is correct, keep building until the code agrees. `/opsx:verify` surfaces the mismatches. See [Editing & Iterating on a Change](/docs/editing-changes#i-edited-the-code-by-hand-how-do-i-reconcile-that-with-openspec). ### When should I update an existing change versus start a new one? [#when-should-i-update-an-existing-change-versus-start-a-new-one] Update when it's the same work, refined. Start fresh when the intent fundamentally changed or the scope exploded into different work. There's a decision flowchart and examples in [Workflows](/docs/the-workflow#when-to-update-vs-start-fresh). ### What if my session runs out of context, or requirements change mid-implementation? [#what-if-my-session-runs-out-of-context-or-requirements-change-mid-implementation] This is where specs earn their keep. Because the plan lives in files (not only in chat history), you can clear your context, start a fresh AI session, and pick up with `/opsx:apply`; it reads the artifacts and resumes from the first unchecked task. If requirements change, edit the artifacts to match the new reality and continue. Keeping a clean context window also produces better results; clear it before implementation. ### Should I commit the `openspec/` folder to git? [#should-i-commit-the-openspec-folder-to-git] Yes. Your specs, active changes, and archive are part of your project's history. Commit them like any other source. The archive in particular becomes a durable record of why your system works the way it does. ## Specs and changes [#specs-and-changes] ### What goes in a spec versus a design? [#what-goes-in-a-spec-versus-a-design] A spec describes observable behavior: what the system does, its inputs, outputs, and error conditions. A design describes how you'll build it: the technical approach, architecture decisions, file changes. If implementation could change without changing externally visible behavior, it belongs in the design, not the spec. [Concepts](/docs/core-concepts#what-a-spec-is-and-is-not) goes deeper. ### What's a delta spec? [#whats-a-delta-spec] A spec that describes only what's changing, using `ADDED`, `MODIFIED`, and `REMOVED` sections, rather than restating the whole spec. It's how OpenSpec handles edits to existing systems cleanly. See [Concepts](/docs/core-concepts#delta-specs). ### Where do archived changes go? [#where-do-archived-changes-go] To `openspec/changes/archive/YYYY-MM-DD-/`, with all artifacts preserved. Nothing is deleted; the change just moves out of your active list. ## Configuration and customization [#configuration-and-customization] ### How do I tell the AI about my tech stack? [#how-do-i-tell-the-ai-about-my-tech-stack] Put it in `openspec/config.yaml` under `context:`. That text is injected into every planning request, so the AI always knows your stack and conventions. See [Customization](/docs/customization#project-configuration). ### Can I generate specs in a language other than English? [#can-i-generate-specs-in-a-language-other-than-english] Yes. Add a language instruction to your config's `context:`. [Multi-Language](/docs/multi-language) has copy-paste snippets for several languages. ### Can I change the workflow itself? [#can-i-change-the-workflow-itself] Yes, with custom schemas. A schema defines which artifacts exist and how they depend on each other. Fork the default with `openspec schema fork spec-driven my-workflow`, then edit it. See [Customization](/docs/customization#custom-schemas). ## Models, privacy, and upgrades [#models-privacy-and-upgrades] ### Which AI model should I use? [#which-ai-model-should-i-use] OpenSpec works best with high-reasoning models. The README recommends models like Codex 5.5 and Opus 4.7 for both planning and implementation. Also keep your context window clean: clear it before implementation for best results. ### Does OpenSpec collect data? [#does-openspec-collect-data] It collects anonymous usage stats: command names and version only. No arguments, paths, content, or personal data, and it's off automatically in CI. Opt out with `export OPENSPEC_TELEMETRY=0` or `export DO_NOT_TRACK=1`. ### How do I upgrade? [#how-do-i-upgrade] Two steps. Upgrade the package (`npm install -g @fission-ai/openspec@latest`), then run `openspec update` inside each project to refresh the generated skills and commands. ### How do I uninstall OpenSpec? [#how-do-i-uninstall-openspec] There's no uninstall command, because it's just a global package plus files in your project. Remove the package (`npm uninstall -g @fission-ai/openspec`), and optionally delete the `openspec/` directory and the generated tool files. Step-by-step, including what's safe to keep, is in [Installation: Uninstalling](/docs/installation#uninstalling). ## Getting help [#getting-help] ### Where do I ask questions or report bugs? [#where-do-i-ask-questions-or-report-bugs] * **Discord:** [discord.gg/YctCnvvshC](https://discord.gg/YctCnvvshC) * **GitHub Issues:** [github.com/Fission-AI/OpenSpec/issues](https://github.com/Fission-AI/OpenSpec/issues) * **From your terminal:** `openspec feedback "your message"` opens a GitHub issue for you. ### These docs are wrong or confusing. What do I do? [#these-docs-are-wrong-or-confusing-what-do-i-do] Tell us, or fix it. Documentation PRs are welcome and valued. Open an issue or send a pull request. # Getting Started (/docs/getting-started) This guide explains how OpenSpec works after you've installed and initialized it. For installation instructions, see the [main README](https://github.com/Fission-AI/OpenSpec/blob/main/README.md#quick-start) or the [Installation guide](/docs/installation). New to the whole docs set? The [documentation home](/docs) maps everything. > **Where do I type these commands?** Two places, and mixing them up is the most common early stumble. > > * `openspec ...` commands (like `openspec init`) run in your **terminal**. > * `/opsx:...` commands (like `/opsx:propose`) run in your **AI assistant's chat**, the same box where you'd ask it to write code. > > There's no separate "interactive mode" to start. You just type the slash command in chat and your assistant takes it from there. Full explanation: [How Commands Work](/docs/how-commands-work). ## Your First Five Minutes [#your-first-five-minutes] The whole loop, with each step labeled by where it happens: ```text TERMINAL $ npm install -g @fission-ai/openspec@latest TERMINAL $ cd your-project && openspec init AI CHAT /opsx:explore (optional: think it through first) AI CHAT /opsx:propose add-dark-mode (AI drafts the plan; you review it) AI CHAT /opsx:apply (AI builds it) AI CHAT /opsx:archive (specs updated, change filed away) ``` Two terminal steps to set up, then you live in chat. The rest of this guide unpacks what each step does and what you'll see. > **Not sure what to build yet? Start with `/opsx:explore`.** It's a no-stakes thinking partner that reads your codebase, weighs options, and sharpens a fuzzy idea into a concrete plan, all before any artifact or code exists. When the picture is clear, it hands off to `/opsx:propose`. This is the single best habit for working with an AI that will otherwise confidently build the wrong thing. See the [Explore guide](/docs/explore). ## How It Works [#how-it-works] OpenSpec helps you and your AI coding assistant agree on what to build before any code is written. **Default quick path (core profile):** ```text /opsx:explore ──► /opsx:propose ──► /opsx:apply ──► /opsx:sync ──► /opsx:archive (optional) ``` Start with `/opsx:explore` when you're figuring out what to do, or jump straight to `/opsx:propose` when you already know. Explore is in the default profile, so it's always there when you want it. **Expanded path (custom workflow selection):** ```text /opsx:new ──► /opsx:ff or /opsx:continue ──► /opsx:apply ──► /opsx:verify ──► /opsx:archive ``` The default global profile is `core`, which includes `propose`, `explore`, `apply`, `sync`, and `archive`. You can enable the expanded workflow commands with `openspec config profile` and then `openspec update`. ## What OpenSpec Creates [#what-openspec-creates] After running `openspec init`, your project has this structure: ``` openspec/ ├── specs/ # Source of truth (your system's behavior) │ └── / │ └── spec.md ├── changes/ # Proposed updates (one folder per change) │ └── / │ ├── proposal.md │ ├── design.md │ ├── tasks.md │ └── specs/ # Delta specs (what's changing) │ └── / │ └── spec.md └── config.yaml # Project configuration (optional) ``` **Two key directories:** * **`specs/`** - The source of truth. These specs describe how your system currently behaves. Organized by domain (e.g., `specs/auth/`, `specs/payments/`). * **`changes/`** - Proposed modifications. Each change gets its own folder with all related artifacts. When a change is complete, its specs merge into the main `specs/` directory. ## Understanding Artifacts [#understanding-artifacts] Each change folder contains artifacts that guide the work: | Artifact | Purpose | | ------------- | ----------------------------------------------------------- | | `proposal.md` | The "why" and "what" - captures intent, scope, and approach | | `specs/` | Delta specs showing ADDED/MODIFIED/REMOVED requirements | | `design.md` | The "how" - technical approach and architecture decisions | | `tasks.md` | Implementation checklist with checkboxes | **Artifacts build on each other:** ``` proposal ──► specs ──► design ──► tasks ──► implement ▲ ▲ ▲ │ └───────────┴──────────┴────────────────────┘ update as you learn ``` You can always go back and refine earlier artifacts as you learn more during implementation. ## How Delta Specs Work [#how-delta-specs-work] Delta specs are the key concept in OpenSpec. They show what's changing relative to your current specs. ### The Format [#the-format] Delta specs use sections to indicate the type of change: ```markdown # Delta for Auth ## ADDED Requirements ### Requirement: Two-Factor Authentication The system MUST require a second factor during login. #### Scenario: OTP required - GIVEN a user with 2FA enabled - WHEN the user submits valid credentials - THEN an OTP challenge is presented ## MODIFIED Requirements ### Requirement: Session Timeout The system SHALL expire sessions after 30 minutes of inactivity. (Previously: 60 minutes) #### Scenario: Idle timeout - GIVEN an authenticated session - WHEN 30 minutes pass without activity - THEN the session is invalidated ## REMOVED Requirements ### Requirement: Remember Me (Deprecated in favor of 2FA) ``` ### What Happens on Archive [#what-happens-on-archive] When you archive a change: 1. **ADDED** requirements are appended to the main spec 2. **MODIFIED** requirements replace the existing version 3. **REMOVED** requirements are deleted from the main spec The change folder moves to `openspec/changes/archive/` for audit history. ## Example: Your First Change [#example-your-first-change] Let's walk through adding dark mode to an application. ### 1. Start the Change (Default) [#1-start-the-change-default] ```text You: /opsx:propose add-dark-mode AI: Created openspec/changes/add-dark-mode/ ✓ proposal.md — why we're doing this, what's changing ✓ specs/ — requirements and scenarios ✓ design.md — technical approach ✓ tasks.md — implementation checklist Ready for implementation! ``` If you've enabled the expanded workflow profile, you can also do this as two steps: `/opsx:new` then `/opsx:ff` (or `/opsx:continue` incrementally). ### 2. What Gets Created [#2-what-gets-created] **proposal.md** - Captures the intent: ```markdown # Proposal: Add Dark Mode ## Intent Users have requested a dark mode option to reduce eye strain during nighttime usage. ## Scope - Add theme toggle in settings - Support system preference detection - Persist preference in localStorage ## Approach Use CSS custom properties for theming with a React context for state management. ``` **specs/ui/spec.md** - Delta showing new requirements: ```markdown # Delta for UI ## ADDED Requirements ### Requirement: Theme Selection The system SHALL allow users to choose between light and dark themes. #### Scenario: Manual toggle - GIVEN a user on any page - WHEN the user clicks the theme toggle - THEN the theme switches immediately - AND the preference persists across sessions #### Scenario: System preference - GIVEN a user with no saved preference - WHEN the application loads - THEN the system's preferred color scheme is used ``` **tasks.md** - Implementation checklist: ```markdown # Tasks ## 1. Theme Infrastructure - [ ] 1.1 Create ThemeContext with light/dark state - [ ] 1.2 Add CSS custom properties for colors - [ ] 1.3 Implement localStorage persistence ## 2. UI Components - [ ] 2.1 Create ThemeToggle component - [ ] 2.2 Add toggle to settings page - [ ] 2.3 Update Header to include quick toggle ## 3. Styling - [ ] 3.1 Define dark theme color palette - [ ] 3.2 Update components to use CSS variables ``` ### 3. Implement [#3-implement] ``` You: /opsx:apply AI: Working through tasks... ✓ 1.1 Created ThemeContext with light/dark state ✓ 1.2 Added CSS custom properties to globals.css ✓ 1.3 Implemented localStorage persistence ✓ 2.1 Created ThemeToggle component ... All tasks complete! ``` During implementation, if you discover the design needs adjustment, just update the artifact and continue. ### 4. Archive [#4-archive] ``` You: /opsx:archive AI: Archiving add-dark-mode... ✓ Merged specs into openspec/specs/ui/spec.md ✓ Moved to openspec/changes/archive/2025-01-24-add-dark-mode/ Done! Ready for the next feature. ``` Your delta specs are now part of the main specs, documenting how your system works. ## Verifying and Reviewing [#verifying-and-reviewing] Use the CLI to check on your changes: ```bash # List active changes openspec list # View change details openspec show add-dark-mode # Validate spec formatting openspec validate add-dark-mode # Interactive dashboard openspec view ``` ## Next Steps [#next-steps] * [Explore First](/docs/explore) - Use `/opsx:explore` to think through an idea before you commit * [Reviewing a Change](/docs/reviewing-changes) - What to check in the plan the AI drafts, before any code * [Writing Good Specs](/docs/writing-specs) - What a strong requirement and scenario look like * [Using OpenSpec in an Existing Project](/docs/existing-projects) - Start on a large brownfield codebase * [Editing & Iterating on a Change](/docs/editing-changes) - Update artifacts, go back, reconcile manual edits * [Core Concepts at a Glance](/docs/overview) - The whole mental model on one page * [Examples & Recipes](/docs/examples) - Real changes, start to finish * [Workflows](/docs/the-workflow) - Common patterns and when to use each command * [Commands](/docs/reference/slash-commands) - Full reference for all slash commands * [Concepts](/docs/core-concepts) - Deeper understanding of specs, changes, and schemas * [Customization](/docs/customization) - Make OpenSpec work your way * [Stores](/docs/stores) - Planning that spans repos or teams? Keep it in its own repo (beta) * [FAQ](/docs/faq) and [Troubleshooting](/docs/troubleshooting) - When you get stuck # Glossary (/docs/glossary) Every OpenSpec term in one place, defined in plain language. Skim it once and the rest of the docs read faster. Terms are grouped by topic, then alphabetized within each group. ## The core nouns [#the-core-nouns] **Spec.** A document describing how part of your system behaves. Specs live in `openspec/specs/`, are organized by domain, and are made of requirements and scenarios. The spec is the agreed-upon answer to "what does this software do?" See [Concepts](/docs/core-concepts#specs). **Source of truth.** The `openspec/specs/` directory as a whole. It holds the current, agreed-upon behavior of your system. Changes propose edits to it; archiving applies them. **Change.** One unit of work, packaged as a folder under `openspec/changes//`. A change holds everything about that work: its proposal, design, tasks, and the spec edits it introduces. One change, one feature or fix. **Artifact.** A document inside a change. The standard artifacts are the proposal, the delta specs, the design, and the tasks. They're created in dependency order and feed into each other. **Delta spec.** A spec inside a change that describes only what's changing, using `ADDED`, `MODIFIED`, and `REMOVED` sections, rather than restating the entire spec. This is what lets OpenSpec edit existing systems cleanly. See [Concepts](/docs/core-concepts#delta-specs). **Domain.** A logical grouping for specs, like `auth/`, `payments/`, or `ui/`. You choose domains that match how you think about your system. ## Inside a spec [#inside-a-spec] **Requirement.** A single behavior the system must have, usually written with an RFC 2119 keyword: "The system SHALL expire sessions after 30 minutes." Requirements state the *what*, not the *how*. **Scenario.** A concrete, testable example of a requirement in action, typically in Given/When/Then form. Scenarios make a requirement verifiable: you could write an automated test from one. **RFC 2119 keywords.** The words MUST, SHALL, SHOULD, and MAY, which carry standardized meaning about how strict a requirement is. MUST and SHALL are absolute. SHOULD is recommended with room for exceptions. MAY is optional. The name comes from the internet standards document that defined them. ## The artifacts [#the-artifacts] **Proposal (`proposal.md`).** The *why* and *what* of a change: its intent, scope, and high-level approach. The first artifact you create. **Design (`design.md`).** The *how*: technical approach, architecture decisions, and the files you expect to touch. Optional for simple changes. **Tasks (`tasks.md`).** The implementation checklist, with checkboxes. The AI works through it during `/opsx:apply` and checks items off as it goes. ## The lifecycle [#the-lifecycle] **Archive.** The act of finishing a change. Its delta specs merge into the main specs, and the change folder moves to `openspec/changes/archive/YYYY-MM-DD-/`. After archiving, your specs describe the new reality. See [Concepts](/docs/core-concepts#archive). **Sync.** Merging a change's delta specs into the main specs *without* archiving the change. Usually automatic (archive offers to do it), but available on its own as `/opsx:sync` for long-running changes. See [Commands](/docs/reference/slash-commands#opsxsync). ## Workflow and commands [#workflow-and-commands] **OPSX.** The current standard OpenSpec workflow, built around fluid actions instead of rigid phases. Its slash commands all start with `/opsx:`. See [OPSX Workflow](/docs/opsx). **Slash command.** A command you type into your AI assistant's chat, like `/opsx:propose`. Slash commands drive the workflow. They are not terminal commands. See [How Commands Work](/docs/how-commands-work). **Explore (`/opsx:explore`).** The thinking-partner command. It reads your codebase, compares options, and clarifies a fuzzy idea into a concrete plan, creating no artifacts and writing no code. The recommended starting point whenever you have a problem but not yet a plan. See [Explore First](/docs/explore). **CLI.** The `openspec` program you run in your terminal. It sets up projects, lists and validates changes, opens the dashboard, and archives. The terminal half of OpenSpec. See [CLI](/docs/reference/cli). **Skill.** A folder of instructions (`.../skills/openspec-*/SKILL.md`) that your AI assistant auto-detects and follows. Skills are the emerging cross-tool standard for delivering the OpenSpec workflow to your assistant. **Command file.** A per-tool slash command file (`.../commands/opsx-*`). The older delivery mechanism, still supported alongside skills. You rarely touch these directly. **Profile.** The set of slash commands installed in your project. **Core** (the default) is `propose`, `explore`, `apply`, `sync`, `archive`. The **expanded** set adds `new`, `continue`, `ff`, `verify`, `bulk-archive`, `onboard`. Change it with `openspec config profile`. **Delivery.** Whether OpenSpec installs skills, command files, or both for your tools. Configured globally and applied with `openspec update`. ## Customization [#customization] **Schema.** The definition of which artifacts a workflow has and how they depend on one another. The built-in default is `spec-driven` (proposal → specs → design → tasks). You can fork it or write your own. See [Customization](/docs/customization#custom-schemas). **Template.** A Markdown file inside a schema that shapes what the AI generates for a given artifact. Editing a template changes the AI's output immediately, with no rebuild. **Project config (`openspec/config.yaml`).** Per-project settings: the default schema, the `context:` injected into every planning request, and per-artifact `rules:`. The easiest way to teach OpenSpec about your stack and conventions. See [Customization](/docs/customization#project-configuration). **Context injection.** Putting project background in `config.yaml`'s `context:` field so it's automatically added to every artifact the AI generates. More reliable than hoping the AI reads a separate file. **Dependency graph.** The directed graph formed by artifact `requires:` relationships. It's a DAG (directed acyclic graph: arrows only point forward, never in a loop), and OpenSpec uses it to know what you can create next. **Enablers, not gates.** The principle that artifact dependencies show what becomes *possible* next, not what's *required* next. You can revisit and edit any artifact at any time. See [Core Concepts at a Glance](/docs/overview#enablers-not-gates). ## Coordination across repos (beta) [#coordination-across-repos-beta] These terms apply only if your planning spans more than one repo. They're in beta. Most users can ignore them. See the [Stores User Guide](/docs/stores). **Store.** A standalone repo whose whole job is planning. It has the same `openspec/` shape you already know (specs and changes) plus a small identity file. You register it on your machine once, by name, and then any OpenSpec command can work in it from anywhere. **Reference.** A declaration, in a code repo's `openspec/config.yaml`, of a store that repo draws on. References are read-only: the repo keeps its own root, and `openspec instructions` gains an index of the referenced store's specs, each with the exact command to fetch it. **Working context.** What `openspec context` assembles for the current repo: its OpenSpec root plus every store it references, each with how to fetch it. The answer to "what am I working with?" **Workset.** A personal, machine-local set of folders you open together (a store alongside the code repos you work on). Created explicitly with `openspec workset create`; nothing about those local paths is committed to the shared planning repo. ## See also [#see-also] * [Core Concepts at a Glance](/docs/overview): the five ideas, on one page * [Concepts](/docs/core-concepts): the long-form explanation * [How Commands Work](/docs/how-commands-work): slash commands versus the CLI # How Commands Work (/docs/how-commands-work) **The one thing to know: OpenSpec has two kinds of commands, and they run in two different places.** * `openspec ...` commands run in your **terminal**. (Example: `openspec init`.) * `/opsx:...` commands run in your **AI assistant's chat**. (Example: `/opsx:propose`.) If you ever type `/opsx:propose` into your terminal and nothing happens, this page is why. You are talking to the wrong half of OpenSpec. Slash commands are not terminal commands. They are instructions you give to your AI coding assistant, in the same chat box where you'd normally type "add a login form." That single distinction is the most common stumbling block for new users, so let's make it crystal clear. ## The two halves [#the-two-halves] OpenSpec is one project wearing two hats. **The CLI (terminal half).** A program named `openspec` that you install and run from your shell. It sets up your project, lists and validates changes, shows a dashboard, and archives finished work. You type these into iTerm, the VS Code terminal, PowerShell, anywhere you'd run `git` or `npm`. ```bash openspec init # set up OpenSpec in this project openspec list # see active changes openspec view # open the interactive dashboard ``` **The slash commands (chat half).** Short commands like `/opsx:propose` and `/opsx:apply` that you type into your AI assistant. These tell the AI to follow the OpenSpec workflow: draft a proposal, write specs, build from the task list, archive when done. You type these into Claude Code, Cursor, Windsurf, Copilot, or whichever assistant you use. ```text /opsx:propose add-dark-mode (typed in your AI chat) /opsx:apply (typed in your AI chat) /opsx:archive (typed in your AI chat) ``` Here's the mental model in one picture: ```text YOUR TERMINAL YOUR AI ASSISTANT'S CHAT ┌──────────────────────┐ ┌──────────────────────────────┐ │ $ openspec init │ installs │ /opsx:propose add-dark-mode │ │ $ openspec list │ ──────────► │ /opsx:apply │ │ $ openspec view │ commands │ /opsx:archive │ └──────────────────────┘ & skills └──────────────────────────────┘ run openspec here run /opsx:* here ``` Notice the arrow. Running `openspec init` in your terminal is what *installs* the slash commands into your AI tool. The terminal half sets up the chat half. After that, day-to-day driving mostly happens in chat. ## "How do I start interactive mode?" [#how-do-i-start-interactive-mode] **There is no separate interactive mode to start.** This question comes up a lot, so it deserves a plain answer. You don't enter a special OpenSpec mode. You just open your AI coding assistant like you always do, and type a slash command into the chat. The slash command *is* how you "enter" OpenSpec. Your assistant recognizes it, loads the matching OpenSpec skill, and starts following the workflow. So the real instructions are: 1. Open your AI coding assistant (Claude Code, Cursor, Windsurf, and so on) in your project. 2. Type `/opsx:propose` in its chat, the same place you type any other request. 3. Watch the autocomplete: if OpenSpec is installed, you'll see `/opsx:propose`, `/opsx:apply`, and friends appear as you type the slash. That's it. No mode to toggle, no daemon to launch, no separate window. One thing that *is* genuinely interactive lives in the terminal: `openspec view`. It opens a dashboard for browsing your specs and changes. But that's a viewer, not the thing you propose and build with. The building happens through slash commands in chat. ## Why this split exists [#why-this-split-exists] It's worth understanding, because it explains why OpenSpec works with 25+ different AI tools. The CLI is the **engine**. It knows the rules: what a change folder looks like, which artifacts depend on which, how to merge a delta spec into your source of truth. It's the same everywhere. The slash commands are the **steering wheel**, and every AI tool has a slightly different one. Claude Code calls them commands. Cursor and Windsurf have their own formats. Some tools call them skills. When you run `openspec init`, OpenSpec generates the right kind of file for each tool you selected, so the same `/opsx:propose` intent works no matter which assistant you prefer. The strength of this design: you learn the workflow once and carry it across tools. The tradeoff: the exact syntax of a command can differ slightly between tools, which is the next section. ## Slash command syntax by tool [#slash-command-syntax-by-tool] The intent is identical everywhere. The punctuation differs. Use the form that matches your assistant. | Tool | How you type it | | -------------------- | ------------------------------------------- | | Claude Code | `/opsx:propose`, `/opsx:apply` | | Cursor | `/opsx-propose`, `/opsx-apply` | | Windsurf | `/opsx-propose`, `/opsx-apply` | | GitHub Copilot (IDE) | `/opsx-propose`, `/opsx-apply` | | CodeArts | skill-style, e.g. `/openspec-propose` | | Codex | skill-style via `.codex/skills/openspec-*` | | Oh My Pi | `/opsx-propose`, `/opsx-apply` | | Kimi CLI | skill-style, e.g. `/skill:openspec-propose` | | Trae | `/opsx-propose`, `/opsx-apply` | Most tools use either the colon form (`/opsx:propose`) or the dash form (`/opsx-propose`). A few tools surface OpenSpec as named skills instead of slash commands; for those you invoke the skill by name. The full per-tool list, including exactly which files get written where, lives in [Supported Tools](/docs/reference/supported-tools). When in doubt, type a slash in your AI chat and look at the autocomplete. Your tool will show you the form it expects. ## How the commands got there: skills and commands [#how-the-commands-got-there-skills-and-commands] When you run `openspec init` (or `openspec update`), OpenSpec writes small files into your project so your AI tool can find the workflow. Depending on your tool and settings, these are **skills**, **commands**, or both. * **Skills** live in places like `.claude/skills/openspec-*/SKILL.md`. They're the emerging cross-tool standard: a folder of instructions your assistant auto-detects. * **Commands** live in places like `.claude/commands/opsx/.md`. They're the older per-tool slash command files. Codex does not get generated command files; use `.codex/skills/openspec-*`. You don't have to care which one your tool uses. You just type the slash command and it works. But knowing these files exist helps when something goes wrong: if your commands vanish, it usually means these files are missing or stale, and `openspec update` regenerates them. See [Supported Tools](/docs/reference/supported-tools) for the exact paths per tool, and [Migration Guide](/docs/migration-guide) for how skills replaced the older command-only approach. ## Confirming it's installed [#confirming-its-installed] Quick checks, fastest first: 1. **Type a slash in your AI chat.** Start typing `/opsx` and watch for autocomplete suggestions. If they appear, you're set. 2. **Look for the files.** For Claude Code, check that `.claude/skills/` contains `openspec-*` folders. Other tools use their own directories ([Supported Tools](/docs/reference/supported-tools) lists them). 3. **Re-run setup.** From your project root, run `openspec update`. This regenerates the skill and command files for whatever tools you configured. 4. **Restart your assistant.** Many tools scan for skills and commands at startup, so a fresh window can be the missing step. ## Which commands do I even have? [#which-commands-do-i-even-have] By default, OpenSpec installs the **core** set of slash commands: * `/opsx:explore`: think through an idea with the AI before committing to a change (great first step when you're unsure) * `/opsx:propose`: create a change and draft all its planning artifacts in one step * `/opsx:apply`: build the change by working through its task list * `/opsx:sync`: merge a change's spec updates into your main specs (usually automatic) * `/opsx:archive`: finish a change and file it away A good default rhythm: `explore` when you're figuring out what to do, then `propose`, `apply`, `archive`. The [Explore First](/docs/explore) guide explains why that opening step pays off. There's also an **expanded** set for people who want finer control (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:bulk-archive`, `/opsx:onboard`). You turn it on with `openspec config profile`, then apply it with `openspec update`. New to all of this? `/opsx:onboard` (in the expanded set) walks you through a complete change on your own codebase, narrating each step. It's the friendliest possible introduction. For what each command does in detail, see [Commands](/docs/reference/slash-commands). For when to reach for which, see [Workflows](/docs/the-workflow). ## A clean first run [#a-clean-first-run] Putting it together, here is the whole sequence with each step labeled by where it happens. ```text TERMINAL $ npm install -g @fission-ai/openspec@latest TERMINAL $ cd your-project TERMINAL $ openspec init (installs slash commands into your AI tool) AI CHAT /opsx:explore (optional: think the idea through with the AI first) AI CHAT /opsx:propose add-dark-mode (AI drafts proposal, specs, design, tasks) AI CHAT /opsx:apply (AI builds it, checking off tasks) AI CHAT /opsx:archive (change is merged into your specs and filed away) ``` Two terminal steps to set up. Then you live in chat. That's the rhythm. ## Related [#related] * [Getting Started](/docs/getting-started): the full first-change walkthrough * [Commands](/docs/reference/slash-commands): every slash command in detail * [CLI](/docs/reference/cli): every terminal command in detail * [Supported Tools](/docs/reference/supported-tools): per-tool syntax and file locations * [FAQ](/docs/faq): more quick answers * [Troubleshooting](/docs/troubleshooting): fixes when commands don't show up # OpenSpec Documentation (/docs) Welcome. This is the home for everything OpenSpec. OpenSpec helps you and your AI coding assistant **agree on what to build before any code is written.** You describe the change, the AI drafts a short spec and a task list, you both look at the same plan, and then the work happens. No more discovering halfway through that the AI built the wrong thing. If you read nothing else, read these two pages: 1. [Getting Started](/docs/getting-started): install, initialize, and ship your first change. 2. [How Commands Work](/docs/how-commands-work): where you actually type `/opsx:propose` (hint: in your AI chat, not the terminal). This trips up almost everyone once. That second one matters more than it looks. OpenSpec has two halves: a command line tool you run in your terminal, and slash commands you give to your AI assistant. Knowing which is which saves you the most common moment of confusion. > **The best habit to build first: when you're not sure what to build, start with `/opsx:explore`.** It's a no-stakes thinking partner that reads your code, weighs options, and sharpens a fuzzy idea into a concrete plan before any artifact or code exists. The [Explore First](/docs/explore) guide makes the case. ## Pick your path [#pick-your-path] **I'm brand new.** Start with [Getting Started](/docs/getting-started), then skim the [Core Concepts at a Glance](/docs/overview). When something feels mysterious, the [FAQ](/docs/faq) and [Glossary](/docs/glossary) are nearby. **I have a problem but not a plan.** This is the common case, and it has a dedicated answer: [Explore First](/docs/explore). Use `/opsx:explore` to think it through with the AI before committing to anything. **I have a big existing codebase.** You don't document all of it. [Using OpenSpec in an Existing Project](/docs/existing-projects) shows how to start on real, brownfield code without boiling the ocean. **I just want to get it working.** [Install](/docs/installation), run `openspec init`, then read [How Commands Work](/docs/how-commands-work) so your first slash command lands in the right place. **I learn by example.** The [Examples & Recipes](/docs/examples) page walks through real changes start to finish: a small feature, a bug fix, a refactor, an exploration. **The AI just drafted a plan — now what?** Read it. [Reviewing a Change](/docs/reviewing-changes) shows the two-minute pass that catches a wrong turn while it's still cheap, and [Writing Good Specs](/docs/writing-specs) covers what a plan worth approving is made of. **I work on a team.** [OpenSpec on a Team](/docs/team-workflow) shows how a change maps onto a branch and a pull request, and how teammates review a plan before the code. **I'm coming from the old workflow.** The [Migration Guide](/docs/migration-guide) explains what changed and why, and promises your existing work is safe. **I want to bend it to my team's process.** [Customization](/docs/customization) covers project config, custom schemas, and shared context. **Something's broken.** [Troubleshooting](/docs/troubleshooting) collects the failures people actually hit, with fixes. ## The whole map [#the-whole-map] ### Start here [#start-here] | Doc | What it gives you | | -------------------------------------------- | ------------------------------------------------------------------------- | | [Getting Started](/docs/getting-started) | Install, initialize, and run your first change end to end | | [Explore First](/docs/explore) | Use `/opsx:explore` to think through an idea before you commit | | [How Commands Work](/docs/how-commands-work) | Where slash commands run, what "interactive mode" means, terminal vs chat | | [Core Concepts at a Glance](/docs/overview) | The whole mental model on one page: specs, changes, deltas, archive | | [Installation](/docs/installation) | npm, pnpm, yarn, bun, Nix, and how to verify it worked | ### Use it day to day [#use-it-day-to-day] | Doc | What it gives you | | ---------------------------------------------------------------- | -------------------------------------------------------------------------------- | | [Workflows](/docs/the-workflow) | Common patterns and when to reach for each command | | [Examples & Recipes](/docs/examples) | Full walkthroughs of real changes, copy-pasteable | | [Writing Good Specs](/docs/writing-specs) | What a strong requirement and scenario look like, and how to right-size a change | | [Reviewing a Change](/docs/reviewing-changes) | The two-minute pass on a drafted plan before any code is written | | [OpenSpec on a Team](/docs/team-workflow) | How changes fit branches, pull requests, and review | | [Using OpenSpec in an Existing Project](/docs/existing-projects) | Adopting OpenSpec on a large brownfield codebase | | [Editing & Iterating on a Change](/docs/editing-changes) | Update artifacts, go back, reconcile manual edits | | [Commands](/docs/reference/slash-commands) | Reference for every `/opsx:*` slash command | | [CLI](/docs/reference/cli) | Reference for every `openspec` terminal command | ### Understand it deeply [#understand-it-deeply] | Doc | What it gives you | | ------------------------------- | --------------------------------------------------------------------------------- | | [Concepts](/docs/core-concepts) | The long-form explanation of specs, changes, artifacts, schemas, and archive | | [OPSX Workflow](/docs/opsx) | Why the workflow is fluid instead of phase-locked, plus an architecture deep dive | | [Glossary](/docs/glossary) | Every term defined in one place | ### Make it yours [#make-it-yours] | Doc | What it gives you | | -------------------------------------------------- | --------------------------------------------------------------- | | [Customization](/docs/customization) | Project config, custom schemas, shared context | | [Multi-Language](/docs/multi-language) | Generate artifacts in languages other than English | | [Supported Tools](/docs/reference/supported-tools) | The 25+ AI tools OpenSpec integrates with, and where files land | ### When you need help [#when-you-need-help] | Doc | What it gives you | | ---------------------------------------- | ---------------------------------------------- | | [FAQ](/docs/faq) | Quick answers to the questions people ask most | | [Troubleshooting](/docs/troubleshooting) | Concrete fixes for concrete failures | | [Migration Guide](/docs/migration-guide) | Moving from the legacy workflow to OPSX | ### Coordinate across repos (beta) [#coordinate-across-repos-beta] | Doc | What it gives you | | ---------------------------------------- | -------------------------------------------------------- | | [Stores: User Guide](/docs/stores) | Plan in its own repo when your work spans repos or teams | | [Agent Contract](/docs/reference/agents) | The machine-readable CLI surfaces agents drive | ## The thirty-second version [#the-thirty-second-version] ```text 1. Install npm install -g @fission-ai/openspec@latest 2. Initialize cd your-project && openspec init 3. Explore (in your AI chat) /opsx:explore ← optional, but a great habit 4. Propose (in your AI chat) /opsx:propose add-dark-mode 5. Build (in your AI chat) /opsx:apply 6. Archive (in your AI chat) /opsx:archive ``` Steps 1 and 2 happen in your terminal. The rest happen in your AI assistant's chat. That split is the one thing worth memorizing, and [How Commands Work](/docs/how-commands-work) explains exactly why. Step 3 is optional, but starting with `/opsx:explore` when you're unsure is the habit most worth forming. ## Where else to get help [#where-else-to-get-help] * **Discord:** [discord.gg/YctCnvvshC](https://discord.gg/YctCnvvshC) for questions, ideas, and help. * **GitHub Issues:** [github.com/Fission-AI/OpenSpec/issues](https://github.com/Fission-AI/OpenSpec/issues) for bugs and feature requests. * **`openspec feedback "your message"`** sends feedback straight from your terminal (it opens a GitHub issue). Found something in these docs that's wrong, stale, or confusing? That's a bug. Open an issue or a PR. Documentation improvements are some of the most valuable contributions you can make. # Installation (/docs/installation) ## Prerequisites [#prerequisites] * **Node.js 20.19.0 or higher** — Check your version: `node --version` ## Package Managers [#package-managers] ### npm [#npm] ```bash npm install -g @fission-ai/openspec@latest ``` ### pnpm [#pnpm] ```bash pnpm add -g @fission-ai/openspec@latest ``` ### yarn [#yarn] ```bash yarn global add @fission-ai/openspec@latest ``` ### bun [#bun] Bun can install OpenSpec globally, but OpenSpec currently runs on Node.js. You still need Node.js 20.19.0 or higher available on `PATH`. ```bash bun add -g @fission-ai/openspec@latest ``` ## Nix [#nix] Run OpenSpec directly without installation: ```bash nix run github:Fission-AI/OpenSpec -- init ``` Or install to your profile: ```bash nix profile install github:Fission-AI/OpenSpec ``` Or add to your development environment in `flake.nix`: ```nix { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; openspec.url = "github:Fission-AI/OpenSpec"; }; outputs = { nixpkgs, openspec, ... }: { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { buildInputs = [ openspec.packages.x86_64-linux.default ]; }; }; } ``` ## Verify Installation [#verify-installation] ```bash openspec --version ``` ## Updating [#updating] Upgrade the package, then refresh each project's generated files: ```bash npm install -g @fission-ai/openspec@latest # or pnpm/yarn/bun equivalent openspec update # run inside each project ``` `openspec update` regenerates the skill and command files for the tools you've configured, so your slash commands stay current with the installed version. ## Uninstalling [#uninstalling] There's no `openspec uninstall` command, because OpenSpec is just a global package plus some files in your project. Removing it is a few manual steps, and nothing here touches your source code. **1. Remove the global package:** ```bash npm uninstall -g @fission-ai/openspec # or: pnpm rm -g / yarn global remove / bun rm -g ``` **2. Remove OpenSpec from a project (optional).** Delete the `openspec/` directory if you no longer want its specs and changes: ```bash rm -rf openspec/ ``` Think before you do this: `openspec/specs/` and `openspec/changes/archive/` are your record of how the system behaves and why it changed. If you might want that history, keep the folder (or keep it in git) even after uninstalling. **3. Remove generated AI tool files (optional).** OpenSpec writes skill and command files into per-tool directories like `.claude/skills/openspec-*/`, `.cursor/commands/opsx-*`, and so on. Delete the `openspec-*` skills and `opsx-*` commands for whichever tools you configured. The exact paths per tool are listed in [Supported Tools](/docs/reference/supported-tools). If you also have OpenSpec marker blocks in files like `CLAUDE.md` or `AGENTS.md`, remove those blocks by hand; your own content in those files is yours to keep. ## Next Steps [#next-steps] After installing, initialize OpenSpec in your project: ```bash cd your-project openspec init ``` See [Getting Started](/docs/getting-started) for a full walkthrough. # Migrating to OPSX (/docs/migration-guide) This guide helps you transition from the legacy OpenSpec workflow to OPSX. The migration is designed to be smooth—your existing work is preserved, and the new system offers more flexibility. ## What's Changing? [#whats-changing] OPSX replaces the old phase-locked workflow with a fluid, action-based approach. Here's the key shift: | Aspect | Legacy | OPSX | | ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | | **Commands** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` | Default: `/opsx:propose`, `/opsx:apply`, `/opsx:sync`, `/opsx:archive` (expanded workflow commands optional) | | **Workflow** | Create all artifacts at once | Create incrementally or all at once—your choice | | **Going back** | Awkward phase gates | Natural—update any artifact anytime | | **Customization** | Fixed structure | Schema-driven, fully hackable | | **Configuration** | `CLAUDE.md` with markers + `project.md` | Clean config in `openspec/config.yaml` | **The philosophy change:** Work isn't linear. OPSX stops pretending it is. *** ## Before You Begin [#before-you-begin] ### Your Existing Work Is Safe [#your-existing-work-is-safe] The migration process is designed with preservation in mind: * **Active changes in `openspec/changes/`** — Completely preserved. You can continue them with OPSX commands. * **Archived changes** — Untouched. Your history remains intact. * **Main specs in `openspec/specs/`** — Untouched. These are your source of truth. * **Your content in CLAUDE.md, AGENTS.md, etc.** — Preserved. Only the OpenSpec marker blocks are removed; everything you wrote stays. ### What Gets Removed [#what-gets-removed] Only OpenSpec-managed files that are being replaced: | What | Why | | -------------------------------------------------- | --------------------------------- | | Legacy slash command directories/files | Replaced by the new skills system | | `openspec/AGENTS.md` | Obsolete workflow trigger | | OpenSpec markers in `CLAUDE.md`, `AGENTS.md`, etc. | No longer needed | **Legacy command locations by tool** (examples—your tool may vary): * Claude Code: `.claude/commands/openspec/` * Cursor: `.cursor/commands/openspec-*.md` * Windsurf: `.windsurf/workflows/openspec-*.md` * Cline: `.clinerules/workflows/openspec-*.md` * Roo: `.roo/commands/openspec-*.md` * GitHub Copilot: `.github/prompts/openspec-*.prompt.md` (IDE extensions only; not supported in Copilot CLI) * Codex: OpenSpec now uses `.codex/skills/openspec-*`; legacy cleanup only targets OpenSpec's allowlisted prompt filenames in `$CODEX_HOME/prompts` or `~/.codex/prompts`, and only removes them after replacement skills exist. * And others (Augment, Continue, Amazon Q, etc.) The migration detects whichever tools you have configured and cleans up their legacy files. The removal list may seem long, but these are all files that OpenSpec originally created. Your own content is never deleted. ### What Needs Your Attention [#what-needs-your-attention] One file requires manual migration: **`openspec/project.md`** — This file isn't deleted automatically because it may contain project context you've written. You'll need to: 1. Review its contents 2. Move useful context to `openspec/config.yaml` (see guidance below) 3. Delete the file when ready **Why we made this change:** The old `project.md` was passive—agents might read it, might not, might forget what they read. We found reliability was inconsistent. The new `config.yaml` context is **actively injected into every OpenSpec planning request**. This means your project conventions, tech stack, and rules are always present when the AI is creating artifacts. Higher reliability. **The tradeoff:** Because context is injected into every request, you'll want to be concise. Focus on what really matters: * Tech stack and key conventions * Non-obvious constraints the AI needs to know * Rules that frequently got ignored before Don't worry about getting it perfect. We're still learning what works best here, and we'll be improving how context injection works as we experiment. *** ## Running the Migration [#running-the-migration] Both `openspec init` and `openspec update` detect legacy files and guide you through the same cleanup process. Use whichever fits your situation: * New installs default to profile `core` (`propose`, `explore`, `apply`, `sync`, `archive`). * Migrated installs preserve your previously installed workflows by writing a `custom` profile when needed. ### Using `openspec init` [#using-openspec-init] Run this if you want to add new tools or reconfigure which tools are set up: ```bash openspec init ``` The init command detects legacy files and guides you through cleanup: ``` Upgrading to the new OpenSpec OpenSpec now uses agent skills, the emerging standard across coding agents. This simplifies your setup while keeping everything working as before. Files to remove No user content to preserve: • .claude/commands/openspec/ • openspec/AGENTS.md Files to update OpenSpec markers will be removed, your content preserved: • CLAUDE.md • AGENTS.md Needs your attention • openspec/project.md We won't delete this file. It may contain useful project context. The new openspec/config.yaml has a "context:" section for planning context. This is included in every OpenSpec request and works more reliably than the old project.md approach. Review project.md, move any useful content to config.yaml's context section, then delete the file when ready. ? Upgrade and clean up legacy files? (Y/n) ``` **What happens when you say yes:** 1. Legacy slash command directories are removed 2. OpenSpec markers are stripped from `CLAUDE.md`, `AGENTS.md`, etc. (your content stays) 3. `openspec/AGENTS.md` is deleted 4. New skills are installed in `.claude/skills/` 5. `openspec/config.yaml` is created with a default schema ### Using `openspec update` [#using-openspec-update] Run this if you just want to migrate and refresh your existing tools to the latest version: ```bash openspec update ``` The update command also detects and cleans up legacy artifacts, then refreshes generated skills/commands to match your current profile and delivery settings. ### Non-Interactive / CI Environments [#non-interactive--ci-environments] For scripted migrations: ```bash openspec init --force --tools claude ``` The `--force` flag skips prompts and auto-accepts cleanup. This includes cleanup of OpenSpec-managed Codex prompt files in the global Codex prompt directory. Cleanup only targets OpenSpec's allowlisted legacy Codex prompt filenames, removes them only after replacement `.codex/skills/openspec-*` skills exist, and preserves all other files. *** ## Migrating project.md to config.yaml [#migrating-projectmd-to-configyaml] The old `openspec/project.md` was a freeform markdown file for project context. The new `openspec/config.yaml` is structured and—critically—**injected into every planning request** so your conventions are always present when the AI works. ### Before (project.md) [#before-projectmd] ```markdown # Project Context This is a TypeScript monorepo using React and Node.js. We use Jest for testing and follow strict ESLint rules. Our API is RESTful and documented in docs/api.md. ## Conventions - All public APIs must maintain backwards compatibility - New features should include tests - Use Given/When/Then format for specifications ``` ### After (config.yaml) [#after-configyaml] ```yaml schema: spec-driven context: | Tech stack: TypeScript, React, Node.js Testing: Jest with React Testing Library API: RESTful, documented in docs/api.md We maintain backwards compatibility for all public APIs rules: proposal: - Include rollback plan for risky changes specs: - Use Given/When/Then format for scenarios - Reference existing patterns before inventing new ones design: - Include sequence diagrams for complex flows ``` ### Key Differences [#key-differences] | project.md | config.yaml | | ---------------------- | ------------------------------------------------------------------------- | | Freeform markdown | Structured YAML | | One blob of text | Separate context and per-artifact rules | | Unclear when it's used | Context appears in ALL artifacts; rules appear in matching artifacts only | | No schema selection | Explicit `schema:` field sets default workflow | ### What to Keep, What to Drop [#what-to-keep-what-to-drop] When migrating, be selective. Ask yourself: "Does the AI need this for *every* planning request?" **Good candidates for `context:`** * Tech stack (languages, frameworks, databases) * Key architectural patterns (monorepo, microservices, etc.) * Non-obvious constraints ("we can't use library X because...") * Critical conventions that often get ignored **Move to `rules:` instead** * Artifact-specific formatting ("use Given/When/Then in specs") * Review criteria ("proposals must include rollback plans") * These only appear for the matching artifact, keeping other requests lighter **Leave out entirely** * General best practices the AI already knows * Verbose explanations that could be summarized * Historical context that doesn't affect current work ### Migration Steps [#migration-steps] 1. **Create config.yaml** (if not already created by init): ```yaml schema: spec-driven ``` 2. **Add your context** (be concise—this goes into every request): ```yaml context: | Your project background goes here. Focus on what the AI genuinely needs to know. ``` 3. **Add per-artifact rules** (optional): ```yaml rules: proposal: - Your proposal-specific guidance specs: - Your spec-writing rules ``` 4. **Delete project.md** once you've moved everything useful. **Don't overthink it.** Start with the essentials and iterate. If you notice the AI missing something important, add it. If context feels bloated, trim it. This is a living document. ### Need Help? Use This Prompt [#need-help-use-this-prompt] If you're unsure how to distill your project.md, ask your AI assistant: ``` I'm migrating from OpenSpec's old project.md to the new config.yaml format. Here's my current project.md: [paste your project.md content] Please help me create a config.yaml with: 1. A concise `context:` section (this gets injected into every planning request, so keep it tight—focus on tech stack, key constraints, and conventions that often get ignored) 2. `rules:` for specific artifacts if any content is artifact-specific (e.g., "use Given/When/Then" belongs in specs rules, not global context) Leave out anything generic that AI models already know. Be ruthless about brevity. ``` The AI will help you identify what's essential vs. what can be trimmed. *** ## The New Commands [#the-new-commands] Command availability is profile-dependent: **Default (`core` profile):** | Command | Purpose | | --------------- | ----------------------------------------------------------- | | `/opsx:propose` | Create a change and generate planning artifacts in one step | | `/opsx:explore` | Think through ideas with no structure | | `/opsx:apply` | Implement tasks from tasks.md | | `/opsx:archive` | Finalize and archive the change | **Expanded workflow (custom selection):** | Command | Purpose | | -------------------- | ---------------------------------------------- | | `/opsx:new` | Start a new change scaffold | | `/opsx:continue` | Create the next artifact (one at a time) | | `/opsx:ff` | Fast-forward—create planning artifacts at once | | `/opsx:verify` | Validate implementation matches specs | | `/opsx:sync` | Merge delta specs into main specs | | `/opsx:bulk-archive` | Archive multiple changes at once | | `/opsx:onboard` | Guided end-to-end onboarding workflow | Enable expanded commands with `openspec config profile`, then run `openspec update`. ### Command Mapping from Legacy [#command-mapping-from-legacy] | Legacy | OPSX Equivalent | | -------------------- | ------------------------------------------------------------------- | | `/openspec:proposal` | `/opsx:propose` (default) or `/opsx:new` then `/opsx:ff` (expanded) | | `/openspec:apply` | `/opsx:apply` | | `/openspec:archive` | `/opsx:archive` | ### New Capabilities [#new-capabilities] These capabilities are part of the expanded workflow command set. **Granular artifact creation:** ``` /opsx:continue ``` Creates one artifact at a time based on dependencies. Use this when you want to review each step. **Exploration mode:** ``` /opsx:explore ``` Think through ideas with a partner before committing to a change. *** ## Understanding the New Architecture [#understanding-the-new-architecture] ### From Phase-Locked to Fluid [#from-phase-locked-to-fluid] The legacy workflow forced linear progression: ``` ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ PLANNING │ ───► │ IMPLEMENTING │ ───► │ ARCHIVING │ │ PHASE │ │ PHASE │ │ PHASE │ └──────────────┘ └──────────────┘ └──────────────┘ If you're in implementation and realize the design is wrong? Too bad. Phase gates don't let you go back easily. ``` OPSX uses actions, not phases: ``` ┌───────────────────────────────────────────────┐ │ ACTIONS (not phases) │ │ │ │ new ◄──► continue ◄──► apply ◄──► archive │ │ │ │ │ │ │ │ └──────────┴───────────┴─────────────┘ │ │ any order │ └───────────────────────────────────────────────┘ ``` ### Dependency Graph [#dependency-graph] Artifacts form a directed graph. Dependencies are enablers, not gates: ``` proposal (root node) │ ┌─────────────┴─────────────┐ │ │ ▼ ▼ specs design (requires: (requires: proposal) proposal) │ │ └─────────────┬─────────────┘ │ ▼ tasks (requires: specs, design) ``` When you run `/opsx:continue`, it checks what's ready and offers the next artifact. You can also create multiple ready artifacts in any order. ### Skills vs Commands [#skills-vs-commands] The legacy system used tool-specific command files: ``` .claude/commands/openspec/ ├── proposal.md ├── apply.md └── archive.md ``` OPSX uses the emerging **skills** standard: ``` .claude/skills/ ├── openspec-explore/SKILL.md ├── openspec-new-change/SKILL.md ├── openspec-continue-change/SKILL.md ├── openspec-apply-change/SKILL.md └── ... ``` Skills are recognized across multiple AI coding tools and provide richer metadata. Codex is skills-only in OPSX. OpenSpec no longer generates Codex custom prompt files; use the generated `.codex/skills/openspec-*` directories instead. *** ## Continuing Existing Changes [#continuing-existing-changes] Your in-progress changes work seamlessly with OPSX commands. **Have an active change from the legacy workflow?** ``` /opsx:apply add-my-feature ``` OPSX reads the existing artifacts and continues from where you left off. **Want to add more artifacts to an existing change?** ``` /opsx:continue add-my-feature ``` Shows what's ready to create based on what already exists. **Need to see status?** ```bash openspec status --change add-my-feature ``` *** ## The New Config System [#the-new-config-system] ### config.yaml Structure [#configyaml-structure] ```yaml # Required: Default schema for new changes schema: spec-driven # Optional: Project context (max 50KB) # Injected into ALL artifact instructions context: | Your project background, tech stack, conventions, and constraints. # Optional: Per-artifact rules # Only injected into matching artifacts rules: proposal: - Include rollback plan specs: - Use Given/When/Then format design: - Document fallback strategies tasks: - Break into 2-hour maximum chunks ``` ### Schema Resolution [#schema-resolution] When determining which schema to use, OPSX checks in order: 1. **CLI flag**: `--schema ` (highest priority) 2. **Change metadata**: `.openspec.yaml` in the change directory 3. **Project config**: `openspec/config.yaml` 4. **Default**: `spec-driven` ### Available Schemas [#available-schemas] | Schema | Artifacts | Best For | | ------------- | --------------------------------- | ------------- | | `spec-driven` | proposal → specs → design → tasks | Most projects | List all available schemas: ```bash openspec schemas ``` ### Custom Schemas [#custom-schemas] Create your own workflow: ```bash openspec schema init my-workflow ``` Or fork an existing one: ```bash openspec schema fork spec-driven my-workflow ``` See [Customization](/docs/customization) for details. *** ## Troubleshooting [#troubleshooting] ### "Legacy files detected in non-interactive mode" [#legacy-files-detected-in-non-interactive-mode] You're running in a CI or non-interactive environment. Use: ```bash openspec init --force ``` ### Commands not appearing after migration [#commands-not-appearing-after-migration] Restart your IDE. Skills are detected at startup. ### "Unknown artifact ID in rules" [#unknown-artifact-id-in-rules] Check that your `rules:` keys match your schema's artifact IDs: * **spec-driven**: `proposal`, `specs`, `design`, `tasks` Run this to see valid artifact IDs: ```bash openspec schemas --json ``` ### Config not being applied [#config-not-being-applied] 1. Ensure the file is at `openspec/config.yaml` (not `.yml`) 2. Validate YAML syntax 3. Config changes take effect immediately—no restart needed ### project.md not migrated [#projectmd-not-migrated] The system intentionally preserves `project.md` because it may contain your custom content. Review it manually, move useful parts to `config.yaml`, then delete it. ### Want to see what would be cleaned up? [#want-to-see-what-would-be-cleaned-up] Run init and decline the cleanup prompt—you'll see the full detection summary without any changes being made. *** ## Quick Reference [#quick-reference] ### Files After Migration [#files-after-migration] ``` project/ ├── openspec/ │ ├── specs/ # Unchanged │ ├── changes/ # Unchanged │ │ └── archive/ # Unchanged │ └── config.yaml # NEW: Project configuration ├── .claude/ │ └── skills/ # NEW: OPSX skills │ ├── openspec-propose/ # default core profile │ ├── openspec-explore/ │ ├── openspec-apply-change/ │ ├── openspec-sync-specs/ │ └── ... # expanded profile adds new/continue/ff/etc. ├── CLAUDE.md # OpenSpec markers removed, your content preserved └── AGENTS.md # OpenSpec markers removed, your content preserved ``` ### What's Gone [#whats-gone] * `.claude/commands/openspec/` — replaced by `.claude/skills/` * `openspec/AGENTS.md` — obsolete * `openspec/project.md` — migrate to `config.yaml`, then delete * OpenSpec marker blocks in `CLAUDE.md`, `AGENTS.md`, etc. ### Command Cheatsheet [#command-cheatsheet] ```text /opsx:propose Start quickly (default core profile) /opsx:apply Implement tasks /opsx:archive Finish and archive # Expanded workflow (if enabled): /opsx:new Scaffold a change /opsx:continue Create next artifact /opsx:ff Create planning artifacts ``` *** ## Getting Help [#getting-help] * **Discord**: [discord.gg/YctCnvvshC](https://discord.gg/YctCnvvshC) * **GitHub Issues**: [github.com/Fission-AI/OpenSpec/issues](https://github.com/Fission-AI/OpenSpec/issues) * **Documentation**: [docs/opsx.md](/docs/opsx) for the full OPSX reference # Multi-Language Guide (/docs/multi-language) Configure OpenSpec to generate artifacts in languages other than English. ## Quick Setup [#quick-setup] Add a language instruction to your `openspec/config.yaml`: ```yaml schema: spec-driven context: | Language: Portuguese (pt-BR) All artifacts must be written in Brazilian Portuguese. # Your other project context below... Tech stack: TypeScript, React, Node.js ``` That's it. All generated artifacts will now be in Portuguese. ## Language Examples [#language-examples] ### Portuguese (Brazil) [#portuguese-brazil] ```yaml context: | Language: Portuguese (pt-BR) All artifacts must be written in Brazilian Portuguese. ``` ### Spanish [#spanish] ```yaml context: | Idioma: Español Todos los artefactos deben escribirse en español. ``` ### Chinese (Simplified) [#chinese-simplified] ```yaml context: | 语言:中文(简体) 所有产出物必须用简体中文撰写。 ``` ### Japanese [#japanese] ```yaml context: | 言語:日本語 すべての成果物は日本語で作成してください。 ``` ### French [#french] ```yaml context: | Langue : Français Tous les artefacts doivent être rédigés en français. ``` ### German [#german] ```yaml context: | Sprache: Deutsch Alle Artefakte müssen auf Deutsch verfasst werden. ``` ## Tips [#tips] ### Handle Technical Terms [#handle-technical-terms] Decide how to handle technical terminology: ```yaml context: | Language: Japanese Write in Japanese, but: - Keep technical terms like "API", "REST", "GraphQL" in English - Code examples and file paths remain in English ``` ### Combine with Other Context [#combine-with-other-context] Language settings work alongside your other project context: ```yaml schema: spec-driven context: | Language: Portuguese (pt-BR) All artifacts must be written in Brazilian Portuguese. Tech stack: TypeScript, React 18, Node.js 20 Database: PostgreSQL with Prisma ORM ``` ## Verification [#verification] To verify your language config is working: ```bash # Check the instructions - should show your language context openspec instructions proposal --change my-change # Output will include your language context ``` ## Related Documentation [#related-documentation] * [Customization Guide](/docs/customization) - Project configuration options * [Workflows Guide](/docs/the-workflow) - Full workflow documentation # OPSX Workflow (/docs/opsx) > Feedback welcome on [Discord](https://discord.gg/YctCnvvshC). ## What Is It? [#what-is-it] OPSX is now the standard workflow for OpenSpec. It's a **fluid, iterative workflow** for OpenSpec changes. No more rigid phases — just actions you can take anytime. ## Why This Exists [#why-this-exists] The legacy OpenSpec workflow works, but it's **locked down**: * **Instructions are hardcoded** — buried in TypeScript, you can't change them * **All-or-nothing** — one big command creates everything, can't test individual pieces * **Fixed structure** — same workflow for everyone, no customization * **Black box** — when AI output is bad, you can't tweak the prompts **OPSX opens it up.** Now anyone can: 1. **Experiment with instructions** — edit a template, see if the AI does better 2. **Test granularly** — validate each artifact's instructions independently 3. **Customize workflows** — define your own artifacts and dependencies 4. **Iterate quickly** — change a template, test immediately, no rebuild ``` Legacy workflow: OPSX: ┌────────────────────────┐ ┌────────────────────────┐ │ Hardcoded in package │ │ schema.yaml │◄── You edit this │ (can't change) │ │ templates/*.md │◄── Or this │ ↓ │ │ ↓ │ │ Wait for new release │ │ Instant effect │ │ ↓ │ │ ↓ │ │ Hope it's better │ │ Test it yourself │ └────────────────────────┘ └────────────────────────┘ ``` **This is for everyone:** * **Teams** — create workflows that match how you actually work * **Power users** — tweak prompts to get better AI outputs for your codebase * **OpenSpec contributors** — experiment with new approaches without releases We're all still learning what works best. OPSX lets us learn together. ## The User Experience [#the-user-experience] **The problem with linear workflows:** You're "in planning phase", then "in implementation phase", then "done". But real work doesn't work that way. You implement something, realize your design was wrong, need to update specs, continue implementing. Linear phases fight against how work actually happens. **OPSX approach:** * **Actions, not phases** — create, implement, update, archive — do any of them anytime * **Dependencies are enablers** — they show what's possible, not what's required next ``` proposal ──→ specs ──→ design ──→ tasks ──→ implement ``` ## Setup [#setup] ```bash # Make sure you have openspec installed — skills are automatically generated openspec init ``` This creates skills in `.claude/skills/` (or equivalent) that AI coding assistants auto-detect. By default, OpenSpec uses the `core` workflow profile (`propose`, `explore`, `apply`, `sync`, `archive`). If you want the expanded workflow commands (`new`, `continue`, `ff`, `verify`, `bulk-archive`, `onboard`), configure them with `openspec config profile` and apply with `openspec update`. During setup, you'll be prompted to create a **project config** (`openspec/config.yaml`). This is optional but recommended. ## Project Configuration [#project-configuration] Project config lets you set defaults and inject project-specific context into all artifacts. ### Creating Config [#creating-config] Config is created during `openspec init`, or manually: ```yaml # openspec/config.yaml schema: spec-driven context: | Tech stack: TypeScript, React, Node.js API conventions: RESTful, JSON responses Testing: Vitest for unit tests, Playwright for e2e Style: ESLint with Prettier, strict TypeScript rules: proposal: - Include rollback plan - Identify affected teams specs: - Use Given/When/Then format for scenarios design: - Include sequence diagrams for complex flows ``` ### Config Fields [#config-fields] | Field | Type | Description | | --------- | ------ | ------------------------------------------------------- | | `schema` | string | Default schema for new changes (e.g., `spec-driven`) | | `context` | string | Project context injected into all artifact instructions | | `rules` | object | Per-artifact rules, keyed by artifact ID | ### How It Works [#how-it-works] **Schema precedence** (highest to lowest): 1. CLI flag (`--schema `) 2. Change metadata (`.openspec.yaml` in change directory) 3. Project config (`openspec/config.yaml`) 4. Default (`spec-driven`) **Context injection:** * Context is prepended to every artifact's instructions * Wrapped in `...` tags * Helps AI understand your project's conventions **Rules injection:** * Rules are only injected for matching artifacts * Wrapped in `...` tags * Appear after context, before the template ### Artifact IDs by Schema [#artifact-ids-by-schema] **spec-driven** (default): * `proposal` — Change proposal * `specs` — Specifications * `design` — Technical design * `tasks` — Implementation tasks ### Config Validation [#config-validation] * Unknown artifact IDs in `rules` generate warnings * Schema names are validated against available schemas * Context has a 50KB size limit * Invalid YAML is reported with line numbers ### Troubleshooting [#troubleshooting] **"Unknown artifact ID in rules: X"** * Check artifact IDs match your schema (see list above) * Run `openspec schemas --json` to see artifact IDs for each schema **Config not being applied:** * Ensure file is at `openspec/config.yaml` (not `.yml`) * Check YAML syntax with a validator * Config changes take effect immediately (no restart needed) **Context too large:** * Context is limited to 50KB * Summarize or link to external docs instead ## Commands [#commands] | Command | What it does | | -------------------- | -------------------------------------------------------------------------------- | | `/opsx:propose` | Create a change and generate planning artifacts in one step (default quick path) | | `/opsx:explore` | Think through ideas, investigate problems, clarify requirements | | `/opsx:new` | Start a new change scaffold (expanded workflow) | | `/opsx:continue` | Create the next artifact (expanded workflow) | | `/opsx:ff` | Fast-forward planning artifacts (expanded workflow) | | `/opsx:apply` | Implement tasks, updating artifacts as needed | | `/opsx:update` | Revise a change's planning artifacts and keep them coherent | | `/opsx:verify` | Validate implementation against artifacts (expanded workflow) | | `/opsx:sync` | Sync delta specs to main (default workflow, optional) | | `/opsx:archive` | Archive when done | | `/opsx:bulk-archive` | Archive multiple completed changes (expanded workflow) | | `/opsx:onboard` | Guided walkthrough of an end-to-end change (expanded workflow) | ## Usage [#usage] ### Explore an idea [#explore-an-idea] ``` /opsx:explore ``` Think through ideas, investigate problems, compare options. No structure required - just a thinking partner. When insights crystallize, transition to `/opsx:propose` (default) or `/opsx:new`/`/opsx:ff` (expanded). ### Start a new change [#start-a-new-change] ``` /opsx:propose ``` Creates the change and generates planning artifacts needed before implementation. If you've enabled expanded workflows, you can instead use: ```text /opsx:new # scaffold only /opsx:continue # create one artifact at a time /opsx:ff # create all planning artifacts at once ``` ### Create artifacts [#create-artifacts] ``` /opsx:continue ``` Shows what's ready to create based on dependencies, then creates one artifact. Use repeatedly to build up your change incrementally. ``` /opsx:ff add-dark-mode ``` Creates all planning artifacts at once. Use when you have a clear picture of what you're building. ### Implement (the fluid part) [#implement-the-fluid-part] ``` /opsx:apply ``` Works through tasks, checking them off as you go. If you're juggling multiple changes, you can run `/opsx:apply `; otherwise it should infer from the conversation and prompt you to choose if it can't tell. ### Updating a change [#updating-a-change] ``` /opsx:update add-dark-mode - we're storing the theme in a cookie now ``` Revises the change's existing planning artifacts and keeps them coherent - in any direction (a design edit may ripple back to the proposal). Planning artifacts only: it never edits code, and it never creates missing artifacts (that's `/opsx:continue`). Every edit is confirmed with you first. If the change was already implemented, it recommends `/opsx:apply` so the code catches up with the revised plan. If your revision changes the change's *intent*, start fresh instead - see [When to Update vs. Start Fresh](#when-to-update-vs-start-fresh). ### Finish up [#finish-up] ``` /opsx:archive # Move to archive when done (prompts to sync specs if needed) ``` ## When to Update vs. Start Fresh [#when-to-update-vs-start-fresh] You can always edit your proposal or specs before implementation. But when does refining become "this is different work"? ### What a Proposal Captures [#what-a-proposal-captures] A proposal defines three things: 1. **Intent** — What problem are you solving? 2. **Scope** — What's in/out of bounds? 3. **Approach** — How will you solve it? The question is: which changed, and by how much? ### Update the Existing Change When: [#update-the-existing-change-when] **Same intent, refined execution** * You discover edge cases you didn't consider * The approach needs tweaking but the goal is unchanged * Implementation reveals the design was slightly off **Scope narrows** * You realize full scope is too big, want to ship MVP first * "Add dark mode" → "Add dark mode toggle (system preference in v2)" **Learning-driven corrections** * Codebase isn't structured how you thought * A dependency doesn't work as expected * "Use CSS variables" → "Use Tailwind's dark: prefix instead" ### Start a New Change When: [#start-a-new-change-when] **Intent fundamentally changed** * The problem itself is different now * "Add dark mode" → "Add comprehensive theme system with custom colors, fonts, spacing" **Scope exploded** * Change grew so much it's essentially different work * Original proposal would be unrecognizable after updates * "Fix login bug" → "Rewrite auth system" **Original is completable** * The original change can be marked "done" * New work stands alone, not a refinement * Complete "Add dark mode MVP" → Archive → New change "Enhance dark mode" ### The Heuristics [#the-heuristics] ``` ┌─────────────────────────────────────┐ │ Is this the same work? │ └──────────────┬──────────────────────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ Same intent? >50% overlap? Can original Same problem? Same scope? be "done" without │ │ these changes? │ │ │ ┌────────┴────────┐ ┌──────┴──────┐ ┌───────┴───────┐ │ │ │ │ │ │ YES NO YES NO NO YES │ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ ▼ UPDATE NEW UPDATE NEW UPDATE NEW ``` | Test | Update | New Change | | ----------------- | --------------------------------- | ------------------------------------------ | | **Identity** | "Same thing, refined" | "Different work" | | **Scope overlap** | >50% overlaps | \<50% overlaps | | **Completion** | Can't be "done" without changes | Can finish original, new work stands alone | | **Story** | Update chain tells coherent story | Patches would confuse more than clarify | ### The Principle [#the-principle] > **Update preserves context. New change provides clarity.** > > Choose update when the history of your thinking is valuable. > Choose new when starting fresh would be clearer than patching. Think of it like git branches: * Keep committing while working on the same feature * Start a new branch when it's genuinely new work * Sometimes merge a partial feature and start fresh for phase 2 ## What's Different? [#whats-different] | | Legacy (`/openspec:proposal`) | OPSX (`/opsx:*`) | | ----------------- | ----------------------------------------- | ----------------------------------------- | | **Structure** | One big proposal document | Discrete artifacts with dependencies | | **Workflow** | Linear phases: plan → implement → archive | Fluid actions — do anything anytime | | **Iteration** | Awkward to go back | Update artifacts as you learn | | **Customization** | Fixed structure | Schema-driven (define your own artifacts) | **The key insight:** work isn't linear. OPSX stops pretending it is. ## Architecture Deep Dive [#architecture-deep-dive] This section explains how OPSX works under the hood and how it compares to the legacy workflow. Examples in this section use the expanded command set (`new`, `continue`, etc.); default `core` users can map the same flow to `propose → apply → sync → archive`. ### Philosophy: Phases vs Actions [#philosophy-phases-vs-actions] ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ LEGACY WORKFLOW │ │ (Phase-Locked, All-or-Nothing) │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ PLANNING │ ───► │ IMPLEMENTING │ ───► │ ARCHIVING │ │ │ │ PHASE │ │ PHASE │ │ PHASE │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ /openspec:proposal /openspec:apply /openspec:archive │ │ │ │ • Creates ALL artifacts at once │ │ • Can't go back to update specs during implementation │ │ • Phase gates enforce linear progression │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────────┐ │ OPSX WORKFLOW │ │ (Fluid Actions, Iterative) │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ ACTIONS (not phases) │ │ │ │ │ │ │ │ new ◄──► continue ◄──► apply ◄──► archive │ │ │ │ │ │ │ │ │ │ │ │ └──────────┴───────────┴───────────┘ │ │ │ │ any order │ │ │ └────────────────────────────────────────────┘ │ │ │ │ • Create artifacts one at a time OR fast-forward │ │ • Update specs/design/tasks during implementation │ │ • Dependencies enable progress, phases don't exist │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ### Component Architecture [#component-architecture] **Legacy workflow** uses hardcoded templates in TypeScript: ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ LEGACY WORKFLOW COMPONENTS │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ Hardcoded Templates (TypeScript strings) │ │ │ │ │ ▼ │ │ Tool-specific configurators/adapters │ │ │ │ │ ▼ │ │ Generated Command Files (.claude/commands/openspec/*.md) │ │ │ │ • Fixed structure, no artifact awareness │ │ • Change requires code modification + rebuild │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` **OPSX** uses external schemas and a dependency graph engine: ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ OPSX COMPONENTS │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ Schema Definitions (YAML) │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ name: spec-driven │ │ │ │ artifacts: │ │ │ │ - id: proposal │ │ │ │ generates: proposal.md │ │ │ │ requires: [] ◄── Dependencies │ │ │ │ - id: specs │ │ │ │ generates: specs/**/*.md ◄── Glob patterns │ │ │ │ requires: [proposal] ◄── Enables after proposal │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ Artifact Graph Engine │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ • Topological sort (dependency ordering) │ │ │ │ • State detection (filesystem existence) │ │ │ │ • Rich instruction generation (templates + context) │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ Skill Files (.claude/skills/openspec-*/SKILL.md) │ │ │ │ • Cross-editor compatible (Claude Code, Cursor, Windsurf) │ │ • Skills query CLI for structured data │ │ • Fully customizable via schema files │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ### Dependency Graph Model [#dependency-graph-model] Artifacts form a directed acyclic graph (DAG). Dependencies are **enablers**, not gates: ``` proposal (root node) │ ┌─────────────┴─────────────┐ │ │ ▼ ▼ specs design (requires: (requires: proposal) proposal) │ │ └─────────────┬─────────────┘ │ ▼ tasks (requires: specs, design) │ ▼ ┌──────────────┐ │ APPLY PHASE │ │ (requires: │ │ tasks) │ └──────────────┘ ``` **State transitions:** ``` BLOCKED ────────────────► READY ────────────────► DONE │ │ │ Missing All deps File exists dependencies are DONE on filesystem ``` ### Information Flow [#information-flow] **Legacy workflow** — agent receives static instructions: ``` User: "/openspec:proposal" │ ▼ ┌─────────────────────────────────────────┐ │ Static instructions: │ │ • Create proposal.md │ │ • Create tasks.md │ │ • Create design.md │ │ • Create specs//spec.md │ │ │ │ No awareness of what exists or │ │ dependencies between artifacts │ └─────────────────────────────────────────┘ │ ▼ Agent creates ALL artifacts in one go ``` **OPSX** — agent queries for rich context: ``` User: "/opsx:continue" │ ▼ ┌──────────────────────────────────────────────────────────────────────────┐ │ Step 1: Query current state │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ $ openspec status --change "add-auth" --json │ │ │ │ │ │ │ │ { │ │ │ │ "artifacts": [ │ │ │ │ {"id": "proposal", "status": "done"}, │ │ │ │ {"id": "specs", "status": "ready"}, ◄── First ready │ │ │ │ {"id": "design", "status": "ready"}, │ │ │ │ {"id": "tasks", "status": "blocked", "missingDeps": ["specs"]}│ │ │ │ ] │ │ │ │ } │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ Step 2: Get rich instructions for ready artifact │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ $ openspec instructions specs --change "add-auth" --json │ │ │ │ │ │ │ │ { │ │ │ │ "template": "# Specification\n\n## ADDED Requirements...", │ │ │ │ "dependencies": [{"id": "proposal", "path": "...", "done": true}│ │ │ │ "unlocks": ["tasks"] │ │ │ │ } │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ Step 3: Read dependencies → Create ONE artifact → Show what's unlocked │ └──────────────────────────────────────────────────────────────────────────┘ ``` ### Iteration Model [#iteration-model] **Legacy workflow** — awkward to iterate: ``` ┌─────────┐ ┌─────────┐ ┌─────────┐ │/proposal│ ──► │ /apply │ ──► │/archive │ └─────────┘ └─────────┘ └─────────┘ │ │ │ ├── "Wait, the design is wrong" │ │ │ ├── Options: │ │ • Edit files manually (breaks context) │ │ • Abandon and start over │ │ • Push through and fix later │ │ │ └── No official "go back" mechanism │ └── Creates ALL artifacts at once ``` **OPSX** — natural iteration: ``` /opsx:new ───► /opsx:continue ───► /opsx:apply ───► /opsx:archive │ │ │ │ │ ├── "The design is wrong" │ │ │ │ │ ▼ │ │ Just edit design.md │ │ and continue! │ │ │ │ │ ▼ │ │ /opsx:apply picks up │ │ where you left off │ │ │ └── Creates ONE artifact, shows what's unlocked │ └── Scaffolds change, waits for direction ``` ### Custom Schemas [#custom-schemas] Create custom workflows using the schema management commands: ```bash # Create a new schema from scratch (interactive) openspec schema init my-workflow # Or fork an existing schema as a starting point openspec schema fork spec-driven my-workflow # Validate your schema structure openspec schema validate my-workflow # See where a schema resolves from (useful for debugging) openspec schema which my-workflow ``` Schemas are stored in `openspec/schemas/` (project-local, version controlled) or `~/.local/share/openspec/schemas/` (user global). **Schema structure:** ``` openspec/schemas/research-first/ ├── schema.yaml └── templates/ ├── research.md ├── proposal.md └── tasks.md ``` **Example schema.yaml:** ```yaml name: research-first artifacts: - id: research # Added before proposal generates: research.md requires: [] - id: proposal generates: proposal.md requires: [research] # Now depends on research - id: tasks generates: tasks.md requires: [proposal] ``` **Dependency Graph:** ``` research ──► proposal ──► tasks ``` ### Summary [#summary] | Aspect | Legacy | OPSX | | ------------------ | ----------------------------------- | ------------------------- | | **Templates** | Hardcoded TypeScript | External YAML + Markdown | | **Dependencies** | None (all at once) | DAG with topological sort | | **State** | Phase-based mental model | Filesystem existence | | **Customization** | Edit source, rebuild | Create schema.yaml | | **Iteration** | Phase-locked | Fluid, edit anything | | **Editor Support** | Tool-specific configurator/adapters | Single skills directory | ## Schemas [#schemas] Schemas define what artifacts exist and their dependencies. Currently available: * **spec-driven** (default): proposal → specs → design → tasks ```bash # List available schemas openspec schemas # See all schemas with their resolution sources openspec schema which --all # Create a new schema interactively openspec schema init my-workflow # Fork an existing schema for customization openspec schema fork spec-driven my-workflow # Validate schema structure before use openspec schema validate my-workflow ``` ## Tips [#tips] * Use `/opsx:explore` to think through an idea before committing to a change * `/opsx:ff` when you know what you want, `/opsx:continue` when exploring * During `/opsx:apply`, if something's wrong — fix the artifact, then continue * Tasks track progress via checkboxes in `tasks.md` * Check status anytime: `openspec status --change "name"` ## Feedback [#feedback] This is rough. That's intentional — we're learning what works. Found a bug? Have ideas? Join us on [Discord](https://discord.gg/YctCnvvshC) or open an issue on [GitHub](https://github.com/Fission-AI/openspec/issues). # Core Concepts at a Glance (/docs/overview) **OpenSpec is a lightweight agreement layer between you and your AI.** You write down what a change should do, the AI drafts the details, you both look at the same plan, and only then does code get written. This page is the whole mental model on one screen. When you want the long version, [Concepts](/docs/core-concepts) has it. Here's the entire idea in five words: **agree first, then build confidently.** ## The five ideas [#the-five-ideas] Everything in OpenSpec is built from five concepts. Learn these and the rest is detail. **1. Specs are the truth.** A spec describes how your system behaves *right now*. It lives in `openspec/specs/`, organized by domain (`auth/`, `payments/`, `ui/`). Specs are made of requirements ("the system SHALL expire sessions after 30 minutes") and scenarios (concrete given/when/then examples). Think of specs as the single agreed-upon answer to "what does this software do?" **2. A change is one unit of work.** When you want to add, modify, or remove behavior, you create a change: a folder in `openspec/changes/` holding everything about that work in one place. A proposal, a design, a task list, and the spec edits. One change, one folder, one feature. **3. Delta specs describe what's changing, not the whole world.** Inside a change, you don't rewrite the entire spec. You write a small delta: `ADDED` this requirement, `MODIFIED` that one, `REMOVED` this other one. This is the trick that makes OpenSpec good at editing existing systems, not just green-field ones. You describe the diff, not the destination. **4. Artifacts build on each other.** A change contains a few documents, created in a natural order, each feeding the next: ```text proposal ──► specs ──► design ──► tasks ──► implement why what how steps do it ``` You can revisit any of them at any time. They're enablers, not gates. (More on that below.) **5. Archiving folds the change back into the truth.** When the work is done, you archive the change. Its delta specs merge into your main specs, and the change folder moves to `changes/archive/` with a date stamp. Now your specs describe the new reality, and you're ready for the next change. The cycle closes. ## The picture [#the-picture] ```text ┌─────────────────────────────────────────────────────────────────┐ │ openspec/ │ │ │ │ ┌──────────────────┐ ┌──────────────────────────┐ │ │ │ specs/ │ │ changes/ │ │ │ │ │ ◄───── │ │ │ │ │ source of truth │ merge │ one folder per change │ │ │ │ how things work │ on │ proposal · design · │ │ │ │ today │ archive │ tasks · delta specs │ │ │ └──────────────────┘ └──────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` Two folders. `specs/` is what's true. `changes/` is what you're proposing. Archiving moves a proposal into truth. ## The loop you'll actually run [#the-loop-youll-actually-run] In the default setup, your day looks like this. Optionally think it through first; then one command drafts the plan, you read it, the next builds it, and the last files it away. ```text /opsx:explore → (optional) think it through with the AI first /opsx:propose add-dark-mode → AI drafts proposal, specs, design, tasks (you read and adjust the plan) /opsx:apply → AI builds it, checking off tasks /opsx:archive → specs updated, change archived ``` **When in doubt, start by exploring.** `/opsx:explore` is a no-stakes thinking partner: it reads your code, lays out options, and turns a fuzzy idea into a concrete plan before any artifact exists. It's the best antidote to an AI that will otherwise build *something* from a vague prompt. Already know exactly what you want? Skip straight to `/opsx:propose`. Either way, explore ships in the default profile, so it's always there. See the [Explore guide](/docs/explore). Those are slash commands, typed in your AI assistant's chat. Setup (`openspec init`) happens in your terminal. If that split is new to you, read [How Commands Work](/docs/how-commands-work) first; it's the most common point of confusion. ## "Enablers, not gates" [#enablers-not-gates] This phrase shows up everywhere in OpenSpec, so here's what it means in plain terms. Old-school spec processes are waterfalls: finish planning, *then* you're allowed to implement, and going back is painful. OpenSpec refuses that. The order `proposal → specs → design → tasks` shows what becomes *possible* next, not what you're *forced* to do next. Discover during implementation that the design was wrong? Edit `design.md` and keep going. Realize the scope should shrink? Update the proposal. Nothing locks. The dependencies exist only so the AI has the context it needs (you can't write good tasks without specs to base them on), not to box you in. The strength here is honesty: real work is messy and iterative, and OpenSpec lets it be. The tradeoff is discipline: because nothing forces you forward, it's on you to keep a change focused rather than letting it sprawl. The [Workflows](/docs/the-workflow) guide has good habits for that. ## Why this is worth the small overhead [#why-this-is-worth-the-small-overhead] Plain truth: OpenSpec adds a step. You write a short plan before building. So what do you get for it? * **You catch wrong turns before they cost you.** Fixing a misunderstanding in a one-paragraph proposal is free. Fixing it after the AI wrote 400 lines is not. * **The plan and the code stay in the same repo.** Six months later, the spec tells you (and the next AI session) why the system works the way it does. * **Changes are reviewable.** A change folder is a tidy package: read the proposal, skim the deltas, check the tasks. No archaeology through chat history. * **It fits existing codebases.** Deltas mean you can specify a change to a 50,000-line app without first documenting the whole thing. And the honest tradeoff: for a truly trivial one-line fix, the ceremony may not pay off, and that's fine. OpenSpec is designed to be lightweight, but it isn't free. Use it where agreement matters, which turns out to be most of the time once you're working with an AI that will confidently build whatever you vaguely asked for. ## Where to go next [#where-to-go-next] * New here? [Getting Started](/docs/getting-started) walks the first change in full. * Not sure what to build yet? [Explore First](/docs/explore) is the place to start. * Confused about where commands run? [How Commands Work](/docs/how-commands-work). * Want the deep version of everything above? [Concepts](/docs/core-concepts). * Learn by example? [Examples & Recipes](/docs/examples). * Need a term defined? [Glossary](/docs/glossary). # Reviewing a Change (/docs/reviewing-changes) OpenSpec's whole promise is that you and your AI **agree on what to build before any code is written.** That agreement only means something if you actually read what the AI drafted. This page is about the two minutes where you do that — what to open, in what order, and what to look for. The bet is simple: catching a wrong turn in a one-paragraph plan is nearly free. Catching the same wrong turn in 300 lines of code is not. Review is where you collect on that bet. ## The two moments you review [#the-two-moments-you-review] There are exactly two: ``` /opsx:propose ──► REVIEW THE PLAN ──► /opsx:apply ──► REVIEW THE CODE ──► /opsx:archive (before any code) (/opsx:verify) ``` 1. **After `/opsx:propose`** (or `/opsx:ff`), before `/opsx:apply` — read the plan while it's still just words. 2. **After building**, with `/opsx:verify` — check that the code actually did what the plan said. The first review is the one that saves you the most, and the one people skip. This page spends most of its time there. ## Read it in this order [#read-it-in-this-order] A change is a folder of plain Markdown in `openspec/changes//`. Read the files in the order that lets you quit earliest if something's wrong: ``` openspec/changes/add-dark-mode/ ├── proposal.md 1. the intent and scope ← if this is wrong, stop here ├── specs/…/spec.md 2. the requirements ← the heart of the review ├── design.md (only for bigger changes) — the technical approach └── tasks.md 3. the plan of work ``` You don't need to read every line. You need to answer three questions, one per file. ## The proposal: is this the right problem? [#the-proposal-is-this-the-right-problem] Open `proposal.md` first. It captures the "why" and "what" — the intent, the scope, the approach in a paragraph or two. **What good looks like:** one clear intent, a scope you recognize, and a reason this is worth doing now. **Red flags:** * It solves a slightly *different* problem than the one you asked for. * The scope has grown — you asked for a theme toggle and the proposal also touches auth "while we're in there." * It's vague. "Improve the settings page" is not a scope; "add a dark-mode toggle that respects the OS preference" is. **The question to answer:** *Does this match what I actually asked for, and is anything sneaking in?* If the answer is no, stop — don't read further, fix the proposal (see [Pushing back](#pushing-back-is-cheap)). ## The spec deltas: is "done" defined correctly? [#the-spec-deltas-is-done-defined-correctly] This is the heart of the review. The delta specs under `specs/` say what will be *true* when the change ships — as requirements and the scenarios that prove them: ```markdown ## ADDED Requirements ### Requirement: Dark Mode Toggle The system SHALL let a user switch between light and dark themes. #### Scenario: Respects the OS preference on first load - GIVEN a user who has never set a theme - WHEN they open the app on a device set to dark mode - THEN the app renders in dark mode ``` **What a good requirement looks like:** one clear `SHALL`/`MUST` statement you could hand to a tester, and at least one scenario whose GIVEN/WHEN/THEN actually exercises that statement. **Red flags:** * **A vague requirement.** "The system SHALL be fast" can't be built or tested. What's fast? * **A requirement with no scenario**, or a scenario that doesn't test the requirement it sits under. * **The most valuable catch of all: what's missing.** The AI faithfully writes down what you *said*. Your job is to notice what you *forgot* to say. If you cared most about the OS-preference case and no scenario mentions it, that's the review paying for itself. Read the deltas asking *would I be happy if the system did exactly — and only — this?* Nothing here is about code yet, so it stays cheap to change. ## The tasks: is the plan of work sane? [#the-tasks-is-the-plan-of-work-sane] Open `tasks.md` last. It's the implementation checklist the AI will work through. **What good looks like:** ordered steps, each traceable to a requirement, nothing mysterious. **Red flags:** * A task with no matching requirement (where did that come from?). * One giant "implement the feature" task that hides all the real decisions. * A task that touches something outside the scope you just approved. You're not estimating or micromanaging here — you're checking that the plan matches the requirements you already accepted. ## Pushing back is cheap [#pushing-back-is-cheap] If any of the three questions came back wrong, say so. There are no phases and nothing is locked — you fix it and move on. Two ways, exactly as in [Editing a change](/docs/editing-changes): * **Edit the file yourself.** It's plain Markdown; change the scope line, tighten a requirement, delete a task. * **Tell the AI what's wrong** and let it revise: *"drop the auth changes — out of scope,"* *"add a scenario for when the user has already picked a theme,"* *"split task 3 into schema and UI."* Then re-read the part you changed. Re-draft until it's a plan you'd sign your name to. That back-and-forth *is* the product working. ## After the code: verify [#after-the-code-verify] Once the work is built, `/opsx:verify` is your second review. It re-reads the artifacts and the code and reports mismatches across three dimensions: | Dimension | What it checks | | ---------------- | ----------------------------------------------------------------- | | **Completeness** | Every task done, every requirement implemented, scenarios covered | | **Correctness** | The implementation matches the spec's intent, edge cases handled | | **Coherence** | Design decisions actually show up in the code | ``` You: /opsx:verify AI: Verifying add-dark-mode... COMPLETENESS ✓ All 8 tasks in tasks.md are checked ✓ All requirements in specs have corresponding code ⚠ Scenario "Respects the OS preference on first load" has no test coverage ``` It flags issues as CRITICAL, WARNING, or SUGGESTION, and it does **not** block archiving — it surfaces the gaps and leaves the call to you. This is the difference between "did the AI write code" and "did it build what we agreed." `/opsx:verify` is in the expanded profile. If you don't have it, turn it on with `openspec config profile` (then `openspec update`), or just re-read the change and the diff yourself. ## Right-size the review [#right-size-the-review] Not every change earns the full pass. A one-file typo fix deserves a twenty-second skim. A change that touches auth, payments, or data you can't recover deserves every question above. The point was never ceremony — it's spending your attention where a mistake would be expensive, and skimming where it wouldn't. ## The two-minute checklist [#the-two-minute-checklist] * [ ] The proposal's intent matches what I asked for. * [ ] Nothing extra has crept into the scope. * [ ] Every requirement is specific enough to test. * [ ] Every requirement has a scenario that actually exercises it. * [ ] The case I care about most is covered. * [ ] Tasks map to requirements; nothing is mysterious or out of scope. * [ ] I'd be comfortable if the AI built exactly this and nothing more. If all seven pass, run `/opsx:apply` with confidence. If any fail, that's not a setback — it's the two minutes doing its job. ## Where to go next [#where-to-go-next] * [Writing Good Specs](/docs/writing-specs) — the flip side: how to draft requirements and scenarios worth approving. * [Editing & Iterating on a Change](/docs/editing-changes) — the mechanics of changing a plan after you've started. * [Workflows](/docs/the-workflow) — where review fits in the larger loop. # Stores: Plan in Its Own Repo (/docs/stores) > **Beta.** Stores, references, working context, and worksets are > new. Command names, flags, file formats, and JSON output may still change > shape between releases. Every walkthrough below was run against the > current build, but re-read this guide after upgrading. ## The problem this solves [#the-problem-this-solves] OpenSpec normally lives inside one code repo: an `openspec/` folder next to your code, holding specs and changes for that repo. That stops fitting the moment your planning is bigger than one repo: * Your work spans several repos — one feature touches the API server, the web app, and a shared library. Whose `openspec/` folder does the plan live in? * Your team plans before code exists, or plans things that never become code in *this* repo. * Requirements are owned by one team and consumed by others. The wiki version drifts, and your coding agent can't read it anyway. A **store** is the answer: a standalone repo whose whole job is planning. It has the same `openspec/` shape you already know — specs and changes — plus a small identity file. You register it on your machine once, by name, and then every normal OpenSpec command can work in it from anywhere. ## The shape [#the-shape] ``` team-plans (a store: planning in its own repo) ├── .openspec-store/store.yaml identity: "I am team-plans" └── openspec/ ├── specs/ what is true └── changes/ what is in motion ▲ │ registered on each machine by name; │ shared by pushing/cloning like any repo ┌─────────────┼─────────────┐ │ │ │ web-app api-server mobile-app (code repo) (code repo) (code repo) ``` Two rules keep this simple: 1. **A store is just a git repo.** You commit, push, pull, and review it yourself. OpenSpec never clones, syncs, or pushes anything on its own. 2. **Declarations, not machinery.** Repos can *declare* how they relate to stores (shown below). Declarations change what OpenSpec can tell you — never where your commands act. ## Five minutes to your first store [#five-minutes-to-your-first-store] Two commands take you from nothing to a working, store-scoped change: ```bash openspec store setup team-plans --path ~/openspec/team-plans ``` ``` Store ready: team-plans Location: /Users/you/openspec/team-plans OpenSpec root: ready Registry: registered Next: run normal OpenSpec commands against this store, for example: openspec new change --store team-plans Share this store by committing and pushing it like any Git repo. ``` ```bash openspec new change add-login --store team-plans ``` ``` Using OpenSpec root: team-plans (/Users/you/openspec/team-plans) Created change 'add-login' at /Users/you/openspec/team-plans/openspec/changes/add-login/ Schema: spec-driven Next: openspec status --change add-login --store team-plans ``` That's the whole model. From here the lifecycle is exactly what you know — `status`, `instructions`, `validate`, `archive` — with `--store team-plans` on each command, and every printed hint carries the flag for you. The `Using OpenSpec root:` line always tells you where a command is acting. ## Story: one team, one planning repo [#story-one-team-one-planning-repo] A team keeps its specs and changes in `team-plans` instead of scattering them across code repos. **Day one (whoever sets it up):** ```bash openspec store setup team-plans --path ~/openspec/team-plans \ --remote git@github.com:acme/team-plans.git git -C ~/openspec/team-plans push -u origin main ``` Passing `--remote` records the clone URL inside the store's own identity file (`.openspec-store/store.yaml`), in the initial commit. Every future clone is born knowing where it came from, so health checks and error messages can print a complete, pasteable fix for teammates who don't have it yet. **Every teammate (once per machine):** ```bash git clone git@github.com:acme/team-plans.git ~/openspec/team-plans openspec store register ~/openspec/team-plans ``` From then on, everyone works in the same planning repo by name: ```bash openspec status --store team-plans --change add-login openspec show add-login --store team-plans ``` **Sharing work is git, on purpose.** A change you create exists only in your checkout until you commit and push it — same as code. Plans get branches, pull requests, and review for free, because a store is an ordinary repo. **Connecting the team's code repos.** A code repo whose planning is fully externalized needs exactly one line, in `openspec/config.yaml`: ```yaml # web-app/openspec/config.yaml store: team-plans ``` Now every OpenSpec command run inside `web-app` acts on `team-plans` with no flags at all: ```bash cd ~/src/web-app openspec status --change add-login ``` ``` Using OpenSpec root: team-plans (/Users/you/openspec/team-plans) ... ``` The pointer is a fallback, never an override: an explicit `--store` always wins, and if the repo grows real planning folders of its own, those win (with a warning to remove the stale pointer). **One default for every repo on your machine.** If you work across many code repos that all plan into the same store, set it once, globally, instead of adding the `store:` line to each repo: ```bash openspec config set defaultStore team-plans ``` Now any command run outside a planning root — and with no `--store` and no project pointer — resolves to `team-plans`. It sits at the bottom of the precedence list, so `--store`, a local root, and a project `store:` pointer all still win. The root banner and JSON `root` block report `source: "global_default"` with the store id, so you can always tell a machine-wide default from a repo's own pointer. Clear it with `openspec config unset defaultStore`. If the id is not registered, commands error and tell you to register it or clear the stale default. ## Story: requirements that cross team lines [#story-requirements-that-cross-team-lines] A platform team owns the requirements. Product teams build against them, in their own repos, with their own designs. A reference describes that relationship without moving anyone's work. ``` platform-reqs (store) api-server (code repo) owned by the platform team owned by a product team ┌──────────────────────────┐ ┌──────────────────────────┐ │ openspec/specs/ │ ◀────────│ openspec/config.yaml │ │ payments/spec.md │ reads │ references: │ │ auth/spec.md │ │ - platform-reqs │ │ │ │ openspec/specs/ │ │ openspec/changes/ │ │ (their own designs) │ │ platform work │ │ openspec/changes/ │ │ │ │ (their own work) │ │ │ └──────────────────────────┘ └──────────────────────────┘ ``` **The product team declares what it draws on** in its repo's `openspec/config.yaml`: ```yaml references: - platform-reqs ``` References are read-only context. The repo keeps its own `openspec/` root; work stays there. What changes: `openspec instructions` in that repo now includes an index of the referenced store's specs — each with a one-line summary and the exact fetch command (`openspec show --type spec --store platform-reqs`). An agent working in `api-server` can find the upstream payment requirements, cite them, and write its low-level design in the repo's own root — without anyone pasting context around. A reference can carry its clone source, so teammates who don't have the store yet get a complete fix instead of a dead end: ```yaml references: - { id: platform-reqs, remote: "git@github.com:acme/platform-reqs.git" } ``` **When you want the plan and code open together, make a workset.** This is personal and explicit: each person chooses the folders they actually work with on their machine. Nothing about those local checkout paths is committed to the shared planning repo. ```bash openspec workset create platform \ --member ~/openspec/platform-reqs \ --member ~/src/api-server \ --member ~/src/web-app ``` ## Two questions you can always ask [#two-questions-you-can-always-ask] **"Is my setup healthy?"** — `openspec doctor` checks the current root and its referenced stores, read-only, with a pasteable fix per finding: ``` Doctor Root Location: /Users/you/src/api-server OpenSpec root: ok References - platform-reqs: ok (/Users/you/openspec/platform-reqs) - design-system: Referenced store 'design-system' is not registered on this machine. Fix: git clone -- git@github.com:acme/design-system.git '/Users/you/openspec/design-system' && openspec store register '/Users/you/openspec/design-system' --id design-system ``` **"What am I working with?"** — `openspec context` assembles the working set from OpenSpec declarations: the root and the stores it references. ``` Working context for api-server (/Users/you/src/api-server) OpenSpec root api-server /Users/you/src/api-server Referenced stores platform-reqs /Users/you/openspec/platform-reqs Fetch: openspec show --type spec --store platform-reqs ``` Both support `--json` for agents. `openspec context --code-workspace ` additionally writes a VS Code workspace file containing the whole set — the only write this command performs. ## Worksets: reopen the folders you work on together [#worksets-reopen-the-folders-you-work-on-together] Separate from all of the above: most people open the same few folders together every session — the planning repo plus two or three code repos. A **workset** is a personal, named view of exactly that, reopened with one command in your tool of choice. ``` workset "platform" openspec workset open platform ├── team-plans ~/openspec/team-plans │ ├── api-server ~/src/api-server ▼ └── web-app ~/src/web-app all three open in your tool ``` ```bash openspec workset create platform \ --member ~/openspec/team-plans --member ~/src/api-server \ --tool code openspec workset list ``` ``` platform (opens in VS Code) team-plans /Users/you/openspec/team-plans api-server /Users/you/src/api-server ``` `openspec workset open platform` then launches the saved tool: editors (VS Code, Cursor) open one window with every member and return. The first member is the primary. Override the tool any time with `--tool `. Worksets are deliberately *not* shared state. They live on your machine, are never committed, and make no claims about the work — they only record what you like open together. Removing one never touches the member folders. New tools are configuration, not code: anything launched via a workspace file or per-folder attach flags can be added under the `openers` key in the global config (`openspec config edit`). ## How commands decide where to act [#how-commands-decide-where-to-act] Every normal command resolves its root the same way, in this order: ``` 1. --store you said so explicitly → that store 2. nearest openspec/ a real planning root here → this repo (walking up from cwd) 3. store: pointer config.yaml declares a store → that store 4. defaultStore global config sets a machine → that store default 5. none of the above stores registered on this → error with a machine? selection hint no stores registered? → the current directory (classic behavior) ``` The `Using OpenSpec root:` line (and the `root` block in `--json` output) tells you which case you're in. ## Known limitations [#known-limitations] * **Beta shape.** Everything on this page may change between releases — names, flags, file formats, JSON keys. * **One checkout per store id per machine.** Registering a second checkout under the same id fails with a hint to `store unregister` first. * **No sync, ever — by design.** OpenSpec never clones, pulls, or pushes. A stale checkout shows stale specs until *you* pull; references are indexed live from whatever is on disk. * **Empty planning folders can be absent.** A new store may not have `openspec/changes/`, `openspec/specs/`, or `openspec/changes/archive/` in Git yet. That is accepted during the beta; those folders appear once normal commands create files for them. * **Pointer repos stay pointers.** A config-only repo whose `openspec/config.yaml` declares `store: ` is treated as externalized planning, not as a store checkout to register. Remove the `store:` line first if you intentionally want to convert that repo into a local store root. * **Some commands stay where they are.** `view`, `templates`, `schemas`, and the deprecated noun forms (`openspec change show`, ...) act on the current directory only — no `--store`. * **Per-machine state is per-machine.** The store registry and worksets are local settings. Nothing about your machine's layout is ever committed to shared planning. * **Two launch styles for worksets.** A tool that can't be launched with a workspace file or per-folder attach flags can't be added as an opener. * **Agent JSON has a known casing split** (store-family keys are snake\_case, workflow-family camelCase). Documented in the [agent contract](/docs/reference/agents); unifying it is deferred to a versioned release. ## Where things live [#where-things-live] | What | Where | Shared? | | ------------------ | ------------------------------------------ | ------------------------------ | | A store's planning | `/openspec/` (specs, changes) | Yes — commit and push it | | A store's identity | `/.openspec-store/store.yaml` | Yes — committed with the store | | The store registry | `/openspec/stores/registry.yaml` | No — this machine only | | Worksets | `/openspec/worksets/` | No — this machine only | `` is `~/.local/share/openspec` on macOS and Linux (or `$XDG_DATA_HOME/openspec` when set), and `%LOCALAPPDATA%\openspec` on Windows. ## Reference [#reference] Exact flags and JSON shapes for every command on this page: [CLI reference](/docs/reference/cli) (Stores, Doctor, Working context, Personal worksets) and the [agent contract](/docs/reference/agents). # OpenSpec on a Team (/docs/team-workflow) Everything in the other guides works the same whether you're solo or on a team of twenty. What changes on a team is the questions around the edges: where do the specs live, how do teammates review a plan, and how does any of this fit the pull-request flow we already have? The short answer: a change is just files, and OpenSpec never touches git. So it fits your existing workflow instead of replacing it. This page spells out the conventions that work well. ## One rule: OpenSpec doesn't touch git [#one-rule-openspec-doesnt-touch-git] OpenSpec reads and writes plain Markdown under `openspec/`. It never commits, branches, pushes, or pulls in your project — and it never clones or syncs a [store](/docs/stores) on its own. That means: * **You commit `openspec/` like any source.** Specs, active changes, and the archive are part of your project's history. (Yes, commit the whole folder — see the [FAQ](/docs/faq#should-i-commit-the-openspec-folder-to-git).) * **A change is a folder you version like code.** `openspec/changes/add-dark-mode/` is just files on a branch. * **Everything below is convention, not enforcement.** OpenSpec won't make you do it this way; it just fits cleanly. ## The everyday loop [#the-everyday-loop] The workflow that works well maps a change onto a branch and a pull request: ``` git switch -c add-dark-mode start a branch, as usual │ /opsx:propose add-dark-mode draft the plan (proposal + specs + tasks) │ REVIEW THE PLAN you read it before any code — see Reviewing a Change │ /opsx:apply build it; artifacts + code change together │ git commit && open a PR the PR contains the spec delta AND the code │ teammate reviews, merges │ /opsx:archive fold the delta into specs/, move the change to archive/ ``` The plan and the code live side by side in the same branch, so your teammates review both together, and six months later the archived spec still explains why the code looks the way it does. ## Reviewing specs in a pull request [#reviewing-specs-in-a-pull-request] This is where a team feels the payoff. When a PR includes the change's delta spec, the reviewer gets something a raw diff never gives them: **a plain-language statement of what this change is supposed to do**, before they read a single line of code. A good review order for the reviewer: 1. **Read `proposal.md`** — is this the right problem and scope? 2. **Read the delta under `specs/`** — is "done" defined correctly? (This is the [Reviewing a Change](/docs/reviewing-changes) two-minute pass, now happening in the PR.) 3. **Then read the code diff** — does it deliver exactly those requirements? A reviewer who disagrees with the *approach* can say so against the proposal, cheaply, instead of relitigating it across 300 lines of code. Put the delta spec near the top of the PR description, or point reviewers at the change folder, so they start there. ## When to archive [#when-to-archive] Archiving folds a change's deltas into your main `openspec/specs/` and moves the change folder to `openspec/changes/archive/YYYY-MM-DD-/`. Because `specs/` is the **shared source of truth**, the timing matters on a team. Two workable conventions: * **Archive after the PR merges (recommended).** The branch carries the active change; once it's merged to your main branch, archive there (often a tiny follow-up commit or a scheduled cleanup). This keeps the shared `specs/` moving forward only with work that actually shipped. * **Archive inside the PR.** Simpler for small teams: the same PR that adds the code also syncs and archives. The tradeoff is that your `specs/` diff and your code diff land together, which can make the PR noisier. Pick one and be consistent. Either way, `/opsx:archive` checks that tasks are complete and offers to sync first, so nothing merges half-finished by accident. ## Two people, parallel changes [#two-people-parallel-changes] Because changes are separate folders, they don't collide: * **Different changes, different people — no problem.** `add-dark-mode` and `rate-limit-login` are different folders on different branches; they never touch each other until they both archive. * **One change, one owner.** Two people editing the same change folder conflict exactly like two people editing the same file. Keep a change to a single author, or split it into two changes (another reason to [right-size](/docs/writing-specs#right-size-the-change)). * **The one place conflicts show up is `specs/`.** If two changes both modify the *same* requirement, archiving the second one will conflict in `openspec/specs/…/spec.md` — resolve it like any merge conflict, keeping the requirement that reflects reality. This is rare, and it's a feature: it's git telling you two changes disagreed about how the system should behave. ## When planning outgrows one repo [#when-planning-outgrows-one-repo] Everything above assumes the plan lives in the code repo's own `openspec/` folder, which is the right default. When your planning genuinely spans several repos or teams — one feature touching three services, or requirements one team owns and others consume — that's what the beta **stores** feature is for: planning gets its own repo that any code repo can point at. Start with the [Stores User Guide](/docs/stores). ## Where to go next [#where-to-go-next] * [Reviewing a Change](/docs/reviewing-changes) — the review pass, now inside your PR. * [Writing Good Specs](/docs/writing-specs) — including how to right-size a change so it fits one branch. * [Stores User Guide](/docs/stores) — planning that spans repos and teams. # Workflows (/docs/the-workflow) This guide covers common workflow patterns for OpenSpec and when to use each one. For basic setup, see [Getting Started](/docs/getting-started). For command reference, see [Commands](/docs/reference/slash-commands). ## Philosophy: Actions, Not Phases [#philosophy-actions-not-phases] Traditional workflows force you through phases: planning, then implementation, then done. But real work doesn't fit neatly into boxes. OPSX takes a different approach: ```text Traditional (phase-locked): PLANNING ────────► IMPLEMENTING ────────► DONE │ │ │ "Can't go back" │ └────────────────────┘ OPSX (fluid actions): proposal ──► specs ──► design ──► tasks ──► implement ``` **Key principles:** * **Actions, not phases** - Commands are things you can do, not stages you're stuck in * **Dependencies are enablers** - They show what's possible, not what's required next > **Customization:** OPSX workflows are driven by schemas that define artifact sequences. See [Customization](/docs/customization) for details on creating custom schemas. ## Two Modes [#two-modes] ### Default Quick Path (`core` profile) [#default-quick-path-core-profile] New installs default to `core`, which provides: * `/opsx:explore` * `/opsx:propose` * `/opsx:apply` * `/opsx:sync` * `/opsx:archive` Typical flow: ```text /opsx:explore ──► /opsx:propose ──► /opsx:apply ──► /opsx:sync ──► /opsx:archive (optional) ``` #### Start by exploring (the habit worth forming) [#start-by-exploring-the-habit-worth-forming] `/opsx:explore` is part of the default profile, not an advanced add-on. It's the move to make whenever you have a problem but not yet a plan, which, with an AI assistant, is most of the time. ```text You: /opsx:explore AI: What would you like to explore? You: Our search results feel stale. I'm not sure if it's caching, indexing, or the query itself. AI: Let me look... [reads the search service and cache layer] It's the index: it only rebuilds nightly, so edits don't show up until the next day. Two options: rebuild on write (simple, more load) or a short-TTL cache invalidation (more moving parts, less load). Given your write volume is low, rebuild-on-write is the cleaner fix. Want to scope it? You: Yes. You: /opsx:propose rebuild-search-index-on-write ``` Explore creates no artifacts and writes no code. It's a free, no-stakes conversation that turns a vague worry into a precise change, so the proposal that follows is sharp. Already know exactly what you want? Skip it and go straight to `/opsx:propose`. Full guide: [Explore First](/docs/explore). ### Expanded/Full Workflow (custom selection) [#expandedfull-workflow-custom-selection] If you want explicit scaffold-and-build commands (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:bulk-archive`, `/opsx:onboard`), enable them with: ```bash openspec config profile openspec update ``` ## Workflow Patterns (Expanded Mode) [#workflow-patterns-expanded-mode] ### Quick Feature [#quick-feature] When you know what you want to build and just need to execute: ```text /opsx:new ──► /opsx:ff ──► /opsx:apply ──► /opsx:verify ──► /opsx:archive ``` **Example conversation:** ```text You: /opsx:new add-logout-button AI: Created openspec/changes/add-logout-button/ Ready to create: proposal You: /opsx:ff AI: Creating all planning artifacts... ✓ proposal.md ✓ specs/ ✓ design.md ✓ tasks.md Ready for implementation! You: /opsx:apply AI: Working through tasks... ✓ Added logout button to header ✓ Implemented session clearing ✓ Added confirmation dialog All tasks complete! You: /opsx:archive AI: ✓ Merged specs ✓ Archived change ``` **Best for:** Small to medium features, bug fixes, straightforward changes. ### Exploratory [#exploratory] When requirements are unclear or you need to investigate first: ```text /opsx:explore ──► /opsx:new ──► /opsx:continue ──► ... ──► /opsx:apply ``` **Example conversation:** ```text You: /opsx:explore AI: What would you like to explore? You: I want to improve page load performance but I'm not sure where the bottlenecks are. AI: Let me help investigate... [Analyzes bundle sizes, identifies slow queries, reviews component render patterns] I found three main bottlenecks: 1. Large unoptimized images 2. Synchronous data fetching in ProductList 3. Re-renders from context changes Which would you like to address first? You: Let's tackle the data fetching issue. You: /opsx:new optimize-product-list-fetching AI: Created change. Ready to create: proposal You: /opsx:continue AI: Creating proposal based on our exploration... [Writes proposal incorporating investigation insights] Ready to create: specs, design Which would you like next? You: /opsx:continue AI: Creating specs... ``` **Best for:** Performance optimization, debugging, architectural decisions, unclear requirements. ### Parallel Changes [#parallel-changes] Work on multiple changes at once: ```text Change A: /opsx:new ──► /opsx:ff ──► /opsx:apply (in progress) │ context switch │ Change B: /opsx:new ──► /opsx:ff ──────► /opsx:apply ``` **Example conversation:** ```text You: I'm working on add-dark-mode but got pulled into a bug fix You: /opsx:new fix-login-redirect AI: Created openspec/changes/fix-login-redirect/ You: /opsx:ff AI: ✓ Created planning artifacts You: /opsx:apply AI: Working on fix-login-redirect... [Implements the fix] All tasks complete! You: /opsx:archive AI: ✓ Archived fix-login-redirect You: Let's get back to dark mode You: /opsx:apply add-dark-mode AI: Resuming add-dark-mode... Picking up at task 2.3: Update Header... ``` **Best for:** Parallel work streams, urgent interrupts, team collaboration. When you have multiple completed changes, use `/opsx:bulk-archive`: ```text You: /opsx:bulk-archive AI: Found 3 completed changes: - add-dark-mode (all tasks done) - fix-login-redirect (all tasks done) - update-footer (all tasks done) Checking for spec conflicts... ⚠ add-dark-mode and update-footer both touch specs/ui/ Inspecting codebase to resolve... Both changes are implemented. Will apply in chronological order. Archive all 3 changes? You: Yes AI: ✓ Archived add-dark-mode ✓ Archived fix-login-redirect ✓ Archived update-footer Specs merged in order: add-dark-mode → update-footer ``` Bulk archive detects when multiple changes touch the same specs and resolves conflicts by checking what's actually implemented. ### Completing a Change [#completing-a-change] The recommended completion flow: ```text /opsx:apply ──► /opsx:verify ──► /opsx:archive │ │ validates prompts to sync implementation if needed ``` #### Verify: Check Your Work [#verify-check-your-work] `/opsx:verify` validates implementation against your artifacts across three dimensions: ```text You: /opsx:verify AI: Verifying add-auth... COMPLETENESS ✓ All 12 tasks in tasks.md are checked ✓ All requirements in specs have corresponding code ⚠ Scenario "Session timeout after inactivity" not tested CORRECTNESS ✓ Implementation matches spec intent ✓ Edge cases from scenarios are handled ✓ Error states match spec definitions COHERENCE ✓ Design decisions reflected in code structure ✓ Naming conventions consistent with design.md ⚠ Design mentions "event-driven" but implementation uses polling SUMMARY ───────────────────────────── Critical issues: 0 Warnings: 2 Ready to archive: Yes (with warnings) Recommendations: 1. Add test for session timeout scenario 2. Consider refactoring to event-driven as designed, or update design.md ``` **What verify checks:** | Dimension | What it validates | | ------------ | --------------------------------------------------------------- | | Completeness | All tasks done, all requirements implemented, scenarios covered | | Correctness | Implementation matches spec intent, edge cases handled | | Coherence | Design decisions reflected in code, patterns consistent | Verify won't block archive, but it surfaces issues you might want to address first. #### Archive: Finalize the Change [#archive-finalize-the-change] `/opsx:archive` completes the change and moves it to the archive: ```text You: /opsx:archive AI: Archiving add-auth... Artifact status: ✓ proposal.md exists ✓ specs/ exists ✓ design.md exists ✓ tasks.md exists (12/12 tasks complete) Delta specs: Not yet synced to main → Would you like to sync now? You: Yes AI: ✓ Synced specs to openspec/specs/auth/spec.md ✓ Moved to openspec/changes/archive/2025-01-24-add-auth/ Change archived successfully. ``` Archive will prompt if specs aren't synced. It won't block on incomplete tasks, but it will warn you. ## When to Use What [#when-to-use-what] ### `/opsx:ff` vs `/opsx:continue` [#opsxff-vs-opsxcontinue] | Situation | Use | | ---------------------------------------- | ---------------- | | Clear requirements, ready to build | `/opsx:ff` | | Exploring, want to review each step | `/opsx:continue` | | Want to iterate on proposal before specs | `/opsx:continue` | | Time pressure, need to move fast | `/opsx:ff` | | Complex change, want control | `/opsx:continue` | **Rule of thumb:** If you can describe the full scope upfront, use `/opsx:ff`. If you're figuring it out as you go, use `/opsx:continue`. ### When to Update vs Start Fresh [#when-to-update-vs-start-fresh] A common question: when is updating an existing change okay, and when should you start a new one? **Update the existing change when:** * Same intent, refined execution * Scope narrows (MVP first, rest later) * Learning-driven corrections (codebase isn't what you expected) * Design tweaks based on implementation discoveries **Start a new change when:** * Intent fundamentally changed * Scope exploded to different work entirely * Original change can be marked "done" standalone * Patches would confuse more than clarify ```text ┌─────────────────────────────────────┐ │ Is this the same work? │ └──────────────┬──────────────────────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ Same intent? >50% overlap? Can original Same problem? Same scope? be "done" without │ │ these changes? │ │ │ ┌────────┴────────┐ ┌──────┴──────┐ ┌───────┴───────┐ │ │ │ │ │ │ YES NO YES NO NO YES │ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ ▼ UPDATE NEW UPDATE NEW UPDATE NEW ``` **Example: "Add dark mode"** * "Need to also support custom themes" → New change (scope exploded) * "System preference detection is harder than expected" → Update (same intent) * "Let's ship toggle first, add preferences later" → Update then archive, then new change ## Best Practices [#best-practices] ### Keep Changes Focused [#keep-changes-focused] One logical unit of work per change. If you're doing "add feature X and also refactor Y", consider two separate changes. **Why it matters:** * Easier to review and understand * Cleaner archive history * Can ship independently * Simpler rollback if needed ### Use `/opsx:explore` for Unclear Requirements [#use-opsxexplore-for-unclear-requirements] Before committing to a change, explore the problem space: ```text You: /opsx:explore AI: What would you like to explore? You: How should we handle rate limiting for our API? AI: Let me investigate your current setup and options... [Researches codebase, considers patterns] I see three approaches we could take: 1. Middleware-based (simple, per-endpoint) 2. Redis-backed (scalable, shared state) 3. Token bucket per user (fair, complex) Your current stack suggests #1 or #2. What's your scale? ``` Exploration clarifies thinking before you create artifacts. ### Verify Before Archiving [#verify-before-archiving] Use `/opsx:verify` to check implementation matches artifacts: ```text You: /opsx:verify AI: Verifying add-dark-mode... ✓ All tasks in tasks.md are checked ✓ Requirements in specs have corresponding code ✓ Design decisions are reflected in implementation Ready to archive! ``` Catches mismatches before you close out the change. ### Name Changes Clearly [#name-changes-clearly] Good names make `openspec list` useful: ```text Good: Avoid: add-dark-mode feature-1 fix-login-redirect update optimize-product-query changes implement-2fa wip ``` ## Command Quick Reference [#command-quick-reference] For full command details and options, see [Commands](/docs/reference/slash-commands). | Command | Purpose | When to Use | | -------------------- | ---------------------------------- | ------------------------------------------------------------------------------ | | `/opsx:propose` | Create change + planning artifacts | Fast default path (`core` profile) | | `/opsx:explore` | Think through ideas with the AI | Start here when unsure: unclear requirements, investigation, comparing options | | `/opsx:new` | Start a change scaffold | Expanded mode, explicit artifact control | | `/opsx:continue` | Create next artifact | Expanded mode, step-by-step artifact creation | | `/opsx:ff` | Create all planning artifacts | Expanded mode, clear scope | | `/opsx:apply` | Implement tasks | Ready to write code | | `/opsx:verify` | Validate implementation | Expanded mode, before archiving | | `/opsx:sync` | Merge delta specs | Expanded mode, optional | | `/opsx:archive` | Complete the change | All work finished | | `/opsx:bulk-archive` | Archive multiple changes | Expanded mode, parallel work | ## Next Steps [#next-steps] * [Writing Good Specs](/docs/writing-specs) - What a strong requirement and scenario look like, and how to right-size a change * [Reviewing a Change](/docs/reviewing-changes) - The two-minute pass on a drafted plan before any code * [OpenSpec on a Team](/docs/team-workflow) - How changes fit branches and pull requests * [Commands](/docs/reference/slash-commands) - Full command reference with options * [Concepts](/docs/core-concepts) - Deep dive into specs, artifacts, and schemas * [Customization](/docs/customization) - Create custom workflows # Troubleshooting (/docs/troubleshooting) Concrete fixes for concrete problems. Each entry names a symptom, explains the likely cause in a sentence, and gives you the fix. If you don't see your issue here, the [FAQ](/docs/faq) may help, and the [Discord](https://discord.gg/YctCnvvshC) definitely will. ## Installation and setup [#installation-and-setup] ### `openspec: command not found` [#openspec-command-not-found] The CLI isn't installed, or your shell can't find it. Install it globally and check: ```bash npm install -g @fission-ai/openspec@latest openspec --version ``` If it installed but still isn't found, your global npm bin directory probably isn't on your `PATH`. Run `npm bin -g` to see where global binaries live, and make sure that path is in your shell profile. ### "Requires Node.js 20.19.0 or higher" [#requires-nodejs-20190-or-higher] OpenSpec runs on Node 20.19.0+. Check your version and upgrade if needed: ```bash node --version ``` If you use bun to install OpenSpec, note that OpenSpec still *runs* on Node, so you need Node 20.19.0+ available on your `PATH` regardless. See [Installation](/docs/installation). ### `openspec init` didn't configure my AI tool [#openspec-init-didnt-configure-my-ai-tool] Init asks which tools to set up. If you skipped your tool or want to add another, just run it again, or use the non-interactive form: ```bash openspec init --tools claude,cursor ``` The full list of tool IDs is in [Supported Tools](/docs/reference/supported-tools). Use `--tools all` for everything, `--tools none` to skip tool setup. ## Commands don't show up [#commands-dont-show-up] If `/opsx:propose` (or your tool's equivalent) doesn't appear or doesn't do anything, work down this list. They're ordered fastest-to-check first. 1. **You may be in the wrong place.** Slash commands go in your AI assistant's chat, not your terminal. If you typed `/opsx:propose` into your shell, that's the issue. See [How Commands Work](/docs/how-commands-work). 2. **Regenerate the files.** From your project root: ```bash openspec update ``` This rewrites the skill and command files for every tool you've configured. 3. **Restart your assistant.** Most tools scan for skills and commands at startup. A fresh window often does it. 4. **Confirm the files exist.** For Claude Code, check that `.claude/skills/` contains `openspec-*` folders. Other tools use their own directories, all listed in [Supported Tools](/docs/reference/supported-tools). 5. **Check you initialized this project.** Skills are written per project. If you cloned a repo or switched folders, run `openspec init` (or `openspec update`) there. 6. **Confirm your tool supports command files.** Codex and a few other tools (CodeArts, Kimi CLI, ForgeCode, Mistral Vibe) don't get generated `opsx-*` command files; they use skill-based invocations instead. For Codex, check `.codex/skills/openspec-*`. The forms differ per tool: see [Supported Tools](/docs/reference/supported-tools) and [How Commands Work](/docs/how-commands-work#slash-command-syntax-by-tool). ## Working with changes [#working-with-changes] ### "Change not found" [#change-not-found] The command couldn't tell which change you meant. Name it explicitly, or check what exists: ```bash openspec list # see active changes /opsx:apply add-dark-mode # name the change in chat ``` Also confirm you're in the right project directory. ### "No artifacts ready" [#no-artifacts-ready] Every artifact is either already created or blocked waiting on a dependency. See what's blocking: ```bash openspec status --change ``` Then create the missing dependency first. Remember the order: proposal enables specs and design; specs and design together enable tasks. ### `openspec validate` reports warnings or errors [#openspec-validate-reports-warnings-or-errors] Validation checks your specs and changes for structural problems. Read the message: it names the file and the issue. ```bash openspec validate # validate one item openspec validate --all # validate everything openspec validate --all --strict # stricter checks, good for CI ``` Common causes are a missing required section (like a spec with no scenarios) or a malformed delta header. Fix the file and re-run. The [CLI reference](/docs/reference/cli#openspec-validate) documents the output format. ### The AI created incomplete or wrong artifacts [#the-ai-created-incomplete-or-wrong-artifacts] The AI didn't have enough context. A few levers help: * Add project context in `openspec/config.yaml` so your stack and conventions are injected into every request. See [Customization](/docs/customization#project-configuration). * Add per-artifact `rules:` for guidance that only applies to, say, specs. * Give a more detailed description when you propose. * Use the expanded `/opsx:continue` to create one artifact at a time and review each, instead of `/opsx:ff` doing them all at once. ### Archive won't finish, or warns about incomplete tasks [#archive-wont-finish-or-warns-about-incomplete-tasks] Archive won't *block* on incomplete tasks, but it warns you, because archiving usually means the work is done. If tasks remain on purpose (you're filing a partial change), proceed. Otherwise finish the tasks first. Archive will also offer to sync your delta specs into the main specs if you haven't synced yet; say yes unless you have a reason not to. ## Configuration [#configuration] ### My `config.yaml` isn't being applied [#my-configyaml-isnt-being-applied] Three usual suspects: 1. **Wrong filename.** It must be `openspec/config.yaml`, not `.yml`. 2. **Invalid YAML.** Run it through any YAML validator; the CLI also reports syntax errors with line numbers. 3. **You expected a restart.** You don't need one. Config changes take effect immediately. ### "Unknown artifact ID in rules: X" [#unknown-artifact-id-in-rules-x] A key under `rules:` doesn't match any artifact in your schema. For the default `spec-driven` schema the valid IDs are `proposal`, `specs`, `design`, `tasks`. To see the IDs for any schema: ```bash openspec schemas --json ``` ### "Context too large" [#context-too-large] The `context:` field is capped at 50KB, on purpose, because it's injected into every request. Summarize it, or link out to longer docs instead of pasting them. Lean context also produces better, faster results. ### "Schema not found" [#schema-not-found] The schema name you referenced doesn't exist. List what's available and check spelling: ```bash openspec schemas # list available schemas openspec schema which # see where a schema resolves from openspec schema init # create a custom one ``` See [Customization](/docs/customization#custom-schemas). ## Migration from the legacy workflow [#migration-from-the-legacy-workflow] ### "Legacy files detected in non-interactive mode" [#legacy-files-detected-in-non-interactive-mode] You're in CI or a non-interactive shell, and OpenSpec found old files to clean up but can't prompt you. Approve automatically: ```bash openspec init --force ``` For Codex, OpenSpec may detect old managed prompt files in `$CODEX_HOME/prompts` or `~/.codex/prompts`. That cleanup is limited to OpenSpec's allowlisted legacy Codex prompt filenames, and non-interactive `openspec init` removes only the files whose replacement `.codex/skills/openspec-*` skills exist. Non-interactive `openspec update` leaves all legacy cleanup untouched unless you pass `--force`. ### Commands didn't appear after migrating [#commands-didnt-appear-after-migrating] Restart your IDE. Skills are detected at startup. If they still don't appear, run `openspec update` and check the file locations in [Supported Tools](/docs/reference/supported-tools). ### My old `project.md` wasn't migrated [#my-old-projectmd-wasnt-migrated] That's intentional. OpenSpec never deletes `project.md` automatically because it may hold context you wrote. Move the useful parts into `config.yaml`'s `context:` section, then delete it yourself. The [Migration Guide](/docs/migration-guide#migrating-projectmd-to-configyaml) walks through this, including a prompt you can hand to your AI to do the distilling. ## Still stuck? [#still-stuck] * **Discord:** [discord.gg/YctCnvvshC](https://discord.gg/YctCnvvshC) * **GitHub Issues:** [github.com/Fission-AI/OpenSpec/issues](https://github.com/Fission-AI/OpenSpec/issues) * **From your terminal:** `openspec feedback "what went wrong"` opens an issue for you. When you report a problem, include your OpenSpec version (`openspec --version`), your Node version (`node --version`), your AI tool, and the exact command and output. It makes help much faster. # Writing Good Specs (/docs/writing-specs) You rarely write a spec from a blank page. You describe a change in plain language, `/opsx:propose` drafts the requirements and scenarios, and then you make them good. This page is about that last part — what "good" looks like, and how to steer the AI toward it. It's the companion to [Reviewing a Change](/docs/reviewing-changes): reviewing is catching the weak spots in a draft, writing is knowing what a strong one is made of. ## A spec is behavior, not code [#a-spec-is-behavior-not-code] A spec says what your system *does*, in terms anyone could check — not how it's built. It's made of **requirements** (statements of behavior) and **scenarios** (concrete examples that prove them). ```markdown ### Requirement: Session Timeout The system SHALL expire a session after 30 minutes of inactivity. #### Scenario: Idle timeout - GIVEN an authenticated session - WHEN 30 minutes pass with no activity - THEN the session is invalidated and the user must re-authenticate ``` Keep the *how* — the queue, the library, the table schema — in `design.md` or the code. When behavior and implementation get mixed into one requirement, the requirement stops being testable and starts going stale the moment the code changes. ## What makes a good requirement [#what-makes-a-good-requirement] A good requirement is one behavior, stated so plainly you could hand it to someone else to test. * **One statement, one `SHALL`/`MUST`.** If a requirement has three "and also" clauses, it's really three requirements. Split them. * **Observable.** Someone outside the code should be able to tell whether it holds. "The system SHALL show an error banner when the upload exceeds 10 MB" is observable. "The system SHALL handle large uploads gracefully" is not. * **The right strength.** OpenSpec uses the RFC 2119 keywords, and they mean different things: | Keyword | Meaning | | ---------------- | ------------------------------------------------------------- | | `MUST` / `SHALL` | A hard requirement. Non-negotiable. | | `SHOULD` | A strong recommendation, with room for a justified exception. | | `MAY` | Genuinely optional. | Reach for `MUST`/`SHALL` by default. Use `SHOULD` only when you truly mean "unless there's a good reason not to." The test for a requirement: *could a tester who's never seen the code tell whether it passed?* If not, it needs sharpening. ## What makes a good scenario [#what-makes-a-good-scenario] Scenarios are where a requirement earns its keep. Each one is a concrete GIVEN / WHEN / THEN that could become an automated test. * **It exercises its requirement.** A scenario that just restates the requirement in other words tests nothing. Make it a specific situation with a specific outcome. * **Cover the cases that matter, not just the happy path.** The valid login is easy. The empty input, the expired token, the second click, the thing that goes wrong — those are where bugs live, and where a scenario is worth the most. * **Name the case in the title.** "Scenario: Rejects an expired token" tells a reviewer what's covered at a glance; "Scenario: Test 2" doesn't. A useful habit: before approving, ask *what's the one case I'd be upset to see broken?* — and make sure a scenario names it. ## Pick the right kind of delta [#pick-the-right-kind-of-delta] A change describes its edits to the specs with three section types. Using the right one keeps your archived specs honest: * **`## ADDED Requirements`** — brand-new behavior that didn't exist before. * **`## MODIFIED Requirements`** — behavior that already existed and is changing. Include the full new version; a short note on what changed helps a reviewer. * **`## REMOVED Requirements`** — behavior going away, with a line on why. On archive, ADDED gets appended to the main spec, MODIFIED replaces the old version, and REMOVED is deleted. If you mark a real change as ADDED, you end up with two competing requirements; if you describe new behavior as MODIFIED, there's nothing to replace. When in doubt, open the current spec and see whether the requirement is already there. ## Right-size the change [#right-size-the-change] The single most common authoring mistake isn't a badly worded requirement — it's a change that's trying to be three changes. **A good change has one intent you can say in a sentence.** "Add a dark-mode toggle." "Rate-limit the login endpoint." "Migrate sessions off cookies." If describing the change needs a lot of "and also," that's the signal to split it. Signs a change is too big: * The proposal's scope reads like a list of unrelated features. * Reviewing it would take an afternoon, so nobody will. * Two people couldn't work on it without colliding. * Half the tasks could ship on their own. Smaller changes are easier to review, easier to build in one focused session, and easier to reason about six months later when the archive is all that's left. You can always run several changes in parallel — see [Editing & iterating](/docs/editing-changes) and [Workflows](/docs/the-workflow). The opposite also happens: a one-line typo fix doesn't need three requirements and a design doc. Match the ceremony to the stakes. ## How to steer the AI toward a good draft [#how-to-steer-the-ai-toward-a-good-draft] Because `/opsx:propose` does the first draft, the quality of what you get back tracks the quality of what you give it. You don't have to write requirements by hand — you have to aim the AI well: * **State the intent and the boundary.** *"Add a dark-mode toggle that follows the OS setting on first load — don't touch the existing theme API."* The out-of-scope half matters as much as the in-scope half. * **Name the cases you care about.** *"Make sure there's a scenario for a user who already picked a theme manually."* The AI covers what you point at. * **Then edit.** It's plain Markdown. Tighten a vague `SHALL`, delete a scenario that tests nothing, add the case it missed — or ask the AI to: *"the timeout requirement is vague, pin it to 30 minutes."* Draft, sharpen, repeat. A few rounds of that produces a spec you'd trust, which is the whole point. ## A quick checklist [#a-quick-checklist] * [ ] Each requirement is one observable behavior with a `SHALL`/`MUST`. * [ ] No implementation details are baked into the requirements. * [ ] Every requirement has at least one scenario that actually exercises it. * [ ] The important edge and error cases have scenarios, not just the happy path. * [ ] Deltas use ADDED / MODIFIED / REMOVED correctly against the current spec. * [ ] The whole change has one intent you can state in a sentence. ## Where to go next [#where-to-go-next] * [Reviewing a Change](/docs/reviewing-changes) — the two-minute pass that catches what slipped through. * [Concepts](/docs/core-concepts) — the deeper model behind specs, changes, and deltas. * [Examples & Recipes](/docs/examples) — real changes from start to finish. # OpenSpec Agent Contract (/docs/reference/agents) Machine-readable surfaces of the `openspec` CLI, verified against `src/` (capstone audit, 2026-06-11). Every shape below is documented from the emitting code. ## 1. General conventions [#1-general-conventions] * **One JSON document per invocation.** In `--json` mode, stdout carries exactly one JSON document (2-space pretty-printed). Human prose, spinners, and the store banner go to stderr. * **Store banner.** In human mode, a store-selected root prints `Using OpenSpec root: ()` to stderr. Never printed in JSON mode. * **Key casing is surface-dependent** (see Known inconsistencies): store/doctor/context payloads use `snake_case`; workflow payloads (`status`, `instructions`, `new change`, `validate`, `list`) use `camelCase`, except the embedded `root` object, which always uses `store_id`. * **Optional keys are omitted, not null**, in most payloads (e.g. `root.store_id`, `member.path`). Exceptions that use explicit `null` are called out per shape (store doctor `git.*`, failure payloads). ## 2. The diagnostic envelope [#2-the-diagnostic-envelope] One envelope shape is shared by every machine-readable diagnostic (`StoreDiagnostic`): ```json { "severity": "error" | "warning" | "info", "code": "snake_case_string", "message": "human sentence", "target": "dotted.surface (optional)", "fix": "one actionable sentence/command (optional)" } ``` Diagnostics appear in two positions: **status arrays** (`status: StoreDiagnostic[]` at top level or per entry) for health findings, and **thrown errors** converted to a single-element `status` array on command failure. ## 3. Root selection and `RootOutput` [#3-root-selection-and-rootoutput] All root-resolving commands (`list`, `show`, `validate`, `status`, `instructions`, `instructions apply`, `new change`, `archive`, `doctor`, `context`) resolve one OpenSpec root with one precedence: 1. `--store ` → the registered store's root (`source: "store"`). 2. Otherwise, nearest ancestor with `openspec/`: planning shape → `source: "nearest"` (a `store:` pointer is ignored with a stderr warning); config-only dir with a valid `store:` pointer → that store, `source: "declared"`. 3. No nearest root + global `defaultStore` set (`openspec config set defaultStore `) → that store, `source: "global_default"`; a stale id fails with the underlying store error and a `fix` naming `openspec config unset defaultStore`. 4. No nearest root, no default + registered stores exist → error `no_root_with_registered_stores`. 5. No root, no default, no stores: scaffolding commands treat the cwd as `source: "implicit"`; diagnostic commands (`doctor`, `context`) fail with `no_openspec_root` instead — they inspect, never scaffold. Successful JSON payloads embed the root: ```json "root": { "path": "/abs/path", "source": "store" | "declared" | "global_default" | "nearest" | "implicit", "store_id": "id (only when store-selected)" } ``` **Root-failure contract**: in JSON mode a resolution failure prints `{ ...commandNullShape, "status": [diagnostic] }` on stdout and exits 1. ## 4. Command JSON shapes [#4-command-json-shapes] ### 4.1 `list --json` [#41-list---json] `{ "changes": [ { "name", "completedTasks", "totalTasks", "lastModified", "status": "no-tasks"|"complete"|"in-progress" } ], "root": RootOutput }` — note the per-change `status` is a string enum here. `--specs`: `{ "specs": [ { "id", "requirementCount" } ], "root" }`. ### 4.2 `show --json` [#42-show-item---json] Change: `{ "id", "title", "deltaCount", "deltas": [...], "root" }`. Spec: `{ "id", "title", "overview", "requirementCount", "requirements": [...], "metadata": { "version", "format", "sourcePath"? }, "root" }`. ### 4.3 `validate --json` [#43-validate---json] `{ "items": [ { "id", "type": "change"|"spec", "valid", "issues": [ { "level", "path", "message", "line"?, "column"? } ], "durationMs" } ], "summary": { "totals": {items,passed,failed}, "byType": {...} }, "version": "1.0", "root" }`. Exit 1 when any item fails. ### 4.4 `status --json` [#44-status---json] `{ "changeName", "schemaName", "planningHome"?: { "kind", "root", "changesDir", "defaultSchema" }, "changeRoot", "artifactPaths": { "": {outputPath, resolvedOutputPath, existingOutputPaths} }, "nextSteps": ["..."], "actionContext": { "mode": "repo-local", "sourceOfTruth": "repo", "planningArtifacts", "linkedContext", "allowedEditRoots", "requiresAffectedAreaSelection", "constraints" }, "isComplete", "applyRequires", "artifacts": [ {id, outputPath, status: "done"|"ready"|"blocked", missingDeps?} ], "root" }`. No active changes: `{ "changes": [], "message", "root" }`, exit 0. ### 4.5 `instructions --json` [#45-instructions-artifact---json] `{ "changeName", "artifactId", "schemaName", "changeDir", "planningHome"?, "outputPath", "resolvedOutputPath", "existingOutputPaths", "description", "instruction"?, "context"?, "rules"?, "references"?: ReferenceIndexEntry[], "template", "dependencies": [{id,done,path,description}], "unlocks", "root" }`. `ReferenceIndexEntry`: `{ "store_id", "root"?, "specs"?: [{id,summary}], "fetch"?, "status": [] }` — resolved entries carry root/specs/fetch; unresolved carry store\_id + warning status. Index capped at 50KB (`reference_index_truncated`). ### 4.6 `instructions apply --json` [#46-instructions-apply---json] `{ "changeName", "changeDir", "schemaName", "contextFiles": { "": ["/abs", ...] }, "progress": {total,complete,remaining}, "tasks": [{id,description,done}], "state": "blocked"|"all_done"|"ready", "missingArtifacts"?, "instruction", "references"?, "root" }`. ### 4.7 `new change --json` [#47-new-change-name---json] Success: `{ "change": { "id", "path", "metadataPath", "schema" }, "root" }`. Failure: `{ "change": null, "status": [d] }`, exit 1. ### 4.8 `archive --json` [#48-archive-name---json] Success: `{ "archive": { "change", "archivedAs": "YYYY-MM-DD-name", "path", "specsUpdated", "totals"? }, "root" }`. Failure: `{ "archive": null, "root"?, "status": [d] }`, exit 1. JSON mode is strictly non-interactive: every prompt point becomes an `archive_*` code. ### 4.9 `doctor --json` [#49-doctor---json] `{ "root": { "path", "source", "store_id"?, "healthy", "status": [] }, "store": { "id", "metadata": {present,valid,remote?}, "origin_url"?, "status": [] } | null, "references": [...], "status": [] }`. Health findings of any severity exit 0. Failure payload: `{ "root": null, "store": null, "references": [], "status": [d] }`, exit 1. ### 4.10 `context --json` [#410-context---json] `{ "root": { "path", "source", "store_id"?, "role": "openspec_root" }, "members": [ { "role": "referenced_store", "id", "path"?, "remote"?, "fetch"?, "status": [] } ], "status": [] }`. AVAILABLE = path present AND status empty. `--code-workspace ` writes `{folders:[{name,path}]}` (available referenced stores only, `ref:` prefixes); in JSON mode the write runs before printing so stdout holds exactly one document even on write failure. Failure: `{ "root": null, "members": [], "status": [d] }`, exit 1. ### 4.11 `store ... --json` [#411-store----json] setup/register: `{ "store": {id, root, metadata_path?}, "registry": {path, registered, already_registered}, "git": {is_repository, initialized, committed}, "created_files": [], "status": [] }`. unregister/remove: `{ "store", "registry": {path, removed}, "files": {deleted, deleted_path, left_on_disk}, "status": [] }`. list: `{ "stores": [{id, root}], "status": [] }`. doctor: `{ "stores": [ { id, root, metadata_path?, openspec_root: {...healthy, status}, metadata: {present, valid, id?, remote}, git: {is_repository, has_commits, has_uncommitted_changes, has_remote, origin_url}, status } ], "status": [] }` (`null` = unknown/not probed). Health findings exit 0; failures exit 1 with the matching null-shape. Prompt cancellation exits 130. ### 4.12 `schemas --json` / `templates --json` [#412-schemas---json--templates---json] `schemas`: bare array `[ {name, description, artifacts, source} ]`. `templates`: keyed object `{ "": {path, source} }`. Both cwd-based, no root/status keys. ## 5. Exit-code contract [#5-exit-code-contract] | Situation | Exit | Stdout | | ------------------------------------------------------------ | ---- | ----------------------------------------------------------------- | | Success, incl. health findings (doctor/context/store doctor) | 0 | the payload | | Command failure in `--json` mode | 1 | one JSON document with `status: [d]` and the command's null-shape | | `validate` with failing items | 1 | full report | | Prompt cancellation (`store` group, human mode) | 130 | stderr only | ## 6. Diagnostic code catalog [#6-diagnostic-code-catalog] ### Resolution [#resolution] `no_openspec_root`, `no_root_with_registered_stores`, `no_registered_stores`, `unknown_store`, `store_identity_mismatch`, `unhealthy_store_root`, `store_path_not_supported`, `invalid_store_pointer`, `initiative_option_removed`, `areas_option_removed`; pass-through: `invalid_store_id`, `invalid_store_registry`, `invalid_store_metadata`. ### OpenSpec-root health (error, no fix) [#openspec-root-health-error-no-fix] `openspec_store_root_missing`, `openspec_store_root_not_directory`, `openspec_root_missing`, `openspec_root_not_directory`, `openspec_config_missing`, `openspec_config_not_file`, `openspec_specs_not_directory`, `openspec_changes_not_directory`, `openspec_archive_not_directory`. During the stores beta, `openspec/specs/`, `openspec/changes/`, and `openspec/changes/archive/` may be absent in a healthy root; they are only health errors when present but not directories. ### Store registry/identity/state [#store-registryidentitystate] `invalid_store_id`, `invalid_store_registry`, `invalid_store_metadata`, `store_registry_busy`, `store_not_found`, `no_store_registry`, `store_registry_changed`, `store_metadata_missing`, `store_metadata_id_mismatch`, `store_metadata_invalid`, `store_id_conflict`, `store_path_conflict`, `store_already_registered` (info). ### Store setup/register/remove [#store-setupregisterremove] `store_setup_id_required`, `store_setup_path_required`, `store_setup_path_not_directory`, `store_setup_inside_git_repo`, `store_setup_non_empty_directory`, `store_setup_cancelled`, `store_path_required`, `store_path_missing`, `store_path_not_directory`, `store_root_pointer_declared`, `store_register_root_unhealthy`, `store_register_identity_confirmation_required`, `store_register_cancelled`, `store_remote_empty`, `store_remote_requires_hand_edit`, `store_remove_confirmation_required`, `store_remove_cancelled`, `store_remove_path_not_directory`, `store_remove_metadata_missing`, `store_root_missing` (warning in remove, error in doctor), `store_root_not_directory`. ### Store git [#store-git] `store_git_init_failed`, `store_git_identity_missing`, `store_git_commit_failed`, `store_git_no_commits` (warning), `store_clone_fragile_directories` (warning), `store_remote_divergence` (info, doctor). ### References (warning) [#references-warning] `reference_invalid_id`, `reference_registry_unreadable`, `reference_unresolved`, `reference_root_unhealthy`, `reference_index_truncated`. ### Relationships (warning; doctor; context keeps only the registry one) [#relationships-warning-doctor-context-keeps-only-the-registry-one] `relationship_registry_unreadable`, `root_pointer_ignored`, `root_pointer_invalid`, `pointer_declarations_inert`. ### Archive (JSON mode) [#archive-json-mode] `archive_change_name_required`, `archive_change_not_found`, `archive_validation_failed`, `archive_confirmation_required`, `archive_tasks_incomplete`, `archive_spec_update_failed`, `archive_spec_validation_failed`, `archive_target_exists`, `archive_error`. ### Context writes [#context-writes] `context_file_exists`, `context_output_dir_missing`. ### Fallbacks [#fallbacks] `doctor_failed`, `context_failed`, `store_error`, `change_error`, `archive_error`. ## Known inconsistencies [#known-inconsistencies] Recorded by the capstone audit; published-key renames are product decisions deferred past this release: 1. ~~In `--json` mode, several failure paths printed stderr only with no JSON document.~~ Fixed in the capstone gauntlet round: `show`/`validate` unknown and ambiguous items emit `{status:[{code: unknown_item | ambiguous_item, ...}]}`; thrown errors in `status`/`instructions`/`list`/`show`/`validate` route through the JSON-aware failure helper (the command's null-shape + `status`); `store --json` emits `{status:[{code: unknown_store_subcommand}]}`; `list` carries its `{changes|specs: [], root: null}` null-shape on resolution failures. 2. `store_root_missing` is emitted with two severities (warning in remove, error in store doctor) — context-dependent, documented above. 3. snake\_case (store family) vs camelCase (workflow family) key casing; `root.store_id` is snake\_case everywhere. 4. Four parallel envelope type declarations exist in src; archive diagnostics never carry `target`. 5. `list --json` reuses the `status` key as a string enum per change. 6. Only `validate` output carries a `version` field. 7. `schemas`/`templates` ignore root selection (cwd-based, no `--store`). 8. Deprecated noun forms (`change`/`spec` subcommands) emit unenveloped payloads without `root`/`status`. # CLI Reference (/docs/reference/cli) The OpenSpec CLI (`openspec`) provides terminal commands for project setup, validation, status inspection, and management. These commands complement the AI slash commands (like `/opsx:propose`) documented in [Commands](/docs/reference/slash-commands). ## Summary [#summary] | Category | Commands | Purpose | | -------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | | **Setup** | `init`, `update` | Initialize and update OpenSpec in your project | | **Stores (standalone OpenSpec repos)** | `store setup`, `store register`, `store unregister`, `store remove`, `store list`, `store doctor` | Manage stores — standalone OpenSpec repos you've registered | | **Health** | `doctor` | Report relationship health for the resolved root | | **Working context** | `context` | Assemble the working set (root + referenced stores) | | **Personal worksets** | `workset create`, `workset list`, `workset open`, `workset remove` | Keep and open personal, local working views in your tool | | **Browsing** | `list`, `view`, `show` | Explore changes and specs | | **Validation** | `validate` | Check changes and specs for issues | | **Lifecycle** | `archive` | Finalize completed changes | | **Workflow** | `new change`, `status`, `instructions`, `templates`, `schemas` | Artifact-driven workflow support | | **Schemas** | `schema init`, `schema fork`, `schema validate`, `schema which` | Create and manage custom workflows | | **Config** | `config` | View and modify settings | | **Utility** | `feedback`, `completion` | Feedback and shell integration | *** ## Human vs Agent Commands [#human-vs-agent-commands] Most CLI commands are designed for **human use** in a terminal. Some commands also support **agent/script use** via JSON output. ### Human-Only Commands [#human-only-commands] These commands are interactive and designed for terminal use: | Command | Purpose | | ------------------------------ | -------------------------------------------------------------- | | `openspec init` | Initialize project (interactive prompts) | | `openspec view` | Interactive dashboard | | `openspec workset open ` | Open a saved workset (editor window or terminal agent session) | | `openspec config edit` | Open config in editor | | `openspec feedback` | Submit feedback via GitHub | | `openspec completion install` | Install shell completions | ### Agent-Compatible Commands [#agent-compatible-commands] These commands support `--json` output for programmatic use by AI agents and scripts: | Command | Human Use | Agent Use | | -------------------------------- | -------------------------------------- | ---------------------------------------------------------------------------- | | `openspec list` | Browse changes/specs | `--json` for structured data | | `openspec show ` | Read content | `--json` for parsing | | `openspec validate` | Check for issues | `--all --json` for bulk validation | | `openspec status` | See artifact progress | `--json` for structured status | | `openspec instructions` | Get next steps | `--json` for agent instructions | | `openspec templates` | Find template paths | `--json` for path resolution | | `openspec schemas` | List available schemas | `--json` for schema discovery | | `openspec store setup ` | Create and register a local store | `--json` with explicit inputs for structured setup output | | `openspec store register ` | Register an existing store | `--json` for structured registration output | | `openspec store unregister ` | Forget a local store registration | `--json` for structured cleanup output | | `openspec store remove ` | Delete a registered local store folder | `--yes --json` for non-interactive deletion | | `openspec store list` | Browse registered stores | `--json` for structured registrations | | `openspec store doctor` | Check local store setup | `--json` for structured diagnostics | | `openspec new change ` | Create repo-local change scaffolding | `--json`, plus `--store ` to use a registered store as the OpenSpec root | | `openspec workset create [name]` | Compose a personal working view | `--member --json` for non-interactive composition | | `openspec workset list` | Browse saved worksets | `--json` for structured views | | `openspec workset remove ` | Delete a saved view | `--yes --json` for non-interactive removal | *** ## Global Options [#global-options] These options work with all commands: | Option | Description | | ----------------- | ------------------------ | | `--version`, `-V` | Show version number | | `--no-color` | Disable color output | | `--help`, `-h` | Display help for command | *** ## Setup Commands [#setup-commands] ### `openspec init` [#openspec-init] Initialize OpenSpec in your project. Creates the folder structure and configures AI tool integrations. Default behavior uses global config defaults: profile `core`, delivery `both`, workflows `propose, explore, apply, sync, archive`. ``` openspec init [path] [options] ``` **Arguments:** | Argument | Required | Description | | -------- | -------- | --------------------------------------------- | | `path` | No | Target directory (default: current directory) | **Options:** | Option | Description | | --------------------- | -------------------------------------------------------------------------------- | | `--tools ` | Configure AI tools non-interactively. Use `all`, `none`, or comma-separated list | | `--force` | Auto-cleanup legacy files without prompting | | `--profile ` | Override global profile for this init run (`core` or `custom`) | `--profile custom` uses whatever workflows are currently selected in global config (`openspec config profile`). **Supported tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codeartsagent`, `codex`, `forgecode`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `hermes`, `iflow`, `junie`, `kilocode`, `kimi`, `kiro`, `lingma`, `vibe`, `oh-my-pi`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`, `zcode` > This list mirrors `AI_TOOLS` in `src/core/config.ts`. See [Supported Tools](/docs/reference/supported-tools) for each tool's skill and command paths. **Examples:** ```bash # Interactive initialization openspec init # Initialize in a specific directory openspec init ./my-project # Non-interactive: configure for Claude and Cursor openspec init --tools claude,cursor # Configure for all supported tools openspec init --tools all # Override profile for this run openspec init --profile core # Skip prompts and auto-cleanup legacy files openspec init --force ``` **What it creates:** ``` openspec/ ├── specs/ # Your specifications (source of truth) ├── changes/ # Proposed changes └── config.yaml # Project configuration .claude/skills/ # Claude Code skills (if claude selected) .cursor/skills/ # Cursor skills (if cursor selected) .cursor/commands/ # Cursor OPSX commands (if delivery includes commands) ... (other tool configs) ``` *** ### `openspec update` [#openspec-update] Update OpenSpec instruction files after upgrading the CLI. Re-generates AI tool configuration files using your current global profile, selected workflows, and delivery mode. ``` openspec update [path] [options] ``` **Arguments:** | Argument | Required | Description | | -------- | -------- | --------------------------------------------- | | `path` | No | Target directory (default: current directory) | **Options:** | Option | Description | | --------- | ------------------------------------------- | | `--force` | Force update even when files are up to date | **Example:** ```bash # Update instruction files after npm upgrade npm update @fission-ai/openspec openspec update ``` *** ## Stores (standalone OpenSpec repos) [#stores-standalone-openspec-repos] > **Beta.** Stores and the features built on them (references, working context, worksets) are new; command names, flags, file formats, and JSON output may change shape between releases. For the problem-first walkthrough, see the [stores guide](/docs/stores). A store is a standalone OpenSpec repo you've registered on this machine — for example a planning repo or a contracts repo. Registering a store lets normal commands (`list`, `show`, `status`, `validate`, `new change`, `archive`, ...) act in it from anywhere by passing `--store `. ### `openspec store setup` [#openspec-store-setup] Create and register a local store. With no arguments in a terminal, OpenSpec guides the user through setup. Agents and scripts should pass explicit inputs and use `--json`. ```bash openspec store setup [id] [options] ``` **Options:** | Option | Description | | ---------------- | ------------------------------------------------------------------ | | `--path ` | Folder where the store should live (for example `~/openspec/`) | | `--remote ` | Record the canonical remote in the new store's `store.yaml` | | `--init-git` | Initialize a Git repository with an initial commit (default) | | `--no-init-git` | Skip every Git action: no init, no initial commit | | `--json` | Output JSON | Non-interactive runs (`--json`, scripts, agents) must pass both the store id and `--path`. In an interactive terminal, setup prompts for the location with an editable suggestion in a visible, user-owned place (for example `~/openspec/`); it never defaults to OpenSpec's managed data directory. Examples: ```bash openspec store setup openspec store setup team-context openspec store setup team-context --path ~/openspec/team-context --no-init-git openspec store setup team-context --path ~/openspec/team-context --no-init-git --json ``` ### `openspec store register` [#openspec-store-register] Register an existing local store folder. During the stores beta, a root may be registered before any changes exist, specs have been applied, or changes have been archived; in that case `openspec/changes/`, `openspec/specs/`, and `openspec/changes/archive/` may be absent until normal commands create them. A config-only repo that declares `store: ` remains a pointer to another store and is not registered as a store root unless that pointer is removed. ```bash openspec store register [path] [options] ``` **Options:** | Option | Description | | ----------- | -------------------------------------------------------------------- | | `--id ` | Store id; defaults to store metadata or folder name | | `--yes` | Confirm creating store identity metadata for a healthy OpenSpec root | | `--json` | Output JSON | ### `openspec store unregister` [#openspec-store-unregister] Forget a local store registration without deleting files. ```bash openspec store unregister [--json] ``` Use this when a store was moved, cloned somewhere else, or should no longer be shown by OpenSpec on this machine. ### `openspec store remove` [#openspec-store-remove] Forget a local store registration and delete its local folder. ```bash openspec store remove [--yes] [--json] ``` `remove` shows the exact folder before deleting in an interactive terminal. Agents, scripts, and JSON callers must pass `--yes` to confirm deletion. OpenSpec refuses to delete a folder that does not contain matching store metadata. ### `openspec store list` [#openspec-store-list] List locally registered stores. ```bash openspec store list [--json] openspec store ls [--json] ``` ### `openspec store doctor` [#openspec-store-doctor] Check local store registration, metadata, and Git presence. ```bash openspec store doctor [id] [--json] ``` Doctor is diagnostic-only; it reports missing roots, metadata mismatches, and invalid local registry state without modifying the store. ### Referencing stores from a project [#referencing-stores-from-a-project] A project repo can declare which stores its work draws on in `openspec/config.yaml`: ```yaml schema: spec-driven references: - team-context ``` From then on, `openspec instructions` output in that repo (both the per-artifact and `apply` surfaces, JSON and human modes) carries an index of each referenced store's specs — spec ids, a one-line summary from each spec's Purpose section, and the fetch command (`openspec show --type spec --store `). The index is built live from the registered checkout on every run; spec content is never copied into the output. References are read-only context. They never change where commands act: work stays in the repo's own root, and writing to a referenced store remains an explicit `--store` action. A reference that cannot be resolved (for example, a store not registered on this machine) degrades to a warning in the index with the exact fix, and instructions still generate. `openspec doctor` reports reference health in one place. ### Recording where a store is cloned from [#recording-where-a-store-is-cloned-from] A store can record its canonical clone source in its committed identity file, so onboarding never dead-ends at "register the store": ```bash openspec store setup team-context --path ~/openspec/team-context \ --remote git@github.com:acme/team-context.git ``` The remote lands in `.openspec-store/store.yaml` inside the initial commit, so every clone is born knowing it. For an existing store, edit `store.yaml` by hand and commit. `store doctor` shows the recorded remote (and the checkout's observed Git origin); setup/register sharing guidance names it; and register records the checkout's origin in the machine-local registry. A reference declaration can carry the clone source too, so a teammate who doesn't have the store yet gets a complete, pasteable fix (`git clone && openspec store register --id `): ```yaml references: - { id: team-context, remote: "git@github.com:acme/team-context.git" } ``` Recording a remote is not sync: OpenSpec never clones, pulls, or pushes on its own. ### Declaring a default store [#declaring-a-default-store] A repo whose planning is fully externalized — no local `openspec/specs/` or `openspec/changes/` — can declare its store once instead of passing `--store` on every command: ```yaml # openspec/config.yaml (the only file under openspec/) store: team-context ``` Normal commands then resolve to the declared store automatically; the root banner and JSON `root` block report `source: "declared"` with the store id, and printed hints still carry `--store `. The declaration is a fallback, never an override: explicit `--store` always wins, and a directory with real planning folders ignores the pointer (with a warning). To convert a pointer repo into a local OpenSpec root, remove the `store:` line and run `openspec init` — init refuses to scaffold while the declaration is present. A machine-level variant covers every repo at once: `openspec config set defaultStore ` (see Configuration). It is consulted only after `--store`, a local root, and a project pointer have all failed to resolve; the root banner and JSON `root` block then report `source: "global_default"`. ## Doctor (relationship health) [#doctor-relationship-health] One read-only question, one place: is the OpenSpec root healthy, and are the stores it references available on this machine? ```bash openspec doctor [--store ] [--json] ``` The report separates root health, store metadata health (including a note when the recorded remote and the checkout's origin diverge), and reference health (the same diagnostics instructions show, with clone fixes for unresolved references). Health findings of any severity exit 0 — agents read the `status` arrays; only command failures (no root, unknown store) exit 1. Doctor never clones, syncs, or repairs. To get the assembled set itself rather than its health, use `openspec context`. ## Working context (the assembled set) [#working-context-the-assembled-set] Everything this work relates to through OpenSpec declarations, in one working set: the OpenSpec root and the stores it references. ```bash openspec context [--store ] [--json] [--code-workspace [--force]] ``` The JSON brief is agent-consumable (each available referenced store carries its fetch recipe; unresolved members carry the same fixes instructions and doctor show). `--code-workspace` additionally writes a VS Code workspace file containing the root plus the available referenced stores (`ref:` folders) — the one write this command performs, refused without `--force` if the file exists. Unavailable members are reported, never guessed at. "Working context" is the assembled set; the `context:` field in `openspec/config.yaml` is project background injected into instructions — two different things. `openspec doctor` answers whether the set is healthy; `openspec context` answers what the set is. ## Personal worksets [#personal-worksets] > **Beta.** Worksets are part of the new beta surface; commands, flags, and file formats may change shape between releases. For the walkthrough, see the [stores guide](/docs/stores#worksets-reopen-the-folders-you-work-on-together). A workset is a personal, named view of the folders you work on together — a planning root plus whatever else you choose — kept on your machine and reopened by name in your tool. It is purely local: never committed, never shared, never derived from declarations, and removing one never touches a member folder. ```bash openspec workset create [name] [--member | --member =]... [--tool ] [--json] openspec workset list [--json] openspec workset open [--tool ] openspec workset remove [--yes] [--json] ``` `create` runs a short guided flow (or takes `--member` flags non-interactively; the first member is the primary — sessions start there). `open` launches the chosen tool: editors (VS Code, Cursor) open a window with every member and return; CLI agents (Claude Code, codex) take over this terminal as a session with every member attached and no prompt pre-filled, ending when you exit. A member folder missing at open time is skipped with a note; the rest opens. The saved tool preference is overridable per open with `--tool`. Supporting a new tool is configuration, not code. Every tool is one of two launch styles — `workspace-file` (launched with the generated `.code-workspace`) or `attach-dirs` (one attach flag per member) — and the `openers` key in the global `config.json` (open it with `openspec config edit`) adds tools or adjusts built-ins per field: ```json { "openers": { "zed": { "style": "workspace-file" }, "claude": { "attach_flag": "--dir" } } } ``` All workset state lives under the global data dir's `worksets/` folder (the saved views plus the generated `.code-workspace` files, regenerated on every open); deleting that folder removes every trace. *** ## Browsing Commands [#browsing-commands] ### `openspec list` [#openspec-list] List changes or specs in your project. ``` openspec list [options] ``` **Options:** | Option | Description | | ---------------- | ------------------------------------ | | `--specs` | List specs instead of changes | | `--changes` | List changes (default) | | `--sort ` | Sort by `recent` (default) or `name` | | `--json` | Output as JSON | **Examples:** ```bash # List all active changes openspec list # List all specs openspec list --specs # JSON output for scripts openspec list --json ``` **Output (text):** ``` Changes: add-dark-mode No tasks just now ``` *** ### `openspec view` [#openspec-view] Display an interactive dashboard for exploring specs and changes. ``` openspec view ``` Opens a terminal-based interface for navigating your project's specifications and changes. *** ### `openspec show` [#openspec-show] Display details of a change or spec. ``` openspec show [item-name] [options] ``` **Arguments:** | Argument | Required | Description | | ----------- | -------- | ------------------------------------------- | | `item-name` | No | Name of change or spec (prompts if omitted) | **Options:** | Option | Description | | ------------------ | --------------------------------------------------------------- | | `--type ` | Specify type: `change` or `spec` (auto-detected if unambiguous) | | `--json` | Output as JSON | | `--no-interactive` | Disable prompts | **Change-specific options:** | Option | Description | | --------------- | --------------------------------- | | `--deltas-only` | Show only delta specs (JSON mode) | **Spec-specific options:** | Option | Description | | ------------------------ | ------------------------------------------------------ | | `--requirements` | Show only requirements, exclude scenarios (JSON mode) | | `--no-scenarios` | Exclude scenario content (JSON mode) | | `-r, --requirement ` | Show specific requirement by 1-based index (JSON mode) | **Examples:** ```bash # Interactive selection openspec show # Show a specific change openspec show add-dark-mode # Show a specific spec openspec show auth --type spec # JSON output for parsing openspec show add-dark-mode --json ``` *** ## Validation Commands [#validation-commands] ### `openspec validate` [#openspec-validate] Validate changes and specs for structural issues. ``` openspec validate [item-name] [options] ``` **Arguments:** | Argument | Required | Description | | ----------- | -------- | ---------------------------------------------- | | `item-name` | No | Specific item to validate (prompts if omitted) | **Options:** | Option | Description | | ------------------- | -------------------------------------------------------------------- | | `--all` | Validate all changes and specs | | `--changes` | Validate all changes | | `--specs` | Validate all specs | | `--type ` | Specify type when name is ambiguous: `change` or `spec` | | `--strict` | Enable strict validation mode | | `--json` | Output as JSON | | `--concurrency ` | Max parallel validations (default: 6, or `OPENSPEC_CONCURRENCY` env) | | `--no-interactive` | Disable prompts | **Examples:** ```bash # Interactive validation openspec validate # Validate a specific change openspec validate add-dark-mode # Validate all changes openspec validate --changes # Validate everything with JSON output (for CI/scripts) openspec validate --all --json # Strict validation with increased parallelism openspec validate --all --strict --concurrency 12 ``` **Output (text):** ``` Validating add-dark-mode... ✓ proposal.md valid ✓ specs/ui/spec.md valid ⚠ design.md: missing "Technical Approach" section 1 warning found ``` **Output (JSON):** ```json { "version": "1.0.0", "results": { "changes": [ { "name": "add-dark-mode", "valid": true, "warnings": ["design.md: missing 'Technical Approach' section"] } ] }, "summary": { "total": 1, "valid": 1, "invalid": 0 } } ``` *** ## Lifecycle Commands [#lifecycle-commands] ### `openspec archive` [#openspec-archive] Archive a completed change and merge delta specs into main specs. ``` openspec archive [change-name] [options] ``` **Arguments:** | Argument | Required | Description | | ------------- | -------- | -------------------------------------- | | `change-name` | No | Change to archive (prompts if omitted) | **Options:** | Option | Description | | --------------- | --------------------------------------------------------------- | | `-y, --yes` | Skip confirmation prompts | | `--skip-specs` | Skip spec updates (for infrastructure/tooling/doc-only changes) | | `--no-validate` | Skip validation (requires confirmation) | **Examples:** ```bash # Interactive archive openspec archive # Archive specific change openspec archive add-dark-mode # Archive without prompts (CI/scripts) openspec archive add-dark-mode --yes # Archive a tooling change that doesn't affect specs openspec archive update-ci-config --skip-specs ``` **What it does:** 1. Validates the change (unless `--no-validate`) 2. Prompts for confirmation (unless `--yes`) 3. Merges delta specs into `openspec/specs/` 4. Moves change folder to `openspec/changes/archive/YYYY-MM-DD-/` *** ## Workflow Commands [#workflow-commands] These commands support the artifact-driven OPSX workflow. They're useful for both humans checking progress and agents determining next steps. ### `openspec new change` [#openspec-new-change] Create a change directory and optional checked-in metadata in the resolved OpenSpec root. ```bash openspec new change [options] ``` Change names must use lowercase kebab-case. They start with a lowercase letter, then contain lowercase letters, numbers, and single hyphens. They cannot start with a number, contain spaces, underscores, uppercase letters, consecutive hyphens, or leading/trailing hyphens. When including an external ticket ID, prefix it with a word, for example `ticket-123-add-notifications` instead of `123-add-notifications`. **Options:** | Option | Description | | ---------------------- | ---------------------------------------------------------------------------------------------- | | `--description ` | Description to add to `README.md` | | `--goal ` | Optional goal metadata to store with the change | | `--schema ` | Workflow schema to use | | `--store ` | Store id to use as the OpenSpec root (a store is a standalone OpenSpec repo you've registered) | | `--json` | Output JSON | Examples: ```bash openspec new change add-billing-api openspec new change add-billing-api --store team-context --json ``` ### `openspec status` [#openspec-status] Display artifact completion status for a change. ``` openspec status [options] ``` **Options:** | Option | Description | | ----------------- | ---------------------------------------------------- | | `--change ` | Change name (prompts if omitted) | | `--schema ` | Schema override (auto-detected from change's config) | | `--json` | Output as JSON | **Examples:** ```bash # Interactive status check openspec status # Status for specific change openspec status --change add-dark-mode # JSON for agent use openspec status --change add-dark-mode --json ``` **Output (text):** ``` Change: add-dark-mode Schema: spec-driven Progress: 2/4 artifacts complete [x] proposal [ ] design [x] specs [-] tasks (blocked by: design) ``` **Output (JSON):** ```json { "changeName": "add-dark-mode", "schemaName": "spec-driven", "isComplete": false, "applyRequires": ["tasks"], "artifacts": [ {"id": "proposal", "outputPath": "proposal.md", "status": "done"}, {"id": "design", "outputPath": "design.md", "status": "ready"}, {"id": "specs", "outputPath": "specs/**/*.md", "status": "done"}, {"id": "tasks", "outputPath": "tasks.md", "status": "blocked", "missingDeps": ["design"]} ] } ``` *** ### `openspec instructions` [#openspec-instructions] Get enriched instructions for creating an artifact or applying tasks. Used by AI agents to understand what to create next. ``` openspec instructions [artifact] [options] ``` **Arguments:** | Argument | Required | Description | | ---------- | -------- | --------------------------------------------------------------- | | `artifact` | No | Artifact ID: `proposal`, `specs`, `design`, `tasks`, or `apply` | **Options:** | Option | Description | | ----------------- | ---------------------------------------------- | | `--change ` | Change name (required in non-interactive mode) | | `--schema ` | Schema override | | `--json` | Output as JSON | **Special case:** Use `apply` as the artifact to get task implementation instructions. **Examples:** ```bash # Get instructions for next artifact openspec instructions --change add-dark-mode # Get specific artifact instructions openspec instructions design --change add-dark-mode # Get apply/implementation instructions openspec instructions apply --change add-dark-mode # JSON for agent consumption openspec instructions design --change add-dark-mode --json ``` **Output includes:** * Template content for the artifact * Project context from config * Content from dependency artifacts * Per-artifact rules from config *** ### `openspec templates` [#openspec-templates] Show resolved template paths for all artifacts in a schema. ``` openspec templates [options] ``` **Options:** | Option | Description | | ----------------- | ------------------------------------------ | | `--schema ` | Schema to inspect (default: `spec-driven`) | | `--json` | Output as JSON | **Examples:** ```bash # Show template paths for default schema openspec templates # Show templates for custom schema openspec templates --schema my-workflow # JSON for programmatic use openspec templates --json ``` **Output (text):** ``` Schema: spec-driven Templates: proposal → ~/.openspec/schemas/spec-driven/templates/proposal.md specs → ~/.openspec/schemas/spec-driven/templates/specs.md design → ~/.openspec/schemas/spec-driven/templates/design.md tasks → ~/.openspec/schemas/spec-driven/templates/tasks.md ``` *** ### `openspec schemas` [#openspec-schemas] List available workflow schemas with their descriptions and artifact flows. ``` openspec schemas [options] ``` **Options:** | Option | Description | | -------- | -------------- | | `--json` | Output as JSON | **Example:** ```bash openspec schemas ``` **Output:** ``` Available schemas: spec-driven (package) The default spec-driven development workflow Flow: proposal → specs → design → tasks my-custom (project) Custom workflow for this project Flow: research → proposal → tasks ``` *** ## Schema Commands [#schema-commands] Commands for creating and managing custom workflow schemas. ### `openspec schema init` [#openspec-schema-init] Create a new project-local schema. ``` openspec schema init [options] ``` **Arguments:** | Argument | Required | Description | | -------- | -------- | ------------------------ | | `name` | Yes | Schema name (kebab-case) | **Options:** | Option | Description | | ---------------------- | --------------------------------------------------------------------- | | `--description ` | Schema description | | `--artifacts ` | Comma-separated artifact IDs (default: `proposal,specs,design,tasks`) | | `--default` | Set as project default schema | | `--no-default` | Don't prompt to set as default | | `--force` | Overwrite existing schema | | `--json` | Output as JSON | **Examples:** ```bash # Interactive schema creation openspec schema init research-first # Non-interactive with specific artifacts openspec schema init rapid \ --description "Rapid iteration workflow" \ --artifacts "proposal,tasks" \ --default ``` **What it creates:** ``` openspec/schemas// ├── schema.yaml # Schema definition └── templates/ ├── proposal.md # Template for each artifact ├── specs.md ├── design.md └── tasks.md ``` *** ### `openspec schema fork` [#openspec-schema-fork] Copy an existing schema to your project for customization. ``` openspec schema fork [name] [options] ``` **Arguments:** | Argument | Required | Description | | -------- | -------- | -------------------------------------------- | | `source` | Yes | Schema to copy | | `name` | No | New schema name (default: `-custom`) | **Options:** | Option | Description | | --------- | ------------------------------ | | `--force` | Overwrite existing destination | | `--json` | Output as JSON | **Example:** ```bash # Fork the built-in spec-driven schema openspec schema fork spec-driven my-workflow ``` *** ### `openspec schema validate` [#openspec-schema-validate] Validate a schema's structure and templates. ``` openspec schema validate [name] [options] ``` **Arguments:** | Argument | Required | Description | | -------- | -------- | --------------------------------------------- | | `name` | No | Schema to validate (validates all if omitted) | **Options:** | Option | Description | | ----------- | ------------------------------ | | `--verbose` | Show detailed validation steps | | `--json` | Output as JSON | **Example:** ```bash # Validate a specific schema openspec schema validate my-workflow # Validate all schemas openspec schema validate ``` *** ### `openspec schema which` [#openspec-schema-which] Show where a schema resolves from (useful for debugging precedence). ``` openspec schema which [name] [options] ``` **Arguments:** | Argument | Required | Description | | -------- | -------- | ----------- | | `name` | No | Schema name | **Options:** | Option | Description | | -------- | ----------------------------------- | | `--all` | List all schemas with their sources | | `--json` | Output as JSON | **Example:** ```bash # Check where a schema comes from openspec schema which spec-driven ``` **Output:** ``` spec-driven resolves from: package Source: /usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven ``` **Schema precedence:** 1. Project: `openspec/schemas//` 2. User: `~/.local/share/openspec/schemas//` 3. Package: Built-in schemas *** ## Configuration Commands [#configuration-commands] ### `openspec config` [#openspec-config] View and modify global OpenSpec configuration. ``` openspec config [options] ``` **Subcommands:** | Subcommand | Description | | ------------------- | ------------------------------------------------------ | | `path` | Show config file location | | `list` | Show all current settings | | `get ` | Get a specific value | | `set ` | Set a value | | `unset ` | Remove a key | | `reset` | Reset to defaults | | `edit` | Open in `$EDITOR` | | `profile [preset]` | Configure workflow profile interactively or via preset | **Examples:** ```bash # Show config file path openspec config path # List all settings openspec config list # Get a specific value openspec config get telemetry.enabled # Set a value openspec config set telemetry.enabled false # Set a string value explicitly openspec config set user.name "My Name" --string # Remove a custom setting openspec config unset user.name # Set a machine-level default store (fallback root when no --store, # local root, or project store: pointer resolves) openspec config set defaultStore team-plans # Reset all configuration openspec config reset --all --yes # Edit config in your editor openspec config edit # Configure profile with action-based wizard openspec config profile # Fast preset: switch workflows to core (keeps delivery mode) openspec config profile core ``` `openspec config profile` starts with a current-state summary, then lets you choose: * Change delivery + workflows * Change delivery only * Change workflows only * Keep current settings (exit) If you keep current settings, no changes are written and no update prompt is shown. If there are no config changes but the current project files are out of sync with your global profile/delivery, OpenSpec will show a warning and suggest `openspec update`. Pressing `Ctrl+C` also cancels the flow cleanly (no stack trace) and exits with code `130`. In the workflow checklist, `[x]` means the workflow is selected in global config. To apply those selections to project files, run `openspec update` (or choose `Apply changes to this project now?` when prompted inside a project). **Interactive examples:** ```bash # Delivery-only update openspec config profile # choose: Change delivery only # choose delivery: Skills only # Workflows-only update openspec config profile # choose: Change workflows only # toggle workflows in the checklist, then confirm ``` *** ## Utility Commands [#utility-commands] ### `openspec feedback` [#openspec-feedback] Submit feedback about OpenSpec. Creates a GitHub issue. ``` openspec feedback [options] ``` **Arguments:** | Argument | Required | Description | | --------- | -------- | ---------------- | | `message` | Yes | Feedback message | **Options:** | Option | Description | | --------------- | -------------------- | | `--body ` | Detailed description | **Requirements:** GitHub CLI (`gh`) must be installed and authenticated. **Example:** ```bash openspec feedback "Add support for custom artifact types" \ --body "I'd like to define my own artifact types beyond the built-in ones." ``` *** ### `openspec completion` [#openspec-completion] Manage shell completions for the OpenSpec CLI. ``` openspec completion [shell] ``` **Subcommands:** | Subcommand | Description | | ------------------- | ---------------------------------- | | `generate [shell]` | Output completion script to stdout | | `install [shell]` | Install completion for your shell | | `uninstall [shell]` | Remove installed completions | **Supported shells:** `bash`, `zsh`, `fish`, `powershell` **Examples:** ```bash # Install completions (auto-detects shell) openspec completion install # Install for specific shell openspec completion install zsh # Generate script for manual installation openspec completion generate bash > ~/.bash_completion.d/openspec # Uninstall openspec completion uninstall ``` *** ## Exit Codes [#exit-codes] | Code | Meaning | | ---- | ----------------------------------------------- | | `0` | Success | | `1` | Error (validation failure, missing files, etc.) | *** ## Environment Variables [#environment-variables] | Variable | Description | | ---------------------- | ----------------------------------------------------- | | `OPENSPEC_TELEMETRY` | Set to `0` to disable telemetry | | `DO_NOT_TRACK` | Set to `1` to disable telemetry (standard DNT signal) | | `OPENSPEC_CONCURRENCY` | Default concurrency for bulk validation (default: 6) | | `EDITOR` or `VISUAL` | Editor for `openspec config edit` | | `NO_COLOR` | Disable color output when set | *** ## Related Documentation [#related-documentation] * [Commands](/docs/reference/slash-commands) - AI slash commands (`/opsx:propose`, `/opsx:apply`, etc.) * [Workflows](/docs/the-workflow) - Common patterns and when to use each command * [Customization](/docs/customization) - Create custom schemas and templates * [Getting Started](/docs/getting-started) - First-time setup guide # Commands (/docs/reference/slash-commands) This is the reference for OpenSpec's slash commands. These commands are invoked in your AI coding assistant's chat interface (e.g., Claude Code, Cursor, Windsurf). For workflow patterns and when to use each command, see [Workflows](/docs/the-workflow). For CLI commands, see [CLI](/docs/reference/cli). ## Quick Reference [#quick-reference] ### Default Quick Path (`core` profile) [#default-quick-path-core-profile] | Command | Purpose | | --------------- | ----------------------------------------------------------- | | `/opsx:propose` | Create a change and generate planning artifacts in one step | | `/opsx:explore` | Think through ideas before committing to a change | | `/opsx:apply` | Implement tasks from the change | | `/opsx:update` | Revise a change's planning artifacts and keep them coherent | | `/opsx:sync` | Merge delta specs into main specs | | `/opsx:archive` | Archive a completed change | ### Expanded Workflow Commands (custom workflow selection) [#expanded-workflow-commands-custom-workflow-selection] | Command | Purpose | | -------------------- | --------------------------------------------------- | | `/opsx:new` | Start a new change scaffold | | `/opsx:continue` | Create the next artifact based on dependencies | | `/opsx:ff` | Fast-forward: create all planning artifacts at once | | `/opsx:verify` | Validate implementation matches artifacts | | `/opsx:bulk-archive` | Archive multiple changes at once | | `/opsx:onboard` | Guided tutorial through the complete workflow | The default global profile is `core`. To enable expanded workflow commands, run `openspec config profile`, select workflows, then run `openspec update` in your project. *** ## Command Reference [#command-reference] ### `/opsx:propose` [#opsxpropose] Create a new change and generate planning artifacts in one step. This is the default start command in the `core` profile. **Syntax:** ```text /opsx:propose [change-name-or-description] ``` **Arguments:** | Argument | Required | Description | | ---------------------------- | -------- | ---------------------------------------------------- | | `change-name-or-description` | No | Kebab-case name or plain-language change description | **What it does:** * Creates `openspec/changes//` * Generates artifacts needed before implementation (for `spec-driven`: proposal, specs, design, tasks) * Stops when the change is ready for `/opsx:apply` **Example:** ```text You: /opsx:propose add-dark-mode AI: Created openspec/changes/add-dark-mode/ ✓ proposal.md ✓ specs/ui/spec.md ✓ design.md ✓ tasks.md Ready for implementation. Run /opsx:apply. ``` **Tips:** * Use this for the fastest end-to-end path * If you want step-by-step artifact control, enable expanded workflows and use `/opsx:new` + `/opsx:continue` *** ### `/opsx:explore` [#opsxexplore] > **Start here when you're unsure.** Explore is a no-stakes thinking partner: it reads your codebase, compares options, and sharpens a fuzzy idea into a concrete plan before any change exists. It ships in the default profile. For the full case and more examples, see the [Explore First](/docs/explore) guide. Think through ideas, investigate problems, and clarify requirements before committing to a change. **Syntax:** ``` /opsx:explore [topic] ``` **Arguments:** | Argument | Required | Description | | -------- | -------- | --------------------------------------- | | `topic` | No | What you want to explore or investigate | **What it does:** * Opens an exploratory conversation with no structure required * Investigates the codebase to answer questions * Compares options and approaches * Creates visual diagrams to clarify thinking * Can transition to `/opsx:propose` (default) or `/opsx:new` (expanded workflow) when insights crystallize **Example:** ```text You: /opsx:explore AI: What would you like to explore? You: How should we handle authentication for the mobile app? AI: Let me investigate your current auth setup... [Analyzes codebase] I see you're using session-based auth for the web app. For mobile, we have three main options: 1. JWT tokens (stateless, works offline) 2. OAuth2 (if you need third-party login) 3. Extend current sessions (simpler, but requires connectivity) Your API already has CORS configured. Which direction interests you? You: Let's go with JWT. Can we start a change for that? AI: Ready when you are. Run /opsx:propose add-jwt-auth to begin. ``` **Tips:** * Use when requirements are unclear or you need to investigate * No artifacts are created during exploration * Good for comparing multiple approaches before deciding * Can read files and search the codebase *** ### `/opsx:new` [#opsxnew] Start a new change scaffold. Creates the change folder and waits for you to generate artifacts with `/opsx:continue` or `/opsx:ff`. This command is part of the expanded workflow set (not included in the default `core` profile). **Syntax:** ``` /opsx:new [change-name] [--schema ] ``` **Arguments:** | Argument | Required | Description | | ------------- | -------- | -------------------------------------------------------------- | | `change-name` | No | Name for the change folder (prompted if not provided) | | `--schema` | No | Workflow schema to use (default: from config or `spec-driven`) | **What it does:** * Creates `openspec/changes//` directory * Creates `.openspec.yaml` metadata file in the change folder * Shows the first artifact template ready for creation * Prompts for change name and schema if not provided **What it creates:** ``` openspec/changes// └── .openspec.yaml # Change metadata (schema, created date) ``` **Example:** ``` You: /opsx:new add-dark-mode AI: Created openspec/changes/add-dark-mode/ Schema: spec-driven Ready to create: proposal Use /opsx:continue to create it, or /opsx:ff to create all artifacts. ``` **Tips:** * Use descriptive names: `add-feature`, `fix-bug`, `refactor-module` * Avoid generic names like `update`, `changes`, `wip` * Schema can also be set in project config (`openspec/config.yaml`) *** ### `/opsx:continue` [#opsxcontinue] Create the next artifact in the dependency chain. Creates one artifact at a time for incremental progress. **Syntax:** ``` /opsx:continue [change-name] ``` **Arguments:** | Argument | Required | Description | | ------------- | -------- | ---------------------------------------------------------------- | | `change-name` | No | Which change to continue (inferred from context if not provided) | **What it does:** * Queries the artifact dependency graph * Shows which artifacts are ready vs blocked * Creates the first ready artifact * Reads dependency files for context * Shows what becomes available after creation **Example:** ``` You: /opsx:continue AI: Change: add-dark-mode Artifact status: ✓ proposal (done) ◆ specs (ready) ◆ design (ready) ○ tasks (blocked - needs: specs) Creating specs... [Reads proposal.md, creates specs based on requirements] ✓ Created openspec/changes/add-dark-mode/specs/ui/spec.md Now available: tasks Run /opsx:continue to create the next artifact. ``` **Tips:** * Use when you want to review each artifact before proceeding * Good for complex changes where you want control * Multiple artifacts may become ready simultaneously * You can edit created artifacts before continuing *** ### `/opsx:ff` [#opsxff] Fast-forward through artifact creation. Creates all planning artifacts at once. **Syntax:** ``` /opsx:ff [change-name] ``` **Arguments:** | Argument | Required | Description | | ------------- | -------- | -------------------------------------------------------------------- | | `change-name` | No | Which change to fast-forward (inferred from context if not provided) | **What it does:** * Creates all artifacts in dependency order * Tracks progress via todo list * Stops when all `apply-required` artifacts are complete * Reads each dependency before creating the next artifact **Example:** ``` You: /opsx:ff add-dark-mode AI: Fast-forwarding add-dark-mode... ✓ Creating proposal.md ✓ Creating specs/ui/spec.md ✓ Creating design.md ✓ Creating tasks.md All planning artifacts complete! Ready for implementation. Run /opsx:apply to begin. ``` **Tips:** * Use when you have a clear picture of what you're building * Faster than `/opsx:continue` for straightforward changes * You can still edit artifacts afterward * Good for small to medium features *** ### `/opsx:apply` [#opsxapply] Implement tasks from the change. Works through the task list, writing code and checking off items. **Syntax:** ``` /opsx:apply [change-name] ``` **Arguments:** | Argument | Required | Description | | ------------- | -------- | ----------------------------------------------------------------- | | `change-name` | No | Which change to implement (inferred from context if not provided) | **What it does:** * Reads `tasks.md` and identifies incomplete tasks * Works through tasks one by one * Writes code, creates files, runs tests as needed * Marks tasks complete with checkboxes `[x]` **Example:** ``` You: /opsx:apply AI: Implementing add-dark-mode... Reading tasks.md: - [ ] 1.1 Create ThemeContext - [ ] 1.2 Add CSS custom properties - [ ] 1.3 Implement localStorage persistence Working on 1.1: Create ThemeContext... [Creates src/context/ThemeContext.tsx] ✓ 1.1 Complete Working on 1.2: Add CSS custom properties... [Updates src/styles/globals.css] ✓ 1.2 Complete ... ``` **Tips:** * Can resume where you left off if interrupted * Use for parallel changes by specifying the change name * Completion state is tracked in `tasks.md` checkboxes *** ### `/opsx:update` [#opsxupdate] Revise a change's existing planning artifacts and keep them coherent with one another. Planning artifacts only - it never edits code. **Syntax:** ```text /opsx:update [change-name] ``` **Arguments:** | Argument | Required | Description | | ------------- | -------- | -------------------------------------------------------------- | | `change-name` | No | Which change to update (inferred from context if not provided) | **What it does:** * Reads the change's artifacts via `openspec status --change --json` * Applies your requested revision, or reviews the artifacts for contradictions if you didn't name one * Reconciles the other existing artifacts in any direction (a design edit may ripple back to the proposal) * Confirms every edit with you before writing, one artifact at a time * Ends by recommending the next step: `/opsx:continue` (artifacts missing), `/opsx:apply` (carry a revised plan into code), or `/opsx:archive` (all done) **Example:** ```text You: /opsx:update add-dark-mode - we're storing the theme in a cookie now, not localStorage AI: Reading add-dark-mode artifacts... The design references localStorage in two places; tasks 1.3 covers localStorage persistence; the proposal doesn't mention storage. Proposed revisions: 1. design.md - swap localStorage decision for cookie storage 2. tasks.md - reword task 1.3 to cookie persistence Apply revision 1? (design.md) ``` **Tips:** * It won't create missing artifacts - that's `/opsx:continue` * If the change was already implemented, follow up with `/opsx:apply` so the code matches the revised plan * If your revision changes the *intent* of the change, start fresh with a new change instead (see [When to Update vs. Start Fresh](/docs/opsx#when-to-update-vs-start-fresh)) *** ### `/opsx:verify` [#opsxverify] Validate that implementation matches your change artifacts. Checks completeness, correctness, and coherence. **Syntax:** ``` /opsx:verify [change-name] ``` **Arguments:** | Argument | Required | Description | | ------------- | -------- | -------------------------------------------------------------- | | `change-name` | No | Which change to verify (inferred from context if not provided) | **What it does:** * Checks three dimensions of implementation quality * Searches codebase for implementation evidence * Reports issues categorized as CRITICAL, WARNING, or SUGGESTION * Does not block archive, but surfaces issues **Verification dimensions:** | Dimension | What it validates | | ---------------- | --------------------------------------------------------------- | | **Completeness** | All tasks done, all requirements implemented, scenarios covered | | **Correctness** | Implementation matches spec intent, edge cases handled | | **Coherence** | Design decisions reflected in code, patterns consistent | **Example:** ``` You: /opsx:verify AI: Verifying add-dark-mode... COMPLETENESS ✓ All 8 tasks in tasks.md are checked ✓ All requirements in specs have corresponding code ⚠ Scenario "System preference detection" has no test coverage CORRECTNESS ✓ Implementation matches spec intent ✓ Edge cases from scenarios are handled ✓ Error states match spec definitions COHERENCE ✓ Design decisions reflected in code structure ✓ Naming conventions consistent with design.md ⚠ Design mentions "CSS variables" but implementation uses Tailwind classes SUMMARY ───────────────────────────── Critical issues: 0 Warnings: 2 Ready to archive: Yes (with warnings) Recommendations: 1. Add test for system preference detection 2. Update design.md to reflect Tailwind usage, or refactor to use CSS variables ``` **Tips:** * Run before archiving to catch mismatches early * Warnings don't block archive but indicate potential issues * Good for reviewing AI's work before committing * Can reveal drift between artifacts and implementation *** ### `/opsx:sync` [#opsxsync] **Optional command.** Merge delta specs from a change into main specs. Archive will prompt to sync if needed, so you typically don't need to run this manually. **Syntax:** ``` /opsx:sync [change-name] ``` **Arguments:** | Argument | Required | Description | | ------------- | -------- | ------------------------------------------------------------ | | `change-name` | No | Which change to sync (inferred from context if not provided) | **What it does:** * Reads delta specs from change folder * Parses ADDED/MODIFIED/REMOVED/RENAMED sections * Merges changes into main `openspec/specs/` directory * Preserves existing content not mentioned in delta * Does not archive the change (remains active) **Example:** ```text You: /opsx:sync AI: Syncing add-dark-mode delta specs... Reading: openspec/changes/add-dark-mode/specs/ui/spec.md Target: openspec/specs/ui/spec.md Changes to apply: ✓ ADDED: Theme Selection requirement (2 scenarios) ✓ ADDED: Accessibility requirement (1 scenario) Merging... ✓ openspec/specs/ui/spec.md updated Change remains active. Run /opsx:archive when ready to complete. ``` **When to use manually:** | Scenario | Use sync? | | -------------------------------------------------------- | ----------------------- | | Long-running change, want specs in main before archiving | Yes | | Multiple parallel changes need the updated base specs | Yes | | Want to preview/review the merge separately | Yes | | Quick change, going straight to archive | No (archive handles it) | **Tips:** * Sync is intelligent, not copy-paste * Can add scenarios to existing requirements without duplicating * Change stays active after sync (not archived) * Most users will never need to call this directly—archive prompts if needed *** ### `/opsx:archive` [#opsxarchive] Archive a completed change. Finalizes the change and moves it to the archive folder. **Syntax:** ``` /opsx:archive [change-name] ``` **Arguments:** | Argument | Required | Description | | ------------- | -------- | --------------------------------------------------------------- | | `change-name` | No | Which change to archive (inferred from context if not provided) | **What it does:** * Checks artifact completion status * Checks task completion (warns if incomplete) * Offers to sync delta specs if not already synced * Moves change folder to `openspec/changes/archive/YYYY-MM-DD-/` * Preserves all artifacts for audit trail **Example:** ```text You: /opsx:archive AI: Archiving add-dark-mode... Artifact status: ✓ proposal.md exists ✓ specs/ exists ✓ design.md exists ✓ tasks.md exists (8/8 tasks complete) Delta specs: Not yet synced → Sync now? (recommended) You: Yes AI: ✓ Synced specs to openspec/specs/ui/spec.md ✓ Moved to openspec/changes/archive/2025-01-24-add-dark-mode/ Change archived successfully. ``` **Tips:** * Archive won't block on incomplete tasks, but will warn * Delta specs can be synced during archive or beforehand * Archived changes are preserved for history * Use `/opsx:verify` first to catch issues *** ### `/opsx:bulk-archive` [#opsxbulk-archive] Archive multiple completed changes at once. Handles spec conflicts between changes. **Syntax:** ``` /opsx:bulk-archive [change-names...] ``` **Arguments:** | Argument | Required | Description | | -------------- | -------- | --------------------------------------------------------------- | | `change-names` | No | Specific changes to archive (prompts to select if not provided) | **What it does:** * Lists all completed changes * Validates each change before archiving * Detects spec conflicts across changes * Resolves conflicts by checking what's actually implemented * Archives in chronological order **Example:** ``` You: /opsx:bulk-archive AI: Found 3 completed changes: - add-dark-mode (8/8 tasks complete) - fix-login-bug (3/3 tasks complete) - update-footer (2/2 tasks complete) Checking for spec conflicts... ⚠ add-dark-mode and update-footer both touch specs/ui/ Inspecting codebase to resolve... Both changes are implemented. Will merge in chronological order: 1. add-dark-mode (created Jan 20) 2. update-footer (created Jan 22) Archive all 3 changes? You: Yes AI: ✓ Archived add-dark-mode ✓ Archived fix-login-bug ✓ Archived update-footer Specs merged: add-dark-mode → update-footer ``` **Tips:** * Good for parallel work streams * Conflict resolution is agentic (checks codebase) * Changes are archived in order of creation * Prompts before overwriting spec content *** ### `/opsx:onboard` [#opsxonboard] Guided onboarding through the complete OpenSpec workflow. An interactive tutorial using your actual codebase. **Syntax:** ``` /opsx:onboard ``` **What it does:** * Walks through a complete workflow cycle with narration * Scans your codebase for real improvement opportunities * Creates an actual change with real artifacts * Implements actual work (small, safe changes) * Archives the completed change * Explains each step as it happens **Phases:** 1. Welcome and codebase analysis 2. Finding an improvement opportunity 3. Creating a change (`/opsx:new`) 4. Writing the proposal 5. Creating specs 6. Writing the design 7. Creating tasks 8. Implementing tasks (`/opsx:apply`) 9. Verifying implementation 10. Archiving the change 11. Summary and next steps **Example:** ``` You: /opsx:onboard AI: Welcome to OpenSpec! I'll walk you through the complete workflow using your actual codebase. We'll find something small to improve, create a proper change for it, implement it, and archive it. Let me scan your codebase for opportunities... [Analyzes codebase] I found a few things we could work on: 1. Add input validation to the contact form 2. Improve error messages in the auth flow 3. Add loading states to async buttons Which interests you? (or suggest something else) ``` **Tips:** * Best for new users learning the workflow * Uses real code, not toy examples * Creates a real change you can keep or discard * Takes 15-30 minutes to complete *** ## Command Syntax by AI Tool [#command-syntax-by-ai-tool] Different AI tools use slightly different command syntax. Use the format that matches your tool: | Tool | Syntax Example | | ------------- | ------------------------------------------------------------------------------------------------------------------------------- | | Claude Code | `/opsx:propose`, `/opsx:apply` | | Cursor | `/opsx-propose`, `/opsx-apply` | | Windsurf | `/opsx-propose`, `/opsx-apply` | | Copilot (IDE) | `/opsx-propose`, `/opsx-apply` | | CodeArts | Skill-based invocations such as `/openspec-propose`, `/openspec-apply-change` (no generated `opsx-*` command files) | | Codex | Skill-based invocations from `.codex/skills/openspec-*` (no generated `opsx-*` prompt files) | | Oh My Pi | `/opsx-propose`, `/opsx-apply` | | Kimi Code | Skill-based invocations such as `/skill:openspec-propose`, `/skill:openspec-apply-change` (no generated `opsx-*` command files) | | Trae | `/opsx-propose`, `/opsx-apply` | The intent is the same across tools, but how commands are surfaced can differ by integration. > **Note:** GitHub Copilot commands (`.github/prompts/*.prompt.md`) are only available in IDE extensions (VS Code, JetBrains, Visual Studio). GitHub Copilot CLI does not currently support custom prompt files — see [Supported Tools](/docs/reference/supported-tools) for details and workarounds. *** ## Legacy Commands [#legacy-commands] These commands use the older "all-at-once" workflow. They still work but OPSX commands are recommended. | Command | What it does | | -------------------- | ------------------------------------------------------------- | | `/openspec:proposal` | Create all artifacts at once (proposal, specs, design, tasks) | | `/openspec:apply` | Implement the change | | `/openspec:archive` | Archive the change | **When to use legacy commands:** * Existing projects using the old workflow * Simple changes where you don't need incremental artifact creation * Preference for the all-or-nothing approach **Migrating to OPSX:** Legacy changes can be continued with OPSX commands. The artifact structure is compatible. *** ## Troubleshooting [#troubleshooting] ### "Change not found" [#change-not-found] The command couldn't identify which change to work on. **Solutions:** * Specify the change name explicitly: `/opsx:apply add-dark-mode` * Check that the change folder exists: `openspec list` * Verify you're in the right project directory ### "No artifacts ready" [#no-artifacts-ready] All artifacts are either complete or blocked by missing dependencies. **Solutions:** * Run `openspec status --change ` to see what's blocking * Check if required artifacts exist * Create missing dependency artifacts first ### "Schema not found" [#schema-not-found] The specified schema doesn't exist. **Solutions:** * List available schemas: `openspec schemas` * Check spelling of schema name * Create the schema if it's custom: `openspec schema init ` ### Commands not recognized [#commands-not-recognized] The AI tool doesn't recognize OpenSpec commands. **Solutions:** * Ensure OpenSpec is initialized: `openspec init` * Regenerate skills: `openspec update` * Check that `.claude/skills/` directory exists (for Claude Code) * Restart your AI tool to pick up new skills ### Artifacts not generating properly [#artifacts-not-generating-properly] The AI creates incomplete or incorrect artifacts. **Solutions:** * Add project context in `openspec/config.yaml` * Add per-artifact rules for specific guidance * Provide more detail in your change description * Use `/opsx:continue` instead of `/opsx:ff` for more control *** ## Next Steps [#next-steps] * [Workflows](/docs/the-workflow) - Common patterns and when to use each command * [CLI](/docs/reference/cli) - Terminal commands for management and validation * [Customization](/docs/customization) - Create custom schemas and workflows # Supported Tools (/docs/reference/supported-tools) OpenSpec works with many AI coding assistants. When you run `openspec init`, OpenSpec configures selected tools using your active profile/workflow selection and delivery mode. ## How It Works [#how-it-works] For each selected tool, OpenSpec can install: 1. **Skills** (if delivery includes skills): `.../skills/openspec-*/SKILL.md` 2. **Commands** (if delivery includes commands): tool-specific `opsx-*` command files Codex is skills-only: OpenSpec installs `.codex/skills/openspec-*/SKILL.md` for Codex even when delivery is set to `commands`, and it does not generate Codex custom prompt files. By default, OpenSpec uses the `core` profile, which includes: * `propose` * `explore` * `apply` * `sync` * `archive` You can enable expanded workflows (`new`, `continue`, `ff`, `verify`, `bulk-archive`, `onboard`) via `openspec config profile`, then run `openspec update`. ## Tool Directory Reference [#tool-directory-reference] | Tool (ID) | Skills path pattern | Command path pattern | | --------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------- | | Amazon Q Developer (`amazon-q`) | `.amazonq/skills/openspec-*/SKILL.md` | `.amazonq/prompts/opsx-.md` | | Antigravity (`antigravity`) | `.agent/skills/openspec-*/SKILL.md` | `.agent/workflows/opsx-.md` | | Auggie (`auggie`) | `.augment/skills/openspec-*/SKILL.md` | `.augment/commands/opsx-.md` | | IBM Bob Shell (`bob`) | `.bob/skills/openspec-*/SKILL.md` | `.bob/commands/opsx-.md` | | Claude Code (`claude`) | `.claude/skills/openspec-*/SKILL.md` | `.claude/commands/opsx/.md` | | Cline (`cline`) | `.cline/skills/openspec-*/SKILL.md` | `.clinerules/workflows/opsx-.md` | | CodeArts (`codeartsagent`) | `.codeartsdoer/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/openspec-*` invocations) | | CodeBuddy (`codebuddy`) | `.codebuddy/skills/openspec-*/SKILL.md` | `.codebuddy/commands/opsx/.md` | | Codex (`codex`) | `.codex/skills/openspec-*/SKILL.md` | Not generated (skills-only; use `.codex/skills/openspec-*`) | | ForgeCode (`forgecode`) | `.forge/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/openspec-*` invocations) | | Continue (`continue`) | `.continue/skills/openspec-*/SKILL.md` | `.continue/prompts/opsx-.prompt` | | CoStrict (`costrict`) | `.cospec/skills/openspec-*/SKILL.md` | `.cospec/openspec/commands/opsx-.md` | | Crush (`crush`) | `.crush/skills/openspec-*/SKILL.md` | `.crush/commands/opsx/.md` | | Cursor (`cursor`) | `.cursor/skills/openspec-*/SKILL.md` | `.cursor/commands/opsx-.md` | | Factory Droid (`factory`) | `.factory/skills/openspec-*/SKILL.md` | `.factory/commands/opsx-.md` | | Gemini CLI (`gemini`) | `.gemini/skills/openspec-*/SKILL.md` | `.gemini/commands/opsx/.toml` | | GitHub Copilot (`github-copilot`) | `.github/skills/openspec-*/SKILL.md` | `.github/prompts/opsx-.prompt.md`\*\* | | Hermes Agent (`hermes`) | `.hermes/skills/openspec-*/SKILL.md`\*\*\* | Not generated (no command adapter; use skill-based `/openspec-*` invocations) | | iFlow (`iflow`) | `.iflow/skills/openspec-*/SKILL.md` | `.iflow/commands/opsx-.md` | | Junie (`junie`) | `.junie/skills/openspec-*/SKILL.md` | `.junie/commands/opsx-.md` | | Kilo Code (`kilocode`) | `.kilocode/skills/openspec-*/SKILL.md` | `.kilocode/workflows/opsx-.md` | | Kimi Code (`kimi`) | `.kimi-code/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/skill:openspec-*` invocations) | | Kiro (`kiro`) | `.kiro/skills/openspec-*/SKILL.md` | `.kiro/prompts/opsx-.prompt.md` | | Lingma (`lingma`) | `.lingma/skills/openspec-*/SKILL.md` | `.lingma/commands/opsx/.md` | | Mistral Vibe (`vibe`) | `.vibe/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/openspec-*` invocations) | | Oh My Pi (`oh-my-pi`) | `.omp/skills/openspec-*/SKILL.md` | `.omp/commands/opsx-.md` | | OpenCode (`opencode`) | `.opencode/skills/openspec-*/SKILL.md` | `.opencode/commands/opsx-.md` | | Pi (`pi`) | `.pi/skills/openspec-*/SKILL.md` | `.pi/prompts/opsx-.md` | | Qoder (`qoder`) | `.qoder/skills/openspec-*/SKILL.md` | `.qoder/commands/opsx/.md` | | Qwen Code (`qwen`) | `.qwen/skills/openspec-*/SKILL.md` | `.qwen/commands/opsx-.md` | | RooCode (`roocode`) | `.roo/skills/openspec-*/SKILL.md` | `.roo/commands/opsx-.md` | | Trae (`trae`) | `.trae/skills/openspec-*/SKILL.md` | `.trae/commands/opsx-.md` | | Windsurf (`windsurf`) | `.windsurf/skills/openspec-*/SKILL.md` | `.windsurf/workflows/opsx-.md` | | ZCode (`zcode`) | `.zcode/skills/openspec-*/SKILL.md` | `.zcode/commands/opsx/.md` | \*\* GitHub Copilot prompt files are recognized as custom slash commands in IDE extensions (VS Code, JetBrains, Visual Studio). Copilot CLI does not currently consume `.github/prompts/*.prompt.md` directly. \*\*\* Hermes loads skills from `~/.hermes/skills/` by default. To use project-local OpenSpec skills, add the project `.hermes/skills/` directory to `skills.external_dirs` in `~/.hermes/config.yaml`; Hermes then exposes skills with user-facing slash invocations such as `/openspec-propose`. ## Non-Interactive Setup [#non-interactive-setup] For CI/CD or scripted setup, use `--tools` (and optionally `--profile`): ```bash # Configure specific tools openspec init --tools claude,cursor # Configure all supported tools openspec init --tools all # Skip tool configuration openspec init --tools none # Override profile for this init run openspec init --profile core ``` **Available tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codeartsagent`, `codex`, `forgecode`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `hermes`, `iflow`, `junie`, `kilocode`, `kimi`, `kiro`, `lingma`, `vibe`, `oh-my-pi`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`, `zcode` ## Workflow-Dependent Installation [#workflow-dependent-installation] OpenSpec installs workflow artifacts based on selected workflows: * **Core profile (default):** `propose`, `explore`, `apply`, `sync`, `archive` * **Custom selection:** any subset of all workflow IDs: `propose`, `explore`, `new`, `continue`, `apply`, `ff`, `sync`, `archive`, `bulk-archive`, `verify`, `onboard` In other words, skill/command counts are profile-dependent and delivery-dependent, not fixed. ## Generated Skill Names [#generated-skill-names] When selected by profile/workflow config, OpenSpec generates these skills: * `openspec-propose` * `openspec-explore` * `openspec-new-change` * `openspec-continue-change` * `openspec-apply-change` * `openspec-update-change` * `openspec-ff-change` * `openspec-sync-specs` * `openspec-archive-change` * `openspec-bulk-archive-change` * `openspec-verify-change` * `openspec-onboard` See [Commands](/docs/reference/slash-commands) for command behavior and [CLI](/docs/reference/cli) for `init`/`update` options. ## Related [#related] * [CLI Reference](/docs/reference/cli) — Terminal commands * [Commands](/docs/reference/slash-commands) — Slash commands and skills * [Getting Started](/docs/getting-started) — First-time setup