spexcode
v0.7.0
Published
SpexCode — a spec-driven, self-developing dev tool. The `spex` CLI + spec server reads the .spec tree and its git history, and serves the dashboard.
Readme
Spec-driven orchestration for your coding agents. SpexCode keeps a versioned tree of specs inside your git repo, links every spec to the code it governs, and runs a session manager that dispatches coding agents into isolated worktrees. You review and merge; the tool keeps intent and implementation from drifting apart.
English | 中文 · Docs: spexcode.net · License: MIT
| Feature | Description | |---|---| | Computable spec–code drift | Every spec pins the file it governs, down to the function. Whether code moved without its spec is computed from commits and line ranges, the same way on every machine: advisory for the file, blocking when an anchored function changes. | | Session & worktree management | Each task runs in its own worktree and branch; independent tasks run in parallel. Sessions form a hierarchy: a session can dispatch and supervise workers of its own, so a worker can have a supervisor and that supervisor another. Workers propose; you review once, at merge time. | | Shareable URLs | Spec nodes, sessions, live terminals: every dashboard view has a stable address you can send to a colleague. Two people can watch the same session board. | | Modular layers | Three separable layers: the spec↔code data asset (L0), the session substrate (L1), the dashboard (L2). Take what you need; L0 and L1 are building bricks for your own software factory. | | Cross-harness support | Claude Code, Codex, OpenCode, pi, each interactive or headless. One materialized workflow contract serves them all; adding a harness is a config entry. |
The model
A spec node is a directory under .spec/ holding a spec.md: frontmatter naming the one file it
governs (code: — optionally pinned to specific functions with path#symbol) and the files it
references (related:), then a prose body stating what that part of the system is supposed to do,
right now. Nodes nest, so the tree mirrors how you think about the project rather than the file
layout. The body can split into two labelled parts: a short raw source a human signs off on, and
an expanded spec the agent iterates freely — as long as it keeps matching the raw source.
Git is the only database: a node's versions are the commits that touched its
spec.md. A change is one commit that updates both the spec and the code it justifies. When code
moves alone, the linter notices:
The check compares plain git facts: which commits came after the spec's last version, and whether they intersect the anchored unit's lines. It cannot judge whether the new behavior is better, only that the spec stopped describing it. The commit in the diagram updated seven other specs in the same rename and missed this one; that kind of miss is normal work, and it is what a mechanical check catches.
Software as heuristic learning
Specs and commits compose into one optimization loop. The spec is the loss function: it states what you want, and it is the half a human signs off on. Commits are the optimizer. Agents prove changes through the product's real surface, then hand the evidence to the reviewer as session files. Drift is the staleness signal; a bug fix is expected to show the real product working before review.
Nobody reads a neural net by staring at its weights, and between merge gates you don't stare at agent diffs either. Attention goes to the two ends — the spec and the product proof; the diff gets read once, at merge time.
Quick start
Requires Node ≥ 22 and git.
npm i -g spexcode # installs the `spex` command
cd your-repo
spex init --harness claude,codex,opencode,pi,zcode,claude-headless,opencode-headless,pi-headless,codex-headless # seeds .spec/, installs hooks, materializes the agent contractsThat's the whole adoption. The example lists all the built-in harnesses; remove the ones you don't
use (--harness is required and takes any one id or comma-separated subset). Want the spec asset and
nothing wired into an agent? --harness none adopts L0 alone and writes nothing into any agent's config.
Only the spec skeleton, with no git hooks either? spex init --pure plants .spec/spexcode.json and the root
spec and nothing else; a later spex init --harness … adopts that tree as it is.
Add --title "Your Project" and the name lands in both places a reader sees it: the root node's own
directory and spec.md, and the dashboard's title — without it the graph is topped by a node called
project and the page is named after the checkout directory, which is often repo or tmp.
spex init works on any existing git repo and does three things: it seeds a root
.spec/<name>/spec.md plus a starter .spec/spexcode.json, installs the git hooks, and materializes
the workflow rules into the files your agent already reads (CLAUDE.md, AGENTS.md): read the
governing spec before the code, land spec and code in one commit, propose merges instead of
performing them. Any agent that opens the repo discovers the workflow on its own.
It is additive, and never replaces a file you own. Where a harness discovers its hooks inside your own
config (.claude/settings.json, .codex/hooks.json), only SpexCode's entries are merged in — your
permissions, env and hooks stay — and spex uninstall takes back exactly those entries. A skill or
agent name you already use is skipped and reported, never overwritten.
When you want the live board (the graph and sessions), start the runtime:
npm i -g @spexcode/spec-dashboard # once: the UI and the server runtime spex serve needs
spex serve # this project's backend — prints its URL
spex dashboard # the machine's one gateway — every project behind one URLThe dashboard is a separate package so writing-only installs carry neither the frontend build nor the server
runtime (an HTTP server and a native PTY addon). One spex dashboard
per machine is enough: every project you serve shows up behind it, and its
/projects page manages them from the browser.
Getting started walks the rest of the setup.
Start from inside your agent, with nothing installed
The fastest way to see what a spec tree is worth is to let your agent draw one. The atlas skill ships
as a plugin for the agents that install plugins, and it runs SpexCode through npx — nothing to install
on the machine, nothing to configure.
Claude Code
claude plugin marketplace add shuxueshuxue/spexcode-plugins
claude plugin install atlas@spexcodeCodex
codex plugin marketplace add shuxueshuxue/spexcode-plugins
codex plugin add atlas@spexcodeThen, in any repository, hand the agent one sentence:
Draw the spec atlas of this repository, and give me the page I can open.
It reads the repository into a spec tree, plants it with spex init --pure --title <your project>,
chooses the parts worth a picture and draws each one, checks every diagram until it passes, commits
.spec/, and hands back one self-contained HTML file that opens from disk — the whole tree with each
node's diagram above its body. It is asked to write the tree in the language you used, so a question in
your own language comes back as a tree in it.
That repository is now adopted at L0: the tree it wrote is the same asset spex init seeds, so
spex init --harness … later picks it up as it is and adds the machinery beside it.
shuxueshuxue/spexcode-plugins is the marketplace —
it holds the packages and nothing else, mirrored from this repo's distribution/. ZCode, gugu and
PenguinHarness install the same skill through their own mechanisms; distribution/README.md has each one.
How does this system work
Three stacked layers, and each is worth having without the ones above it:
L0 is the asset an organisation adopts and keeps: plain files in plain git, useful offline. (Watch this repo's own L0 grow from its git history, 160 spec nodes over three weeks.) L1 puts agents to work on that asset: the session state machine below. L2 is the workspace you watch it all from, and because it is only a consumer of L1, anything the dashboard does, your scripts and agents can do through the same CLI.
Working with agents (L1)
This part needs tmux on the machine (on Windows, run inside WSL2).
The Windows desktop bootstrap runs spex doctor from the WSL user's home so it can validate host prerequisites.
Its layer 1 ABSENT and agent ungoverned lines are expected in that host-scoped context; they do not mean the
adopted project is missing its hooks. Project-scoped doctor output is the appropriate check for a repository.
spex session new "[[uploader]] retry failed chunks with backoff"launches a worker session in its own worktree on branch node/uploader-…. The prompt's first
[[uploader]] mention sets the branch name and board attribution; the worker finds and reads
the governing spec before it changes code. It makes the change, rewrites the spec body to
match, puts both in one commit, then files a merge proposal and stops:
spex session ls # the living table below
spex session watch stream # follow transitions: working → review → done …
spex session review uploader # commits ahead of trunk, merge-base diff, merge/lint gates
spex session merge uploader # hands the gated merge to the session's own agent
spex session close uploader # remove the worktree; branch, record and transcript stay resumableEach rule has a mechanism enforcing it: the backend creates the branch, a git hook attributes
every commit to its session, a pre-commit guard rejects direct commits to the trunk, and the
remaining conventions live in the materialized CLAUDE.md/AGENTS.md. Your dispatch prompt only
has to state the task. More: working with agents.
The dashboard (L2)
The spec tree and sessions have live pages on the dashboard. Start spex serve and spex dashboard, then:
Your whole repo as one map — SpexCode's own board shown. Each node carries its version and drift state, an agent's avatar hovers on the node it is editing right now, and the rail top-left is the live session console.
Click a node: the raw source on top, the expanded spec below it, the file it governs, its current drift state, and tabs for the version history git already kept and its issues.
The whole workspace is served over HTTP, so every view (a spec node, a session, a live terminal) is a stable URL you can hand to a colleague; you can sit on the same board together. The terminal pane is a real tmux session: copy the printed command and attach from your own terminal.
Contributing
docs/CONTRIBUTING.md gets you from a clone to a first merged change.
spexcode.net has the full mechanics of the node model and the
reflexive plugin system.
Credit
First introduced on the LINUX DO community — thanks to everyone there for the first round of discussion.
License
MIT.
