Multi-CLI Spawn (cross-provider parallel seats)
When to use
- Need several providers to answer the same brief in parallel
- Multi-LLM council / second opinions / cross-vendor review
- You already have (or will install) the per-CLI
*-cli-agentwrappers
This is not a substitute for vendor-native multi-agent inside one CLI (-T / ultracode /
teamwork). Use those for fan-out within one provider; use this skill to fan-out across providers.
Why
Each vendor has native multi-agent inside one CLI (agy teamwork, Claude ultracode, Codex subagents, Grok spawn_subagent, …). This skill is the cross-CLI layer: one brief → N providers → N answer files.
Usage
./spawn.sh --outdir /tmp/council-$$ \
-f /tmp/brief.md \
--seat agy:readonly \
--seat claude:ultracode \
--seat codex:team \
--seat grok \
--seat kimi:readonly \
--seat qwen:readonly \
-C /path/to/repo \
-t 1200s
Seat forms: name, name:readonly, name:ultracode|team, name:readonly,team, name@label
(unique output key when duplicating a CLI).
Seat modifiers (comma-separated after :): readonly/r, team/ultracode/T.
Outputs
| File | Meaning |
|---|---|
<key>.log |
Live CLI stdout/stderr |
<key>.md |
Final answer, or BLOCKED:… stub (written when the seat finishes) |
<key>.pid |
Seat process-group id (kill target) |
<key>.rc |
Seat exit code |
<key>.status |
RUNNING → DONE rc=0 | BLOCKED rc=N (atomic) |
spawn.pid / spawn.status |
Parent: RUNNING → DONE, or SPAWNED if --no-wait |
brief.md |
Copied/normalized brief inside outdir |
Waiting contract
- Default: do not poll. Run
spawn.shin the foreground (wait mode). Its exit code andCLI_AGENT_RESULT: PASS|BLOCKED <seat>lines are the completion signal. --no-wait/ external watcher: wait until every seat.statusis terminal (DONE/BLOCKED), e.g.:
Do not treat missingwhile grep -qlE '^RUNNING' "$OUTDIR"/*.status 2>/dev/null; do sleep 15; done*.mdor a dead*.pidalone as "no answer" —.mdappears only when the seat finishes; pidfiles can look dead if the parent spawn was killed while seats continue.- Kill only via numeric PIDs in seat
*.pidfiles (process groups). Skipspawn.pidwhen iterating kill targets unless you intend to stop the parent. Neverpkill -flong patterns.
Hard rules
- PID files only — never
pkill -fwith a pattern that also appears in the launcher argv - Quota fail-open — provider errors / empty output →
BLOCKEDstub; do not retry-loop - agy needs PTY — handled inside
agy-exec.sh - Orchestrator owns git — spawn always passes
--no-git - Parallel writers should use separate worktrees (
-Cper seat) to avoid collisions - Seat
rc != 0isBLOCKED(missing binary is not a council vote)
Synthesize
Read *.md only for seats whose .status is terminal. Strictest blockers win. Divergent
findings are high value. Re-run only BLOCKED seats after the user refreshes quota/auth.
See also: docs/CORRECTNESS.md, docs/FEATURES.md.