Lesson 03 · Using Herdr Effectively

Parallel Work

Give every agent a clear place, checkout, scope, and handoff contract

Your tangible win

After this lesson, you can set up a safe parallel review: one Herdr workspace, an isolated Git worktree, a helper agent in its own pane, and a result you can inspect without stealing focus from the main task.

The operating model

Separate location from identity. A pane is a terminal location. An agent is the recognized process inside it. A worktree is a Git checkout opened as a Herdr workspace.

One project, many places

Herdr's layout primitives compose from broad to narrow: a workspace contains tabs, a tab contains panes, and a pane may contain an agent or an ordinary terminal process.

flowchart TB W["Workspace"] --> T1["Main tab"] W --> T2["Review tab"] T1 --> P1["Agent pane"] T1 --> P2["Server pane"] T2 --> P3["Test pane"] T2 --> P4["Review agent"] style W fill:#faf5ff,stroke:#9333ea,stroke-width:2px style T1 fill:#dbeafe,stroke:#2563eb,stroke-width:2px style T2 fill:#dbeafe,stroke:#2563eb,stroke-width:2px style P1 fill:#fef9c3,stroke:#ca8a04,stroke-width:2px style P2 fill:#f0fdf4,stroke:#16a34a,stroke-width:2px style P3 fill:#f0fdf4,stroke:#16a34a,stroke-width:2px style P4 fill:#fef9c3,stroke:#ca8a04,stroke-width:2px
Figure 1: Tabs organize related terminal layouts; panes hold agents and ordinary processes.
PrimitiveResponsibilityExample
workspaceCreate the project or task boundary.API migration
tabCreate another terminal layout in that workspace.Review, logs
paneControl a raw terminal process.Server, test runner
agentControl a recognized coding agent.Prompt, wait, read
worktreeCreate an isolated Git checkout and open it as a workspace.Feature branch

Why worktrees matter

Two agents in two panes can still collide if they edit the same checkout. A worktree gives a parallel branch its own directory while Herdr keeps it visible as a normal workspace.

Create an isolated checkout

herdr worktree create \
  --cwd ~/project \
  --branch feature/review \
  --label "Feature review" \
  --no-focus
herdr worktree list

Herdr creates the Git checkout, opens it as a workspace, and groups it with the parent repository workspace. To attach to an existing checkout without creating another one:

herdr worktree open \
  --cwd ~/project \
  --branch feature/review \
  --no-focus
flowchart TB R["Main repo"] --> B1["Worktree: feature-a"] R --> B2["Worktree: feature-b"] B1 --> A1["Agent A"] B2 --> A2["Agent B"] A1 --> O1["Review A"] A2 --> O2["Review B"] style R fill:#faf5ff,stroke:#9333ea,stroke-width:2px style B1 fill:#dbeafe,stroke:#2563eb,stroke-width:2px style B2 fill:#dbeafe,stroke:#2563eb,stroke-width:2px style A1 fill:#fef9c3,stroke:#ca8a04,stroke-width:2px style A2 fill:#fef9c3,stroke:#ca8a04,stroke-width:2px style O1 fill:#f0fdf4,stroke:#16a34a,stroke-width:2px style O2 fill:#f0fdf4,stroke:#16a34a,stroke-width:2px
Figure 2: Worktree isolation lets parallel agents work on separate branches without sharing one checkout.

Build the layout before starting the agent

agent start does not create or split panes. First create the workspace or tab, capture the returned root pane, and split only when you need another terminal.

created=$(herdr workspace create \
  --cwd ~/project \
  --label review \
  --no-focus)
pane=$(printf '%s\n' "$created" | jq -r \
  '.result.root_pane.pane_id')
split=$(herdr pane split "$pane" \
  --direction right \
  --no-focus)
helper=$(printf '%s\n' "$split" | jq -r \
  '.result.pane.pane_id')
herdr agent start reviewer \
  --kind codex \
  --pane "$helper"

The --no-focus flag matters in orchestration: create the helper without yanking the user's current view away from the main task.

Give the helper a bounded job

Use an explicit scope and output contract. A good handoff names the checkout, permitted paths, validation command, and required report.

herdr agent prompt reviewer \
  "Review only src/api and tests/api. \
  Do not edit files. Run the focused tests. \
  Report findings by severity and include paths." \
  --wait \
  --timeout 120000

Then read the result without relying on the state badge alone:

herdr agent read reviewer \
  --source recent-unwrapped \
  --lines 120

Use the state machine for handoff

For agents, use agent wait; for ordinary servers and test runners, use pane wait-output. They solve different problems.

herdr agent wait reviewer \
  --until idle \
  --until done \
  --until blocked \
  --timeout 120000
Do not confuse these

pane wait-output searches terminal text. It does not understand agent lifecycle. agent wait understands working, blocked, done, idle, and unknown.

Move a live pane carefully

A pane move can change its workspace-qualified pane ID. Capture and use the new ID from the response. A running process keeps its launch-time Herdr environment, and --current remains safe from inside that process.

moved=$(herdr pane move w1:p2 \
  --new-workspace \
  --label "Review handoff" \
  --no-focus)
printf '%s\n' "$moved" | jq \
  '.result.move_result | {previous_pane_id, pane}'

Checkpoint: choose the isolation boundary

  1. You need two agents to work on two branches of the same repo.
  2. Create a worktree for each branch.
  3. Open each worktree as a Herdr workspace.
  4. Start one agent in a pane per workspace.
  5. Give each agent a bounded prompt and a verification command.
  6. Wait, read, and review before merging either result.
Two agents must edit separate branches of one repo. Which primitive provides the checkout isolation?

Remember this

Build the place first, isolate the checkout when branches diverge, start the agent second, and hand off with a bounded scope plus proof requirement.

Primary sources

This lesson follows Herdr's official Agent automation, CLI Reference, and Socket API. Use the parallel work cheat sheet for retrieval practice.