OpenSpec Documentation

Spec-driven development (SDD) for AI coding assistants.

64,701 stars TypeScript TypeScript 1 file · ~42,909 tokens #ai#context-engineering#engineering#planning#prd#sdd#sdlc#spec
RAW Doc

File: README.md

The most loved spec framework.



Our philosophy:

text
→ fluid not rigid
→ iterative not waterfall
→ easy not complex
→ built for brownfield not just greenfield
→ scalable from personal projects to enterprises

[!TIP]
New workflow now available! We've rebuilt OpenSpec with a new artifact-guided workflow.

Run /opsx:propose "your idea" to get started. → Learn more here

See it in action

text
You: /opsx:explore
AI:  What would you like to explore?
You: I want dark mode but I'm not sure how to do it cleanly.
AI:  Let me look at your styling setup...
     Cleanest path here: CSS variables + a small theme context,
     with system-preference detection. No new dependencies. Scope it?
You: Yes, let's do it.

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!

You: /opsx:apply
AI:  Implementing tasks...
     ✓ 1.1 Add theme context provider
     ✓ 1.2 Create toggle component
     ✓ 2.1 Add CSS variables
     ✓ 2.2 Wire up localStorage
     All tasks complete!

You: /opsx:archive
AI:  Archived to openspec/changes/archive/2025-01-23-add-dark-mode/
     Specs updated. Ready for the next feature.

What do the specs actually look like?

Plain Markdown — requirements with concrete scenarios, no special syntax to learn. Here's what goes in the specs/ folder created above:

markdown
## ADDED Requirements

### Requirement: Theme selection
The app SHALL let users switch between light and dark themes,
defaulting to the system preference.

#### Scenario: User toggles dark mode
- **WHEN** the user clicks the theme toggle
- **THEN** the app switches to dark mode and persists the choice

Your AI writes these; you review the plan before any code is written.

OpenSpec is built with OpenSpec — browse this repo's live specs and in-flight changes for real examples at scale.

OpenSpec Dashboard

Why teams adopt OpenSpec

Solo, OpenSpec keeps you and your AI honest on a single repo. On a team, the hard part moves: a feature spans the API server, the web app, and a shared library; requirements are owned by one team and consumed by others; planning starts before any code exists.

Stores are the answer — planning in a repo of its own. The same openspec/ shape you already know (specs and changes), shared by git push like anything else. One source of truth your whole team and every coding agent can read, across every repo.

  • Cross-repo features — one change, one plan, even when the code lands in three repos.
  • Shared requirements — a platform team owns the specs; product teams reference them read-only, right where their coding agent can read them. No drifting wiki.
  • Plan before code — capture the plan in the store now; the code repos catch up later.

Stores are in beta. Start with the Stores User Guide.

Quick Start

Requires Node.js 20.19.0 or higher.

Install OpenSpec globally:

bash
npm install @fission-ai/openspec@latest

Then navigate to your project directory and initialize:

bash
cd your-project
openspec init

Want your AI to do it? Paste the setup prompt into your coding assistant — it installs the CLI, runs openspec init, and verifies the result.

Now talk to your AI:

  • Not sure what to build yet? Start with /opsx:explore, a no-stakes thinking partner that reads your code, weighs options, and shapes a plan before anything is written. (Explore guide)
  • Already know what you want? Go straight to /opsx:propose <what-you-want-to-build>.

Both are in the default profile. If you want the expanded workflow (/opsx:new, /opsx:continue, /opsx:ff, /opsx:verify, /opsx:bulk-archive, /opsx:onboard), select it with openspec config profile and apply with openspec update.

/opsx:propose is the canonical name; your tool may spell it /opsx-propose (Cursor, GitHub Copilot), @opsx-propose (Amazon Q) or $openspec-propose (Codex). openspec init prints the right form for the tools you picked — see How To Invoke.

[!NOTE]
Not sure if your tool is supported? View the full list – we support 30+ tools and growing.

Also works with pnpm, yarn, bun, and nix. See installation options.

Docs

Start here: the Documentation Home maps everything. New to OpenSpec? Read Getting Started, then How Commands Work (where you actually type /opsx:propose).

→ Getting Started: first steps
→ Explore First: think it through with /opsx:explore before you commit
→ How Commands Work: where slash commands run vs the CLI
→ Core Concepts at a Glance: the whole mental model, one page
→ Examples & Recipes: real changes, start to finish
→ Workflows: combos and patterns
→ Existing Projects: adopt OpenSpec on a brownfield codebase
→ Editing a Change: update artifacts, go back, reconcile manual edits
→ Commands: slash commands & skills
→ CLI: terminal reference
→ Stores: plan in a separate repo, shared across your team (beta)
→ Supported Tools: tool integrations & install paths
→ Concepts: how it all fits
→ Multi-Language: multi-language support
→ Customization: make it yours
→ FAQ · Troubleshooting · Glossary: quick help

Community schemas

Third-party schema bundles distributed via standalone repositories — these provide opinionated workflows that integrate OpenSpec with other tools, similar to how github/spec-kit's community extension catalog handles tool integrations.

→ Browse the catalog in the customization docs.

Why OpenSpec?

AI coding assistants are powerful but unpredictable when requirements live only in chat history. OpenSpec adds a lightweight spec layer so you agree on what to build before any code is written.

  • Agree before you build — human and AI align on specs before code gets written
  • Stay organized — each change gets its own folder with proposal, specs, design, and tasks
  • Work fluidly — update any artifact anytime, no rigid phase gates
  • Use your tools — works with 30+ AI assistants via slash commands

How we compare

vs. Spec Kit (GitHub) — Thorough but heavyweight. Rigid phase gates, lots of Markdown, Python setup. OpenSpec is lighter and lets you iterate freely.

vs. Kiro (AWS) — Powerful but you're locked into their IDE and limited to Claude models. OpenSpec works with the tools you already use.

vs. nothing — AI coding without specs means vague prompts and unpredictable results. OpenSpec brings predictability without the ceremony.

Updating OpenSpec

Upgrade the package

bash
npm install @fission-ai/openspec@latest

Refresh agent instructions

Run this inside each project to regenerate AI guidance and ensure the latest slash commands are active:

bash
openspec update

Usage Notes

Model selection: OpenSpec works best with high-reasoning models. We recommend Codex 5.5 and Opus 4.7 for both planning and implementation.

Context hygiene: OpenSpec benefits from a clean context window. Clear your context before starting implementation and maintain good context hygiene throughout your session.

Contributing

Small fixes — Bug fixes, typo corrections, and minor improvements can be submitted directly as PRs.

Larger changes — For new features, significant refactors, or architectural changes, please submit an OpenSpec change proposal first so we can align on intent and goals before implementation begins.

When writing proposals, keep the OpenSpec philosophy in mind: we serve a wide variety of users across different coding agents, models, and use cases. Changes should work well for everyone.

AI-generated code is welcome — as long as it's been tested and verified. PRs containing AI-generated code should mention the coding agent and model used (e.g., "Generated with Claude Code using claude-opus-4-5-20251101").

Development

  • Install dependencies: pnpm install
  • Build: pnpm run build
  • Test: pnpm test
  • Develop CLI locally: pnpm run dev or pnpm run dev:cli
  • Conventional commits (one-line): type(scope): subject

Other

Telemetry

OpenSpec collects anonymous usage stats.

We collect only command names and version to understand usage patterns. No arguments, paths, content, or PII. Automatically disabled in CI.

Opt-out (any one is enough):

  • openspec config set telemetry.enabled false (global config; unset means on)
  • export OPENSPEC_TELEMETRY=0 or export DO_NOT_TRACK=1 (env overrides config)

Maintainers & Advisors

See MAINTAINERS.md for the list of core maintainers and advisors who help guide the project.

License

MIT


File: docs/cli.md

CLI Reference

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.

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

Most CLI commands are designed for human use in a terminal. Some commands also support agent/script use via JSON output.

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 <name> 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

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; --store to select a registered root
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 <name> Delete a saved view --yes --json for non-interactive removal

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

`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, update, sync, archive.

text
openspec init [path] [options]

Use --language <language> to add a language instruction to a new project's
openspec/config.yaml. For an existing project, edit the config's context
field so OpenSpec never overwrites project-specific guidance.

Arguments:

Argument Required Description
path No Target directory (default: current directory)

Options:

Option Description
--tools <list> Configure AI tools non-interactively. Use all, none, or comma-separated list
--language <language> Write artifacts in this language when creating a new config
--force Auto-cleanup legacy files without prompting
--profile Override global profile for this init run (core or custom)
--no-animation Show a static welcome screen instead of the animated one
--copilot-cloud Set up GitHub Copilot cloud coding-agent files without prompting
--no-copilot-cloud Skip GitHub Copilot cloud coding-agent files without prompting

--profile custom uses whatever workflows are currently selected in global config (openspec config profile).

The welcome animation is also skipped when the OPENSPEC_NO_ANIMATION environment variable is set (any value, including empty), when NO_COLOR is set to a non-empty value, or when the OS reduced-motion preference is enabled (macOS Reduce Motion, GNOME animations disabled).

Supported tool IDs (--tools) — windsurf is also accepted, as an alias for devin: amazon-q, antigravity, auggie, bob, claude, cline, command-code, codeartsagent, codex, devin, forgecode, codebuddy, continue, costrict, crush, cursor, factory, gemini, github-copilot, hermes, iflow, junie, kilocode, kimi, kiro, lingma, minimax-code, vibe, oh-my-pi, opencode, pi, qoder, qwen, roocode, trae, zed, zcode, agents

This list mirrors AI_TOOLS in src/core/config.ts. See 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

# Non-interactive: configure global MiniMax Code skills
openspec init --tools minimax-code

# 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:

text
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)
.agents/skills/         # Shared skills for AGENTS.md-compatible tools (if agents selected)
... (other tool configs)

`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.

text
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 install @fission-ai/openspec@latest
openspec update

Upgrade the package first. Instruction files are generated by the installed CLI, so running openspec update against a stale install reports everything up to date without adding the workflows newer releases ship.

To make that visible, openspec update asks the npm registry whether a newer CLI has been published. When yours is behind, it offers to upgrade:

text
A newer OpenSpec CLI is available (v1.6.0 → v1.7.0).
  Running from: /usr/local/lib/node_modules/@fission-ai/openspec
? Upgrade to v1.7.0 now? (Y/n)

Answer yes and it runs npm install @fission-ai/openspec@latest, then re-runs the update with the new CLI so the new workflows land in the same command. It confirms the upgrade by asking the installed binary its version rather than trusting npm's exit code, so if another install earlier on your PATH is still answering, it tells you instead of claiming success. Answer no and it prints the command and updates with the CLI you have. Ctrl-C stops the command.

The offer appears only in an interactive terminal, and only when npm owns the install — the one case npm install -g actually fixes. Everything else gets the command that matches how it was installed instead:

How OpenSpec is installed What you get
Global npm install The prompt, and the upgrade run for you — in an interactive terminal; piped output gets the printed command instead
Global pnpm, bun, yarn, or volta install That manager's own command: pnpm add …@latest, bun add -g …@latest, yarn global add …@latest, or volta install …@latest
A dependency of the project A note to update the dependency, since its package manager owns the lockfile
An npx / dlx cache npx @fission-ai/openspec@latest update — that command is the update, so there is no second step
A git clone Nothing — your version is whatever the branch says

Whenever anything is printed, it names the directory the running CLI was loaded from — the thing to check when you did upgrade but a stale shim still owns your PATH.

It asks the registry in npm_config_registry when npm exports it, and https://registry.npmjs.org otherwise. No .npmrc is read: letting file contents choose where an outbound request goes is a flow worth avoiding, and a project's .npmrc travels with the repository. On a private mirror, export npm_config_registry — or set OPENSPEC_NO_UPDATE_CHECK to skip the check entirely. The check is skipped when CI is set to anything but an explicit off-value (false, 0, no, off, or empty), under NODE_ENV=test, and whenever OPENSPEC_NO_UPDATE_CHECK (any value), DO_NOT_TRACK=1, or OPENSPEC_TELEMETRY=0 is set. It runs before the update and can delay it by at most 1.5 seconds — it gives up after that even when the network drops packets silently, and stays quiet when the registry is unreachable.

How "up to date" is decided: skill files record the version that generated
them, so OpenSpec compares that against the installed CLI. Command files carry no
version stamp, so for a tool that has commands but no skills (delivery
commands), OpenSpec compares the file contents against what it would generate
now — edits to those files count as drift and are overwritten. With delivery
skills or both, only the recorded version is checked, so a hand-edited file
whose version still matches is left alone; use --force to rewrite it. Either
way, generated files are OpenSpec's to own — keep your own instructions
elsewhere.


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.

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`

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`

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`

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`

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`

List locally registered stores.

bash
openspec store list [--json]
openspec store ls [--json]

`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

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 <spec-id> --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

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 [email protected]: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 <remote> && openspec store register --id ):

yaml
references:
  - { id: team-context, remote: "[email protected]:acme/team-context.git" }

Recording a remote is not sync: OpenSpec never clones, pulls, or pushes on its own.

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)

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 a note when the store checkout has drifted behind its last-fetched upstream tracking ref), 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)

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

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.

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 <name>=]... [--tool ] [--json]
openspec workset list [--json]
openspec workset open <name> [--tool ]
openspec workset remove <name> [--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 <name>.code-workspace files, regenerated on every open); deleting that folder removes every trace.


Browsing Commands

`openspec list`

List changes or specs in your project.

text
openspec list [options]

Options:

Option Description
--specs List specs instead of changes
--changes List changes (default)
--sort <order> 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):

text
Changes:
  add-dark-mode     No tasks      just now

`openspec view`

Display an interactive dashboard for exploring specs and changes.

text
openspec view

Opens a terminal-based interface for navigating your project's specifications and changes.


`openspec show`

Display details of a change or spec.

text
openspec show [item-name] [options]

Arguments:

Argument Required Description
item-name No Name of change or spec (prompts if omitted)

Options:

Option Description
--type <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

`openspec validate`

Validate changes and specs for structural issues, and check a change's MODIFIED requirements against the main specs they would replace.

text
openspec validate [item-name] [options]

A change with zero spec deltas fails validation unless its .openspec.yaml declares skip_specs: true (for pure refactors, tooling, or docs work — see Recipe 5).

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
--archived Validate that archived changes have all tasks completed (for pre-commit linting)
--type <type> Specify type when name is ambiguous: change or spec
--strict Enable strict validation mode
--json Output as JSON
--concurrency <n> Max parallel validations (default: 6, or OPENSPEC_CONCURRENCY env)
--no-interactive Disable prompts

--archived is its own scope: it does not validate spec deltas (already applied at archive time), it verifies that every change under changes/archive/ has all of its tasks.md checkboxes ticked, exiting non-zero if any are unchecked. This catches changes that were archived with unfinished work — handy in a pre-commit hook.

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

# Fail if any archived change still has unchecked tasks
openspec validate --archived

Output (text):

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

`openspec archive`

Archive a completed change and merge delta specs into main specs.

text
openspec archive [change-name] [options]

Arguments:

Argument Required Description
change-name No Change to archive (prompts if omitted; required when nothing can answer the prompt)

Options:

Option Description
-y, --yes Skip confirmation prompts. Required when nothing can answer them — an AI agent, a CI job, or any run with stdin closed
--skip-specs Skip spec updates for one archive run. A change that permanently has no spec deltas should declare skip_specs: true in its .openspec.yaml instead — it archives with no flag
--no-validate Skip validation (requires confirmation). Also disables capability retirement — with no validator verdict, nothing is retired

Examples:

bash
# Interactive archive (asks which change, then confirms)
openspec archive

# Archive specific change
openspec archive add-dark-mode

# Archive without prompts (agents, 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. Claims the archive destination before changing any main spec
  4. Validates and merges the active delta specs into openspec/specs/ — a capability whose last requirement the change removes is retired, and its spec file deleted, but only when the change's .openspec.yaml declares retire_capabilities: true next to its schema:
  5. Moves the change folder to openspec/changes/archive/YYYY-MM-DD-<name>/
  6. If a spec mutation or final move fails before a complete archive is secured, restores the specs and leaves or returns the change at its active path
  7. If a verified fallback copy completes but staged-source cleanup fails, retains the complete archive and committed spec state for recovery

Without a terminal: an AI agent, a CI job, or any run with stdin closed cannot
answer step 2, so archive stops before touching anything, exits 1, and names the
command to rerun — openspec archive <name> --yes, carrying whatever other flags
you passed. Pass --yes (and the change name) up front to skip the round trip.


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`

Create a change directory and optional checked-in metadata in the resolved OpenSpec root.

bash
openspec new change <name> [options]

Change names must use lowercase kebab-case: lowercase letters, numbers, and
single hyphens. They cannot contain spaces, underscores, uppercase letters,
consecutive hyphens, or leading/trailing hyphens. A leading number is allowed,
so you can prefix names to order or tier changes, for example 100-add-feature
or 00001-add-auth.

Options:

Option Description
--description <text> Description to add to README.md
--goal <text> Optional goal metadata to store with the change
--schema <name> 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`

Display artifact completion status for a change.

text
openspec status [options]

Options:

Option Description
--change Change name (prompts if omitted)
--schema <name> 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):

text
Change: add-dark-mode
Schema: spec-driven
Progress: 2/4 artifacts complete

[x] proposal
[x] specs
[ ] design
[-] tasks (blocked by: design)

A change that declares skip_specs: true shows its specs stage as [~] specs (skipped: change declares skip_specs) and excludes it from the progress count.

Output (JSON):

json
{
  "changeName": "add-dark-mode",
  "schemaName": "spec-driven",
  "isPlanningComplete": false,
  "isComplete": false,
  "applyRequires": ["tasks"],
  "artifacts": [
    {"id": "proposal", "outputPath": "proposal.md", "status": "done", "requires": []},
    {"id": "specs", "outputPath": "specs/**/*.md", "status": "done", "requires": ["proposal"]},
    {"id": "design", "outputPath": "design.md", "status": "ready", "requires": ["proposal"]},
    {"id": "tasks", "outputPath": "tasks.md", "status": "blocked", "requires": ["specs", "design"], "missingDeps": ["design"]}
  ]
}

isPlanningComplete reports whether every non-skipped planning artifact exists;
skipped artifacts count as satisfied without being created. It does not report
whether implementation tasks are complete. isComplete is retained as a
compatibility alias with the same value.

Artifacts are listed in dependency order - a dependency never appears after
something that requires it - and artifacts that become ready at the same time
(spec-driven's specs and design both need only proposal) keep the order the
schema declares them rather than an alphabetical one. So the first ready entry
is the artifact to write next.


`openspec instructions`

Get enriched instructions for creating an artifact or applying tasks. Used by AI agents to understand what to create next.

text
openspec instructions [artifact] [options]

Arguments:

Argument Required Description
artifact No Artifact ID, or workflow input surface: apply or archive

Options:

Option Description
--change Change name (required in non-interactive mode)
--schema <name> Schema override
--json Output as JSON

Special cases: Use apply to get task implementation instructions. Use
archive to fetch current, read-only archive inputs (context and
operationGuidance) for a valid change; it does not archive or mutate anything.

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

# Get current archive operation inputs without archiving
openspec instructions archive --change add-dark-mode --json

# 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
  • Current project context and matching operation guidance for apply/archive

Operation inputs are read from the resolved repo or selected store on every
invocation. Project context is a required prompt-level input: agents read it and
apply relevant project facts, conventions, and constraints. Operation guidance is
optional additive advice: agents consider every entry and follow only entries that
are applicable and compatible with the built-in workflow. Both fields remain
separate from explicit user choices, CLI-controlled state, built-in instructions,
and artifact rules. Conflicting context is reported; conflicting or inapplicable
guidance is not followed and the reason is explained. These are behavioral
contracts for generated agents, not enforceable CLI checks. instructions archive
returns only the selected change, optional inputs, and root metadata; it does not
include the static archive workflow.

For an artifact skipped via skip_specs: true, the output is a warning only (JSON adds skipped/warning fields) — the artifact must not be created.


`openspec templates`

Show resolved template paths for all artifacts in a schema.

text
openspec templates [options]

Options:

Option Description
--schema <name> 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):

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`

List available workflow schemas with their descriptions and artifact flows.

text
openspec schemas [options]

Options:

Option Description
--json Output as JSON
--store Use a registered store as the OpenSpec root

Example:

bash
openspec schemas

Output:

text
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

Commands for creating and managing custom workflow schemas.

`openspec schema init`

Create a new project-local schema.

text
openspec schema init <name> [options]

Arguments:

Argument Required Description
name Yes Schema name (kebab-case)

Options:

Option Description
--description <text> Schema description
--artifacts <list> 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:

text
openspec/schemas/<name>/
├── schema.yaml           # Schema definition
└── templates/
    ├── proposal.md       # Template for each artifact
    ├── specs.md
    ├── design.md
    └── tasks.md

`openspec schema fork`

Copy an existing schema to your project for customization.

text
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`

Validate a schema's structure and templates.

text
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`

Show where a schema resolves from (useful for debugging precedence).

text
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:

text
spec-driven resolves from: package
  Source: /usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven

Schema precedence:

  1. Project: openspec/schemas/<name>/
  2. User: ~/.local/share/openspec/schemas/<name>/
  3. Package: Built-in schemas

Configuration Commands

`openspec config`

View and modify global OpenSpec configuration.

text
openspec config <subcommand> [options]

Subcommands:

Subcommand Description
path Show config file location
list Show all current settings
get <key> Get a specific value
set <key> <value> Set a value
unset <key> 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 (disable anonymous usage telemetry)
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

Telemetry opt-out: telemetry.enabled defaults to on when unset (opt-out model).
Set it to false to disable anonymous usage stats and the openspec update version check.
Environment variables take precedence over config: OPENSPEC_TELEMETRY=0, DO_NOT_TRACK=1,
and a truthy CI value (e.g. true/1/yes) always disable telemetry regardless of the config value.

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

`openspec feedback`

Submit feedback about OpenSpec. Creates a GitHub issue.

text
openspec feedback <message> [options]

Arguments:

Argument Required Description
message Yes Feedback summary; long text is shortened in the issue title and preserved in the body

Options:

Option Description
--body <text> Additional details included after the summary

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`

Manage shell completions for the OpenSpec CLI.

text
openspec completion <subcommand> [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

Completions are opt-in. The CLI mentions them once, on stderr, the first time you
run a command in an interactive terminal, and never again — it also stays quiet
if you already have completions installed. Set OPENSPEC_NO_COMPLETIONS=1 to
suppress that tip entirely.


Exit Codes

Code Meaning
0 Success
1 Error (validation failure, missing files, etc.)

Environment Variables

Variable Description
OPENSPEC_TELEMETRY Set to 0 to disable telemetry and the openspec update version check (overrides telemetry.enabled in global config)
DO_NOT_TRACK Set to 1 to disable telemetry and the openspec update version check (standard DNT signal; overrides config)
OPENSPEC_CONCURRENCY Default concurrency for bulk validation (default: 6)
EDITOR or VISUAL Editor for openspec config edit
NO_COLOR Disable color output when set
OPENSPEC_NO_ANIMATION Disable the openspec init welcome animation when set
OPENSPEC_NO_COMPLETIONS Set to 1 to suppress the one-time tip about shell completions
OPENSPEC_NO_UPDATE_CHECK Disable the openspec update check for a newer published CLI when set (any value, including empty). Also skipped when CI is set (unless false/0/no/off) or NODE_ENV=test
npm_config_registry Registry the openspec update version check asks. Must be an http(s) URL or it falls back to https://registry.npmjs.org. No .npmrc file is read


File: docs/commands.md

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, Devin Desktop).

For workflow patterns and when to use each command, see Workflows. For CLI commands, see CLI.

These pages use /opsx:<command> as the canonical name. Some tools spell it
differently — Cursor and GitHub Copilot register /opsx-propose, Codex uses
$openspec-propose — so check How To Invoke
for your tool. The files OpenSpec generates already use the right form.

Quick Reference

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)

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

`/opsx:propose`

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/<change-name>/
  • 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`

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 guide.

Think through ideas, investigate problems, and clarify requirements before committing to a change.

Syntax:

text
/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`

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:

text
/opsx:new [change-name] [--schema <schema-name>]

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/<change-name>/ 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:

text
openspec/changes/<change-name>/
└── .openspec.yaml    # Change metadata (schema, created date)

Example:

text
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`

Create the next artifact in the dependency chain. Creates one artifact at a time for incremental progress.

Syntax:

text
/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:

text
You: /opsx:continue

AI:  Change: add-dark-mode

     Artifact status:
     ✓ proposal    (done)
     ◆ specs       (ready)
     ◆ design      (ready)
     ○ tasks       (blocked - needs: specs, design)

     Creating specs...

     [Reads proposal.md, creates specs based on requirements]

     ✓ Created openspec/changes/add-dark-mode/specs/ui/spec.md

     Now available: design
     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`

Fast-forward through artifact creation. Creates all planning artifacts at once.

Syntax:

text
/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:

text
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`

Implement tasks from the change. Works through the task list, writing code and checking off items.

Syntax:

text
/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:

text
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`

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 <name> --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)

`/opsx:verify`

Validate that implementation matches your change artifacts. Checks completeness, correctness, and coherence.

Syntax:

text
/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:

text
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`

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:

text
/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`

Archive a completed change. Finalizes the change and moves it to the archive folder.

Syntax:

text
/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-<name>/
  • 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`

Archive multiple completed changes at once. Handles spec conflicts between changes.

Syntax:

text
/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:

text
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`

Guided onboarding through the complete OpenSpec workflow. An interactive tutorial using your actual codebase.

Syntax:

text
/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:

text
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

Different AI tools use slightly different command syntax. Use the format that matches your tool:

Your tool's command file Syntax example Example tools
.../commands/opsx/.* /opsx:propose, /opsx:apply Claude Code, Gemini CLI, Crush
.../opsx-.* /opsx-propose, /opsx-apply Cursor, Devin Desktop, Copilot (IDE), Trae, Oh My Pi
none — skills only /openspec-propose, /openspec-apply-change CodeArts, ForgeCode, Hermes, MiniMax Code, Mistral Vibe, Zed Agent, shared .agents
none — Kimi Code /skill:openspec-propose Kimi Code
none — Codex CLI $openspec-propose Codex

Devin Desktop vs Devin Local: the .devin/workflows/opsx-*.md files give
Devin Desktop /opsx-propose. Devin Local has no workflows — use the skills
OpenSpec writes to .devin/skills/, e.g. /openspec-propose, which work on
both agents.

The intent is the same across tools, but how commands are surfaced can differ by integration. How To Invoke lists every supported tool; this table shows only examples of each shape.

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 for details and workarounds.


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

"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"

All artifacts are either complete or blocked by missing dependencies.

Solutions:

  • Run openspec status --change <name> to see what's blocking
  • Check if required artifacts exist
  • Create missing dependency artifacts first

"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 <name>

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

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

  • Workflows - Common patterns and when to use each command
  • CLI - Terminal commands for management and validation
  • Customization - Create custom schemas and workflows

File: docs/concepts.md

Concepts

This guide explains the core ideas behind OpenSpec and how they fit together. For practical usage, see Getting Started and Workflows.

Philosophy

OpenSpec is built around four principles:

text
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

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

OpenSpec organizes your work into two main areas:

text
┌────────────────────────────────────────────────────────────────────┐
│                        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 describe your system's behavior using structured requirements and scenarios.

Structure

text
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

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

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)

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

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

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

A change is a proposed modification to your system, packaged as a folder with everything needed to understand and implement it.

Change Structure

text
openspec/changes/add-dark-mode/
├── proposal.md           # Why and what
├── design.md             # How (technical approach)
├── tasks.md              # Implementation checklist
├── .openspec.yaml        # Change metadata (optional): schema, created, skip_specs, retire_capabilities
└── 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

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 are the documents within a change that guide the work.

The Artifact Flow

text
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

Proposal (`proposal.md`)

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/`)

Delta specs describe what's changing relative to the current specs. See Delta Specs below.

Design (`design.md`)

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 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 are the key concept that makes OpenSpec work for brownfield development. They describe what's changing rather than restating the entire spec.

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

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; removing the last requirement retires the capability and deletes its spec file, when the change declares retire_capabilities: true
## Purpose What a brand-new capability is for Seeds the Purpose of the main spec being created; ignored when the spec already exists

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 define the artifact types and their dependencies for a workflow.

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:

text
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

spec-driven (default)

The standard workflow for spec-driven development:

text
proposal → specs → design → tasks → implement

Best for: Most feature work where you want to agree on specs before implementation.

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 for full details on creating and using custom schemas.

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

text
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

  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

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

text
/* Detailed source-code truncated for AI context efficiency. */

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

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


File: docs/customization.md

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

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
  • Add per-operation guidance - Advisory preferences for apply and archive work
  • Remember integration choices - e.g. the GitHub Copilot cloud coding agent opt-in

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

operations:
  apply:
    guidance:
      - Run focused tests before the full suite
  archive:
    guidance:
      - Keep the completion summary concise

# Set by `openspec init` when you choose (or decline) the GitHub Copilot
# cloud coding agent; controls whether `init`/`update` generate its files.
githubCopilot:
  cloudAgent: false

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
<context>
Tech stack: TypeScript, React, Node.js, PostgreSQL
...
</context>

<rules>
- Include rollback plan
- Identify affected teams
</rules>

<template>
[Schema's built-in template]
</template>
  • Context appears in ALL artifacts
  • Rules ONLY appear for the matching artifact

Operation guidance:

operations.apply.guidance and operations.archive.guidance are optional arrays
of advisory instructions for how an agent should conduct those operations. They
are separate from rules: operation guidance does not constrain artifact content,
and artifact rules are never relabeled as operation guidance.

Apply and archive fetch these inputs at execution time:

bash
openspec instructions apply --change my-feature --json
openspec instructions archive --change my-feature --json

Both surfaces return current project context and matching
operationGuidance as separate optional fields. Each invocation reads a fresh
snapshot from the resolved root. When --store is selected, the change,
context, and guidance all come from that store rather than the current repository.
The archive instruction command is read-only: it does not inspect or merge delta
specs, write main specs, move the change, or run the static archive workflow.

Project context is a required prompt-level input. Generated workflows read it and
apply relevant project facts, conventions, and constraints. Operation guidance is
optional additive advice: workflows consider every entry and follow entries that
are applicable and compatible with the built-in workflow.

Both fields remain separate from CLI-controlled state, resolved paths, built-in
steps, explicit user choices, and artifact rules. A workflow reports context
conflicts while preserving the controlling value. It does not follow inapplicable
or conflicting guidance and explains why. Neither field is an enforceable check,
and workflows do not copy their text into implementation files, specs, change
artifacts, or summaries unless the user separately requests that content.

Archive and spec-sync input safety:

Archive, bulk archive, and standalone sync use
artifactPaths.specs.existingOutputPaths from openspec status --json as the
only delta-spec source. A schema without a specs artifact, or a change whose
concrete output list is empty, has nothing to sync; other artifacts are not used
to infer delta specs.

Before a semantic merge writes a main spec, the workflow consumes current
openspec instructions specs --change <name> --json output. The returned
specs rules constrain only the main specs produced by that merge. Single archive
passes that snapshot into inline sync, standalone sync fetches it directly, and
bulk archive obtains every required snapshot before its first spec write. A
non-zero or invalid JSON archive/specs instruction response is a lookup failure,
not an empty input: the workflow stops before the affected spec write or change
move (for bulk archive, before any batch write or move).

This configuration does not change archive execution phases, user prompts,
filesystem operations, semantic merge ownership, the direct openspec archive
command, or the structure and output of artifact rules.

Schema Resolution Order

When OpenSpec needs a schema, it checks in this order:

  1. CLI flag: --schema <name>
  2. Change metadata (.openspec.yaml in the change folder)
  3. Project config (openspec/config.yaml)
  4. Default (spec-driven)

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

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

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

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
artifacts:
  - id: proposal
    generates: proposal.md
    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
    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
    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

List artifacts in the order you want them written. requires decides what is
possible; the order of the artifacts: list decides what comes first when
several artifacts are ready at once.

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

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

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

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

Rapid Iteration Workflow

A minimal workflow for quick iterations:

yaml
# openspec/schemas/rapid/schema.yaml
name: rapid
version: 1
artifacts:
  - id: proposal
    generates: proposal.md
    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
    template: tasks.md
    requires: [proposal]

apply:
  requires: [tasks]
  tracks: tasks.md

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
    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

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 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/<schema-name>/ directory (each repo's README has install instructions).

Schema Maintainer Repository Description
intent-driven @harikrishnan83 intent-driven-dev/openspec-schemas Captures change intent, observable behaviour, technical design, and durable architectural decisions before implementation. Adds a change-local ADR review manifest and writes qualifying long-lived decisions as immutable, supersedable ADRs.
superpowers-bridge @JiangWay JiangWay/openspec-schemas Integrates OpenSpec's artifact governance with 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.
nanopm @nmrtn nmrtn/nanopm PM-first workflow. Runs nanopm's planning pipeline (audit → strategy → roadmap → PRD) upstream of implementation. Bridges product planning to OpenSpec's spec-driven engineering workflow. Artifacts read from .nanopm/ if present — proposal sources the audit, design sources the strategy, and tasks source the PRD breakdown.
e2e-runbooks @Lukk17 Lukk17/openspec-schemas Capability-level end-to-end test runbooks. Each capability gets an immutable spec, an immutable tasks-template, and one timestamped run record per execution. Assertions are observable behaviour only (HTTP status, response body, persisted state — never log substrings); each run records start/end UTC, duration, and best-estimate LLM token consumption.
anvil @jikkujoyce jikkujoyce/openspec-schemas Spec-driven workflow with TDD discipline and an adversarial review step. Flow: proposal → specs → design → review → test-plan → tasks → apply → verify. review is written by a fresh-context, read-only reviewer (a second model when one is available) and emits a VERDICT: line telling the agent to gate test-plan, tasks, and apply; OpenSpec only checks that artifacts exist, so enforce the gate with your own CI or hook. test-plan maps every spec scenario to a named test and doubles as a red/green ledger that verify audits.

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


File: docs/getting-started.md

Getting Started

This guide explains how OpenSpec works after you've installed and initialized it. For installation instructions, see the main README or the Installation guide. New to the whole docs set? The documentation home 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.

Your First Five Minutes

The whole loop, with each step labeled by where it happens:

text
TERMINAL   $ npm install @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.

Don't want to do the terminal part yourself? Paste the setup prompt into your assistant and it handles both lines, then reports what it created.

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.

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, update, sync, and archive. You can enable the expanded workflow commands with openspec config profile and then openspec update.

What OpenSpec Creates

After running openspec init, your project has this structure:

text
openspec/
├── specs/              # Source of truth (your system's behavior)
│   └── <domain>/
│       └── spec.md
├── changes/            # Proposed updates (one folder per change)
│   └── <change-name>/
│       ├── proposal.md
│       ├── design.md
│       ├── tasks.md
│       └── specs/      # Delta specs (what's changing)
│           └── <domain>/
│               └── 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

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:

text
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

Delta specs are the key concept in OpenSpec. They show what's changing relative to your current specs.

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

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

Let's walk through adding dark mode to an application.

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

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

text
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

text
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

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


File: docs/installation.md

Installation

Prerequisites

  • Node.js 20.19.0 or higher — Check your version: node --version

Install with your AI assistant

Rather not do this by hand? Paste the prompt below into any coding assistant that can run shell commands — Claude Code, Codex, Cursor, Gemini CLI, Copilot, and the rest of the supported tools. It installs the CLI, initializes this project, and reports back what actually happened.

The manual steps below are the source of truth — the prompt just runs them for you. If your assistant stops and hands something back, that's by design: it asks before anything privileged and never edits your shell startup files. Finish those bits yourself with Package Managers and Troubleshooting.

text
/* Detailed source-code truncated for AI context efficiency. */

Nothing in the prompt is vendor-specific: it's plain instructions plus the same commands documented on this page. It works on macOS, Linux, and Windows, and it deliberately stops rather than improvising when a step needs your permission. Your assistant does need to be able to run shell commands — a few IDE integrations can't.

Package Managers

npm

bash
npm install @fission-ai/openspec@latest

pnpm

bash
pnpm add @fission-ai/openspec@latest

yarn

bash
yarn global add @fission-ai/openspec@latest

Yarn 2 and later (Berry) removed the global command. On those versions, install OpenSpec with npm, pnpm, or bun instead — a global CLI doesn't need to share your project's package manager.

deno

Deno sometimes has issues parsing the @latest tag, but we can specify a version while installing initially.
If that happens, you could try to change the @latest tag with the version, something like @^1.3.1

bash
deno install --global \
  --allow-read --allow-write --allow-env --allow-sys=cpus,homedir --allow-net=edge.openspec.dev \
  npm:@fission-ai/openspec@latest
# or
deno install --global \
  --allow-read --allow-write --allow-env --allow-sys=cpus,homedir --allow-net=edge.openspec.dev \
  npm:@fission-ai/openspec@^1.3.1

Note: If your subcommands launch external tools, like config edit, feedback, or workspace open, you may need a scoped --allow-run=.

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

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

bash
openspec --version

Updating

Upgrade the package, then refresh each project's generated files:

bash
npm install @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. It also checks whether a newer CLI has been published and offers to upgrade, since upgrading is what makes new workflows available in the first place — see CLI Reference.

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.

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

After installing, initialize OpenSpec in your project:

bash
cd your-project
openspec init

See Getting Started for a full walkthrough.


File: docs/migration-guide.md

Migrating to OPSX

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?

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:explore, /opsx:apply, /opsx:update, /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

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

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
  • Devin Desktop, formerly 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 the canonical .agents/skills/openspec-* path. OpenSpec-managed SKILL.md files under the former .codex/skills path are reconciled only after replacements exist; custom files and divergent copies stay in place. If an unmarked .agents tree already contains OpenSpec skills, OpenSpec preserves its existing Codex ($openspec-*) or generic (/openspec-*) rendering instead of guessing from the legacy directory. Select codex explicitly with openspec init to switch ownership. Legacy prompt cleanup still targets only OpenSpec's allowlisted filenames in $CODEX_HOME/prompts or ~/.codex/prompts.
  • 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

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

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, update, sync, archive).
  • Migrated installs preserve your previously installed workflows by writing a custom profile when needed.

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:

text
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`

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

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 .agents/skills/openspec-* skills exist, and preserves all other files.


Migrating project.md to config.yaml

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)

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)

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

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

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

  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

If you're unsure how to distill your project.md, ask your AI assistant:

text
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

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:update Revise a change's planning artifacts and keep them coherent
/opsx:sync Merge delta specs into main specs
/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: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

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

These capabilities are part of the expanded workflow command set.

Granular artifact creation:

text
/opsx:continue

Creates one artifact at a time based on dependencies. Use this when you want to review each step.

Exploration mode:

text
/opsx:explore

Think through ideas with a partner before committing to a change.


Understanding the New Architecture

From Phase-Locked to Fluid

The legacy workflow forced linear progression:

text
┌──────────────┐      ┌──────────────┐      ┌──────────────┐
│   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:

text
┌───────────────────────────────────────────────┐
         │           ACTIONS (not phases)                │
         │                                               │
         │     new ◄──► continue ◄──► apply ◄──► archive │
         │      │          │           │             │   │
         │      └──────────┴───────────┴─────────────┘   │
         │                    any order                  │
         └───────────────────────────────────────────────┘

Dependency Graph

Artifacts form a directed graph. Dependencies are enablers, not gates:

text
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

The legacy system used tool-specific command files:

text
.claude/commands/openspec/
├── proposal.md
├── apply.md
└── archive.md

OPSX uses the emerging skills standard:

text
.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 .agents/skills/openspec-* directories instead.


Continuing Existing Changes

Your in-progress changes work seamlessly with OPSX commands.

Have an active change from the legacy workflow?

text
/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?

text
/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

config.yaml 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

When determining which schema to use, OPSX checks in order:

  1. CLI flag: --schema <name> (highest priority)
  2. Change metadata: .openspec.yaml in the change directory
  3. Project config: openspec/config.yaml
  4. Default: spec-driven

Available Schemas

Schema Artifacts Best For
spec-driven proposal → specs → design → tasks Most projects

List all available schemas:

bash
openspec 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 for details.


Troubleshooting

"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

Restart your IDE. Skills are detected at startup.

"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

  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

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?

Run init and decline the cleanup prompt—you'll see the full detection summary without any changes being made.


Quick Reference

Files After Migration

text
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-update-change/
│       ├── openspec-sync-specs/
│       ├── openspec-archive-change/
│       └── ...                   # 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

  • .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

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


File: docs/multi-language.md

Multi-Language Guide

Configure OpenSpec to generate artifacts in languages other than English.

Quick Setup

For a new project, set the language during initialization:

bash
openspec init --language "Portuguese (pt-BR)"

This writes the language instruction to openspec/config.yaml. If the project
already has a config, edit its context field directly so existing project
guidance is preserved.

You can also configure the same behavior manually:

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.
  Keep OpenSpec structural headings and SHALL/MUST keywords in English.

  # Your other project context below...
  Tech stack: TypeScript, React, Node.js

That's it. All generated artifacts will now be in Portuguese.

OpenSpec's document structure and normative SHALL/MUST keywords remain in
English because validation relies on them. The surrounding requirement and
scenario prose can use your selected language.

Language Examples

Portuguese (Brazil)

yaml
context: |
  Language: Portuguese (pt-BR)
  All artifacts must be written in Brazilian Portuguese.

Spanish

yaml
context: |
  Idioma: Español
  Todos los artefactos deben escribirse en español.

Chinese (Simplified)

yaml
context: |
  语言:中文(简体)
  所有产出物必须用简体中文撰写。

Japanese

yaml
context: |
  言語:日本語
  すべての成果物は日本語で作成してください。

French

yaml
context: |
  Langue : Français
  Tous les artefacts doivent être rédigés en français.

German

yaml
context: |
  Sprache: Deutsch
  Alle Artefakte müssen auf Deutsch verfasst werden.

Tips

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

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

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

File: docs/opsx.md

OPSX Workflow

Feedback welcome on Discord.

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

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
text
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 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
text
proposal ──→ specs ──→ design ──→ tasks ──→ implement

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, update, 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 config lets you set defaults and inject project-specific context into all artifacts.

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

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

Schema precedence (highest to lowest):

  1. CLI flag (--schema <name>)
  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 <context>...</context> tags
  • Helps AI understand your project's conventions

Rules injection:

  • Rules are only injected for matching artifacts
  • Wrapped in <rules>...</rules> tags
  • Appear after context, before the template

Artifact IDs by Schema

spec-driven (default):

  • proposal — Change proposal
  • specs — Specifications
  • design — Technical design
  • tasks — Implementation tasks

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

"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

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 Merge delta specs into main specs (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

Explore an idea

text
/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

text
/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

text
/opsx:continue

Shows what's ready to create based on dependencies, then creates one artifact. Use repeatedly to build up your change incrementally.

text
/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)

text
/opsx:apply

Works through tasks, checking them off as you go. If you're juggling multiple changes, you can run /opsx:apply <name>; otherwise it should infer from the conversation and prompt you to choose if it can't tell.

Updating a change

text
/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.

Sync delta specs

text
/opsx:sync

Merges the current change's delta specs into your main openspec/specs/ without archiving — the change stays active. It applies the whole delta: a requirement under ## REMOVED is deleted from the main spec and a renamed one is retitled in place, while content the delta doesn't mention is left untouched. Syncing is optional — archive prompts you to sync first if you haven't. Reach for it when you want main specs updated before archiving, when a parallel change needs to build on specs this one just added, or when you want to review the merged main spec before archiving.

Finish up

text
/opsx:archive   # Move to archive when done (prompts to sync specs if needed)

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

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:

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:

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

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
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

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?

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

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

text
/* Detailed source-code truncated for AI context efficiency. */

Component Architecture

Legacy workflow uses hardcoded templates in TypeScript:

text
┌─────────────────────────────────────────────────────────────────────────────┐
│                      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:

text
/* Detailed source-code truncated for AI context efficiency. */

Dependency Graph Model

Artifacts form a directed acyclic graph (DAG). Dependencies are enablers, not gates:

text
proposal
                             (root node)
                                  │
                    ┌─────────────┴─────────────┐
                    │                           │
                    ▼                           ▼
                 specs                       design
              (requires:                  (requires:
               proposal)                   proposal)
                    │                           │
                    └─────────────┬─────────────┘
                                  │
                                  ▼
                               tasks
                           (requires:
                           specs, design)
                                  │
                                  ▼
                          ┌──────────────┐
                          │ APPLY PHASE  │
                          │ (requires:   │
                          │  tasks)      │
                          └──────────────┘

State transitions:

text
BLOCKED ────────────────► READY ────────────────► DONE
      │                        │                       │
   Missing                  All deps               File exists
   dependencies             are DONE               on filesystem

Information Flow

Legacy workflow — agent receives static instructions:

text
User: "/openspec:proposal"
           │
           ▼
  ┌─────────────────────────────────────────┐
  │  Static instructions:                   │
  │  • Create proposal.md                   │
  │  • Create tasks.md                      │
  │  • Create design.md                     │
  │  • Create delta spec files              │
  │                                         │
  │  No awareness of what exists or         │
  │  dependencies between artifacts         │
  └─────────────────────────────────────────┘
           │
           ▼
  Agent creates ALL artifacts in one go

OPSX — agent queries for rich context:

text
/* Detailed source-code truncated for AI context efficiency. */

Iteration Model

Legacy workflow — awkward to iterate:

text
┌─────────┐     ┌─────────┐     ┌─────────┐
  │/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:

text
/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

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:

text
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:

text
research ──► proposal ──► tasks

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 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

  • 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

This is rough. That's intentional — we're learning what works.

Found a bug? Have ideas? Join us on Discord or open an issue on GitHub.