Projects · Open source

SpecKit Extension

The open-source pipeline behind the Companion — the commands, hooks, and state model, on their own.

Role
Creator and maintainer
Timeline
Mar 2026 – present
Stars
66
Forks
16
License
MIT
PythonMarkdown commandsJSON Schemaspec-kit
SpecKit Extension

The problem

The GUI was never the point.

SpecKit Companion is a VS Code extension, and the visible part of it — the viewer, the review comments, the phase timeline — is what people install. But underneath sits the thing that actually does the work: a pipeline of commands, hooks, and a state model that turns "build this feature" into specify → plan → tasks → implement, and records what happened at each step.

Locking that inside an editor extension would have been a mistake. Not everyone uses VS Code. Not everyone wants a GUI. And a workflow you can only run through a button is a workflow you can't put in CI.

Why I built it

Ship the pipeline separately, so the GUI is an option rather than a prerequisite.

The extension installs into spec-kit and gives you the whole spec-driven flow at the command line. The Companion sits on top as a visual front-end. Neither owns the workflow: they're two front-ends over one set of files on disk, and that's a deliberate architectural line. You can drive a step from the terminal and watch the viewer update, or drive it from the viewer and see the files change in your terminal. Nothing is hidden in a private database.

This project also exists because a previous one failed, and it's worth saying why. I'd built a standalone Claude Code plugin for the same workflow. It worked. It went nowhere — because a spec-driven methodology is hard to grow alone, and spec-kit already had the users and an extension model. I wrote an ADR arguing to kill my own plugin and rebuild it as a spec-kit extension, then red-teamed that ADR — and found four of my own load-bearing claims were wrong. Corrected them, and migrated anyway. The technology wasn't the constraint. Distribution was.

How it works

The pipeline is a set of markdown command definitions, Python scripts for the parts that must be deterministic, and a JSON-schema'd context file that records the run.

The decisions worth naming:

Right-sized process. A one-line CSS fix and a new auth system should not go through the same ceremony. The pipeline detects complexity and takes a fast path for small changes. Every gate that survives prevents a real category of mistake — no checkpoint exists "just because". That principle killed several phases I was fond of.

One executable resolver, not prose. Where the spec files live, which ones are in scope, how they're ordered — that logic lives in a single script that every command calls. It used to be described in prose in each command, which meant four descriptions that could drift. Now there's one implementation and no room for interpretation.

A write-ahead log for state. Recording every task as a read-modify-write against a shared JSON file doesn't survive parallel workers — two agents finishing at once will lose an update. So writes append to an event journal instead, and a separate drain folds them into the context file at safe boundaries. It's crash-safe, replayable, and lets sub-agents record their own progress without contending on one file. Boring distributed-systems hygiene, applied to a workflow tool.

Brownfield adoption that refuses to lie. Pointing it at an existing codebase generates drafts, explicitly labelled: requirements tagged as observed or inferred, low-confidence ones flagged for a human, unreadable files listed under "Uncovered". It never scans a whole repo at once, and it never overwrites a spec you've reviewed. A tool that confidently invents your requirements is worse than one that admits what it couldn't work out.

Results

  • Open source, MIT, and independently installable — the GUI is genuinely optional.
  • Sixteen commands, a documented context schema, and three review checkpoints.
  • 66 stars, 16 forks on the parent repo.
  • Powers every workflow SpecKit Companion dispatches.

What I'd do differently

I should have reconciled the schemas before shipping the integration, not after. When I proposed folding the standalone plugin into spec-kit, I claimed the Companion would "light up with no schema change". That was wrong — the schemas diverged, and the Companion silently coerced the mismatch, which mis-rendered a finished spec's terminal state. Silent coercion is the worst possible failure: it doesn't crash, it just tells you something false. I caught it by red-teaming my own proposal, which is the only reason it isn't still there.

"Tracking works with any agent" was an overclaim. It's best-effort and agent-mediated: strongest on Claude, weaker elsewhere, and absent when work happens outside the commands. I wrote it down as a hard capability before I'd tested the edges. It's now documented as best-effort, with the failure modes named — but I'd rather have been precise the first time than have to walk it back.

Living in someone else's house has a rent. Moving onto spec-kit bought me distribution and cost me expressiveness: their hooks are far more limited than mine were, my parallel-agent features degrade to sequential on other providers, and I'm now coupled to their versioning. I'd make the same trade again — adoption was the binding constraint — but I'd go in with the costs itemised rather than discovering them one at a time.

Written & spoken about it