Parallel Coding Agents — herdr Protocol
You are running parallel-agents. Goal: turn a git repo + an issue (or a
whole backlog) into a real herdr session where four (or N) coding agents work
side-by-side in their own worktrees, and hand back either a DIFF_COMPARE.md
of four takes on one issue, or a STATUS.md of a whole backlog.
The end user's agent CLI (Claude Code, Codex, Cursor, opencode, droid, Amp, etc.) does the actual coding — herdr is just the multiplexer that lets them run at the same time without stepping on each other's files. You never touch the user's main checkout, never merge, never push — the user picks which branch to keep.
Prerequisites
- Linux or macOS (Windows preview beta).
git ≥ 2.5withgit worktreeavailable (git worktree --help).- At least one coding-agent CLI the user is already logged into:
claude,codex,cursor-agent,opencode,droid,amp,grok,gemini,kilo, or one of the other agents herdr detects. Uses the user's own agent subscription — herdr does not proxy or hold any key. herdr ≥ 0.7.1— one Rust binary, ~10 MB, no Electron, no daemon. Install with any of:curl -fsSL https://herdr.dev/install.sh | shbrew install herdrmise use -g herdrnix run github:ogulcancelik/herdr
No Clawvard SDK key required. This course runs entirely on the user's local machine. Nothing here calls a Clawvard backend, and nothing here needs the Clawvard SDK.
License note
herdr is dual-licensed: AGPL-3.0-or-later for personal, internal-R&D,
and open-source use, and a commercial license for organizations that
plan to bundle or redistribute it and cannot meet AGPL's network-
distribution terms. Running the course locally is always free — the
commercial license is only relevant if you plan to ship herdr inside a
product of your own. Full terms and contact at
https://herdr.dev → license.
Consume the upstream skill
herdr ships its own agent skill — a self-contained SKILL.md published from
the herdr repo — that documents the raw socket API and the herdr workspace
/ herdr tab / herdr pane / herdr wait commands. Install it once, and
your agent knows how to drive herdr from inside a pane:
npx skills add ogulcancelik/herdr --skill herdr -g
This Clawvard skill is a thin protocol on top of that — it fixes the
four-worktree layout and the DIFF_COMPARE.md / STATUS.md templates for
the two shipped tasks. Everything about pane control (pane split,
pane read, wait agent-status, …) lives in the upstream skill; do not
reimplement it here.
How to read herdr's agent state (read this before anything else)
Read this section before you promise the user anything about "watching agents finish". herdr's status detection is live-output-driven — it reads what the agent is printing right now — and it has some non-obvious edges:
working— the agent is producing output right now (spinner, streaming tokens, tool call). Sidebar shows a yellow indicator.blocked— the agent is displaying a permission prompt or a select-an- option menu and waiting on a human. Sidebar shows a red indicator.idle— the agent is at its input prompt with no pending question. Sidebar shows a green indicator. This is the "work has stopped, over to you" state you should poll for, usingherdr wait agent-status <pane> --status idle.done— a UI-only sidebar affordance herdr renders when a pane transitionsworking → idlewhile unfocused, so a returning user sees what changed. It is not a separate value returned byagent_statusin the socket API. Do notwait --status done; wait foridleand check the branch instead.unknown— herdr has no live text to read from. This is the normal state when the agent CLI process has already exited (the pane is at a bare shell prompt). It is also what you see immediately after starting a pane before the first output arrives.
Practical consequence: once you tell an agent "you're done" and it exits,
the pane will show unknown, not idle. That's not a regression — the
sidebar is telling you truthfully "there's no live agent here anymore".
Ground truth for "the work is finished" is the branch tip (a real
commit on the expected branch), not the pane's status field.
Recommended polling pattern:
# 1) While the agent is live, wait for it to come back to the input prompt:
herdr wait agent-status <pane> --status idle --timeout 900000
# 2) Then verify the work landed by reading the branch, not the pane:
git -C <worktree> log --oneline -1
git -C <worktree> diff <base>...HEAD --shortstat
If a pane goes to unknown before you've seen a commit, that means the
agent exited early. Read the last screen (herdr pane read <pane> --lines
80) and tell the user what happened — do not silently retry.
Protocol A — one issue, four takes, diff-off
The default shipped popularTask. Use this when the user has a single issue they want to hand to several agents at once so they can pick the best branch.
-
Ask for the issue in one paragraph (paste, link, or a
.mdpath). Confirm the base branch to fork from (defaultmain). -
Slugify the issue — e.g.
issues/1.md "stats crashes on empty input"→ slugstats. All four worktrees / branches share this slug. -
Create four isolated worktrees off the base branch, one per agent:
git worktree add ../wt-<slug>-a -b <slug>-a <base> git worktree add ../wt-<slug>-b -b <slug>-b <base> git worktree add ../wt-<slug>-c -b <slug>-c <base> git worktree add ../wt-<slug>-d -b <slug>-d <base>Worktrees are the only way to have four agents edit the same repo at the same time without clobbering each other's index. Do not put more than one agent in the main checkout.
-
Open a herdr workspace named after the slug (
stats-parallel) and split it into a 2×2 pane grid, one pane per worktree. Useherdr panesplit --cwd <worktree>andherdr pane renameso each pane's label reads<slug>-<letter> · <agent-name>(e.g.stats-a · claude). -
Start one coding agent per pane, each with the same issue text but a distinct angle. Use whichever CLI the user has (
claude,codex,cursor-agent,opencode, …). Angle templates:pane angle prompt hint A minimal patch "smallest possible diff that closes the issue" B rewrite for clarity "treat this file as legacy; rewrite for readability" C test-first (TDD) "write failing tests first, then greenify" D root-cause note + minimum fix "write ROOT_CAUSE.md first, then only the change it justifies" Pass the issue as the very first message, followed by the angle hint.
-
Watch the sidebar while agents are live, then confirm from git. Use
herdr agent listfor a quick roll-up, or wait per pane withherdr wait agent-status <pane> --status idle --timeout 900000— that is the "agent is back at its prompt" state. If a pane goes red (blocked), read the last screen withherdr pane read <pane> --lines 80and tell the user what the block is — do not press keys on the agent's behalf. If a pane flips tounknownbefore you've seen a commit on its branch, the agent process exited early; report why, do not silently retry. -
Do not merge, do not push. When every branch tip is a real commit you can name (
git -C <worktree> log --oneline -1), producereports/<slug>/DIFF_COMPARE.mdoff the base branch (not on any of the four). Use the template below. -
Hand back: the four branch names, the four commit SHAs, and the
DIFF_COMPARE.mdpath. The user decides which branch to keep.
DIFF_COMPARE.md template
Fill one row per branch and one wrap-up paragraph. Every column must be a
real number pulled from git diff <base>...<branch> --shortstat and a real
test result — no invented figures.
# <slug> · N parallel takes
| branch | angle | diff | tests | key files |
| ---------- | ------------------ | ----------- | -------- | ------------------ |
| <slug>-a | minimal patch | +X / −Y | P / T | … |
| <slug>-b | rewrite | +X / −Y | P / T | … |
| <slug>-c | test-first (TDD) | +X / −Y | P / T | … |
| <slug>-d | root-cause | +X / −Y | P / T | … |
## Verdict
**Merge `<slug>-?`.** One paragraph: why this one, what to carry forward
from the others, what to squash. Concrete — no "either could work".
Never write a verdict of "any of them is fine" — the whole point of the diff-off is to pick one and explain the tradeoffs.
Protocol B — N issues, one pane each, long-run detach + reattach
Use this when the user hands over a backlog of N mostly-independent issues and wants to clear them overnight or between other tasks.
-
Take the issue list; each issue gets a stable
<issue-key>(e.g.LOG-1132or a short slug). -
One worktree per issue — do not share a worktree between two issues, even if the files look independent (they never really are):
git worktree add ../wt-<repo>-<issue-key> -b <issue-key> <base> -
Open a herdr workspace named
backlog-YYYY-MM-DD. Give each pane a tab or split that fits — herdr keeps up to six panes readable per tab; past that, open a new tab (herdr tab create --workspace <id>). -
Start the coding agent in each pane with the corresponding issue text. Rename each pane to the issue key so the sidebar is scannable.
-
Detach and reattach are the whole point. Tell the user before they close the laptop:
ctrl+bthenqdetaches — the herdr server keeps every pane alive.- Later,
herdr(no args) reattaches the local session. - From a phone or another machine:
herdr --remote ssh://you@host— nossh + tmux, because that breaks image pastes. Before the user detaches, sanity-check every pane is actually running a detected agent —herdr agent listshould list every pane with a realagent_status(working / idle / blocked). If a pane is alreadyunknownat this point the agent hasn't started; fix that first.
-
Poll the sidebar during the run, and treat the branch tip as ground truth after the run. When a pane's agent finishes and exits its shell, herdr will show
unknownfor that pane — that's expected. TheSTATUS.mdfor that entry should be driven bygit -C <worktree> log --oneline -1andgit -C <worktree> diff<base>...HEAD --shortstat, not by the current pane status. Suggested report shape:# backlog-YYYY-MM-DD | issue-key | branch | branch state | pane now | notes | | ----------- | --------- | ------------------------- | --------- | --------------------- | | LOG-1132 | LOG-1132 | committed · +42/−7 · green | unknown | ready for review | | LOG-1145 | LOG-1145 | untouched | blocked | agent asked for API key value | | LOG-1178 | LOG-1178 | wip · +18/−2 · red | working | rerunning failing test |For every
blockedpane, include the concrete blocker (last stderr, last prompt).unknownis a legitimate pane state at the end of a run — pair it with the branch state so the user sees the full story. -
Do not auto-merge, do not push. Even in Protocol B, the user picks.
Etiquette
- One agent, one worktree, one branch. Never let two agents share a branch; the merge story is a nightmare.
- Don't press keys for a blocked agent unless the user explicitly says
so.
blockedmeans the agent is waiting on a human decision; forwarding keys defeats the whole safety story. - Do not enable auto-merge, auto-push, or any destructive git operation
from inside this skill. The end of Protocol A is a report and four branch
names; the end of Protocol B is a report and N branch names. The user's
next
git mergeis theirs to run. - Everything is local. No API key ever leaves the user's shell. If a workflow ever asks you to send agent output to a Clawvard endpoint, stop — that's out of scope for this skill.
Learning complete
Tell the user:
I've learned parallel-agents. Give me a repo + an issue and I'll open a herdr session with four coding agents in four worktrees on four different angles, and hand back a
DIFF_COMPARE.mdso you can pick the branch to merge. Or give me a backlog and I'll open one pane per issue withdetach + reattachset up, and drop aSTATUS.mdyou can check from your phone. Fully local — your agent CLI, your keys, your machine. The sidebar tells youworking / blocked / idlewhile the agents are live; once they exit, the branch tips are ground truth for "the work is done".