Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
gbasin avatar

Agent Fanout

  • 3 installs
  • 1 repo stars
  • Updated July 15, 2026
  • gbasin/agent-fanout

Delegates implementation work to parallel headless agent CLIs (codex or omp) in persistent git worktrees, with Claude orchestrating plan, review, and merge.

About

An orchestration skill that decomposes work, launches cheaper headless agent CLIs across disjoint worktrees, then reviews and merges each diff. A developer uses it to parallelize implementation across subagents while keeping Claude as the reviewing orchestrator.

  • Runner table for codex (sandboxed) and omp/Gemini Flash with launch flags and gotchas
  • Persistent-worktree recipe, disjoint file ownership, and subagent visual QA via dev-browser

Agent Fanout by the numbers

  • 3 all-time installs (skills.sh)
  • Ranked #13,657 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Jul 24, 2026 (Skillselion catalog sync)
npx skills add https://github.com/gbasin/agent-fanout --skill agent-fanout

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs3
repo stars1
Last updatedJuly 15, 2026
Repositorygbasin/agent-fanout

What it does

Delegates implementation work to parallel headless agent CLIs (codex or omp) in persistent git worktrees, with Claude orchestrating plan, review, and merge.

Files

SKILL.mdMarkdownGitHub ↗

Agent fan-out delegation

Claude is the orchestrator: decompose, write precise briefs, review every diff, merge, and own final verification. Headless agent CLIs implement. They are cheaper and faster, not smarter — never merge their work unreviewed.

Runners

Any agent CLI qualifies as a runner if it (a) runs headless and exits when the task is done (completion = process exit, which fires the Bash background notification automatically), (b) operates on the current working directory, and (c) follows a "do not commit" instruction. Pick per phase; mixed fleets are fine.

RunnerLaunch coreBest forSandbox
codex (default)codex exec --sandbox workspace-write ...substantial phases needing judgmentmacOS seatbelt; reads everywhere, writes workspace+/tmp
omp (oh-my-pi)omp -p --no-session --auto-approve --model gemini-3.5-flash ...mechanical/template phases, high-volume cheap worknone — full user permissions

Runner notes:

  • codex: ALWAYS pass --sandbox workspace-write explicitly — the global

~/.codex/config.toml may set danger-full-access, and a bare codex exec would run unsandboxed. Knobs: -m <model>, -c model_reasoning_effort="high".

  • omp: --auto-approve means it can touch anything the user can; the

worktree is discipline, not containment — keep briefs tightly scoped. Model is fuzzy-matched (--model gemini-3.5-flash, --model flash); --thinking low|medium|high trades speed for depth. Needs one-time auth (omp then /login, or a provider key like GEMINI_API_KEY in env) — headless runs fail fast with "Use /login, set an API key..." if missing. Briefs attach via @/path/to/brief.md; capture stdout as the result.

Hard-won architecture rules

1. Never combine the Agent tool's `isolation: worktree` with an async runner. If the launching subagent exits before the runner finishes, the harness reaps the "unchanged" worktree and orphans the still-running task in a deleted directory. Create persistent worktrees manually (below). 2. Launch runners directly via backgrounded Bash; completion = process exit. No status-polling watcher loops. (History: codex-companion background jobs key their state per-cwd, so status from any other directory says "No job found" — which grep watchers misread as "finished".) 3. Visual QA from inside a runner works, with preconditions. Pre-start the dev-browser daemon from the orchestrator before launching (avoids concurrent auto-start races; and under codex's seatbelt, daemon auto-start is impossible — Chrome dies at Mach-port registration, and the task may wedge for hours retrying fallbacks). codex additionally needs -c 'sandbox_workspace_write.network_access=true' or the connect to ~/.dev-browser/daemon.sock is blocked ("Daemon failed to start within 5 seconds"). Screenshot writes happen daemon-side into ~/.dev-browser/tmp/, readable by all runners — they can view the PNGs and check their own work.

Procedure

0. Plan phases

  • If the work needs shared conventions (design system, schema, API shape), run

a foundation phase first as a single task, review and commit it, THEN fan out. Parallel phases inherit the committed foundation.

  • Give parallel phases disjoint ownership: each owns specific files or

specific functions. Additions to shared files go in a clearly marked appendix block (# === <phase> additions ===) to keep merges trivial.

  • Assign runners by difficulty: codex for phases needing judgment, omp+flash

for mechanical ones.

1. Pre-flight (orchestrator, main repo)

# avoid the gitlink trap: embedded worktrees must never reach `git add -A`
grep -qx '.claude/worktrees/' .git/info/exclude 2>/dev/null \
  || echo '.claude/worktrees/' >> .git/info/exclude

# if any phase needs visual QA: warm the daemon OUTSIDE any sandbox
dev-browser <<< 'console.log("daemon warm")'

Start from a clean, committed state — runner diffs are reviewed against HEAD.

2. Persistent worktrees (one per parallel phase)

git worktree add .claude/worktrees/<phase> -b wt-<phase>

3. Briefs

Write each brief to /tmp/<phase>-brief.md (avoids shell quoting issues). Template:

<one-paragraph goal and context>

You are working in <ABSOLUTE worktree path>. Run `pwd` first to confirm.
If this directory does not exist or is not a git worktree, STOP and report —
do not work anywhere else.

SCOPE — you own ONLY: <files / functions>. Additions to shared files go in an
appendix block marked `# === <phase> additions ===`. Touch nothing else.

Do NOT commit. The orchestrator reviews and merges your working-tree diff.

TEST PROCEDURE (run before reporting):
<exact build/test commands>
# visual check (daemon is already running; use a unique browser name):
cat > /tmp/<phase>-shot.js <<'JS'
const page = await browser.getPage("<phase>");
await page.setViewportSize({ width: 1440, height: 1000 });
await page.goto("file://<path under the worktree>");
await page.waitForTimeout(300);
console.log(await saveScreenshot(await page.screenshot({ fullPage: true }), "<phase>.png"));
JS
dev-browser --browser <phase> run /tmp/<phase>-shot.js
# then VIEW the saved png and verify: <concrete visual criteria>

REPORT: what changed, how you tested (including what the screenshot showed),
known gaps.

4. Launch (one backgrounded Bash call per phase)

codex:

cd <abs worktree path> && codex exec \
  --sandbox workspace-write \
  -c 'sandbox_workspace_write.network_access=true' \
  -o /tmp/<phase>-result.md \
  "$(cat /tmp/<phase>-brief.md)"

omp (e.g. Gemini Flash):

cd <abs worktree path> && omp -p --no-session --auto-approve \
  --model gemini-3.5-flash \
  @/tmp/<phase>-brief.md > /tmp/<phase>-result.md

Run with run_in_background: true. The completion notification fires when the process exits — do not write watcher loops.

5. Monitor (only when prompted or suspicious)

Tail the Bash output file. If no new output for ~10 minutes, check git -C <worktree> diff --stat — runners sometimes wedge AFTER the work is done. If the diff looks complete, kill the process and salvage the tree; the work is rarely lost.

6. Review and merge (orchestrator)

git -C .claude/worktrees/<phase> diff > /tmp/<phase>.patch
# READ the patch, check the result file, then:
git apply --3way /tmp/<phase>.patch

Re-run build/tests on main after each apply. Overlapping hunks across phases mean the ownership split failed — resolve manually, don't re-delegate.

7. Final QA — yours, not the runners'

Runner screenshots are a first-line filter. Before committing, re-verify the key surfaces yourself (desktop + mobile widths at minimum). Then commit and:

git worktree remove .claude/worktrees/<phase> --force
git branch -D wt-<phase>

Failure-mode quick reference

SymptomCauseAction
codex: "Daemon failed to start within 5 seconds"daemon not pre-warmed, or network_access not setwarm daemon from orchestrator; relaunch with the -c flag
codex stuck retrying browser fallbacks (node_repl, NODE_PATH, --connect)same as abovesame; salvage any completed diff first
omp: "Use /login, set an API key environment variable..."no stored credentials and no provider key in envone-time omp + /login, or export the provider key; then relaunch
omp touched files outside its scopeno sandbox + loose brieftighten SCOPE wording; review patch hunks before apply (you do this anyway)
worktree vanished mid-taskit was harness-managed (Agent isolation)kill orphans, recreate persistent worktree, relaunch
companion status: "No job found"per-cwd state; checked from wrong dircd to the exact launch dir; never treat as completion
task "running" for an hour with frozen progress tail but full diff presentend-of-run wedgekill, salvage tree, do verification yourself
stray gitlinks in a commit.claude/worktrees/ not excludedpre-flight exclude line; fix commit with git rm --cached

Related skills

AI & Agent Buildingagentsautomation

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.