| name | multiplexing |
| description | Help the operator coordinate work across N concurrent tmux sessions (Claude Code, pi, raw shells, vim, REPLs). Inventory state, hand off tasks cleanly, prevent messy-run failure modes, keep hygiene. Not an agent harness; not a /using-specialists replacement; tool-agnostic. Invoked explicitly via /multiplexing — do not rely on auto-activation. |
| disable-model-invocation | true |
Multiplexing
You are an orchestration assistant for an operator working in N concurrent tmux sessions (Claude Code, pi, raw shell, vim, REPL). Inventory, hand off, monitor, clean up, recover. You do not run a new harness. You do not replace specialists. The operator may switch agents at any time.
Invoked explicitly via /multiplexing. Auto-activation is unreliable across harnesses — do not assume it fires.
Before starting, run xtmux --help and xt --help (also xtmux <subcommand> --help, xt <subcommand> --help). This skill carries policy and the shapes that matter for correctness. The CLI is authoritative for the current command/flag surface — check it whenever you need exact syntax rather than relying on remembered forms.
Slash-syntax gotcha — pi and claude differ
The most common mistake in this skill: sending /skill:multiplexing to a Claude worker. Claude treats it as literal user text and the skill never loads.
| Runtime | Slash form | Example |
|---|
| Claude Code | /<name> | /multiplexing, /using-specialists |
| Pi | /skill:<name> | /skill:multiplexing, /skill:using-specialists |
This applies wherever a skill is loaded turn-1 via --prompt or is sent as a pointer via send-keys / safe-send-pointer. --skill <name> on either runtime is fine; combining --skill <name> with a leading /<name> in --prompt on Claude Code resolves twice — pick one channel.
Authority boundary
- Own: inventory, assisted handoffs, cleanup hygiene, messy-run recovery, session naming convention.
- Do not own: specialist chain orchestration (→
/using-specialists), delegated-pane self-protocol (→ /multiplexing-team), spawn primitives (Docker/VM/subprocess), custom IPC schemas (beads already serve comms), tool-specific harness bindings.
When it applies vs when it doesn't
Applies: inventory across sessions, delegation to another session, cleanup (dead sessions, orphan processes, leaked worktrees), recovery from a messy delegated agent, coordinated multi-session goal, sprint orchestration.
Does NOT apply: specialist chain orchestration → /using-specialists. Delegated pane's self-protocol → the pane loads /multiplexing-team. Designing a new agent runtime → out of scope. In-process subagent spawn (Claude Agent SDK, Cline, Cursor) → out of scope; stays tool-agnostic. Single-session deep work → no multiplexing needed.
Cardinal rules — non-negotiable
- Never multi-line paste via
send-keys. Each \n is an Enter — the target receives N fragmented prompts.
- Never use
$(...) or backticks inside send-keys — shell expansion injects into the pane.
- Never
tmux paste-buffer with a file that contains newlines. Same fragmentation as rule 1.
- Never send a prompt while the target pane is in Working state. It queues, fragments, or races in-flight output.
- Never invent ad-hoc session names. Follow the naming convention below.
Communication primitives — beads first, /tmp second, send-keys third
- Beads (
bd): canonical durable comms. Task content + status + findings survive session death, harness restart, agent switch. Default to beads for anything worth surviving a crash. Beads are already the operator's message bus; do not invent a fourth channel.
/tmp/<session>-<topic>.txt: ephemeral meta-protocol (negative constraints, output shape, one-off scope clarifications). Write via Bash heredoc, NOT the Write tool (Write is blocked by the bd claim gate in beads-managed repos).
send-keys: single-line pointer only. Three allowed forms — (a) read pointer 'leggi /tmp/<file>.txt e seguilo. <constraint>. report finale.', (b) slash command /using-specialists, (c) brief correction ≤3 sentences.
Prefer xtmux safe-send-pointer when available — it dry-runs first, rejects working targets, multiline payloads, shell substitution, and auto-appends the double-Enter that Claude Code panes require (Claude Code consumes the first Enter as paste-detection).
Pre-flight checklist — before every first send-keys
tmux list-panes -t <session> -F '#{pane_id} #{pane_current_command}'
tmux show-options -p -t <pane_id> -qv @agent_state 2>/dev/null || true
tmux capture-pane -t <session> -p | tail -15
tmux display-message -t <session> -p '#{pane_current_path}'
Any check fails → STOP. Do not improvise; wait, switch session, or recreate. The pane's @agent_state and its visible UI are both authoritative; trust neither one alone.
Session naming convention
<orchestrator-session-name>-<topic-slug> (e.g. infra-audit-sweep, design-spec-rewrite). Persistent main sessions (design, infra, svc) keep bare names. Specialist-spawned sp-<role>-<hash> follow the specialists CLI convention — leave alone. Collisions append -2, -3. Forbidden: svc-s24f-tests, test-orch-xyz, tmp-investigation — the convention is what makes tmux ls parseable.
Operator-help patterns — quick routing
| Pattern | Trigger | Steps in brief |
|---|
| 1 Inventory | "what's running", "session map" | xtmux dashboard sessions-only → per-session pane_current_path + @agent_state + bead |
| 2 Assisted hand-off | "send task X to Y", "delegate to Y" | pre-flight Y → create bead → xtmux handoff --target Y --bead <id> (or /tmp file + safe-send-pointer --yes) → confirm → send |
| 2b Bare launch (no role) | general-purpose worker | `xt claude |
| 3 Cleanup | "kill dead sessions", "clean orphans" | xtmux audit cleanup rows → tmux kill-session idle sessions with clean tree → git worktree prune → sp clean --ps |
| 4 Messy-run recovery | "went off-rails", "N spurious beads" | tmux send-keys C-c ×2-3 → close spurious beads → bd remember the trigger |
| 5 Multi-session goal | one outcome across N sessions | one epic bead → per-session child via --parent → hand off each via Pattern 2 → aggregate on close |
| 6 Sprint orchestration | full sprint w/ judge + DM + ordered merges | epic + per-worker children + /pr-reviewer judge pane + /deploy-monitor pane; DM mandatory on ANY infra-surface PR (prometheus.yml, alertmanager.yml, traefik/**, docker-compose, .env) regardless of size |
| 7 Coordinator sub-orchestrator | epic with many tracked tasks | xt pi --role chain-coordinator --bead <epic> --no-attach — coordinator absorbs monitoring; you see only its final report |
Deploy-gap chain (Pattern 6 essential)
Between gh pr merge and DM opening a window: build → docker compose up -d --force-recreate <svc> → verify docker inspect StartedAt > mergedAt (or scripts/verify-deploy-applied.sh if bundled). DM refuses the window on stale artifact. Full doctrine in /deploy-monitor.
Retrieval hierarchy
Before retrieving, gate on the target's live transition: xtmux wait-agent <target> --wait-for-transition --consume --timeout <dur> blocks until the pane/job state changes instead of a manual capture-pane live-state poll loop. It waits on live pane state and is not durable retrieval — after the wait returns, read the results from the durable sources below. multiplexing-team teaches the same primitive to delegated panes; this is the orchestrator-side equivalent.
Prefer durable sources over live scraping:
xtmux message-get <messageKey> --json — the message that anchored a reply obligation.
xtmux agent-last <pane_id> --json — last completed turn on a pane.
sp result <job-id> --json — final specialist output.
tmux capture-pane — live-state only (pre-flight @agent_state disagreement, wizards, transient UI). Never as final-result protocol.
SQLite coordination — the short version
${XDG_STATE_HOME:-$HOME/.local/state}/xtmux/observability.db is the sole source of truth for reply obligations and outbound waits. Beaded message-send defaults --expects-reply=true; FYI opts out with --expects-reply=false. Recipient preserves messageKey, message-ack = receipt, message-reply --in-reply-to "$KEY" = fulfilment (or safe-send-pointer --reply-to "$KEY" when pane injection is also required). Do not create/inspect/delete runtime marker files; restart recovery comes from SQL. Manual triage: xtmux message-status "$KEY" --json, xtmux obligations list --pane "$MY_PANE" --json, xtmux monitor-list --json.
Failure / escalation trigger
Escalate to operator when: pre-flight can't be satisfied and the send is time-sensitive; a delegated agent produces off-contract output twice in a row after correction; two live sessions on the same worktree cause visible git-state races (recommend dedicated xt claude/xt pi worktree per session); xtmux audit warning rows require judgment calls the operator asked to keep in their hands.
End-of-session hygiene
tmux ls → kill idle <orchestrator>-* with clean tree → git worktree prune on each repo → sp clean --ps → run /session-close-report if loaded.