OpenSpectra: a Rust CLI for managing specs, changes, and implementation tasks
An open-source, CI-friendly reimplementation of the Spectra spec-driven development CLI — reverse-engineered from the closed-source binary, starting with the drift command.
Status: early. spectra init / drift / validate (+ minimal list / show / park / unpark / new change / task done / in-progress add / completion / archive ) is implemented in Rust and runs on Linux/macOS with zero runtime dependencies (just git on PATH ). The reverse-engineering write-ups are in docs/reverse-engineering/drift.md , docs/reverse-engineering/task.md , docs/reverse-engineering/archive.md , docs/reverse-engineering/in-progress.md , and docs/reverse-engineering/init.md (the last one is not oracle-verified — see that doc). validate is likewise not oracle-verified: it matches the OSS openspec validate contract, not the macOS binary — see docs/reverse-engineering/validate.md .
The upstream Spectra CLI is closed-source and updated infrequently. drift — which detects when a change's spec artifacts have diverged from the codebase — is the most valuable piece to run in CI as a gate. It turns out to be pure git + filesystem + regex heuristics (no AI), so it reimplements cleanly and runs anywhere.
Given a change under <spec_dir>/changes/<name>/ , it scores drift across four dimensions and prints a single recommended next step:
It outputs a human-readable, conclusion-first report or --json for tooling. Like the reference binary, a successful run always exits 0 regardless of severity — CI gates on the severity field of the JSON output (see below).
spectra init [--json] # scaffolds .spectra.yaml + <spec_dir>/{changes,specs}/ at the resolved project root (nearest ancestor with .spectra.yaml, else cwd) spectra drift [CHANGE] [--json] # auto-detects if one active change spectra validate [CHANGE] [--changes] [--strict] [--json] # OpenSpec structural gate; exits non-zero when any change is invalid spectra list [--json] # lists active changes spectra list --changes [--json] # same as above, explicitly (mutually exclusive with --specs/--parked) spectra list --specs [--json] # lists capability specs instead of changes spectra list --parked [--json] # lists parked changes instead of active ones spectra show < CHANGE | SPEC > [--json] # prints the change's proposal, or a spec's content spectra park < CHANGE > [--json] # marks a change on hold (excluded from the active listing) spectra unpark < CHANGE > [--json] # resumes a parked change spectra new change < NAME > [--json] # creates a change dir + .openspec.yaml only (kebab-case name; artifact files come later via `new artifact`) spectra new artifact < TYPE > [CAPABILITY] [--change < NAME > ] [--stdin] [--force] [--json] # creates one artifact (proposal|design|tasks|spec) from stdin or its built-in template, with per-type validation spectra schemas [--json] # lists the built-in workflow schema registry (only spec-driven) spectra status [--change < NAME > ] [--schema < NAME > ] [--json] # shows the artifact DAG (proposal → {design, specs} → tasks) as done/ready/blocked spectra instructions [ARTIFACT] [--change < NAME > ] [--json] # prints the artifact's authoring instruction + template; with all artifacts done, switches to apply mode (tasks progress + preflight) spectra analyze [CHANGE] [--json] # 4-dimension artifact consistency report (Coverage/Consistency/Ambiguity/Gaps); always exits 0 spectra task done < TASK_ID > [--change < NAME > ] [--json] # marks a tasks.md checkbox done, records touched files spectra in-progress add < NAME > # records a write-only in-progress marker (no --json, no removal path, no effect on any listing) spectra completion generate [SHELL] # prints a shell completion script (bash|zsh|fish|elvish|powershell; detects $SHELL when omitted) spectra completion install [SHELL] [--verbose] # writes it to the shell's user completion dir (bash|zsh|fish; never edits your rc files) spectra completion uninstall [SHELL] [-y] # removes that file spectra archive [CHANGE] [--skip-specs] [--mark-tasks-complete] # moves a change to changes/archive/<date>-<name>, applies added spec requirements Exit codes for drift (pinned against the reference binary): 0 on any successful run — severity does not map to the exit code — and 1 on errors (e.g. change not found). To gate CI on drift severity, check the JSON severity field.
Hacker News
news.ycombinator.com