From 30 to 100 agents
Running 100 agents is a different structure from running 30, not the same thing done more. At 30 you dispatch work and review diffs. At 100 you own the contract, the checks and the exceptions, and coordinators run everything else. Most of the 100 agents check work instead of writing it, and they coordinate through files that move between folders.
Every number on this page is an illustrative estimate chosen to make the mechanics concrete. None of it is measured. The models are toys built to show which constraint binds.
What each scale looks like
Drag through the tiers. Watch three things change together: how many layers sit between you and the work, how much of the fleet is checking rather than building, and what you personally do all day.
Show every tier as one table
| Agents | Coordination | Example projects | Your job | What breaks next |
|---|
Your current setup is about 30 agents spread as five projects of six. The same 30 on one project already needs a queue. The step to 100 on one project adds a second layer of coordinators, and it only works if the project has a mechanical check.
It's the Large-Scale Change process with agents
Google published how it makes one change across a huge monorepo, in Software Engineering at Google, chapter 22. Almost every part of a 100-agent project has a counterpart there. If you have ever watched an LSC go through, you already have most of the intuition.
| LSC concept | Agent-fleet equivalent | What carries over |
|---|---|---|
| The LSC proposal and its review | Phase 0 brief and phase 3 design | The change is approved as a design before anyone touches thousands of files. |
| Codemod tools (ClangMR, Refaster, and similar) | Codemod-first decomposition | Do the mechanical majority with one tool and one review, then hand only the exceptions to builders. |
| Rosie sharding the change | Tasks in the queue, split by touches | Shards are sized so each can be tested and reviewed alone, and split along ownership lines. |
| TAP testing each shard | The phase 2 checks, run by verifiers | A shard that fails its tests never reaches a reviewer. |
| Owners and global approvers in review | Verifiers, plus you for judgment-only tasks | Review is cheap because the change is mechanical and already tested. Judgment is spent only where needed. |
| Retrying flaky or failed shards | The reaper and attempts | Failures are normal and retried automatically, up to a cap. |
| Cleaning up the old API | Phase 9 deletion | A migration isn't finished until the old path is gone. |
The one big difference: an LSC changes code a human already understands, using a tool a human wrote. An agent fleet also lets the agents write the non-mechanical parts. That is exactly the work that needs verifiers, which is why the fleet is mostly checkers.
Why more agents often ships nothing more
Shipped work is the minimum of every stage's capacity. Builders, verifiers, CI and you form a pipeline, and the narrowest stage sets the output. Adding agents widens two stages. It does nothing for the other two. Try the presets, then move the sliders.
Assumptions: a builder finishes about 10 attempts a day. A verification pass takes longer than people expect (replay, driving the app, blast-radius), so a verifier finishes about 8 a day, and each attempt gets about 1.6 passes on average once risky tasks get two or three verifiers. That's why a balanced fleet has about two verifiers per builder. A rejected task costs another build and more passes. Tasks without a mechanical check need your review. Coordinators are added at one per 20 workers. Change the assumptions in your head and the shape stays the same.
What the lift actually is
With strong checks and enough CI, going from about 25 to 100 agents might roughly double verified output per day. That's a guess, and it costs about four times the tokens. With weak checks, output stays flat, because you were already the limit.
The larger gains are usually not speed:
- Confidence per change. The same volume, but each change raced, attacked and independently verified.
- Hours you aren't working. Coordinators keep going overnight. Running more hours is cheaper than running more agents at once.
- Projects you wouldn't attempt. A 40-service migration that would take a team a quarter becomes something one person can run.
Reading the model
The red bar is the stage that limits output. Raising any other slider changes nothing shipped and only raises idle capacity.
Three lessons fall out:
- The mechanical check share is the most powerful slider. It moves your own review out of the critical path.
- After that, CI and merges are usually the limit, and more agents can't fix that.
- The reject rate eats every agent stage at once. Lowering it through clearer tasks and encoded lessons beats adding agents.
What can be checked without you
Checks run from mechanical (a script says pass or fail) to judgment (someone decides). The more of a project's tasks sit high on this ladder, the more agents it can use. Pick a project type to see which checks apply and roughly where it stops scaling.
The bar is a rough judgment of how much a pass tells you, from green (a pass means a lot) to red (a pass means little).
Choosing the check for a task
Ask one question: if this change were wrong, what would fail? The answer is the task's done_when. If the honest answer is "someone would notice it looks off", the task has no mechanical check. Batch those for yourself and keep them out of the pipeline.
Plant bugs before you trust a check
Before fan-out, make a few wrong changes of the kind builders will make, and confirm the check catches each one. A check that has never caught a planted bug can pass everything, and the dashboard stays green until production. Also measure its flakiness: a check that fails 3% of the time for no reason rejects dozens of good tasks per wave.
The stage decides the role
Agents are interchangeable. A slot that claims from todo/ is a builder. A slot that claims from review/ is a verifier. You change the mix by starting and stopping slots, and no agent needs reconfiguring. Only the coordinator and you are long-lived.
You
Owns the brief, the contract, the gates and the exceptions.
- Decides design and product calls
- Hand-reviews a random sample of passed work
- Approves anything irreversible
- Fixes the system, not individual tasks
Coordinator
One interactive chat per project or area. The only agent you talk to.
- Writes and promotes tasks
- Reaps stalled tasks, rebalances slots
- Merges passed work in dependency order
- Writes the summary twice a day
- Restarted on a schedule, with state in files
Builder
Fresh headless session per task. Claims from todo/.
- Works in its own worktree or jj workspace
- Runs
done_whenitself before submitting - Never edits outside
touches - Asks through
q ask, never waits
Verifier
Fresh session per check, ideally a different model family. Claims from review/.
- Gets only
done_whenand the branch, not the builder's story - Runs the check and attaches the output
- Accepts or rejects with evidence
- Never fixes anything
Racer
For tasks that failed twice, or are known to be hard.
- Two or three builders attempt the same task
- A verifier picks a base and grafts the best parts (pstack
arena)
Integrator, summarizer, watcher
Small supporting roles.
- Integrator: one agent that merges, in order
- Summarizer: turns result files into your briefing
- Watcher: compares production metrics to baseline during rollout
Rules that keep verification honest
- No agent verifies its own work, ever.
- Verifiers use another model family where possible. Agreement across families is strong evidence. Agreement within one family is weak.
- Verifiers don't see the builder's explanation. A persuasive write-up makes it easier to approve wrong work.
- Risk sets the number of verifiers: one for a rename, three plus a
blast-radiuspass for auth or data migrations. - A verifier's job is to run things. If the only way to verify a task is to read the diff and decide, that task belongs in your queue.
Typical ratios at 100
| Role | Count | Why that many |
|---|---|---|
| Verifiers | 50 to 55 | One to three per task, plus rechecks after rejects |
| Builders | about 25 | Limited by merge rate and conflict risk |
| Racers | about 10 | Only on hard or twice-failed tasks |
| Coordinators | 6 | Five areas plus one top coordinator |
| Support | 4 to 5 | Integrator, summarizer, watchers |
The queue: folders as a message bus
Agents mostly don't message each other. A coordinator writes task files. Workers claim a task by moving its file, and a task's status is the folder it sits in. Nothing needs a server, everything survives crashes, and you can inspect it with ls. The simulation below runs the real rules: claiming, heartbeats, reaping dead workers, independent verification, retries with a cap, and parking questions for you.
The rules the simulation follows
- Claim by rename.
mv todo/T12.md doing/T12.mdis atomic on one filesystem. Two workers can't both win, and the loser just picks another task. - Heartbeat or be reaped. Working agents touch a heartbeat file every few minutes. When one goes stale, the reaper returns its task to
todo/withattemptsincreased. - Builders never verify their own work. Finished work goes to
review/, and a separate agent claims it from there. - Cap retries. After three attempts a task goes to
failed/for a human or a redesign, instead of looping. - Park, don't block. A question goes to
inbox/, and the worker moves on to another task. - Dependencies wait in backlog. Tasks move to
todo/only when what they depend on is done.
Where it lives, and why
~/.queues/rest-to-grpc/
backlog/ blocked on depends_on
todo/ ready to claim
doing/ claimed by a builder
review/ built, waiting for a verifier
verifying/ claimed by a verifier
done/ verified; the coordinator merges
failed/ gave up after 3 attempts
inbox/ questions only you can answer
results/ one file per task, one writer each
hb/ heartbeat files, touched by workers
Put it at an absolute path outside every worktree and outside your vault. Each worktree or jj workspace has its own copy of repo files, so a queue inside the repo splits into copies. Sync services (iCloud, Dropbox, Obsidian Sync, Drive) break atomic renames and create conflict copies.
A task file, field by field
A task file has to stand on its own: workers start fresh, with no memory of your conversations. Tap any highlighted field to see what it's for and what goes wrong without it.
---
id: grpc-billing-paginated
goal: Billing's callers get typed pagination,
so a renamed cursor field breaks the build
done_when: >
scripts/check rest-left billing == 0 &&
scripts/check replay billing --pattern paginated
touches: [services/billing/client/, protos/billing/]
depends_on: [proto-billing-v1, retry-interceptor]
risk: medium # 2 verifiers
base: main
attempts: 0
owner: ~ # set by q claim
verifier: ~
---
Migrate the 23 paginated call sites in billing
(list: results/discovery-billing.md#paginated).
Contract: protos/README.md, decisions D3 and D5.
Two callers branch on the JSON "next" field
being absent. Keep that behavior; see D5.
The q command
Every command takes the queue directory first (q ~/.queues/x claim build w1); the table drops it for brevity. A tested starting version is in the starter kit below. Write one small script like it and tell every agent to use only it. If ten agents run mv and edit frontmatter by hand, one will eventually skip the heartbeat, edit a task it doesn't own, or move a file to the wrong folder. The rules belong in code, not in every prompt.
| Command | Who runs it | What it does |
|---|---|---|
q claim build <name> | Builder loop | Takes the oldest ready task whose touches don't overlap anything in doing/. The overlap check and the move happen under one lock, or two claimers could each see "no overlap" and grab conflicting tasks. |
q claim review <name> | Verifier loop | Moves a task from review/ to verifying/. Builders and verifiers are separate slots, so a verifier never holds its own work. |
q beat <id> | Any worker | Touches the heartbeat. Called from the worker loop, not by the model. |
q submit <id> | Builder | Moves to review/. The builder has already written results/<id>.md: revision, what changed, its own check output. |
q accept <id> / q reject <id> --why … | Verifier | Accept moves to done/ for the coordinator to merge. Reject returns to todo/ with findings attached and attempts +1, or to failed/ at the cap. |
q ask <id> "…" | Any worker | Writes the question to inbox/ and parks the task. |
q answer <id> "…" | Coordinator | Appends your answer and releases the task to todo/. |
q reap [minutes] | Coordinator, on a loop | Returns stale builder tasks to todo/ (attempts +1) and stale verifier tasks to review/. |
q promote | Coordinator | Moves backlog tasks whose dependencies are done into todo/. |
q status | You and coordinators | Counts per folder. Extend it with reject rate per cluster and the oldest heartbeat. |
Past a few hundred active tasks, or once you need queries like "everything touching services/billing", move the same rules into SQLite. It's still one local file, with real transactions. If teammates also need to see and comment on tasks, the issue tracker can be the queue, with the same claim, heartbeat and review rules.
The five files that make it run
Everything above comes down to a queue script, a worker loop and three role files. q was run against a test queue on Linux, including the overlap lock and the reaper. The loop and the role files are templates. Read all of them before running them on anything you care about, and adapt the paths.
qthe queue · about 70 lines · bash, perl, find
#!/usr/bin/env bash
# q: a minimal file queue. Works on macOS and Linux (bash, perl, find).
# usage: q <queue-dir> <command> [args]
set -euo pipefail
Q=$1; cmd=$2; shift 2
mkdir -p "$Q"/{backlog,todo,doing,review,verifying,done,failed,inbox,results,hb}
lock() { until mkdir "$Q/.lock" 2>/dev/null; do sleep 0.2; done; trap 'rmdir "$Q/.lock"' EXIT; }
field() { perl -ne "print \$1 and exit if /^$2:\\s*(.*)\$/" "$1"; }
setf() { perl -pi -e "s|^$2:.*|$2: $3|" "$1"; }
paths() { field "$1" touches | tr -d '[] ' | tr ',' ' '; }
overlaps() { # does task file $1 touch a path held in doing/?
local d p m
for d in "$Q"/doing/*.md; do [ -e "$d" ] || continue
for p in $(paths "$d"); do for m in $(paths "$1"); do
case "$m" in "$p"*) return 0;; esac; case "$p" in "$m"*) return 0;; esac
done; done
done; return 1; }
stale() { [ ! -e "$Q/hb/$1" ] || [ -n "$(find "$Q/hb/$1" -mmin +"$2")" ]; }
bump() { local a; a=$(( $(field "$1" attempts) + 1 )); setf "$1" attempts "$a"; echo "$a"; }
case $cmd in
claim) # q DIR claim build|review WORKER-NAME -> prints task id, or exits 1
stage=$1 me=$2; lock
from=$([ "$stage" = build ] && echo todo || echo review)
to=$([ "$stage" = build ] && echo doing || echo verifying)
for t in $(ls -tr "$Q/$from"/*.md 2>/dev/null); do
[ "$stage" = build ] && overlaps "$t" && continue
id=$(basename "$t" .md)
mv "$t" "$Q/$to/"; setf "$Q/$to/$id.md" "$([ "$stage" = build ] && echo owner || echo verifier)" "$me"
touch "$Q/hb/$id"; echo "$id"; exit 0
done; exit 1 ;;
beat) touch "$Q/hb/$1" ;;
submit) mv "$Q/doing/$1.md" "$Q/review/"; rm -f "$Q/hb/$1" ;;
accept) mv "$Q/verifying/$1.md" "$Q/done/"; rm -f "$Q/hb/$1" ;;
reject) # q DIR reject ID "why"
f="$Q/verifying/$1.md"; a=$(bump "$f")
printf '\n## Rejected, attempt %s\n%s\n' "$a" "$2" >> "$f"; rm -f "$Q/hb/$1"
if [ "$a" -ge 3 ]; then mv "$f" "$Q/failed/"; else mv "$f" "$Q/todo/"; fi ;;
ask) # q DIR ask ID "question"
printf '\n## Question\n%s\n' "$2" >> "$Q/doing/$1.md"
mv "$Q/doing/$1.md" "$Q/inbox/"; rm -f "$Q/hb/$1" ;;
answer) # q DIR answer ID "answer" (coordinator, after you reply)
printf '\n## Answer\n%s\n' "$2" >> "$Q/inbox/$1.md"; mv "$Q/inbox/$1.md" "$Q/todo/" ;;
reap) # q DIR reap [minutes] default 20
mins=${1:-20}; lock
for f in "$Q"/doing/*.md "$Q"/verifying/*.md; do [ -e "$f" ] || continue
id=$(basename "$f" .md); stale "$id" "$mins" || continue; rm -f "$Q/hb/$id"
case "$f" in
*/verifying/*) mv "$f" "$Q/review/"; echo "reaped $id: back to review" ;;
*) a=$(bump "$f"); if [ "$a" -ge 3 ]; then mv "$f" "$Q/failed/"; else mv "$f" "$Q/todo/"; fi
echo "reaped $id: attempt $a" ;;
esac
done ;;
promote)
for f in "$Q"/backlog/*.md; do [ -e "$f" ] || continue; ok=1
for d in $(field "$f" depends_on | tr -d '[] ' | tr ',' ' '); do [ -e "$Q/done/$d.md" ] || ok=0; done
if [ $ok = 1 ]; then mv "$f" "$Q/todo/"; echo "promoted $(basename "$f" .md)"; fi
done ;;
status)
for s in backlog todo doing review verifying done failed inbox; do
printf '%-10s %3s\n' "$s" "$(find "$Q/$s" -name '*.md' | wc -l | tr -d ' ')"; done ;;
*) echo "unknown command: $cmd" >&2; exit 2 ;;
esac
worker.shone slot · claim, run, repeat
#!/usr/bin/env bash
# worker.sh <queue-dir> <build|review> <claude|codex>
# One slot. Claims a task, runs one fresh headless agent on it, repeats.
set -u
Q=$1 STAGE=$2 CLI=$3 ME="$STAGE-$(hostname -s)-$$"
LIMIT=90m # macOS: brew install coreutils, then use gtimeout
while true; do
task=$(q "$Q" claim "$STAGE" "$ME") || { sleep 30; continue; }
# heartbeat from the loop; stops by itself if this script dies
( while kill -0 $$ 2>/dev/null; do q "$Q" beat "$task"; sleep 120; done ) &
beat=$!
dir=$([ "$STAGE" = build ] && echo doing || echo verifying)
brief="$(cat ~/fleet/roles/$STAGE.md)
Queue: $Q
Task id: $task
Task file: $Q/$dir/$task.md"
case "$CLI" in
claude) timeout "$LIMIT" claude -p "$brief" ;;
codex) timeout "$LIMIT" codex exec "$brief" ;;
esac
kill "$beat" 2>/dev/null
# an agent that exits without submit/accept/reject/ask leaves a stale
# heartbeat, and the coordinator's reap returns the task
doneroles/build.mdbuilder brief
You are a builder in an agent fleet. Do one task, then exit.
1. Read the task file in full, then every file it points to, including
the contract and the decisions it cites.
2. Create your workspace and work only there:
jj workspace add ~/ws/<task-id> -r <base from the task file>
3. Change only paths listed in touches. If the task needs anything outside
them, run q <queue> ask <task-id> "<what and why>" and exit.
4. If the brief is ambiguous and running code can't settle it, ask the same
way. Never guess on a contract question.
5. Run every command in done_when yourself. Do not submit until all pass.
6. Write <queue>/results/<task-id>.md with: the revision id, what changed,
and the done_when output. Do not argue that it is correct.
7. Run q <queue> submit <task-id> and exit.
Never edit the task's frontmatter, touch other tasks, merge, push to main,
or disable, skip or weaken a check.roles/review.mdverifier brief
You are a verifier in an agent fleet. Check one task, then exit.
You did not build it, and you must not fix it.
1. Read only the task file's frontmatter (goal, done_when, touches, risk)
and the revision id in <queue>/results/<task-id>.md. Do not read the
builder's description of why the change works.
2. Confirm the diff stays inside touches.
3. Run every done_when command against that revision. Keep the full output.
4. If risk is high, also look for effects outside the diff: callers of
what changed, shared config, anything the checks don't exercise.
5. If every command passed and the diff is in scope:
q <queue> accept <task-id>
Otherwise:
q <queue> reject <task-id> "<failing command, its output, file:line>"
6. Append your check output to the results file, then exit.
If a done_when command can't run (missing script, broken environment),
reject with that reason. Never accept on reading alone.roles/coordinator.mdcoordinator brief
You coordinate one area of the <project> fleet. You never write product code.
Every 10 minutes
q <queue> reap 20 ; q <queue> promote ; q <queue> status
Merging
For each task in done/ not yet merged, in dependency order: rebase its
revision onto main, run the area's merge check, land it, and note the
merge in its results file. On conflict, return it to todo/ with the
conflict described.
Watching
Track reject rate per cluster over the last 20 tasks. If a cluster passes
25%, stop promoting its tasks and write the pattern to the inbox.
Reporting
Twice a day write Projects/<project>/Runs/<date>-<area>.md in the vault
from the run template. Numbers come from q status and results files only.
Inbox
Each loop, read Projects/<project>/Inbox.md. For a ticked item with an
answer under it: q <queue> answer <task-id> "<the answer>"
Never approve rollout steps, delete data, force-push, or change the
contract. Those go to the inbox.
Your state lives in the queue and the vault. When your context gets long,
write a handoff note to the vault and stop. A fresh coordinator continues
from the files.Choices baked into these files
- The lock is a directory.
mkdiris atomic everywhere and macOS has noflock. If a claim is killed withkill -9, delete.lockby hand. - Verifiers get less information on purpose. They see the finish condition and the revision, not the builder's reasoning.
- Reaped verification doesn't count as an attempt. Only builder failures use up the three tries.
- The coordinator's numbers come from files. A summary written from memory drifts within a day.
What's missing on purpose
- Reject rate per cluster in
q status. Add acluster:field and count reject sections indone/andtodo/. - Merging. It depends on your repo and CI, so it stays in the coordinator's hands.
- Sandboxing. Run agents with only the credentials the task needs, never production ones.
- Any trust in task text. Workers act on whatever
todo/says, so only the coordinator should write there.
Panes are slots, not conversations
You don't drive dozens of interactive chats. Each pane runs a loop: claim a task, start a fresh headless agent on it, finish, repeat. The pane mostly shows logs. The sidebar becomes a status board, and the only panes you type into are the coordinators. Configure a fleet below and the mock sidebar and launch script update.
States here are random, to show the layout. Real states come from each pane.
workspace create, agent start and agent prompt are from Herder's docs. Using --kind shell for a plain shell pane and agent prompt to type a command into it are my assumptions. If your version differs, use herdr pane split and herdr pane run for the worker slots.
The worker loop
Each slot runs worker.sh from the starter kit: claim, start a fresh headless agent with a time limit, repeat. The heartbeat comes from the loop, so the model never has to remember it, and the time limit catches a model that hangs while its loop is still alive.
Three ways agents connect
Subagents. A coordinator spawns workers with its Task tool and gets their reports back. Most of the 100 live here, and Herder never sees them.
Pane to pane. An agent inside Herder can drive another pane through the CLI. Use this for long-lived roles you want to watch, like a different-model reviewer:
herdr agent start reviewer --kind codex
herdr agent prompt reviewer "Review branch grpc-billing \
against done_when in ~/.queues/…/review/grpc-billing.md" \
--wait --until done --timeout 600000
herdr agent read reviewer
Files. The queue. It's the only one of the three that survives a crash, so anything another agent depends on should end up in a file.
Install the Claude integration (herdr integration install claude) so pane states come from the session rather than screen-scraping, and still confirm completion from result files, not pane state.
jj instead of git worktrees
One writing agent per workspace keeps changes apart. With jj, jj workspace add ../ws/<task> is cheap, and every workspace shares one repo store, so the coordinator can see all in-flight changes with one jj log.
Two jj behaviors help at scale. Conflicts are recorded in commits instead of stopping a rebase, so the integrator can rebase the whole queue onto main and see which tasks now conflict without anything blocking. And the operation log (jj op log, jj op restore) gives the coordinator a clean undo for a bad merge.
# coordinator, per task
jj workspace add ../ws/grpc-billing-paginated \
-r main
# integrator, after a verifier accepts
# (<workspace>@ names that workspace's working-copy commit)
jj rebase -s grpc-billing-paginated@ -d main
jj log -r 'conflicts()' # who now conflicts?
# cleanup
jj workspace forget grpc-billing-paginated
Ten phases, one peak
The agent count stays low for most of the calendar and peaks in one phase. Your effort is the opposite: heavy at the start, at the pilot, and at the gates. The running example is moving 40 services from REST to gRPC. Pick a phase for the full detail.
Design is where your hours go
At 100 agents a contract mistake doesn't stay one mistake: every builder copies it, and every verifier passes it because each task correctly follows the contract. The chart shows how many tasks need rework depending on when the mistake is caught.
Production adds an incident on top of the rework. Caught in design, the cost is one prototype you throw away anyway.
Prototype the alternatives
Agents build two or three competing designs as throwaway sketches. You compare working versions, not documents. (pstack arena, Prototype playbook.)
Write the hardest callers first
Once types exist, an agent writes the five most awkward real call sites against them. Ugly calls or workarounds mean the design is wrong.
Build one path end to end
One representative piece goes through every layer and passes the real checks. Where it's painful to build, the design is weak.
Model the risky state
Retries, ordering and concurrency get a TLA+ model or statechart that tries every ordering of events. (pstack statechart.)
Attack it
A different model family argues against it with interrogate. Only objections it can demonstrate with a run count.
Decide and write it down
A decision log with each choice, the rejected options and why. Builders and verifiers read it when a task is ambiguous.
Yours
- Core types and interfaces, edited line by line
- Product calls
- Choosing between prototypes
- Each task's finish condition
- The design checkpoint after the pilot
Agents'
- Research: how the current system works and why (
how,why) - Building the prototypes and the end-to-end path
- Writing the test callers
- Arguing against the design
- Over time, more of the design, once your past decisions are written where they can follow them
Lauren Tan's stack, mapped to the phases
pstack (version 0.15.36, cursor/plugins/pstack) is 58 skills, 23 playbooks and 2 agents. Nearly every skill is marked disable-model-invocation: true, so nothing triggers by itself. /poteto-mode routes each task to a playbook and pulls in the rest, or you call a skill by name. Tap a phase to highlight the skills it uses.
The playbooks that matter at scale
- Orchestrate. A standing project for one coordinator chat: multi-day, many stacked PRs, many subagents.
- Autopilot-full. A queue of independent PRs, one owner each, root-verified before merge.
- Autopilot-stack. The same without merging. You land it.
- Autonomous run and Pause safely / Session pickup. Long unattended runs, and stopping and resuming them cleanly.
- Babysit and Shipping. Driving PRs to green, then landing only the verified run from the root.
Porting notes
pstack names Cursor's Task tool, Cursor model slugs (grok-4.7-xhigh-fast for code, claude-opus-5-5-xhigh for judgment) and cursor-team-kit skills. Community ports exist for Claude Code (michael-denyer/pstack-claude), T3 and Oh My Pi. They mostly substitute those terms, and the Claude Code port adds a session-start hook so poteto-mode engages without the slash command.
The parts that carry over to any setup: the 24 one-rule principle files, correct, the why source adapters, and show-me-your-work's decision log.
The vault as the control room
Your vault is where the human-facing state belongs: the brief, the decisions, the daily summaries, the inbox and the retro. The machine-facing state (the queue, the workspaces) stays outside it on a plain local disk. Coordinators write into the vault, and you read and answer there.
Projects/rest-to-grpc/
Brief.md phase 0, you write it
Decisions.md D1…Dn, with rejected options
Contract.md links to protos/README.md
Inbox.md - [ ] tasks the fleet needs you for
Runs/
2026-11-03.md coordinator summary, twice a day
2026-11-04.md
Retro.md phase 9
~/.queues/rest-to-grpc/ the queue
~/ws/rest-to-grpc/… one jj workspace per task
~/fleet/roles/ build.md, review.md, coordinator.md
---
project: "[[rest-to-grpc]]"
phase: 6-fanout
area: payments
date: 2026-11-04
merged: 17
rejected: 2
reject_rate: 0.11
failed: 1
inbox_open: 1
agents_peak: 19
---
## Since this morning
- 17 tasks merged; 2 rejected (proto3 optional
fields again, lint caught one in review)
- failed: ledger-export (custom serializer, see Inbox)
## Needs you
- [ ] ledger uses a custom JSON serializer not in
[[Decisions]]. Add to contract or exclude?
How to wire it
- The coordinator's role file names the vault path and the summary template. It writes notes. It never reads the vault for instructions, so a stray note can't steer the fleet.
- Frontmatter numbers make every run queryable. A Bases view or Dataview table over
Runs/gives you reject rate per area per day. A frontmatter watcher like the one behind your dashboard could turn the same fields into a live fleet panel. - Answer the inbox in Obsidian by ticking a task and writing the answer under it. The coordinator reads
Inbox.mdon its loop and releases parked tasks. herdr notification showon a new inbox item means you don't watch the vault.
What not to do
- Don't keep the queue in the vault. Sync breaks atomic renames, creates conflict copies, and turns a crash-safe queue into a race.
- Don't let 20 agents append to one note. Each writes its own result file outside the vault, and one summarizer writes the note.
- Don't paste raw agent output into the vault. Summaries only, with links to result files or PRs.
- Check what your employer allows before pointing agents at work code or syncing anything about it into a personal vault.
What your day looks like during fan-out
During phase 6 you spend roughly two to three hours on the fleet. The rest goes to the next project's design, which is where your judgment matters most.
failed/. 20 minutesreview/ is backing up. 20 minutesFrom 15 to 30 today, to 100
Each step has a condition for moving on. Skipping one usually means the next step stalls for a reason from the skipped one. Tick steps off as you go; this page remembers them in your browser.
Symptoms and fixes
Most problems show up first as a number in the coordinator's summary. Learn the symptoms and you can diagnose from the summary without reading any code.
| Symptom | Likely cause | Fix |
|---|---|---|
Agents idle, todo/ empty | Decomposition ran dry or tasks are stuck in backlog | Coordinator plans more work, or check depends_on for a blocked foundation task |
review/ keeps growing | Too few verifiers, or checks are slow | Move slots from building to verifying, or speed up the check |
| Reject rate climbing in one cluster | A role file or check drifted, or a new pattern appeared | Pause the cluster, read five rejects, fix the template or contract |
| Reject rate near zero | Verifiers approving without running checks | Hand-review a sample. Require check output in every acceptance. |
| Same mistake rejected repeatedly | A lesson that lives only in prompts | Encode it as a lint, type or check (pstack correct) |
| Lots of merge conflicts | Overlapping touches, or a shared file every task edits | Make the shared piece its own task that lands first, or generate it at build time |
| Merges slow while agents idle | CI capacity is the bottleneck | Fewer builders, faster or sharded CI, batch merges |
Tasks stuck in doing/ | Dead workers and no reaper | Run q reap on a loop; heartbeat from the worker loop |
| Coordinator forgetting rules after days | Its context is full | Restart on a schedule with state in files, not context |
| Your inbox is the busiest folder | Brief or contract has gaps, or tasks lack mechanical checks | Back to phase 0 or 3 for that area; move judgment tasks out of the pipeline |
| Everything green, production breaks | Checks never caught a planted bug, or no integration phase | Plant bugs in every check; run phase 7 before rollout |
| Project "done", old code still there | Phase 9 skipped | Deletion tasks, verified by the discovery script returning zero |
Terms used on this page
- Brief
- The phase 0 page: goal, finish condition as checks, constraints, out of scope, irreversible steps.
- Contract
- The shared types, interfaces and decisions every builder follows. Settled before fan-out.
- Coordinator
- A long-lived interactive agent that owns one area's queue, merges passed work and writes summaries.
- Builder / verifier
- Roles set by queue stage. Builders claim from
todo/, verifiers fromreview/. - Racer
- One of several builders attempting the same hard task, compared and grafted together.
- Integrator
- The single agent allowed to merge, in dependency order.
done_when- A task's finish condition, stated as a command that passes or fails.
touches- Paths a task may change. Used to avoid running overlapping tasks at once.
- Heartbeat
- A file a working agent's loop touches every few minutes to show it's alive.
- Reaper
- The coordinator loop that returns tasks with stale heartbeats to
todo/. - Planted bug
- A deliberate wrong change used to prove a check catches that kind of mistake.
- Differential test
- Run old and new code on the same inputs and require the same outputs.
- Characterization test
- A test that records what code currently does, so a migration can't silently change it.
- Pilot wave
- About 10% of tasks run with every role, to measure the process before scaling it.
- Fan-out
- The phase where the full agent count drains the queue.
- Mechanical check share
- The fraction of tasks a script can verify. The main thing that sets how far a project scales.