* fix(archive): read a wrapped scenario bullet as one bullet A repository that wraps its prose at a column limit writes most scenario bullets over two lines. The retirement guard read the continuation line as content the merge could not account for, so `retire_capabilities` refused every such spec - and because the hint that names the marker is gated on that same count, an unmarked author got the bare "must have at least one requirement" abort and never learned the retirement path exists. A line indented to the content column of the item above it, with no blank line between, is part of that item. It is accounted for when the item was and already reported when it was not, so nothing is deleted unmentioned either way. A blank line still ends the item, so a note written below the scenarios is still the author's own however it is indented. Closes #1780 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(archive): keep an indented heading out of a bullet's continuation Continuation is for wrapped prose. A raw HTML heading indented under a scenario bullet was absorbed by it, so indenting a section one level would have smuggled it past the audit and deleted it with the file. ATX headings were already excluded; HTML ones now are too, matching how the pass above the requirements section reads them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(archive): flag a setext heading indented under a bullet A setext underline turns the line above it into a heading, so indenting the pair one level under a scenario bullet let a whole section be absorbed as continuation and deleted with the file. Checked ahead of the continuation branch now, the same way the ATX and raw HTML forms already are. Found by CodeRabbit on this PR. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(archive): read an unindented wrapped bullet as one bullet too Not every wrap indents its continuation, and the indent-only rule left the reported bug fixed for one spelling and live for the other: a hand-wrapped scenario bullet still refused the retirement. Inside a scenario's unbroken bullet run a lazy continuation is now read as part of the bullet above it. This widens nothing - a sibling bullet written in that same position is already read as the scenario's own, and a lazy line is part of the bullet where a sibling is merely next to it. Past the blank line that ends the run the indent is still required, so a note bulleted below the scenarios and the line that wraps it stay the author's. Also covers CRLF specs, and asserts the refusal report names only the real leftover in a wrapped multi-requirement spec rather than burying it under continuations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(archive): stop a lazy continuation at anything that opens a block CommonMark lets a blockquote, thematic break, table, list item or raw HTML interrupt a paragraph, so one written flush against a scenario bullet starts something new rather than continuing it. The lazy allowance absorbed all of them, which would have deleted an author's note with the file and named nothing. The bullet's paragraph is now tracked as its own state: opened by a bullet, closed by a blank line, a fence, a heading, or a line that opens a block - including one indented inside the item, whose own paragraph ends the bullet's. Lazy continuation applies only while it is open. Indented continuation is unaffected: a nested list or quote sitting inside the item is still the item's own content. Each of the six holes is pinned by a test proven to fail with the narrower rule removed. Found by CodeRabbit on this PR. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(archive): classify a line as the list item sees it A marker as wide as `100. ` puts the item's content past the three columns a Markdown construct is allowed at the file's left margin, so `## Retention` written inside such an item read as five spaces of nothing and was absorbed as continuation - a regression against the behavior before continuation existed, which named it. Every syntax test in the audit now reads the line with the item's indent removed, so a heading, a setext underline or a block start is recognized wherever the item sits. Found by CodeRabbit on this PR. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: drop test scratch directory committed by mistake `test-spec-command-tmp/` is a fixture a test run leaves behind, swept up by `git add -A` in the previous commit. It is not part of the change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(archive): share one list-marker definition with the paragraph rule Folds in the marker coverage from the duplicate PR #1789, which fixes the same issue (#1780) with a shallower model. The audit named `-`, `*` and ordered items as list markers, while INTERRUPTS_PARAGRAPH, added in this same PR, already named `+` and capped an ordered marker at CommonMark's nine digits. The two disagreed, so a line one called a bullet and the other did not was read as both at once. Both now use one LIST_ITEM constant: - `+` is the behavior fix. A spec bulleted with `+` validates like any other, and every one of its scenario bullets was reported as unaccounted content, so that capability could not be retired at all. Regression added, verified to fail against the old marker set. - The nine-digit cap changes no verdict in this design, since a line the pattern rejects is weighed by the same rules either way. It is here for the consistency, and the comment says so rather than claiming a fix. The case is pinned so a later change cannot start deleting such a note. LIST_ITEM also no longer requires content after the marker, so an empty `- ` reads as the bullet it is instead of falling through to the leftovers, which is what the surrounding indent tracking already assumed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
→ 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
Follow @0xTab on X for updates · Join the OpenSpec Discord for help and questions.
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 choice
Your AI writes these; you review the plan before any code is written.
OpenSpec is built with OpenSpec — browse this repo's live specs and in-flight changes for real examples at scale.
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 -g @fission-ai/openspec@latest
Then navigate to your project directory and initialize:
cd your-project
openspec init
Want your AI to do it? Paste the setup prompt into your coding assistant — it installs the CLI, runs
openspec init, and verifies the result.
Now talk to your AI:
- Not sure what to build yet? Start with
/opsx:explore, a no-stakes thinking partner that reads your code, weighs options, and shapes a plan before anything is written. (Explore guide) - Already know what you want? Go straight to
/opsx:propose <what-you-want-to-build>.
Both are in the default profile. If you want the expanded workflow (/opsx:new, /opsx:continue, /opsx:ff, /opsx:verify, /opsx:bulk-archive, /opsx:onboard), select it with openspec config profile and apply with openspec update.
/opsx:propose is the canonical name; your tool may spell it /opsx-propose (Cursor, GitHub Copilot), @opsx-propose (Amazon Q) or $openspec-propose (Codex). openspec init prints the right form for the tools you picked — see How To Invoke.
Note
Not sure if your tool is supported? View the full list – we support 30+ tools and growing.
Also works with pnpm, yarn, bun, and nix. See installation options.
Docs
Start here: the Documentation Home maps everything. New to OpenSpec? Read Getting Started, then How Commands Work (where you actually type /opsx:propose).
→ Getting Started: first steps
→ Explore First: think it through with /opsx:explore before you commit
→ How Commands Work: where slash commands run vs the CLI
→ Core Concepts at a Glance: the whole mental model, one page
→ Examples & Recipes: real changes, start to finish
→ Workflows: combos and patterns
→ Existing Projects: adopt OpenSpec on a brownfield codebase
→ Editing a Change: update artifacts, go back, reconcile manual edits
→ Commands: slash commands & skills
→ CLI: terminal reference
→ Stores: plan in a separate repo, shared across your team (beta)
→ Supported Tools: tool integrations & install paths
→ Concepts: how it all fits
→ Multi-Language: multi-language support
→ Customization: make it yours
→ Community Showcase: projects and resources built with and for OpenSpec
→ 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 -g @fission-ai/openspec@latest
Refresh agent instructions
Run this inside each project to regenerate AI guidance and ensure the latest slash commands are active:
openspec update
Usage Notes
Model selection: OpenSpec works best with high-reasoning models. We recommend Codex 5.5 and Opus 4.7 for both planning and implementation.
Context hygiene: OpenSpec benefits from a clean context window. Clear your context before starting implementation and maintain good context hygiene throughout your session.
Contributing
Open a discussion (for core design changes) or an issue before you open a PR, and link the issue or discussion from the PR. New features, significant refactors, and architectural changes need an OpenSpec change proposal first.
→ CONTRIBUTING.md: the full process, from first issue to merged PR
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
