Running 10 Agents at Once with herdr, Conductor and Worktrees
Running ten coding agents at once takes three layers: a git worktree per task so edits never collide, a supervisor that shows which agent needs you (Claude Code’s agent view, herdr, or Conductor), and a review queue that merges one verified pull request at a time. Worktrees isolate files only, so ports, databases and browser profiles need their own plan.
It is Friday afternoon and the backlog holds twelve small, independent issues. You open three terminals, start an agent in each, and go to a meeting. When you come back, one agent has sat on a permission prompt for 40 minutes, a second agent’s dev server quietly started on the next free port, and the third agent’s Playwright run passed against the second agent’s server. On Monday you have nine pull requests and no idea which of them were really tested.
This page is for the developer running a batch of agents, and for the tech lead making it repeatable for a team.
What a ten-agent setup gives you
Section titled “What a ten-agent setup gives you”- A launch recipe for three to ten agents in worktrees, with Claude Code, Codex and Cursor
- The Worktrunk-plus-herdr example: three
wt switchcommands and one screen that shows who is blocked - A per-worktree plan for ports, databases, secrets and browser profiles
- The workflow from issue batch to merge train, with three copy-paste prompts
- The evidence each pull request carries before sign-off, and the failure modes to watch
How many agents can one person supervise?
Section titled “How many agents can one person supervise?”The limit is not how many agents you can start but your review capacity, quota and machine.
- Quota. Anthropic’s agent view documentation states that background sessions “consume your subscription usage the same as interactive sessions, so running ten agents in parallel uses quota roughly ten times as fast as running one” (code.claude.com, read 2026-09-26).
- Disk and CPU. The Next.js repository’s
conductor.jsonrecommends"parallel_agents": 3and notes “Each worktree uses ~500MB-1GB disk space after build” (vercel/next.js,canary, read 2026-09-26). - Review. Faros AI’s 2025 report found that developers on high-AI teams merge about 98% more pull requests while PR review time rises about 91% (secondary: search extract of faros.ai, read 2026-09-26). More agents move the bottleneck to review.
- Measurement. METR wrote on 2026-02-24 that “our measurements of time-spent on each task are unreliable for the fraction of developers who use multiple AI agents concurrently.” Measure pull requests merged, reverted and time in review instead.
| Agents at once | What works | Where the limit shows |
|---|---|---|
| 1–3 | Native worktrees and your terminal tabs, or Claude Code’s agent view | Remembering which tab is waiting |
| 3–10 | A supervisor: herdr, cmux or a desktop app such as Conductor, plus per-worktree ports | Review queue and quota |
| 10+ | An orchestrator (Gas Town, CLI Agent Orchestrator), with dispatch paused when the review queue is full | Merge conflicts and reviewer load |
Which tool runs which layer?
Section titled “Which tool runs which layer?”Every tool below sits on the git worktree and adds a launcher, a state-aware terminal or a review GUI. Start with the built-ins; a third-party tool earns its place with mixed-agent fleets, state detection or a review board.
| Tool | Layer | What it adds | Install (verified) | Licence |
|---|---|---|---|---|
| Claude Code built-ins | Worktree + supervisor | --worktree, .worktreeinclude, --bg, claude agents (agent view, research preview), --tmux | ships with Claude Code 2.1.283 | vendor |
| Codex built-ins | Worktree + session list | --worktree, codex agents | ships with codex-cli 0.157.1 | vendor |
| Cursor | Worktree + cloud | Worktrees, Cloud Agents in isolated VMs | in the app | vendor |
Worktrunk (wt) | Worktree launcher | Worktree plus agent in one command; hooks; hash_port | brew install worktrunk && wt config shell install | MIT or Apache-2.0 |
git gtr (CodeRabbit) | Worktree launcher | git gtr new … --ai, PR worktrees, cleanup of merged branches | brew tap coderabbitai/tap && brew install git-gtr | Apache-2.0 |
| herdr | Supervisor terminal | Panes marked working, blocked, idle, done or unknown; CLI and socket API; 24 agent kinds | brew install herdr | Apache-2.0 |
| cmux | Supervisor terminal (macOS) | Ghostty-based terminal, notification rings, cmux claude-teams | brew tap manaflow-ai/cmux && brew install --cask cmux | GPL-3.0-or-later |
Claude Squad (claude-squad) | tmux + worktree TUI | Diff view, commit and push per session | brew install claude-squad (for the short cs name, add the README’s symlink) | AGPL-3.0 |
| ccmanager | Session TUI | Busy/waiting/idle state, .worktreeinclude, devcontainers | npm install -g ccmanager | MIT |
| Conductor | Desktop app (macOS, closed) | Claude Code and Codex in worktrees, one review board | download from conductor.build | proprietary |
Gas Town (gt) | Orchestrator | A “Mayor” agent coordinating workers via Beads | brew install gastown | MIT |
CLI Agent Orchestrator (cao) | Orchestrator | Supervisor and worker agents in tmux, web UI | uv tool install git+https://github.com/awslabs/cli-agent-orchestrator.git@main --upgrade | Apache-2.0 |
Popularity as of 2026-09-26 (GitHub stars, read through the GitHub API for this site’s ecosystem dossier): herdr 40,779; cmux 27,412; Gas Town 18,195; Claude Squad 8,533; Worktrunk 8,416; git gtr 1,786; CLI Agent Orchestrator 1,350; ccmanager 1,250. Conductor is closed source and publishes no comparable metric. Stars measure attention, not fitness.
Start parallel agents with native worktrees
Section titled “Start parallel agents with native worktrees”Each tool can put a session in its own worktree without extra software.
Start one session per issue, each in its own worktree. Claude Code creates the worktree under .claude/worktrees/<name>/ on a new branch named worktree-<name>:
# Terminal (repository root). One terminal per agent.claude --worktree issue-101claude --worktree issue-102 --tmux # same, inside a tmux sessionclaude --worktree "#1234" # worktree from pull request 1234For more than three agents, dispatch them to the background and supervise from one screen; each background session moves into its own worktree before it edits files:
claude --bg --name issue-101 "Fix issue #101: pagination skips the last page. Add a failing test first."claude --bg --name issue-102 "Fix issue #102: CSV export drops the header row. Add a failing test first."claude agents # one screen: Ready for review, Needs input, Working, Completedclaude agents --json # the same state for scriptsBefore the first run, add .claude/worktrees/ to .gitignore and create a .worktreeinclude in the repository root. It uses .gitignore syntax and copies only files that are both listed and gitignored:
.env.env.localAgent teams (experimental, CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1) suit one feature split among collaborating agents, not a batch of independent issues; the bundled /batch skill splits one large change into 5–30 worktree units.
Codex worktree support is on by default since codex-cli 0.156.0, but a session runs in a worktree only when you opt in with --worktree or /worktree:
# Terminal (repository root). One terminal per agent.codex --worktree "Fix issue #101: pagination skips the last page. Add a failing test first."codex --worktree "Fix issue #102: CSV export drops the header row. Add a failing test first."
# Headless, for a script that fans out a batch:codex exec --worktree "Fix issue #103: the date filter ignores the time zone. Add a failing test first."
# See every session on the local app-server daemon:codex agentsCodex 0.157.1 documents no .worktreeinclude equivalent, so copy .env and other gitignored files with a launcher such as Worktrunk (below).
Cursor’s documentation describes Worktrees as letting “Agent work in isolated Git checkouts”, and Cloud Agents as running “in isolated VMs in the cloud with full development environments” (cursor.com, checked 2026-08-28). The exact UI steps could not be re-checked for this page, so follow Cursor’s Worktrees page for the current flow. For a terminal fleet, the launchers below are agent-agnostic: Worktrunk’s -x runs any program, and herdr lists cursor among its agent kinds.
Launch three agents with Worktrunk and watch them in herdr
Section titled “Launch three agents with Worktrunk and watch them in herdr”Worktrunk creates the worktree and starts the agent in one command, and herdr shows every agent’s state in a sidebar. Both run on macOS and Linux.
-
Install both tools and the herdr integration for your agent, which lets a restart restore the agent’s session:
Terminal window brew install worktrunk && wt config shell installbrew install herdrherdr integration install claude # also: codex, cursor, opencode, …On Windows, winget installs Worktrunk as
git-wtbecausewtclashes with Windows Terminal, so rungit-wt config shell install. -
Commit a project config so every new worktree gets its gitignored files, dependencies and its own dev-server port.
pre-startsteps block until they finish, so.envandnode_modulesexist before the agent starts;post-startruns in the background, which suits only the dev server.hash_portturns the branch name into a stable port between 10000 and 19999:.config/wt.toml [[pre-start]]copy = "wt step copy-ignored"[[pre-start]]install = "pnpm install"[post-start]server = "wt step tether -- pnpm dev --port {{ branch | hash_port }} --strictPort"[list]url = "http://localhost:{{ branch | hash_port }}"Worktrunk copies every gitignored file unless a
.worktreeinclude(as in the Claude Code tab) limits it. -
Start
herdrand create one workspace per agent, from the sidebar or withherdr workspace create --label feature-a. Run one line in each:Terminal window wt switch -c feature-a -x env -- 'PORT={{ branch | hash_port }}' claude 'Add user authentication'wt switch -c feature-b -x env -- 'PORT={{ branch | hash_port }}' claude 'Fix the pagination bug'wt switch -c feature-c -x env -- 'PORT={{ branch | hash_port }}' claude 'Write tests for the API'-ccreates the branch and worktree, and-xruns one program after switching with the arguments after--. Worktrunk expands templates in those arguments, soenvstarts the agent withPORTset to the samehash_portvalue the dev server uses. The worker prompt and the Playwright config later on this page both read thatPORT, so the agent’s tests hit its own server. -
Read the overview. herdr’s sidebar shows each agent’s state and rolls it up per workspace, so with one workspace per agent a blocked agent is visible without visiting each pane. For scripts, the CLI gives the same view; a manually launched agent has no name, so target it by the pane ID that
agent listprints:Terminal window herdr agent listherdr agent wait w2:p1 --until blocked --timeout 600000herdr agent read w2:p1 --source recent-unwrapped --lines 80 -
Merge each finished branch, one at a time.
wt merge mainsquashes, rebases ontomain, fast-forwards and removes the worktree; in a pull-request workflow, rungh pr createfrom the worktree andwt removeafter the merge.
What you should see: three workspaces, each with Claude Code running in ../repo.feature-a, ../repo.feature-b or ../repo.feature-c; wt list shows three branches with three different ports in the URL column; each workspace’s sidebar state moves from working to idle or blocked as its agent progresses.
For a larger batch, script it. This loop was assembled from the herdr 0.9.1 CLI reference:
# Run from a shell inside herdr, at the repository root.while IFS='|' read -r branch task; do created=$(herdr workspace create --cwd "$PWD" --label "$branch" --no-focus) pane=$(printf '%s\n' "$created" | jq -r '.result.root_pane.pane_id') # task text must not contain single quotes herdr pane run "$pane" "wt switch -c $branch -x env -- 'PORT={{ branch | hash_port }}' claude '$task'"done <<'EOF'issue-101|Fix issue #101 (pagination skips the last page). Write a failing test first.issue-102|Fix issue #102 (CSV export drops the header row). Write a failing test first.issue-103|Fix issue #103 (date filter ignores the time zone). Write a failing test first.EOFConductor: the desktop path on macOS
Section titled “Conductor: the desktop path on macOS”Conductor (Melty Labs) is a closed-source Mac app that runs Claude Code and Codex agents in parallel worktrees, with one board for reviewing them. Choose it for a GUI diff board on macOS; it does not run on Linux or Windows.
The verifiable part is the repository config. This is an abridged version of the conductor.json the Next.js repository commits (read 2026-09-26; the full file also has name, description, TURBO_TELEMETRY_DISABLED and a notes list):
{ "scripts": { "setup": "./.conductor/scripts/setup.sh", "run": "./.conductor/scripts/run.sh" }, "worktree": { "default_branch": "canary" }, "environment": { "NEXT_TELEMETRY_DISABLED": "1" }, "recommendations": { "parallel_agents": 3 }}Give each worktree its own ports, database and browser
Section titled “Give each worktree its own ports, database and browser”A worktree isolates files and the branch. Everything else is shared unless you split it, and most collisions are silent.
| Resource | Shared by default? | What goes wrong | Fix |
|---|---|---|---|
| Files and branch | No | — | The worktree itself |
Gitignored files (.env) | Missing in the new worktree | Tests fail on config, or the agent invents values | .worktreeinclude (Claude Code, Worktrunk, ccmanager), wt step copy-ignored, gtr.copy.include |
| Dev-server port | Yes | Vite moves to the next free port unless strictPort is set | A fixed port per worktree: hash_port, a port block per worktree index, or CONDUCTOR_PORT (secondary) |
| Test runner’s server | Yes | Playwright’s reuseExistingServer attaches to whatever listens on the port, even another agent’s server | Derive baseURL, webServer.url and the dev-server port from one per-worktree value |
| Browser profile | Yes | A persistent Playwright MCP profile can be used by only one browser at a time | Start Playwright MCP with --isolated in each agent |
| Local database | Yes | Two agents migrate the same schema | One database per worktree (Worktrunk’s hash_port vars, a container per branch) or a sandbox |
git config and the .git directory | Yes | A config write in one worktree changes all of them | Never let an agent run git config; keep settings in committed files |
| Permission approvals (Claude Code) | Yes | “Don’t ask again” in one worktree applies to all of them | Put deliberate rules in .claude/settings.json and review them |
| Production data, deploys, secrets, third-party APIs | Yes | One agent’s “quick check” writes live data | Deny the commands, and give agents sandbox credentials only |
Tie the test runner to the same PORT the launcher gave the agent (the env prefix in the Worktrunk step), and fail loudly when it is missing instead of falling back to a shared default. For a Vite project with Playwright:
import { defineConfig } from '@playwright/test';
// Locally, PORT comes from the agent's launch line; CI runs one server, so a default is safe there.const port = process.env.PORT ?? (process.env.CI ? '5173' : '');if (!port) throw new Error('PORT is not set: start the agent with its worktree port');const baseURL = `http://localhost:${port}`;
export default defineConfig({ use: { baseURL }, webServer: { command: `pnpm dev --port ${port} --strictPort`, url: baseURL, reuseExistingServer: !process.env.CI, },});Give each agent its own browser for UI checks. The --isolated flag keeps the browser profile in memory, so parallel agents do not fight over one persistent profile. The commands are derived from the vendor’s install instructions for each tool:
claude mcp add playwright -- npx @playwright/mcp@latest --isolatedcodex mcp add playwright -- npx @playwright/mcp@latest --isolated{ "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest", "--isolated"] } }}An MCP server’s tool schemas load into every agent’s context. Run /context in Claude Code before and after adding the server to see what it costs each of your ten sessions.
When file-level isolation is not enough (services, containers, networks), move each agent into a sandbox; the options are compared in agent sandboxes, and the full-stack pattern is in ephemeral environments per agent task.
Run the workflow from issue batch to merge train
Section titled “Run the workflow from issue batch to merge train”The launcher is the easy half. What decides whether ten agents help is the work around them: a batch that does not collide, a standard prompt, supervision by exception, and a queue that merges one verified change at a time.
-
Pick a batch that cannot collide. Choose independent issues with acceptance criteria, no two touching the same module. A read-only planning agent can triage.
-
Create one worktree per issue, named after it (
issue-101), so branch, pull request and agent row share one name. -
Dispatch with one standard prompt. Each agent writes a failing test, fixes the issue, runs the checks on its own port, and opens a draft pull request with the evidence.
-
Supervise by exception. Watch only
blockedor Needs input. Pause dispatch when the review queue reaches its cap; the review queue guide shows how to set it. -
Review evidence, not every line. A reviewer agent checks each diff against its acceptance criteria first (
/code-reviewin Claude Code,codex review --base mainin Codex). The human reads the test names, the evidence and the findings, and reads code where a finding or the risk level asks for it. -
Merge as a train. Merge one pull request at a time, rebase the next onto the new
main, and re-run CI. GitHub’s merge queue does this for a team (add themerge_groupevent to the workflow that runs your required checks);wt merge maindoes it locally. When a rebase conflicts, re-dispatch the losing issue on a fresh worktree. -
Clean up. Remove merged worktrees:
wt remove,git gtr clean --merged --closed, orclaude rm <id>for a background session. Commit and push before you delete a session in agent view: deleting the session can remove the worktree Claude created for it (it is kept when it holds unpushed work unless you pass--discard-unpushed).
To start these agents from the issue tracker, see the issue-to-PR pipeline; to split one task among agents, see multi-agent orchestration patterns.
How do you know ten parallel pull requests are safe to merge?
Section titled “How do you know ten parallel pull requests are safe to merge?”Each change has to prove itself without a human reading every line. Require four things per pull request, and let the merge queue enforce the last.
| Evidence | Produced by | Checked by |
|---|---|---|
| A test that fails without the change and passes with it | The worker agent, shown in the Evidence section | Reviewer agent (PASS on the first check) |
| Type check, lint and test suite run in the agent’s own worktree, on its own port | The worker agent | CI on the pull request |
| A diff limited to the issue’s files, with no config, migration or lockfile changes | The worker agent | Reviewer agent, then a CODEOWNERS rule for the sensitive paths |
Green CI on the head rebased onto the latest main | The merge queue | Required status check |
Sign-off stays with a person. The developer who dispatched the batch owns each merge. The tech lead owns the rules: batch size, the review-queue cap, which paths always need a human, and the numbers to watch (pull requests merged per day, time in review, reverts within a week). A rising revert count means the batch is too large or the criteria too thin; the fix is fewer agents, not faster review. For review bots that can take the first pass, see AI code review bots.
What breaks when you run ten agents at once?
Section titled “What breaks when you run ten agents at once?”Tests pass against the wrong server. A dev server moved to the next free port and the test runner reused another agent’s server. Recovery: stop every dev server, pass each agent a fixed PORT with --strictPort, and re-run the tests of every pull request in that batch.
Two agents edit the same file. The second rebase conflicts. Recovery: merge the first and re-dispatch the second issue on a fresh worktree from the new main. Prevent it by listing expected files at triage.
A blocked agent goes unnoticed. herdr shows an unrecognized prompt as idle (unknown for Codex). Recovery: check anything idle or unknown for a few minutes with herdr agent read, or dispatch with claude --bg so the session lands in Needs input.
A worktree is missing .env or dependencies. Tests fail on configuration, or the agent writes placeholder values. Recovery: add the files to .worktreeinclude (or wt step copy-ignored), add the dependency install as a pre-start hook, and restart the agent.
The disk fills up. Next.js cites 500 MB to 1 GB per worktree. Recovery: git worktree list, then git worktree remove for merged work; run git worktree unlock first when git refuses a lock that Claude Code left on a -p run.
Work disappears. Deleting a session in agent view can remove its worktree (it is kept when it holds unpushed work unless you pass --discard-unpushed), and git worktree remove --force discards uncommitted work. Recovery: commit and push before you delete; if the branch is gone, git fsck --lost-found lists its commits until garbage collection.
The quota runs out mid-batch. Recovery: cap the batch, move routine issues to a cheaper model once your evals support it (see the models hub), and run long batches off-hours.
An agent touches shared state. A migration on the shared local database, a git config write or a production command affects every worktree. Recovery: restore from your backup, deny the command, and give agents sandbox credentials only. Keep Claude Code updated: its security advisories list a “Sandbox Escape via Git Worktree Path Confusion” rated High (2026-06-25).