File: README.md
The most loved spec framework.
Our philosophy:
→ 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
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:
## 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 choiceYour 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:
npm install @fission-ai/openspec@latestThen navigate to your project directory and initialize:
cd your-project
openspec initWant 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
npm install @fission-ai/openspec@latestRefresh agent instructions
Run this inside each project to regenerate AI guidance and ensure the latest slash commands are active:
openspec updateUsage 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 devorpnpm 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=0orexport 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.
openspec init [path] [options]Use --language <language> to add a language instruction to a new project'sopenspec/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_TOOLSinsrc/core/config.ts. See Supported Tools for each tool's skill and command paths.
Examples:
# 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 --forceWhat it creates:
openspec/
├── specs/ # Your specifications (source of truth)
├── changes/ # Proposed changes
└── config.yaml # Project configuration
.claude/skills/ # Claude Code skills (if claude selected)
.cursor/skills/ # Cursor skills (if cursor selected)
.cursor/commands/ # Cursor OPSX commands (if delivery includes commands)
.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.
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:
# Update instruction files after npm upgrade
npm install @fission-ai/openspec@latest
openspec updateUpgrade 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:
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 (deliverycommands), OpenSpec compares the file contents against what it would generate
now — edits to those files count as drift and are overwritten. With deliveryskills 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.
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:
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/, andopenspec/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.
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.
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.
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.
openspec store list [--json]
openspec store ls [--json]`openspec store doctor`
Check local store registration, metadata, and Git presence.
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:
schema: spec-driven
references:
- team-contextFrom 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":
openspec store setup team-context --path ~/openspec/team-context \
--remote [email protected]:acme/team-context.gitThe 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 ):
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:
# openspec/config.yaml (the only file under openspec/)
store: team-contextNormal 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?
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.
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.
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:
{
"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.
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:
# List all active changes
openspec list
# List all specs
openspec list --specs
# JSON output for scripts
openspec list --jsonOutput (text):
Changes:
add-dark-mode No tasks just now`openspec view`
Display an interactive dashboard for exploring specs and changes.
openspec viewOpens a terminal-based interface for navigating your project's specifications and changes.
`openspec show`
Display details of a change or spec.
openspec show [item-name] [options]Arguments:
| Argument | Required | Description |
|---|---|---|
item-name |
No | Name of change or spec (prompts if omitted) |
Options:
| Option | Description |
|---|---|
--type <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:
# 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 --jsonValidation Commands
`openspec validate`
Validate changes and specs for structural issues, and check a change's MODIFIED requirements against the main specs they would replace.
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:
# 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 --archivedOutput (text):
Validating add-dark-mode...
✓ proposal.md valid
✓ specs/ui/spec.md valid
⚠ design.md: missing "Technical Approach" section
1 warning foundOutput (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.
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:
# 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-specsWhat it does:
- Validates the change (unless
--no-validate) - Prompts for confirmation (unless
--yes) - Claims the archive destination before changing any main spec
- 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.yamldeclaresretire_capabilities: truenext to itsschema: - Moves the change folder to
openspec/changes/archive/YYYY-MM-DD-<name>/ - 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
- 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.
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:
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.
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:
# 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 --jsonOutput (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):
{
"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.
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. Usearchive to fetch current, read-only archive inputs (context andoperationGuidance) for a valid change; it does not archive or mutate anything.
Examples:
# 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 --jsonOutput 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.
openspec templates [options]Options:
| Option | Description |
|---|---|
--schema <name> |
Schema to inspect (default: spec-driven) |
--json |
Output as JSON |
Examples:
# Show template paths for default schema
openspec templates
# Show templates for custom schema
openspec templates --schema my-workflow
# JSON for programmatic use
openspec templates --jsonOutput (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.
openspec schemas [options]Options:
| Option | Description |
|---|---|
--json |
Output as JSON |
--store |
Use a registered store as the OpenSpec root |
Example:
openspec schemasOutput:
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 → tasksSchema Commands
Commands for creating and managing custom workflow schemas.
`openspec schema init`
Create a new project-local schema.
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:
# Interactive schema creation
openspec schema init research-first
# Non-interactive with specific artifacts
openspec schema init rapid \
--description "Rapid iteration workflow" \
--artifacts "proposal,tasks" \
--defaultWhat it creates:
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.
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:
# Fork the built-in spec-driven schema
openspec schema fork spec-driven my-workflow`openspec schema validate`
Validate a schema's structure and templates.
openspec schema validate [name] [options]Arguments:
| Argument | Required | Description |
|---|---|---|
name |
No | Schema to validate (validates all if omitted) |
Options:
| Option | Description |
|---|---|
--verbose |
Show detailed validation steps |
--json |
Output as JSON |
Example:
# 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).
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:
# Check where a schema comes from
openspec schema which spec-drivenOutput:
spec-driven resolves from: package
Source: /usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-drivenSchema precedence:
- Project:
openspec/schemas/<name>/ - User:
~/.local/share/openspec/schemas/<name>/ - Package: Built-in schemas
Configuration Commands
`openspec config`
View and modify global OpenSpec configuration.
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:
# 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 coreTelemetry 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:
# 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 confirmUtility Commands
`openspec feedback`
Submit feedback about OpenSpec. Creates a GitHub issue.
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:
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.
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:
# 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 uninstallCompletions 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 |
Related Documentation
- Commands - AI slash commands (
/opsx:propose,/opsx:apply, etc.) - Workflows - Common patterns and when to use each command
- Customization - Create custom schemas and templates
- Getting Started - First-time setup guide
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:
/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:
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:
/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:
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:
/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.yamlmetadata file in the change folder - Shows the first artifact template ready for creation
- Prompts for change name and schema if not provided
What it creates:
openspec/changes/<change-name>/
└── .openspec.yaml # Change metadata (schema, created date)Example:
You: /opsx:new add-dark-mode
AI: Created openspec/changes/add-dark-mode/
Schema: spec-driven
Ready to create: proposal
Use /opsx:continue to create it, or /opsx:ff to create all artifacts.Tips:
- Use descriptive names:
add-feature,fix-bug,refactor-module - Avoid generic names like
update,changes,wip - Schema can also be set in project config (
openspec/config.yaml)
`/opsx:continue`
Create the next artifact in the dependency chain. Creates one artifact at a time for incremental progress.
Syntax:
/opsx:continue [change-name]Arguments:
| Argument | Required | Description |
|---|---|---|
change-name |
No | Which change to continue (inferred from context if not provided) |
What it does:
- Queries the artifact dependency graph
- Shows which artifacts are ready vs blocked
- Creates the first ready artifact
- Reads dependency files for context
- Shows what becomes available after creation
Example:
You: /opsx:continue
AI: Change: add-dark-mode
Artifact status:
✓ proposal (done)
◆ specs (ready)
◆ design (ready)
○ tasks (blocked - needs: specs, 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:
/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-requiredartifacts are complete - Reads each dependency before creating the next artifact
Example:
You: /opsx:ff add-dark-mode
AI: Fast-forwarding add-dark-mode...
✓ Creating proposal.md
✓ Creating specs/ui/spec.md
✓ Creating design.md
✓ Creating tasks.md
All planning artifacts complete!
Ready for implementation. Run /opsx:apply to begin.Tips:
- Use when you have a clear picture of what you're building
- Faster than
/opsx:continuefor 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:
/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.mdand identifies incomplete tasks - Works through tasks one by one
- Writes code, creates files, runs tests as needed
- Marks tasks complete with checkboxes
[x]
Example:
You: /opsx:apply
AI: Implementing add-dark-mode...
Reading tasks.md:
- [ ] 1.1 Create ThemeContext
- [ ] 1.2 Add CSS custom properties
- [ ] 1.3 Implement localStorage persistence
Working on 1.1: Create ThemeContext...
[Creates src/context/ThemeContext.tsx]
✓ 1.1 Complete
Working on 1.2: Add CSS custom properties...
[Updates src/styles/globals.css]
✓ 1.2 Complete
...Tips:
- Can resume where you left off if interrupted
- Use for parallel changes by specifying the change name
- Completion state is tracked in
tasks.mdcheckboxes
`/opsx:update`
Revise a change's existing planning artifacts and keep them coherent with one another. Planning artifacts only - it never edits code.
Syntax:
/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:
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:applyso 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:
/opsx:verify [change-name]Arguments:
| Argument | Required | Description |
|---|---|---|
change-name |
No | Which change to verify (inferred from context if not provided) |
What it does:
- Checks three dimensions of implementation quality
- Searches codebase for implementation evidence
- Reports issues categorized as CRITICAL, WARNING, or SUGGESTION
- Does not block archive, but surfaces issues
Verification dimensions:
| Dimension | What it validates |
|---|---|
| Completeness | All tasks done, all requirements implemented, scenarios covered |
| Correctness | Implementation matches spec intent, edge cases handled |
| Coherence | Design decisions reflected in code, patterns consistent |
Example:
You: /opsx:verify
AI: Verifying add-dark-mode...
COMPLETENESS
✓ All 8 tasks in tasks.md are checked
✓ All requirements in specs have corresponding code
⚠ Scenario "System preference detection" has no test coverage
CORRECTNESS
✓ Implementation matches spec intent
✓ Edge cases from scenarios are handled
✓ Error states match spec definitions
COHERENCE
✓ Design decisions reflected in code structure
✓ Naming conventions consistent with design.md
⚠ Design mentions "CSS variables" but implementation uses Tailwind classes
SUMMARY
─────────────────────────────
Critical issues: 0
Warnings: 2
Ready to archive: Yes (with warnings)
Recommendations:
1. Add test for system preference detection
2. Update design.md to reflect Tailwind usage, or refactor to use CSS variablesTips:
- 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:
/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:
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:
/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:
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:verifyfirst to catch issues
`/opsx:bulk-archive`
Archive multiple completed changes at once. Handles spec conflicts between changes.
Syntax:
/opsx:bulk-archive [change-names...]Arguments:
| Argument | Required | Description |
|---|---|---|
change-names |
No | Specific changes to archive (prompts to select if not provided) |
What it does:
- Lists all completed changes
- Validates each change before archiving
- Detects spec conflicts across changes
- Resolves conflicts by checking what's actually implemented
- Archives in chronological order
Example:
You: /opsx:bulk-archive
AI: Found 3 completed changes:
- add-dark-mode (8/8 tasks complete)
- fix-login-bug (3/3 tasks complete)
- update-footer (2/2 tasks complete)
Checking for spec conflicts...
⚠ add-dark-mode and update-footer both touch specs/ui/
Inspecting codebase to resolve...
Both changes are implemented. Will merge in chronological order:
1. add-dark-mode (created Jan 20)
2. update-footer (created Jan 22)
Archive all 3 changes?
You: Yes
AI: ✓ Archived add-dark-mode
✓ Archived fix-login-bug
✓ Archived update-footer
Specs merged: add-dark-mode → update-footerTips:
- 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:
/opsx:onboardWhat 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:
- Welcome and codebase analysis
- Finding an improvement opportunity
- Creating a change (
/opsx:new) - Writing the proposal
- Creating specs
- Writing the design
- Creating tasks
- Implementing tasks (
/opsx:apply) - Verifying implementation
- Archiving the change
- Summary and next steps
Example:
You: /opsx:onboard
AI: Welcome to OpenSpec!
I'll walk you through the complete workflow using your actual codebase.
We'll find something small to improve, create a proper change for it,
implement it, and archive it.
Let me scan your codebase for opportunities...
[Analyzes codebase]
I found a few things we could work on:
1. Add input validation to the contact form
2. Improve error messages in the auth flow
3. Add loading states to async buttons
Which interests you? (or suggest something else)Tips:
- Best for new users learning the workflow
- Uses real code, not toy examples
- Creates a real change you can keep or discard
- Takes 15-30 minutes to complete
Command Syntax by AI Tool
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-*.mdfiles 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:continueinstead of/opsx:fffor 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:
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 greenfieldWhy 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:
┌────────────────────────────────────────────────────────────────────┐
│ 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
openspec/specs/
├── auth/
│ └── spec.md # Authentication behavior
├── payments/
│ └── spec.md # Payment processing
├── notifications/
│ └── spec.md # Notification system
└── ui/
└── spec.md # UI behavior and themesOrganize 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:
# 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-authenticateKey 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.mdortasks.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:
- Human provides intent, context, and constraints.
- Agent converts this into behavior-first requirements and scenarios.
- Agent keeps implementation detail in
design.mdandtasks.md, notspec.md. - 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
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.mdEach 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:
Everything together. Proposal, design, tasks, and specs live in one place. No hunting through different locations.
Parallel work. Multiple changes can exist simultaneously without conflicting. Work on
add-dark-modewhilefix-auth-bugis also in progress.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.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
proposal ──────► specs ──────► design ──────► tasks ──────► implement
│ │ │ │
why what how steps
+ scope changes approach to takeArtifacts 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.
# 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.
# 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.
# 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 accessibilityTask 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
# 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
# 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 firstArtifacts form a dependency graph:
proposal
(root node)
│
┌─────────────┴─────────────┐
│ │
▼ ▼
specs design
(requires: (requires:
proposal) proposal)
│ │
└─────────────┬─────────────┘
│
▼
tasks
(requires:
specs, design)Dependencies are enablers, not gates. They show what's possible to create, not what you must create next. You can skip design if you don't need it. You can create specs before or after design — both depend only on proposal.
Built-in Schemas
spec-driven (default)
The standard workflow for spec-driven development:
proposal → specs → design → tasks → implementBest for: Most feature work where you want to agree on specs before implementation.
Custom Schemas
Create custom schemas for your team's workflow:
# Create from scratch
openspec schema init research-first
# Or fork an existing one
openspec schema fork spec-driven research-firstExample custom schema:
# 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 tasksSee 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
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.mdThe Archive Process
Merge deltas. Each delta spec section (ADDED/MODIFIED/REMOVED) is applied to the corresponding main spec.
Move to archive. The change folder moves to
changes/archive/with a date prefix for chronological ordering.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
/* Detailed source-code truncated for AI context efficiency. */The virtuous cycle:
- Specs describe current behavior
- Changes propose modifications (as deltas)
- Implementation makes the changes real
- Archive merges deltas into specs
- Specs now describe the new behavior
- 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
- Getting Started - Practical first steps
- Workflows - Common patterns and when to use each
- Commands - Full command reference
- Customization - Create custom schemas and configure your project
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
--schemaon 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
openspec initThis walks you through creating a config interactively. Or create one manually:
# 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: falseHow It Works
Default schema:
# Without config
openspec new change my-feature --schema spec-driven
# With config - schema is automatic
openspec new change my-featureContext and rules injection:
When generating any artifact, your context and rules are injected into the AI prompt:
<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:
openspec instructions apply --change my-feature --json
openspec instructions archive --change my-feature --jsonBoth surfaces return current project context and matchingoperationGuidance 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 useartifactPaths.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 currentopenspec instructions specs --change <name> --json output. The returnedspecs 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:
- CLI flag:
--schema <name> - Change metadata (
.openspec.yamlin the change folder) - Project config (
openspec/config.yaml) - 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.
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:
openspec schema fork spec-driven my-workflowThis copies the entire spec-driven schema to openspec/schemas/my-workflow/ where you can edit it freely.
What you get:
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 tasksNow 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:
# Interactive
openspec schema init research-first
# Non-interactive
openspec schema init rapid \
--description "Rapid iteration workflow" \
--artifacts "proposal,tasks" \
--defaultSchema Structure
A schema defines the artifacts in your workflow and how they depend on each other:
# 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.mdKey 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.
## Why
## What Changes
## ImpactTemplates 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:
openspec schema validate my-workflowThis checks:
schema.yamlsyntax is correct- All referenced templates exist
- No circular dependencies
- Artifact IDs are valid
Use Your Custom Schema
Once created, use your schema with:
# Specify on command
openspec new change feature --schema my-workflow
# Or set as default in config.yaml
schema: my-workflowDebug Schema Resolution
Not sure which schema is being used? Check with:
# See where a specific schema resolves from
openspec schema which my-workflow
# List all available schemas
openspec schema which --allOutput shows whether it's from your project, user directory, or the package:
Schema: my-workflow
Source: project
Path: /path/to/project/openspec/schemas/my-workflowNote: OpenSpec also supports user-level schemas at
~/.local/share/openspec/schemas/for sharing across projects, but project-level schemas inopenspec/schemas/are recommended since they're version-controlled with your code.
Examples
Rapid Iteration Workflow
A minimal workflow for quick iterations:
# 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.mdAdding a Review Artifact
Fork the default and add a review step:
openspec schema fork spec-driven with-reviewThen edit schema.yaml to add:
- 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 tooCommunity 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
- CLI Reference: Schema Commands - Full command documentation
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 (likeopenspec 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:
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):
/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):
/opsx:new ──► /opsx:ff or /opsx:continue ──► /opsx:apply ──► /opsx:verify ──► /opsx:archiveThe 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:
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 mainspecs/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:
proposal ──► specs ──► design ──► tasks ──► implement
▲ ▲ ▲ │
└───────────┴──────────┴────────────────────┘
update as you learnYou 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:
# 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:
- ADDED requirements are appended to the main spec
- MODIFIED requirements replace the existing version
- 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)
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:
# 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:
# 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 usedtasks.md - Implementation checklist:
# 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 variables3. Implement
You: /opsx:apply
AI: Working through tasks...
✓ 1.1 Created ThemeContext with light/dark state
✓ 1.2 Added CSS custom properties to globals.css
✓ 1.3 Implemented localStorage persistence
✓ 2.1 Created ThemeToggle component
...
All tasks complete!During implementation, if you discover the design needs adjustment, just update the artifact and continue.
4. Archive
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:
# List active changes
openspec list
# View change details
openspec show add-dark-mode
# Validate spec formatting
openspec validate add-dark-mode
# Interactive dashboard
openspec viewNext Steps
- Explore First - Use
/opsx:exploreto think through an idea before you commit - Reviewing a Change - What to check in the plan the AI drafts, before any code
- Writing Good Specs - What a strong requirement and scenario look like
- Using OpenSpec in an Existing Project - Start on a large brownfield codebase
- Editing & Iterating on a Change - Update artifacts, go back, reconcile manual edits
- Core Concepts at a Glance - The whole mental model on one page
- Examples & Recipes - Real changes, start to finish
- Workflows - Common patterns and when to use each command
- Commands - Full reference for all slash commands
- Concepts - Deeper understanding of specs, changes, and schemas
- Customization - Make OpenSpec work your way
- Stores - Planning that spans repos or teams? Keep it in its own repo (beta)
- FAQ and Troubleshooting - When you get stuck
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.
/* 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
npm install @fission-ai/openspec@latestpnpm
pnpm add @fission-ai/openspec@latestyarn
yarn global add @fission-ai/openspec@latestYarn 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
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.1Note: 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.
bun add -g @fission-ai/openspec@latestNix
Run OpenSpec directly without installation:
nix run github:Fission-AI/OpenSpec -- initOr install to your profile:
nix profile install github:Fission-AI/OpenSpecOr add to your development environment in flake.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
openspec --versionUpdating
Upgrade the package, then refresh each project's generated files:
npm install @fission-ai/openspec@latest # or pnpm/yarn/bun equivalent
openspec update # run inside each projectopenspec 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:
npm uninstall -g @fission-ai/openspec # or: pnpm rm -g / yarn global remove / bun rm -g2. Remove OpenSpec from a project (optional). Delete the openspec/ directory if you no longer want its specs and changes:
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:
cd your-project
openspec initSee 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-managedSKILL.mdfiles under the former.codex/skillspath are reconciled only after replacements exist; custom files and divergent copies stay in place. If an unmarked.agentstree already contains OpenSpec skills, OpenSpec preserves its existing Codex ($openspec-*) or generic (/openspec-*) rendering instead of guessing from the legacy directory. Selectcodexexplicitly withopenspec initto switch ownership. Legacy prompt cleanup still targets only OpenSpec's allowlisted filenames in$CODEX_HOME/promptsor~/.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:
- Review its contents
- Move useful context to
openspec/config.yaml(see guidance below) - 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
customprofile when needed.
Using `openspec init`
Run this if you want to add new tools or reconfigure which tools are set up:
openspec initThe init command detects legacy files and guides you through cleanup:
Upgrading to the new OpenSpec
OpenSpec now uses agent skills, the emerging standard across coding
agents. This simplifies your setup while keeping everything working
as before.
Files to remove
No user content to preserve:
• .claude/commands/openspec/
• openspec/AGENTS.md
Files to update
OpenSpec markers will be removed, your content preserved:
• CLAUDE.md
• AGENTS.md
Needs your attention
• openspec/project.md
We won't delete this file. It may contain useful project context.
The new openspec/config.yaml has a "context:" section for planning
context. This is included in every OpenSpec request and works more
reliably than the old project.md approach.
Review project.md, move any useful content to config.yaml's context
section, then delete the file when ready.
? Upgrade and clean up legacy files? (Y/n)What happens when you say yes:
- Legacy slash command directories are removed
- OpenSpec markers are stripped from
CLAUDE.md,AGENTS.md, etc. (your content stays) openspec/AGENTS.mdis deleted- New skills are installed in
.claude/skills/ openspec/config.yamlis 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:
openspec updateThe 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:
openspec init --force --tools claudeThe --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)
# 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 specificationsAfter (config.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 flowsKey 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
Create config.yaml (if not already created by init):
yamlschema: spec-drivenAdd your context (be concise—this goes into every request):
yamlcontext: | Your project background goes here. Focus on what the AI genuinely needs to know.Add per-artifact rules (optional):
yamlrules: proposal: - Your proposal-specific guidance specs: - Your spec-writing rulesDelete 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:
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:
/opsx:continueCreates one artifact at a time based on dependencies. Use this when you want to review each step.
Exploration mode:
/opsx:exploreThink 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:
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ PLANNING │ ───► │ IMPLEMENTING │ ───► │ ARCHIVING │
│ PHASE │ │ PHASE │ │ PHASE │
└──────────────┘ └──────────────┘ └──────────────┘
If you're in implementation and realize the design is wrong?
Too bad. Phase gates don't let you go back easily.OPSX uses actions, not phases:
┌───────────────────────────────────────────────┐
│ ACTIONS (not phases) │
│ │
│ new ◄──► continue ◄──► apply ◄──► archive │
│ │ │ │ │ │
│ └──────────┴───────────┴─────────────┘ │
│ any order │
└───────────────────────────────────────────────┘Dependency Graph
Artifacts form a directed graph. Dependencies are enablers, not gates:
proposal
(root node)
│
┌─────────────┴─────────────┐
│ │
▼ ▼
specs design
(requires: (requires:
proposal) proposal)
│ │
└─────────────┬─────────────┘
│
▼
tasks
(requires:
specs, design)When you run /opsx:continue, it checks what's ready and offers the next artifact. You can also create multiple ready artifacts in any order.
Skills vs Commands
The legacy system used tool-specific command files:
.claude/commands/openspec/
├── proposal.md
├── apply.md
└── archive.mdOPSX uses the emerging skills standard:
.claude/skills/
├── openspec-explore/SKILL.md
├── openspec-new-change/SKILL.md
├── openspec-continue-change/SKILL.md
├── openspec-apply-change/SKILL.md
└── ...Skills are recognized across multiple AI coding tools and provide richer metadata.
Codex is skills-only in OPSX. OpenSpec no longer generates Codex custom prompt files; use the generated .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?
/opsx:apply add-my-featureOPSX reads the existing artifacts and continues from where you left off.
Want to add more artifacts to an existing change?
/opsx:continue add-my-featureShows what's ready to create based on what already exists.
Need to see status?
openspec status --change add-my-featureThe New Config System
config.yaml Structure
# 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 chunksSchema Resolution
When determining which schema to use, OPSX checks in order:
- CLI flag:
--schema <name>(highest priority) - Change metadata:
.openspec.yamlin the change directory - Project config:
openspec/config.yaml - Default:
spec-driven
Available Schemas
| Schema | Artifacts | Best For |
|---|---|---|
spec-driven |
proposal → specs → design → tasks | Most projects |
List all available schemas:
openspec schemasCustom Schemas
Create your own workflow:
openspec schema init my-workflowOr fork an existing one:
openspec schema fork spec-driven my-workflowSee Customization for details.
Troubleshooting
"Legacy files detected in non-interactive mode"
You're running in a CI or non-interactive environment. Use:
openspec init --forceCommands 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:
openspec schemas --jsonConfig not being applied
- Ensure the file is at
openspec/config.yaml(not.yml) - Validate YAML syntax
- 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
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 preservedWhat's Gone
.claude/commands/openspec/— replaced by.claude/skills/openspec/AGENTS.md— obsoleteopenspec/project.md— migrate toconfig.yaml, then delete- OpenSpec marker blocks in
CLAUDE.md,AGENTS.md, etc.
Command Cheatsheet
/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 artifactsGetting Help
- Discord: discord.gg/YctCnvvshC
- GitHub Issues: github.com/Fission-AI/OpenSpec/issues
- Documentation: docs/opsx.md for the full OPSX reference
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:
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:
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.jsThat'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)
context: |
Language: Portuguese (pt-BR)
All artifacts must be written in Brazilian Portuguese.Spanish
context: |
Idioma: Español
Todos los artefactos deben escribirse en español.Chinese (Simplified)
context: |
语言:中文(简体)
所有产出物必须用简体中文撰写。Japanese
context: |
言語:日本語
すべての成果物は日本語で作成してください。French
context: |
Langue : Français
Tous les artefacts doivent être rédigés en français.German
context: |
Sprache: Deutsch
Alle Artefakte müssen auf Deutsch verfasst werden.Tips
Handle Technical Terms
Decide how to handle technical terminology:
context: |
Language: Japanese
Write in Japanese, but:
- Keep technical terms like "API", "REST", "GraphQL" in English
- Code examples and file paths remain in EnglishCombine with Other Context
Language settings work alongside your other project context:
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 ORMVerification
To verify your language config is working:
# Check the instructions - should show your language context
openspec instructions proposal --change my-change
# Output will include your language contextRelated Documentation
- Customization Guide - Project configuration options
- Workflows Guide - Full workflow documentation
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:
- Experiment with instructions — edit a template, see if the AI does better
- Test granularly — validate each artifact's instructions independently
- Customize workflows — define your own artifacts and dependencies
- Iterate quickly — change a template, test immediately, no rebuild
Legacy workflow: OPSX:
┌────────────────────────┐ ┌────────────────────────┐
│ Hardcoded in package │ │ schema.yaml │◄── You edit this
│ (can't change) │ │ templates/*.md │◄── Or this
│ ↓ │ │ ↓ │
│ Wait for new release │ │ Instant effect │
│ ↓ │ │ ↓ │
│ Hope it's better │ │ Test it yourself │
└────────────────────────┘ └────────────────────────┘This is for everyone:
- Teams — create workflows that match how you actually work
- Power users — tweak prompts to get better AI outputs for your codebase
- OpenSpec contributors — experiment with new approaches without releases
We're all still learning what works best. OPSX lets us learn together.
The User Experience
The problem with linear workflows:
You're "in planning phase", then "in implementation phase", then "done". But real work doesn't work that way. You implement something, realize your design was wrong, need to update specs, continue implementing. Linear phases fight against how work actually happens.
OPSX approach:
- Actions, not phases — create, implement, update, archive — do any of them anytime
- Dependencies are enablers — they show what's possible, not what's required next
proposal ──→ specs ──→ design ──→ tasks ──→ implementSetup
# Make sure you have openspec installed — skills are automatically generated
openspec initThis 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:
# 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 flowsConfig 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):
- CLI flag (
--schema <name>) - Change metadata (
.openspec.yamlin change directory) - Project config (
openspec/config.yaml) - 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 proposalspecs— Specificationsdesign— Technical designtasks— Implementation tasks
Config Validation
- Unknown artifact IDs in
rulesgenerate 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 --jsonto 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
/opsx:exploreThink 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
/opsx:proposeCreates the change and generates planning artifacts needed before implementation.
If you've enabled expanded workflows, you can instead use:
/opsx:new # scaffold only
/opsx:continue # create one artifact at a time
/opsx:ff # create all planning artifacts at onceCreate artifacts
/opsx:continueShows what's ready to create based on dependencies, then creates one artifact. Use repeatedly to build up your change incrementally.
/opsx:ff add-dark-modeCreates all planning artifacts at once. Use when you have a clear picture of what you're building.
Implement (the fluid part)
/opsx:applyWorks 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
/opsx:update add-dark-mode - we're storing the theme in a cookie nowRevises 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
/opsx:syncMerges 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
/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:
- Intent — What problem are you solving?
- Scope — What's in/out of bounds?
- 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
┌─────────────────────────────────────┐
│ 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
/* Detailed source-code truncated for AI context efficiency. */Component Architecture
Legacy workflow uses hardcoded templates in TypeScript:
┌─────────────────────────────────────────────────────────────────────────────┐
│ LEGACY WORKFLOW COMPONENTS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Hardcoded Templates (TypeScript strings) │
│ │ │
│ ▼ │
│ Tool-specific configurators/adapters │
│ │ │
│ ▼ │
│ Generated Command Files (.claude/commands/openspec/*.md) │
│ │
│ • Fixed structure, no artifact awareness │
│ • Change requires code modification + rebuild │
│ │
└─────────────────────────────────────────────────────────────────────────────┘OPSX uses external schemas and a dependency graph engine:
/* Detailed source-code truncated for AI context efficiency. */Dependency Graph Model
Artifacts form a directed acyclic graph (DAG). Dependencies are enablers, not gates:
proposal
(root node)
│
┌─────────────┴─────────────┐
│ │
▼ ▼
specs design
(requires: (requires:
proposal) proposal)
│ │
└─────────────┬─────────────┘
│
▼
tasks
(requires:
specs, design)
│
▼
┌──────────────┐
│ APPLY PHASE │
│ (requires: │
│ tasks) │
└──────────────┘State transitions:
BLOCKED ────────────────► READY ────────────────► DONE
│ │ │
Missing All deps File exists
dependencies are DONE on filesystemInformation Flow
Legacy workflow — agent receives static instructions:
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 goOPSX — agent queries for rich context:
/* Detailed source-code truncated for AI context efficiency. */Iteration Model
Legacy workflow — awkward to iterate:
┌─────────┐ ┌─────────┐ ┌─────────┐
│/proposal│ ──► │ /apply │ ──► │/archive │
└─────────┘ └─────────┘ └─────────┘
│ │
│ ├── "Wait, the design is wrong"
│ │
│ ├── Options:
│ │ • Edit files manually (breaks context)
│ │ • Abandon and start over
│ │ • Push through and fix later
│ │
│ └── No official "go back" mechanism
│
└── Creates ALL artifacts at onceOPSX — natural iteration:
/opsx:new ───► /opsx:continue ───► /opsx:apply ───► /opsx:archive
│ │ │
│ │ ├── "The design is wrong"
│ │ │
│ │ ▼
│ │ Just edit design.md
│ │ and continue!
│ │ │
│ │ ▼
│ │ /opsx:apply picks up
│ │ where you left off
│ │
│ └── Creates ONE artifact, shows what's unlocked
│
└── Scaffolds change, waits for directionCustom Schemas
Create custom workflows using the schema management commands:
# 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-workflowSchemas are stored in openspec/schemas/ (project-local, version controlled) or ~/.local/share/openspec/schemas/ (user global).
Schema structure:
openspec/schemas/research-first/
├── schema.yaml
└── templates/
├── research.md
├── proposal.md
└── tasks.mdExample schema.yaml:
name: research-first
artifacts:
- id: research # Added before proposal
generates: research.md
requires: []
- id: proposal
generates: proposal.md
requires: [research] # Now depends on research
- id: tasks
generates: tasks.md
requires: [proposal]Dependency Graph:
research ──► proposal ──► tasksSummary
| 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
# 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-workflowTips
- Use
/opsx:exploreto think through an idea before committing to a change /opsx:ffwhen you know what you want,/opsx:continuewhen 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.