OpenSpec projects

Run an OpenSpec change task by task under the same judge: scenarios become failing tests, ticks need evidence, broken deltas are caught before any model call, and archiving stays yours.

speccoder runs OpenSpec changes under the same judge as Spec Kit features. What differs:

Spec KitOpenSpec
Unit of worka feature, specs/NNN-name/a change, openspec/changes/<id>/
Acceptance examplesthe task’s user storythe #### Scenario: blocks of ADDED and MODIFIED requirements
Task IDsT001the number the task starts with (1.2), else #n
Orderphases, [P] runs, depends ona chain: groups in order, tasks in order
Intent the model cannot edit.specify/, specs/all of openspec/

Supported: OpenSpec 1.0 and newer, the default spec-driven schema, in the repository’s own openspec/ directory.

Running a change

speccoder inspect                 # the change, its requirements and its tasks
speccoder run                     # work the change through, task by task
speccoder run --change add-x      # when more than one change is active
speccoder run --task 1.2          # one task

The format is detected: the nearest openspec/ (with config.yaml, specs/ or changes/) or .specify/ decides. When a directory has both, choose with --format openspec, SPECCODER_FORMAT or [spec] format. --change is an alias of --feature.

Commit the change’s files before a run; the work happens on speccoder/<change-id>. A task ticked before speccoder ran it is reported as ticked without evidence. Each attempt sees config.yaml’s context (as the project’s rules), proposal.md and design.md (as the plan), and every delta of the change in full. OpenSpec does not link a task to a requirement, so acceptance tests come from the change’s scenarios that the task concerns. The archive is never shown.

Caught before any model call

openspec validate --strict accepts some deltas that openspec archive later refuses, so speccoder refuses to run while any of these hold:

CodeMeaning
missing_targeta MODIFIED, REMOVED or RENAMED requirement does not exist in openspec/specs/<capability>/spec.md
renamed_conflicta requirement is modified under the name this change renames
missing_scenarioan ADDED or MODIFIED requirement has no #### Scenario:
scenario_wrong_level### Scenario: instead of #### Scenario: (OpenSpec ignores it)
no_deltasthe change has no spec delta: nothing to derive tests from
unsupported_schema, store_root, legacy_roota custom schema, a shared store, or the pre-1.0 layout
textless, duplicate_id, no_taskstasks.md cannot be run as written
config_unreadableopenspec/config.yaml is not valid YAML

Warnings do not stop a run:

CodeMeaning
removed_without_reasona REMOVED requirement has no Reason or Migration
purpose_missingarchive would write a TBD placeholder for the purpose
marker_not_space, empty_brackets[~] or []: speccoder cannot tick it
misplaced_ida task’s number does not match its group (3.1 under ## 2.)
in_fencea checkbox inside a code block, which OpenSpec counts as a task
unnumbered_sectiona group heading without a number; its tasks run after everything before them
extension_dependencydepends on 1.2 is speccoder’s extension; OpenSpec ignores it

When openspec is on your PATH, speccoder run also runs openspec validate --strict --json and openspec instructions apply --json (read-only, sandboxed, telemetry off). Its validation errors (crosscheck_error) and a different task count (crosscheck_mismatch) stop the run. Without openspec, this cross-check is skipped.

What the model may run

openspec … (also via npx)in an attemptin a hosted planning skill
list, show, view, status, instructions, validate, schemas, templates, context, --version, --helpallowedallowed
new changerefusedallowed
archive, sync, init, update, config, store, schemarefusedrefused

Every command in an OpenSpec project runs with OPENSPEC_TELEMETRY=0, DO_NOT_TRACK=1 and OPENSPEC_NO_UPDATE_CHECK=1. Writes under openspec/ are refused during implementation; a command that changes them fails the verdict. OpenSpec’s per-tool commands and skills (.claude/commands/opsx/, .claude/skills/openspec-*/, …) are agent configuration, protected like any other.

Planning

speccoder spec                       # OpenSpec's installed skills
speccoder spec propose "add a --bye flag"
speccoder spec explore
speccoder spec update-change

OpenSpec’s own skills, run by speccoder’s model under the planning policy: they may write active changes (openspec/changes/, never the archive) and run openspec new change and the read commands. Not hosted: apply-change (use speccoder run), sync-specs and archive-change (merging into the main specs is yours: speccoder spec archive).

Archiving

Archiving rewrites the main specs, so you do it:

speccoder spec archive add-x
  1. It needs openspec on your PATH and no uncommitted changes under openspec/.
  2. A task ticked without a speccoder verdict commit stops it, named. Run it, accept it with speccoder task accept, or name it with --allow-unverified 1.1 (recorded as Archived-Unverified: on the commit).
  3. It asks OpenSpec first without --yes — OpenSpec’s --yes also skips its check for open tasks — and stops if tasks are open.
  4. It shows openspec show <id> --diff and asks. --yes answers in advance; without a terminal and without --yes it stops with the command to run.
  5. On yes: openspec archive <id> --yes, then one commit archive <id> with Archived-By: and Speccoder-Archive: trailers.

Run it in your checkout, typically after merging speccoder/<id>.

Not supported

Shared stores, custom schemas, parallel tasks (a change is a chain), and absence checks for REMOVED requirements.

Edit this page