Specstride CLI
The gated loop as it ships today. Bash and Python, standard library only. Drives Claude, Codex or dsh through a Spec Kit feature, phase by phase, behind the critic gate.
Released as v0.1.0. Runs on Linux with Python 3.13 and Bash.
Open source Runs on your machine Your models, your keys
Specstride drives your coding agent through a Spec Kit feature, phase by phase. Nothing advances until a critic approves it on cited evidence. When a phase is stuck, a diagnostician finds out why and an accelerator fixes only what failed.
Clone the CLI and run the bundled three-phase Spec Kit example end to end. Claude writes the code; a critic signs off each phase.
git clone https://github.com/mairp/specstride && cd specstride mkdir -p /tmp/demo/specs/001-greeting && cp examples/speckit-tasks.example.md /tmp/demo/specs/001-greeting/tasks.md SPECSTRIDE_PROPOSER=claude SPECSTRIDE_CRITIC=claude ./specstride run -w /tmp/demo --verification off
Follow it from a second terminal with ./specstride watch -w /tmp/demo. --verification off skips the test-plan gate, which wants a test command the empty demo directory doesn't have yet; leave it on in a real project.
Keep one checkout and get a specstride command everywhere. The script owns its routing, so the function is only a pointer. Add these two lines to ~/.bashrc or ~/.zshrc.
export SPECSTRIDE_HOME="$HOME/specstride" specstride() { "$SPECSTRIDE_HOME/specstride" "$@"; } # then, from any directory specstride status -w /tmp/demo
specstride run, watch, events, verdicts, stop and resume all go through the same command.
No spec yet? Inventory a codebase and see the five gated phases that would write its as-is Spec Kit feature. The dry run makes no model call and changes nothing.
./specstride reverse ~/projects/foo --dry-run
Drop --dry-run to write specs/NNN-as-is-foo/ through the gated loop. It reads your source and never changes it.
specstride-run and specstride-reverse as Claude Code skills. Specified, and built after the TypeScript core it sits on. There is nothing to install yet.
01 · the loop
The proposer works in fresh, stateless passes until the phase's evidence file exists. The critic reads the acceptance criteria, the evidence and the files it cites, then approves or rejects. A rejection with new unmet criteria goes to the diagnostician; its hint drives a narrowed retry that touches only what failed.
14:02:11 ┏ run start — 5 phases · codex→claude · resume @ phase 3 14:02:11 ◆ phase 3/5 — Wire session middleware 14:02:12 ✱ proposer working — phase 3, attempt 1, codex 14:03:40 ✎ Edit start src/session/middleware.ts 14:05:02 ❯ Bash start npm test -- session 14:09:31 ◇ evidence → .specstride/features/add-session-auth/gates/GATE3-EVIDENCE.md (4 iter) 14:09:40 ┿ critic judging phase 3, claude 14:10:02 ✗ REJECTED phase 3 (attempt 1) — C3.2 cites a test that never ran ━━━━┿━━━━━━━━━┿━━━━━━━━━┿╍╍╍╍╍╍╍╍╍┿╍╍╍╍╍╍╍╍╍┿╍╍╍╍ 2/5 approved · attempt 1/3 ✓ 1 ✓ 2 ✗ 3 · 4 · 5 14:10:03 ! diagnosing phase 3, after attempt 1 — writing a hint for the next pass 14:10:41 ✚ accelerator acting on the hint — phase 3, attempt 2, codex · C3.2 14:11:15 ❯ Bash start npm test -- session.middleware 14:16:30 ◇ evidence → .specstride/features/add-session-auth/gates/GATE3-EVIDENCE.md (2 iter) 14:16:48 ┿ critic judging phase 3, claude 14:17:05 ✓ APPROVED phase 3 14:17:06 ◆ phase 3 done (attempt 2) ━━━━┿━━━━━━━━━┿━━━━━━━━━┿━━━━━━━━━┿╍╍╍╍╍╍╍╍╍┿╍╍╍╍ 3/5 approved · 14m55s ✓ 1 ✓ 2 ✓ 3 · 4 · 5 14:17:06 ⎇ git checkpoint (phase 3)
A recorded run (the one the project README replays), rendered by the shipped presenter. Phase 3 is rejected, diagnosed, accelerated and approved.
02 · why
A long real-world run spent about two-thirds of its live time waiting on verification jobs, one of which kept going long after it had already failed. Over a third of the agent's time went to passes killed at their time cap, their work lost. One phase ran about fifty passes while blocked on a human decision it had no way to report. The critic took well under one percent.
Long checks stop at the first failure, so a broken phase shows up in minutes, not after an hour-long job finishes failing.
Units sized so no pass is killed by its time cap, and work that was done is kept when a pass ends.
Relaunch after a transient stop, within a budget, and a plain signal when a run is blocked on you instead of retrying forever.
A pass picks up a ledger and a handoff instead of re-reading the whole feature from cold, mostly to cut cost.
Per-phase budgets learned from telemetry, judged against their baseline after every approved phase, and reverted automatically when a guardrail breaks.
Available: in the CLI today. In progress: specified for the TypeScript core and being built.
03 · bring your own agents
The proposer and the critic are chosen independently, so a cheap model can write while a stronger one judges. This list is a starting point, not a boundary.
proposer · critic · tested in the CLI
proposer · critic · tested in the CLI
proposer · critic · tested in the CLI
proposer · critic
proposer · critic
proposer
proposer · critic
critic
critic
discovered
04 · hosts and plugins
The engine runs detached. Hosts reach it through one CLI protocol, so a plugin is a thin layer of skills over it.
The gated loop as it ships today. Bash and Python, standard library only. Drives Claude, Codex or dsh through a Spec Kit feature, phase by phase, behind the critic gate.
Released as v0.1.0. Runs on Linux with Python 3.13 and Bash.
One TypeScript codebase in place of three drifting tools. A detached runtime that relaunches itself, micro-loops that fail fast, harness discovery, and a plugin seam for hosts.
Specified as 41 Spec Kit features. Being implemented unattended by the CLI. Not public yet.
Specstride inside Claude Code. Two skills hand specified work to the detached engine and report back in a few lines, so the host keeps its context for judgment.
Specified in the first wave. Built after the core it sits on.
specstride-run Take Spec Kit features that already exist, derive and validate a launch contract, launch the gated loop detached, supervise it and report the digest.specstride-reverse Reverse-engineer a codebase into an as-is Spec Kit feature through the gated loop, with lint and guard checks.The same two skills on dsh, through the same CLI protocol. Alerts come from the engine through status and the digest.
Second wave, after the Claude Code plugin.
The same two skills inside Codex. Codex can already be the proposer or the critic; this puts Specstride behind a Codex prompt too.
On the roadmap. No code yet.
05 · observability
A run is a stream of structured events in .specstride/events.jsonl. The live presenter renders it in your terminal; the same stream ships to Loki or over OTLP to an OpenTelemetry collector, with cost, tokens and duration as metrics.
{"time": "2026-09-26T14:10:02+0000", "event": "verdict", "phase": 3, "result": "REJECTED", "attempt": 1, "max_rejects": 3, "reason": "C3.2 cites a test that never ran"}# format, as printed by the launcher
[DIGEST] state=completed exit=0 last-stage=<stage> evidence=<run dir>--otel --otel-url http://localhost:4318 ships OTLP/HTTP with no SDK; --telemetry ships to Loki. Off by default.[DIGEST] is the one line a supervising agent reads at the end of a run: state, exit code, last stage, evidence. Today it comes from the mixture-of-loops launcher.06 · built by itself
The TypeScript core was specified first: 41 Spec Kit features, 1,643 functional requirements, 2,983 tasks, and a parity suite the port has to pass against today's CLI before any release.
Since 30 September 2026 the current Specstride has been implementing those features unattended, one at a time, each phase held at the gate until its critic approved it. A human reads the result and arbitrates only what the machines can't settle.
The TypeScript repository isn't public yet. Its status here is In progress.
specstride: phase 7 approved — User Story 5 - A consumer invokes a host skill specstride: phase 6 approved — User Story 4 - An author describes a harness as data specstride: phase 5 approved — User Story 3 - An author adds an implementation without touching the core specstride: phase 4 approved — User Story 2 - An operator reads an exit code and a stop reason
07 · open source
The whole product: the CLI, the TypeScript core and every plugin. A patent grant from every contributor, contributions taken under the same licence with no CLA, and the Specstride name kept for the project.
No service in the middle. Runs, state and logs live under .specstride/ in your project, readable and resumable from the files alone.
It calls the agents and providers you configure, with your credentials, and nothing else. Telemetry stays off until you point it at your own collector.
08 · faq
The CLI reads a Spec Kit feature's tasks.md, an OpenSpec change, or its own plain format; the feature's spec.md, plan.md and contracts ride along as read-only context. No spec yet? specstride reverse writes an as-is feature from an existing codebase.
Today the CLI drives Claude, Codex or dsh, and the proposer and the critic are chosen independently, so a cheap model can write while a stronger one judges. The TypeScript core adds pi in its first wave, more adapters later, and discovers agents you already have installed.
The critic never takes the agent's word. It reads the phase's acceptance criteria and the evidence, then reads the files the evidence cites in a read-only grounding pass before it answers. A reply it can't parse counts as a rejection. The self-tuning loop can't change anything the critic reads, and a test locks that.
When a rejection names new unmet criteria, the diagnostician reads the whole rejection history and the full files and says whether the critic couldn't see the proof or the gap is real. The accelerator then fixes only those criteria. After a bounded number of rejections the run halts with exit code 2 and leaves everything on disk for you.
Specstride runs where you run it. It calls the agents and providers you configure, with your keys, and nothing else. Telemetry is off until you point it at your own collector, and every record is redacted before it is shown or written.
Specstride is free and open source. You pay your model providers as usual; the live view prints the cost, tokens and duration of every pass, so the spend is visible while the run is going.
It takes the same Spec Kit features. It is held to a parity suite that replays today's CLI behaviour, and it is not released until every parity test passes.
Issues, Discussions and pull requests on GitHub. Sign off your commits (git commit -s); there is no CLA.