What you need
| Tool | Why |
|---|---|
| Node 26 or newer | harness-demo is TypeScript that Node runs directly, with no build step |
| pnpm | installs harness-demo and the example app |
| git | every project is a git repository, and the loop works on branches |
Claude Code (claude), logged in | only for real units, at the end of this page |
GitHub CLI (gh), logged in | only for delivery by pull request, described on Task lifecycle |
npx and Google Chrome | only for the browser of real qa and prototype units; the example project sets app |
Get harness-demo
git clone https://github.com/floatrx/harness-demo
cd harness-demo
pnpm install
alias harness="node $PWD/harness/bin/harness.ts"
harness self-test
self-test runs every contract case on a throwaway git repository with the fake agent, so it spends no tokens. It
takes about fifteen seconds and ends with:
41/41 cases passed
The alias lasts for this shell. Run the commands below from the harness-demo folder.
Make the example project
harness example ~/harness-bookmarks
copied examples/app → ~/harness-bookmarks
pnpm install …
initial commit on main
registered aab2de · harness-bookmarks
next:
harness submit T-002 --project harness-bookmarks
harness run --project harness-bookmarks --once-through
harness example copies the small bookmarks app from examples/app into its own git repository, installs it, makes
the first commit and registers it as harness-bookmarks. The loop creates branches and commits there, never inside
harness-demo. The id differs on your machine, and the paths here are shortened. Three seed tasks wait as drafts:
| Seed task | What it exercises |
|---|---|
| T-001 · Search box that filters the bookmark list | a UI task: the prototype step |
| T-002 · Do not add the same URL twice | a logic task with a test |
| T-003 · Make the bookmarks better | a vague draft: the interview |
Open the dashboard
In a second terminal, in the harness-demo folder, start the dashboard with the fake agent:
AGENT_CMD="node $PWD/harness/testkit/fake-agent.ts" pnpm dashboard
Right after Next's Ready line, the terminal names the agent that Start runs:
harness · Start runs a stand-in for claude (AGENT_CMD: node …/fake-agent.ts) — no tokens
Open http://127.0.0.1:4777 and pick harness-bookmarks. The line above the board says "3 drafts are yours — Submit
starts the loop on each." The board updates by itself while the loop runs. The Dashboard chapter walks
through every screen.
The first task, with zero tokens
The fake agent plays every role from a script. It spends nothing, so you can watch a whole task move before you pay for one.
Pick one way: the dashboard or the CLI. On the dashboard, press Submit on T-002, press Start · stand-in, press Approve when the plan waits for you, and watch the card go through implement, qa and judge to done. With the CLI, step by step:
-
Point the harness at the fake agent, and submit T-002:
export AGENT_CMD="node $PWD/harness/testkit/fake-agent.ts" harness submit T-002 --project harness-bookmarksThe card moves from
drafttospec. -
Run the loop until it needs you:
harness run --project harness-bookmarks --once-throughsupervisor · start · pid 78911 · once-through supervisor · billing: a stand-in replaces claude — no tokens unit 1 · T-002 · spec · writer · start unit 1 · T-002 · spec · exit 0 · spec → plan unit 2 · T-002 · plan · planner · start unit 2 · T-002 · plan · exit 0 · plan → planned supervisor · exit 0 · drained: nothing left to takeThe writer wrote the spec, and the planner wrote the plan. The card stops in
planned: with the defaultautonomy.mode: gated, a plan waits for your approval. -
Approve the plan, then run again:
harness approve T-002 --project harness-bookmarks harness run --project harness-bookmarks --once-throughsupervisor · start · pid 79005 · once-through supervisor · billing: a stand-in replaces claude — no tokens unit 3 · T-002 · implement · implementer · start unit 3 · T-002 · implement · exit 0 · implementing → qa · commit 40b83f1 unit 4 · T-002 · qa · qa · start unit 4 · T-002 · qa · exit 0 · qa → judge unit 5 · T-002 · judge · judge · start unit 5 · T-002 · judge · exit 0 · judge → done supervisor · exit 0 · drained: nothing left to take -
Check the result:
harness status --project harness-bookmarks git -C ~/harness-bookmarks log --oneline --allsupervisor: not running T-001 draft Search box that filters the bookmark list T-002 done Do not add the same URL twice T-003 draft Make the bookmarks better 40b83f1 T-002: Do not add the same URL twice (round 1) da96747 chore: example app from harness-demoThe harness made one commit on the task branch, after the gate passed. Nothing else changed.
Switch to real Claude
Drop the fake agent. First look at what a real unit would receive. Neither command below spends a token:
unset AGENT_CMD
harness preview T-001 --project harness-bookmarks
harness agents --check --project harness-bookmarks
T-001 is still a draft, so preview shows the spec unit it gets after Submit, and writes nothing to the task. It prints
the exact claude command line and the full prompt:
# T-001 is a draft: this is the spec unit it gets after Submit
# T-001 · stage spec · coordinator writer
# specialists: writer
# argv: claude "-p" "--output-format" "stream-json" "--verbose" "--model" "sonnet" "--permission-mode" "dontAsk" …
# prompt (4948 chars) — sent on stdin:
# Stage: spec — coordinator
…
agents --check lists the nine agents with their models and stages, and ends with ok: no drift, no model clash.
When both look right, submit T-001 and run the loop:
harness submit T-001 --project harness-bookmarks
harness run --project harness-bookmarks --once-through
The run stops each time a column is yours: questions in needs-input, the plan in planned, and, because T-001 is a
UI task, the prototype in prototype. Answer, approve or accept, on the dashboard or with the CLI, then run again. To
drive it from the dashboard, restart the dashboard without AGENT_CMD first; its button then reads Start · claude.
harness stats --project harness-bookmarks then prints the units, time, tokens and API-equivalent cost per stage and
per task.
When the example works, put the harness on your own repository.