Write a task. Agents finish it: plan, implement, QA, review, report.
A Claude Code harness that runs coding tasks across several repos at once.
You keep one /dispatch session open. It picks up tasks from inbox/, runs a worker agent per task in an isolated git worktree,
has a QA agent start the app on its own ports and take screenshots, has a reviewer agent grade the result against your "done when" list,
and loops until it passes. Then it leaves a report. Nothing reaches a shared branch until you say "merge".
you ── /dispatch (dispatcher: never edits code — plans, runs agents, talks to you)
├─ task-worker plan → implement → self-check → commit (one per task, same one for rework)
├─ task-qa start servers on isolated ports, call APIs, log in, screenshot
└─ task-reviewer compares task.md with the result only (never sees the plan)
inbox → doing ─ work → QA → review ─┬─ pass → report → done → (you: "merge") → merged
↑ │
└─ rework (≤ 3 rounds)
- Parallel without collisions. Each task gets its own worktree per repo (
task/<id>branch), and servers run on slot ports (base + 10000·n). Your own checkouts and dev servers are never touched. - Evidence, not claims. QA opens real screens and saves screenshots; the reviewer treats any ✅ without evidence as ❌.
- A fresh reviewer. The reviewer sees only what you asked for and what was built — not the worker's plan or reasoning.
- You stay in the loop cheaply. Questions arrive as
❓ Q3 …with options and a recommendation; answer "Q3 A" whenever. Other tasks keep running. - Guardrails first. No pushes, no production access, no real messages or payments, no force. See
guardrails.md.
- Claude Code
- git, bash, Node.js (for Playwright screenshots)
- macOS or Linux. Your repos cloned side by side in one folder.
# Put this repo next to the repos you want agents to work on:
# workspace/claude-dispatch, workspace/api-server, workspace/web …
git clone <this repo> workspace/claude-dispatch
cd workspace/claude-dispatch
bin/setup.sh # Playwright, qa/.env.qa, pre-commit secret checkThen make it yours:
| File | What to fill in |
|---|---|
repos.md |
Your repos: base branch, how to build, boot, lint, test, what never to start. The examples are fictional — replace them. |
guardrails.md |
Keep the defaults, add your own traps under "Project-specific". |
qa/.env.qa |
Local test accounts — login, password and a role comment per account. Git-ignored; secrets are blocked from commits. |
harness.env |
Where repos and worktrees live, number of slots, protected branches. |
Each repo should already work locally as you use it (npm install, .env.local …) — worktrees copy installed dependencies and untracked root files like .env*.
- Add a task: copy
templates/task.mdtoinbox/<YYMMDD>_<kebab-name>.md(e.g.260101_export-stats-csv.md). Only Goal and Done when are required. See a complete sample task folder — request, question, plan, QA evidence, a rework round, and the final report. Or just tell the dispatch session: "also do: …" — it writes the file and confirms the done-when list with you. - Run
claudein this repo and type/dispatch. Leave it open.- It reads every task, decides order and parallelism (up to 5 workers,
SLOTSrunning servers), and starts them. New files ininbox/are picked up automatically. - It reports one line per stage change. Say "status" for the board.
- Questions come as
❓ Q3 [id] …. Answer "Q3 A" when convenient.
- It reads every task, decides order and parallelism (up to 5 workers,
- On
✅, readdone/<id>/report.md. Screenshots are indone/<id>/shots/. - In the same session: "merge x" → merged into each repo's base branch and cleaned up · "change x like this" → rework · "park x" → moved to
todo/.
Single task only: /task <id>. Merge without the dispatcher: /task-merge <id>.
inbox/ doing/ done/ merged/ todo/ |
Task lifecycle. Each task becomes a folder: task.md, plan.md, qa.md, log.md, report.md, shots/ |
templates/ |
Task, plan and report formats |
repos.md, guardrails.md, harness.env |
Your configuration |
qa/ |
env.qa.example → copy to .env.qa for test accounts (local only) |
bin/ |
claim · worktree · slot · merge · cleanup · sync · wait-inbox · check-secrets · paths · setup |
.claude/skills/ |
/dispatch, /task, /task-merge |
.claude/agents/ |
task-worker, task-qa, task-reviewer |
.claude/settings.json |
Common commands allowed; force push, pkill, ssh, cloud CLIs denied; git push asks |
- Tasks and reports are committed to this repo automatically (
bin/sync.sh); with anoriginremote it also pulls and pushes, so a team can share one inbox. In-progress work (doing/), screenshots and logs stay local. - Agents commit only to local
task/<id>branches./task-mergefast-forwardsorigin/<base>— never force, never a branch inPROTECTED_BRANCHES(defaultmain master). Your open checkout is fast-forwarded only if it is on that branch and has no conflicting changes. - If the session dies,
board.mdanddoing/survive. Run/dispatchagain to continue. - Workers read the target repo's
CLAUDE.mdand any Claude Code memory you built up in that repo, so project knowledge carries over. - Things agents can't do — real devices, payments, third-party logins, production deploys — come back under "For a human to test" in the report.