From orchestration-studio
Run a tmux/rmux director-workers orchestration: spawn and command multiple Claude Code workers in panes, each in its own git worktree, monitor their state with background watchers, and coordinate their output into PRs. Use when the user wants to parallelize work across multiple agent sessions, set up a multi-agent workflow on a server, or asks to "orchestrate" tasks across tmux panes.
How this skill is triggered — by the user, by Claude, or both
Slash command
/orchestration-studio:directorThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Full key/command cheat sheet: [rmux-reference.md](rmux-reference.md) · End-to-end flow: [WORKFLOW.md](../../WORKFLOW.md)
Full key/command cheat sheet: rmux-reference.md · End-to-end flow: WORKFLOW.md
You are the director: a long-lived Claude Code session that commands N worker Claude Code sessions running in tmux (or rmux) panes. Workers do the heavy lifting; you plan, dispatch, monitor, integrate, and report.
session "workers" ← one tmux session, one window, N panes
pane 0.0 → worker A (worktree wt-area-a)
pane 0.1 → worker B (worktree wt-area-b)
pane 0.2 → worker C (worktree wt-area-c)
session "director" ← you live here
One worker = one git worktree. Workers sharing a checkout WILL destroy each
other's uncommitted state (a git reset/checkout by one wipes the others'
files). Create them before dispatching anything:
git worktree add .claude/worktrees/wt-area-a -b work/area-a origin/main
Every dispatch follows this exact sequence — each step exists because skipping it caused a real failure:
rmux send-keys -t workers:0.N Escape # 1. dismiss any overlay ("How is Claude doing?")
sleep 0.5
rmux send-keys -t workers:0.N C-u # 2. clear the input line
sleep 0.5
rmux send-keys -t workers:0.N -l "the full prompt as ONE literal string"
sleep 3 # long mandates land as a collapsed paste — let the TUI ingest
rmux send-keys -t workers:0.N Enter # 3. submit
sleep 6
rmux capture-pane -p -t workers:0.N | tail -5 # 4. VERIFY: composer empty + pane WORKING
Rules:
-l (literal) always — without it, tmux interprets prompt text as key names.C-u first, always. (Production
sighting: ghost text once suggested the exact decision the director was about
to send — still not input.)❯ and a busy indicator is up; if the text is still sitting there,
re-send Enter (one retry is normal on panes ≤55 cols — or zoom first with
rmux resize-pane -Z). Symmetrically, verify the composer is EMPTY before
typing, or you ship a hybrid of stale draft + new mandate.Cold workers + self-contained mandates is the cheap default. When the task needs workers that share deep project context (a long diagnosis, DB access patterns, architecture decisions), fork a template session instead:
/branch it once yourself so
your own director chatter stays out of it.claude -r <template-session-id>, then immediately
send /branch — the pane is now on its own fork; the template stays
pristine for the next worker.Trade-off: every fork starts with the template's full context — smarter workers, pricier turns. Use for diagnosis-heavy waves; stick to cold workers for mechanical ones.
Two signals, OR'd — neither is reliable alone:
esc to interrupt hint. In narrow panes (~60 cols) the bottom bar
truncates, so grep the prefix only ('esc to'). Newer CLI builds drop
this hint entirely in some states while the worker is hard at work.Honking… (1m 22s · ↓ 41.5k tokens). Match the
elapsed-time-in-parens shape, never the verb: completed turns print
✻ Churned for 4m 7s (note for, no parens), and matching verbs marks
finished workers busy forever.pane=$(rmux capture-pane -p -t workers:0.N)
busy=$(( $(echo "$pane" | grep -c 'esc to') + $(echo "$pane" | grep -cE '… \([0-9]+m? ?[0-9]*s') ))
# busy>0 → WORKING ; busy=0 → idle candidate
Debounce before declaring IDLE: between tool calls both signals blip off for a few seconds. Require 6–8 consecutive idle polls at 20s intervals (~2 min) before treating a worker as done.
Pane titles are stale (they show the first prompt of the session) — never use them for state.
Never poll in the foreground. Launch a background watcher per wave and let its completion notification re-invoke you:
# run with run_in_background=true
busy_check() { # 'esc to' hint + live spinner — see "Detecting worker state"
local pane; pane=$(rmux capture-pane -p -t workers:0.$1 2>/dev/null)
echo $(( $(echo "$pane" | grep -c 'esc to') + $(echo "$pane" | grep -cE '… \([0-9]+m? ?[0-9]*s') ))
}
declare -A ic; ic[0]=0; ic[1]=0
for i in $(seq 1 250); do
for p in 0 1; do
b=$(busy_check $p)
if [ "$b" -gt 0 ]; then ic[$p]=0; else ic[$p]=$((${ic[$p]}+1)); fi
if [ "${ic[$p]}" -eq 8 ]; then
echo "🔔 pane$p IDLE"
rmux capture-pane -p -S -42 -t workers:0.$p | grep -vE '^\s*$' | tail -16
exit 0
fi
done
sleep 20
done; echo timeout
The capture-pane -S -42 … | tail dump gives you the worker's final report
without entering its pane. When the watcher fires, read the worker's output,
act (merge / re-dispatch / escalate), and arm the next watcher.
A watcher can false-complete: if a worker dies (rate limit, filter block),
it looks idle. On every IDLE signal, verify the expected artifact exists (the
report file, the PR, the branch) before treating the task as done — see the
worker-recovery skill for the failure taxonomy.
pr-triage skill) and merge in dependency order.release-train skill).| Anti-pattern | Consequence |
|---|---|
| Workers share one checkout | One worker's git surgery wiped another's uncommitted files |
| Blind Enter on a pane | Ghost text submitted as a prompt |
grep 'esc to interrupt' in narrow panes | Truncated → permanent false IDLE |
| No debounce | Inter-tool blips → false IDLE → premature merge |
| Restarting a worker to "give it a new task" | Lost plan/context it had built |
| Director does worker-sized tasks inline | Context bloat; you lose the map |
| Trusting pane titles | They show the session's FIRST prompt forever |
| Enter racing a long paste, no capture-verify | Mandate stranded in the composer; pane reads idle while "dispatched" work never started |
Busy-detection on the esc to hint alone | Newer CLIs omit it mid-work → false IDLE on an active worker |
| Busy-detection on spinner VERBS | ✻ Churned for 4m is a COMPLETED turn → finished workers read busy forever |
Parallel claude -r of one template session | Two panes appending to the same transcript |
npx claudepluginhub rp4ri/orchestration-studioProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.