Key Takeaways
- OpenSpec is a free command-line tool that makes your coding agent write a short plan before it touches code: why the change is needed, what must be true afterwards, how it will be built, and the steps. Those plans live next to the code as specs.
- Use it when you are changing an app that already exists. Each change is written as a delta against the current spec, and archiving the change merges it in, so the spec stays accurate without anyone rewriting it.
- In Claude Code the loop is three commands:
/opsx:proposewrites the plan,/opsx:applyimplements it in a fresh session,/opsx:archivemerges it. Tutorials that show/openspec:proposalare out of date. - Your job is the review between propose and apply. The spec delta is the contract the agent codes against, and a scenario heading at the wrong level drops a requirement without any error.
- Skip it for one-file fixes and copy changes. Four files per change is real overhead, and the merged spec is only worth keeping if someone will read it.
OpenSpec is a small command-line tool that makes a coding agent plan a change before it writes any code. It has become one of the most-used tools of its kind, with about 72,000 GitHub stars (Fission-AI/OpenSpec, October 17, 2026). It also replaced its commands in January, so most tutorials you will find still teach commands that no longer exist.
This guide walks through one real change in Claude Code from start to finish: we propose it, let the agent build it, then archive it, and we show every file OpenSpec creates on the way. Every terminal output is pasted from a real run on the current version, 1.14.3, in October 2026, including the one where we broke the spec on purpose to see whether the validator would notice. If you want the case for why a written spec beats a prompt, our spec-driven development guide makes it. This post covers how to run the tool.
What OpenSpec Does, in One Paragraph
OpenSpec is a command-line tool plus a set of slash commands that keep a folder of specs next to your code and route every change through four short files before the agent writes a line: a proposal that says why, a spec delta that says what must be true afterwards, a design note that says how, and a task list with the steps. OpenSpec calls those four files artifacts. The part that separates it from a folder of PRDs is the delta. You describe a change as requirements that are ADDED, MODIFIED, REMOVED or RENAMED, and when the work is done, openspec archive merges those deltas into the standing spec. The spec stays current without anyone rewriting it, which is why the project calls itself a tool for code that already exists rather than for green-field projects.
It is MIT-licensed, it is a single Node package, and the same six workflows install into Claude Code, Codex, Cursor, Copilot and most other coding agents, each with its own spelling of the command names.
Before You Start: Node 20.19, Claude Code, a Codebase That Exists
We ran everything below on our own codebase: a Next.js 16 SaaS with Prisma, Clerk and an organization-scoped REST API, the stack described on our Next.js SaaS starter page. The change is organization API keys, the same example the spec-driven guide uses. Commands are for macOS and Linux shells; on Windows the openspec commands are identical and only the shell around them changes. OpenSpec needs Node.js 20.19 or newer and a project that already has code in it, since an empty repo gives the proposal step nothing to read.
npm install -g @fission-ai/openspec@latest
openspec --version
# Homebrew works too, but it is usually one patch behind npm
brew install openspec Install it globally. We do not show an npx form because the docs do not document one. Patch releases land most weeks, so openspec version --check is worth running before you follow any tutorial, including this one, and Homebrew is usually one patch behind npm. You also need a current Claude Code: if the commands exist on disk but /opsx: shows nothing after setup, the fix in the docs is to update Claude Code and restart it.
Two notes on the blocks below. Terminal output is pasted from the run and trimmed to the lines that matter: spinner lines, absolute paths and footer links are cut. The four planning files are ours, written to the templates the CLI hands the agent and checked with openspec validate, because an agent’s wording differs on every run.
How big is this thing
About 2.9 million npm downloads in the last 30 days, up from about 81,000 in January (npm download counts, October 2026). Downloads include CI runs and mirrors, so read that as installs, not developers.
Step 1: openspec init and the Six Commands It Installs
Run init in the repo root and name the tools you use. Without --tools it asks interactively, and inside a script it uses whatever it detects.
cd acme-saas
openspec init --tools claude OpenSpec Setup Complete
Created: Claude Code
6 skills and 6 commands in .claude/
Config: openspec/config.yaml (schema: spec-driven)
Getting started:
Start your first change: /opsx:propose "your idea" The full output goes on to name the six optional workflows and print two links; we cut those. Here is everything it created, as find lists it: six command files under .claude/commands/opsx/, six matching skills, and an openspec/ folder with one config file and two empty directories. The project says the command and the skill for a workflow carry the same instructions and that it expects to retire the commands eventually, so the skill is the one that will still exist next year.
find openspec .claude -type f | sort
.claude/commands/opsx/apply.md
.claude/commands/opsx/archive.md
.claude/commands/opsx/explore.md
.claude/commands/opsx/propose.md
.claude/commands/opsx/sync.md
.claude/commands/opsx/update.md
.claude/skills/openspec-apply-change/SKILL.md
.claude/skills/openspec-archive-change/SKILL.md
.claude/skills/openspec-explore/SKILL.md
.claude/skills/openspec-propose/SKILL.md
.claude/skills/openspec-sync-specs/SKILL.md
.claude/skills/openspec-update-change/SKILL.md
openspec/changes/archive/.gitkeep
openspec/config.yaml
openspec/specs/.gitkeep What each of the six does:
- explore reads the code and the specs, answers questions, and writes nothing.
- propose creates a change and writes all four planning files for it.
- apply implements the task list and ticks each task off as it goes.
- update revises the planning files after your feedback, without touching code.
- sync merges the change’s deltas into the specs but leaves the change open.
- archive merges the deltas and closes the change.
Six more (new, continue, ff, verify, bulk-archive, onboard) are an openspec config profile away. verify is the one worth adding: it checks a finished change against its spec and reports, without changing anything.
Notice what is absent. There is no CLAUDE.md, no AGENTS.md and no project.md. Version 1.0.0 stopped generating all three and removed the old /openspec:* commands in the same release (OpenSpec changelog, January 2026). If an older install left those files behind, init finds them and offers to clean up. Your own AGENTS.md stays yours; OpenSpec reads it like any other context.
The one file to edit by hand is openspec/config.yaml. Its context: field holds the constraints an agent cannot work out from the code, and rules: caps how long each planning file may be.
schema: spec-driven
context: |
Every Prisma query is scoped by organizationId.
API routes return 403 for a role that lacks the permission.
A new route needs a test before it merges.
rules:
proposal:
- Keep the proposal under 300 words Restart Claude Code so it picks up the commands, commit the new folder, and the setup is done. Slash commands are skills under the hood, and the primitives guide explains why that matters for where the instructions live.
Step 2: /opsx:propose the API-Keys Change
Open Claude Code in the repo and describe the change in plain language. The argument after the command is either a kebab-case name or a description; a description is better, because the agent names the change and the capability for you after reading the existing specs. A capability is OpenSpec’s word for one area of behaviour that gets its own spec file, such as user-auth or org-api-keys.
Your prompt
/opsx:propose Add organization-scoped API keys. Owners and admins create and revoke keys from Settings; keys are hashed at rest and shown once; a request with a Bearer key runs with that key’s organization scope; every create, revoke and failed auth writes an audit row.
The command file spells out what happens next. The agent is told that your request “authorizes planning only, even if it asks to build or fix something”, that it must not edit project code, and that it must stop once the files exist and wait for you. Nothing but those instructions enforces that boundary. If you want it enforced by something stronger, add a hook or a review step.
Under the hood the agent runs openspec context --json to find the project root and read config.yaml, then openspec new change add-org-api-keys, which creates the folder with a single .openspec.yaml inside, then asks openspec status what to write first. The artifacts form a dependency graph, and status shows it: specs and design both wait on the proposal, tasks wait on both.
openspec status --change add-org-api-keys
Change: add-org-api-keys
Schema: spec-driven
Progress: 0/4 artifacts complete
[ ] proposal
[-] specs (blocked by: proposal)
[-] design (blocked by: proposal)
[-] tasks (blocked by: specs, design)
Next: openspec instructions proposal --change "add-org-api-keys" --json For each artifact the agent calls openspec instructions <artifact>, gets the template and the rules back, and writes the file. The proposal instructions also make it run openspec list --specs first so it reuses an existing capability name instead of inventing a near duplicate. When the agent is done, the folder looks like this.
openspec/changes/add-org-api-keys/
├── .openspec.yaml
├── proposal.md
├── design.md
├── tasks.md
└── specs/
└── org-api-keys/
└── spec.md The proposal is the file to read first, because it decides what the rest will cover. Ours has four sections and fits on one screen.
# Proposal
## Why
Customers on the Team plan want to call our REST API from their own
scripts without sharing a login. Today the only credential is a Clerk
session, so there is no way to automate against an organization's data.
## What Changes
- Add organization-scoped API keys: create, list, and revoke from the
dashboard.
- Keys are shown once at creation and stored as a SHA-256 hash.
- Requests with `Authorization: Bearer <key>` resolve to the key's
organization and role.
- Every key read or write is logged to the existing audit log.
## Capabilities
### New Capabilities
- `org-api-keys`: issuing, authenticating, and revoking organization
API keys.
### Modified Capabilities
- (none)
## Impact
- `prisma/schema.prisma`: new `ApiKey` model.
- `src/app/api/keys/`: new routes.
- `src/lib/auth/`: bearer-key resolution next to the Clerk session check.
- `src/app/(dashboard)/settings/api-keys/`: new settings page. Step 3: Read the Delta Spec Before You Trust It
The spec delta lives at openspec/changes/add-org-api-keys/specs/org-api-keys/spec.md, and the path is part of the contract: a delta written as specs/org-api-keys.md is rejected by both validate and archive, because archive never merges a file at that location. This is the file the agent will code against in the next step, so it is the one to spend your review time on. Here is ours in full.
# Spec Delta
## Purpose
Lets an organization issue, use, and revoke API keys so customers can
automate against their own data without sharing a login.
## ADDED Requirements
### Requirement: Owner can create an organization API key
The system SHALL let a user with the owner or admin role create an API
key scoped to their organization, and SHALL show the full key exactly
once at creation.
#### Scenario: Successful creation
- **WHEN** an admin submits a key name on the API keys settings page
- **THEN** the system creates a key, stores only its SHA-256 hash, and
displays the plaintext once
#### Scenario: Member cannot create keys
- **WHEN** a user with the member role requests key creation
- **THEN** the system returns 403 and creates nothing
### Requirement: Bearer key authenticates API requests
The system SHALL accept `Authorization: Bearer <key>` on REST routes
and SHALL resolve the request to the key's organization and the role of
the user who created it.
#### Scenario: Valid key
- **WHEN** a request carries a key whose hash matches an active key
- **THEN** the request runs with that key's organization scope
#### Scenario: Revoked key
- **WHEN** a request carries a key that has been revoked
- **THEN** the system returns 401 and logs the attempt
### Requirement: Key use is audited
The system SHALL write an audit log entry for every key creation,
revocation, and failed authentication attempt.
#### Scenario: Revocation is logged
- **WHEN** an admin revokes a key
- **THEN** the audit log records the actor, the key id, and the time The grammar is small and the validator holds you to it. A new capability opens with ## Purpose; a delta for an existing capability omits that section, and the tool ignores it if you leave it in. Every requirement uses SHALL or MUST and has at least one scenario, and a scenario is a #### heading followed by WHEN and THEN bullets (OpenSpec spec-driven schema docs). The four operations:
| Header | Use it for | Validator rule |
|---|---|---|
ADDED | New behaviour | At least one #### Scenario: per requirement |
MODIFIED | Changed behaviour | Restate the whole requirement with every scenario; a partial block loses detail at archive |
REMOVED | Retired behaviour | Needs a Reason and a Migration line |
RENAMED | Name change only | A FROM: and a TO: line, nothing else |
The mistake to know about is a scenario heading with three hashtags instead of four. We broke one on purpose. The first requirement in our delta has two scenarios, and we gave the second one, the 403 for members, three hashtags. The validator still reported the change as valid. It printed one INFO line, easy to miss, and dropped that scenario, so as far as the agent was concerned the 403 rule no longer existed.
openspec validate add-org-api-keys --strict
Change 'add-org-api-keys' is valid
ℹ [INFO] org-api-keys/spec.md: Header "### Scenario: Member cannot create
keys" in ADDED Requirements is not a "### Requirement:" header and is
ignored by validation. Use "### Requirement: Scenario: Member cannot
create keys" if it should be validated as a requirement. We then did the same to the last requirement, which has only one scenario. With no valid scenario left, the validator fails properly, with an ERROR that stops the run.
openspec validate add-org-api-keys --strict
Change 'add-org-api-keys' has issues
ℹ [INFO] org-api-keys/spec.md: Header "### Scenario: Revocation is logged"
in ADDED Requirements is not a "### Requirement:" header and is ignored
by validation. Use "### Requirement: Scenario: Revocation is logged" if
it should be validated as a requirement.
✗ [ERROR] org-api-keys/spec.md: ADDED "Key use is audited" must include
at least one scenario
Next steps:
- Ensure change has deltas in specs/: use headers
## ADDED/MODIFIED/REMOVED/RENAMED Requirements
- Each requirement MUST include at least one #### Scenario: block
- Debug parsed deltas: openspec show add-org-api-keys --json --deltas-only So the rule is: read the scenarios, count them against what you asked for, and treat an INFO line from the validator as a finding. Once the delta says what you mean, run the strict check and move on.
openspec validate add-org-api-keys --strict
Change 'add-org-api-keys' is valid If something is wrong, edit the file by hand or run /opsx:update add-org-api-keys with your feedback and let the agent revise the artifacts. Either way this is the ten minutes that save the apply step.
Step 4: Fresh Session, Then /opsx:apply
Clear the context first. The quickstart says to “start a fresh chat session, since implementation goes better on a clean context window” (OpenSpec quickstart), and the reason is plain: the planning transcript holds every draft, question and discarded idea from the propose step, and the agent only needs the four files. In Claude Code that is /clear or a new session.
Your prompt
/opsx:apply add-org-api-keys
The agent reads tasks.md, implements the tasks in order, and flips each - [ ] to - [x] as it goes. The tracking rules are strict in a way that matters: only a box holding x counts as done, so [~] and [-] read as unfinished, and a line without a checkbox is not tracked at all. Progress shows up in openspec list: ours read zero of seven tasks before the apply and a tick afterwards.
openspec list
Changes:
add-org-api-keys 0/7 tasks just now openspec list
Changes:
add-org-api-keys ✓ Complete just now Nothing about the session changes because OpenSpec is running. Your hooks still fire, your review subagent still reads the diff, and your CI gate still has the last word; in our kit the security reviewer runs on every change before we accept it, and the apply step is no exception. If the agent ignores a rule from your CLAUDE.md during the apply, the ten causes are the same as for any other session.
Step 5: Check the Diff, Then /opsx:archive
Before closing the change, look at what will merge. openspec show add-org-api-keys --diff prints the proposal and then the spec changes against the standing specs; for a brand-new capability every requirement shows as added, each with its full text underneath, which we cut here. The old openspec diff command was removed as redundant; show --diff is the replacement.
openspec show add-org-api-keys --diff
Specifications Changed (diffs)
org-api-keys
ADDED: Owner can create an organization API key
ADDED: Bearer key authenticates API requests
ADDED: Key use is audited If you added the optional profile, /opsx:verify gives you a completeness, correctness and coherence report and changes nothing. Then archive, either with /opsx:archive add-org-api-keys in the agent or straight from the terminal.
openspec archive add-org-api-keys -y
Task status: ✓ Complete
Specs to update:
org-api-keys: create
Applying changes to openspec/specs/org-api-keys/spec.md:
+ 3 added
Totals: + 3, ~ 0, - 0, → 0
Specs updated successfully.
Change 'add-org-api-keys' archived as '2026-10-17-add-org-api-keys'. Three things happened in that output. The change was validated again. The deltas were merged into openspec/specs/org-api-keys/spec.md, a file that did not exist before. And the change folder moved into changes/archive/ with the date prefixed. Unticked tasks produce a warning and the -y flag carries on past it; a delta that fails validation stops the archive with nothing written, which we confirmed by trying.
openspec/
├── config.yaml
├── specs/
│ └── org-api-keys/
│ └── spec.md <- the merged, standing spec
└── changes/
└── archive/
└── 2026-10-17-add-org-api-keys/
├── .openspec.yaml
├── proposal.md
├── design.md
├── tasks.md
└── specs/org-api-keys/spec.md The merged file is a normal spec now, with a Purpose and a Requirements section and no delta headers. The next change that touches API keys will write MODIFIED deltas against it, and the archive will merge those too. That is the loop: the next change starts from a spec that is already current.
# org-api-keys Specification
## Purpose
Lets an organization issue, use, and revoke API keys so customers can
automate against their own data without sharing a login.
## Requirements
### Requirement: Owner can create an organization API key
The system SHALL let a user with the owner or admin role create an API
key scoped to their organization, and SHALL show the full key exactly
once at creation.
#### Scenario: Successful creation
- **WHEN** an admin submits a key name on the API keys settings page
- **THEN** the system creates a key, stores only its SHA-256 hash, and
displays the plaintext once
... When OpenSpec Is Too Much Ceremony
Every change produces four markdown files, and the loudest criticism of OpenSpec is about exactly that. When the project reached the Hacker News front page in September 2026, the top comment came from someone whose team had adopted it: “every change, medium or larger, turns into a large set of multiple markdown documents, each that need review. and they are never handwritten - always slop” (Hacker News, 204 points). The second complaint in the same thread was drift: on a long-lived codebase with several developers, the specs stop matching the code, and a spec that no longer matches the code is a liability.
Both are fair, and the research agrees. An academic survey of spec-driven tools, OpenSpec included, names the same two risks: specs drifting away from the code, and no benchmark for the whole process (arXiv, June 2026). So treat any “half the tokens of Spec Kit” claim as one person’s test. Nobody has measured it properly.
What we do about it. A one-file fix or a copy change does not go through OpenSpec at all; it is a normal prompt. A refactor that changes no behaviour gets skip_specs: true in its .openspec.yaml. The rules: block in config.yaml caps the proposal length, which cuts most of the slop. And the archive is only worth running if someone reads the merged spec afterwards; if nobody will, you are maintaining a document for its own sake, and a plain design note in the PR is cheaper.
OpenSpec vs BMad Method: Which One for Your Next Change
BMad Method is the other free tool people compare OpenSpec with, and it works differently. Instead of commands, you talk to named roles: Mary the analyst, John the product manager, Winston the architect. Each one writes a document, in order: a brief, a product requirements document, an architecture note, and finally the stories to build.
One warning before the comparison. Everything here describes version 6.12.4 (bmad-method on npm, October 2026). Version 7 is not out yet and will change how you install it, so check the repo before you follow any BMad tutorial, including this section.
| Axis | OpenSpec | BMad Method |
|---|---|---|
| Unit of work | One change, as a delta against the specs | A planning path: a session, an epic, or a project |
| Who you talk to | Verbs: propose, apply, archive | Personas with names and roles |
| Output | Deltas merged into one standing spec | Standing documents rewritten as a whole |
| Runtime | One Node CLI | Node plus Python and uv |
| Where planning runs | Inside the coding agent | Optional web bundles for ChatGPT or Gemini to save IDE tokens |
Pick by the size of the job. Changing code that already exists, like the API keys above, is what OpenSpec is for, because archiving keeps the spec accurate afterwards. A big piece of work that you want to talk through with a product manager and an architect before anyone builds it is what BMad is for. GitHub Spec Kit is the third option; our spec-driven guide compares all three, so we will not repeat that here.
OpenSpec gives the agent a contract per change. If you’d rather start from a Next.js foundation where the specs, scoped rules, review subagents and CI gates are already wired and tested, that’s the VibeReady AI Framework. See editions from $99 →
Frequently Asked Questions
Is OpenSpec free?
Yes. OpenSpec is MIT-licensed, installs from npm or Homebrew, and needs no account. The only cost is whatever your coding agent charges for the tokens it spends writing and reading the artifacts, which is why the project tells you to clear context before implementation.
Does OpenSpec need an MCP server?
No. openspec init writes slash commands and skills into your agent's folder, and the agent shells out to the openspec CLI from there. There is no MCP (Model Context Protocol) server in the project; a pull request that added one was closed unmerged in September 2026.
What happened to /openspec:proposal, /openspec:apply and /openspec:archive?
Version 1.0.0 on January 26, 2026 removed them along with the generated CLAUDE.md, AGENTS.md and project.md files. The replacements are /opsx:propose, /opsx:apply and /opsx:archive. Running openspec init in an old project detects the legacy files and offers to clean them up.
Should I use OpenSpec or GitHub Spec Kit?
Use Spec Kit when you are starting a new feature and want a spec, a plan and a task list with a converge step at the end. Use OpenSpec when you are changing code that already exists, because archiving a change merges it into the standing spec. Our spec-driven development guide compares both with BMad and Superpowers: https://vibeready.sh/blog/what-is-spec-driven-development/#spec-kit-vs-openspec-vs-bmad
Does OpenSpec work with Cursor or Codex?
Yes. Run openspec init --tools cursor,codex and you get the same six workflows with that tool's spelling: /opsx-propose in Cursor and GitHub Copilot, $openspec-propose in Codex, @opsx-propose in Amazon Q. The init output prints the right form for the tools you picked.
Which model should I use with OpenSpec?
The project recommends high-reasoning models for both planning and implementation, and its one firm rule is to start implementation in a fresh session so the planning transcript is not in the context. In Claude Code that means /clear, or a new session, between /opsx:propose and /opsx:apply.
Have more questions? See our full FAQ →