Drive a run
At the end you will have started a run for a new site, closed its first steps, and seen the gate refuse one. The loop is the same for all 15 steps: ask what is next → do it → close it. Only the middle part changes.
What you need first
READ-DO checklist- The plugin installed and the doctor passing — Install the plugin.
- An empty directory for the site, outside the plugin. Say
~/sites/example. This page uses<site-dir>for it — always as a full path. - A terminal open in your site-machine clone. Every
node tools/…command below runs from there; the site directory is passed as an argument, never entered. - A Claude Code session started after the install, opened anywhere but the plugin repository.
The loop in three commands
Every command takes the site directory, because all run state lives there. The plugin directory is only code.
| Command | Asks | Writes |
|---|---|---|
site-step.mjs next <site-dir> | Which steps may be worked on now? | Nothing |
site-step.mjs start <site-dir> <step> | Mark the step in progress and point the ledger at this site. | run-state.json, the active-run pointer |
site-step.mjs done <site-dir> <step> | Do all exit predicates pass? Close, or halt. | run-state.json |
Three more you will meet: status prints one line per step, sign records a named human on a step that wants one, and block records a validated reason a step cannot be done. None of them closes a step.
A run's profile (that is: which of the 15 steps apply) defaults to site. Only an application that brings its own build needs site-context.mjs init <site-dir> --profile app before the first command.
Step 1 — ask the gate
With nothing recorded yet, only the first step is open.
node tools/site-step.mjs next <site-dir>
It prints one line: preflight [orchestrator]. The word in brackets is the actor — who is expected to do the work. orchestrator means whoever drives the run — the agent, or you when you type the commands by hand — as opposed to a named skill.
Step 2 — close preflight (your first win)
Start the step, then close it. done runs the doctor as the step's only predicate.
node tools/site-step.mjs start <site-dir> preflight
node tools/site-step.mjs done <site-dir> preflight
done prints ok for the doctor and ends with closed preflight. next now offers brief [site-brief].
Step 3 — let a skill do a step
When the actor is a skill, invoke it in Claude Code — type /site-machine:site-brief in the prompt — and let it produce the artefact. For brief, the skill interviews you and writes brief.md at the site root.
Then close the step. The gate does not care who wrote the file; it checks that the file exists, that required fields are filled, and that there is exactly one primary action.
node tools/site-step.mjs done <site-dir> brief
Two ok lines (file present, brief-complete.mjs) and closed brief.
Step 4 — see a refusal, on purpose
Try to close a step whose prerequisite is still open. This is worth doing once so the halt output is familiar before it matters.
node tools/site-step.mjs done <site-dir> mwg-install
Exit code 1 and a block on stderr starting HALTED —, naming the step and the cause (prerequisites, because repo is not closed). next now prints only the halt, and a wrangler pages deploy from the agent would be denied.
Lift it by going back to the halted step: start it again, or succeed on it. There is no separate "unhalt" command — and lifting the halt does not make the predicates pass; they are waiting for the same evidence the next time you run done.
Here that evidence is a closed repo. Inside <site-dir>: git init, one commit, then gh repo create example --private --source . --push. Back in the clone, done <site-dir> repo, then done <site-dir> mwg-install after running node tools/mwg-install.mjs install <site-dir>.
Step 5 — the middle of the run
From here the loop repeats. Each step's actor and artefact are on The workflow, step by step; the short version:
- Orchestrator steps (
repo,mwg-install,build,security,flows,ship-check): the agent runs a tool —gh,mwg-install.mjs,flow-kit.mjsfor the frozen flow,measure.mjs— or writes code, thendone. - Skill steps (
brief,design,scaffold,ux-review,publish-*): invoke the skill, let it write its record, thendone. - Skill, then a person (
commercial-review,legal-check): the skill writes the record, a person signs —sign <site-dir> <step> --by "Name"— and thendone. Signing closes nothing.
The one proof that needs a specific command: before writing any component, the agent must search the guidance with npx -y modern-web-guidance@latest search "<what you want to build>" --skill-version 2026_05_16-c5e78707. The hook records that command; step build checks it came before the component's first write.
The machine works best when the agent is told to look, not to guess: "go to localhost:4321, run done build, act on every FAIL line" beats "make it accessible". Each predicate prints what it saw, so the FAIL lines are the to-do list.
Step 6 — publish
The last three steps deploy a noindex preview, check the legal texts on it, then go live. Each needs facts only you know, declared through site-context.mjs (the one tool that writes site-context.json): the preview and live URLs, whether the domain sends mail, and the hosting processor — the company that hosts the site, which the privacy policy must name. The site-publish skill walks through them.
Right before the last step, write a fresh receipt — publish-live refuses one older than the newest file in the site:
node scripts/verify-receipt.mjs audit <site-dir> https://example.de
done publish-live ends with closed publish-live and status shows 15 done · 0 blocked · 0 in progress · 0 open (of 15).
You are done when
status reports every step OK or BLK (blocked with recorded evidence), and the site answers at its live URL without x-robots-tag: noindex.
If it did not work
done build fails mwg_precedes_component although the guidance was read
The ledger only recognises a Bash command that contains modern-web-guidance and search, list or retrieve, run before the component's first write. Reading the guidance another way is not recorded. Also check that the session postdates the install.
A closed step refuses again after an edit
Expected for ux-review, commercial-review and publish-live: their records must be newer than the newest file under src/, public/ or dist/. Re-run the review, jury or receipt. See freshness.
I want to skip a step
Only steps with a blocker vocabulary can be blocked, and every blocker wants evidence — a file, a failing preflight.json, a declaration in site-context.json. Eight steps have no blockers and can only be done. This is the point of the machine, not a gap in it.
measure.mjs refuses with "spread"
Five Lighthouse runs disagreed by more than 5 points. The gate would rather have no number than a noisy one. Close other apps, stop the dev server's hot reload, and run it again.
console-clean fails on a page that shows no errors
A failed request counts, including a missing /favicon.ico. Check the network log, not only the console.