Tmux Multi Agent
Use this skill when parallel agent work is actually cheaper than doing the task in one session, or when the user wants a long-running worker they can inspect directly. The coordinator stays in the current shell, launches workers in tmux, gives each worker a bounded task, and records the run on disk so another human or agent can inspect it later.
When Not To Use It
- Do not use this for small edits, single-file fixes, or tasks that need constant back-and-forth.
- Do not use it when multiple workers would touch the same files at the same time.
- Do not use it if you cannot run tmux plus at least one of
claudeorcodex.
Preconditions
Verify the tools first:
command -v tmux
command -v claude
command -v codexThe bundled launcher defaults to:
TA_CLAUDE_CMD='claude --dangerously-skip-permissions'
TA_CODEX_CMD='codex --dangerously-bypass-approvals-and-sandbox'These flags are required for non-interactive orchestration. Override via env vars if your setup uses different approval modes.
Optional env vars:
TA_SESSION_ID: run id used to prefix tmux session namesTA_CWD: working directory for launched workers; defaults to the current directory
1. Meta Step
Before spawning workers, write a grounded brief. Do not launch sessions until this exists.
The brief must state:
- scope
- out-of-scope
- exact files or directories each worker may touch
- verification commands the reviewer must run
- definition of done with checkable criteria
Example:
export SESSION_ID="$(head -c2 /dev/urandom | xxd -p)"
export SESSION_DIR=".tmux-multi-agent/sessions/${SESSION_ID}"
mkdir -p "${SESSION_DIR}"/{tasks,handoffs,reviews,artifacts}
cat > "${SESSION_DIR}/brief.md" <<'EOF'
# Scope
Implement the requested change in the target repo.
# Out Of Scope
Anything not required for this task.
# Owned Files
- worker-a: path/glob-a
- worker-b: path/glob-b
# Verification Commands
- bun test ...
- bun run ...
# Definition Of Done
- exact behavior exists
- verification commands pass
- reviewer writes approval or findings
EOF2. Session Setup
Export the run id before using the helper script so every worker session is namespaced:
export SESSION_ID="${SESSION_ID:-$(head -c2 /dev/urandom | xxd -p)}"
export TA_SESSION_ID="${SESSION_ID}"
export SESSION_DIR=".tmux-multi-agent/sessions/${SESSION_ID}"
mkdir -p "${SESSION_DIR}"/{tasks,handoffs,reviews,artifacts}Naming rules:
- every tmux session must be
${SESSION_ID}-<worker-name> - the helper applies that prefix automatically when
TA_SESSION_IDorSESSION_IDis set ta kill allonly kills sessions with the current session id prefix
Helper path:
- local/live copies may expose
scripts/ta - stored marketplace bundles may expose
scripts/ta.shwhen the plaintafilename is inconvenient for packaging scripts/ta.shmust stay functionally identical toscripts/ta; treat it as a compatibility mirror, not a fork- prefer
scripts/tain live checkouts; usescripts/ta.shonly when that is the path the bundle exposes
3. Launch Workers
Launch bounded workers from the repo root:
TA_BIN="${TA_BIN:-$( [ -x scripts/ta ] && printf '%s' scripts/ta || printf '%s' scripts/ta.sh )}"
ui_session="$(${TA_BIN} claude ui)"
review_session="$(${TA_BIN} codex review)"Useful commands:
${TA_BIN} ls
${TA_BIN} attach "${ui_session}"
${TA_BIN} attach "${review_session}"3a. Open The Worker In A Real Desktop Window
If the user says things like "show it on the screen", "open it in a window", "launch it for me on my computer", or otherwise clearly wants the worker visible in a normal terminal window, do not stop at ta read output or an in-chat pane dump. Open a real desktop terminal and attach it to the managed tmux session.
First verify that a GUI session and terminal emulator exist:
printf 'DISPLAY=%s\nWAYLAND_DISPLAY=%s\nXDG_CURRENT_DESKTOP=%s\n' \
"${DISPLAY:-}" "${WAYLAND_DISPLAY:-}" "${XDG_CURRENT_DESKTOP:-}"
command -v gnome-terminal || command -v kitty || command -v x-terminal-emulator
${TA_BIN} lsPreferred GNOME example:
export DISPLAY="${DISPLAY:-:0}"
export WAYLAND_DISPLAY="${WAYLAND_DISPLAY:-wayland-0}"
nohup gnome-terminal --title "Codex review" \
-- bash -lc "tmux attach-session -t ${review_session} || exec bash" \
>/tmp/tmux-window.log 2>&1 &Kitty fallback:
export DISPLAY="${DISPLAY:-:0}"
nohup kitty --title "Codex review" \
bash -lc "tmux attach-session -t ${review_session} || exec bash" \
>/tmp/tmux-window.log 2>&1 &Rules:
- Prefer opening the already running managed session instead of launching a second duplicate worker.
- Use the exact session name from
${TA_BIN} ls. - Only tell the user it is "open" after the desktop terminal process starts successfully.
- If tmux attach inside the current chat shell fails because the terminal does not support clear or alternate-screen behavior, opening an external desktop terminal is the correct recovery path.
4. Send Bounded Tasks
Every worker task must be self-contained. It should reference the brief, state owned files, forbid out-of-scope edits, and say exactly where the worker must write its handoff or review.
Example worker task:
cat > "${SESSION_DIR}/tasks/ui.md" <<EOF
Read ${SESSION_DIR}/brief.md first.
Own only src/components/settings/*.
Do not touch API, database, CI, or build files.
Run only the verification commands that apply to your slice if feasible.
Write your handoff to ${SESSION_DIR}/handoffs/ui.md with:
- files changed
- commands run
- tests run or not run
- blockers or open questions
EOF
${TA_BIN} send "${ui_session}" "${SESSION_DIR}/tasks/ui.md"Rules:
- split by file ownership, not vague themes
- do not assign the same file tree to multiple workers at once
- require written handoffs; do not trust scrollback alone
- use
${TA_BIN} send <session> <file-or-text>for the common path - use
${TA_BIN} send --file <session> <path>or${TA_BIN} send --text <session> <text>when the payload is ambiguous - the helper uses bracketed paste and a short pre-submit settle delay for Codex; do not add your own manual Enter unless you are deliberately recovering a broken session
5. Monitoring
Use the helper script instead of ad hoc tmux commands:
${TA_BIN} ls
${TA_BIN} wait "${ui_session}"
${TA_BIN} read "${ui_session}" 80
${TA_BIN} watch "${ui_session}"Discipline:
- use
ta waitfor blocking waits when you only need exit status; useta watchwhen you want the final assistant text as soon as the turn completes - use
ta readfor detail at most once per minute unless something broke - treat
busyas "leave it alone" - if a worker is
idle, read the tail before sending another prompt
Monitoring model:
- the helper writes sidecar state under
${SESSION_DIR}/ta-state/<session>/ session.jsonstores the last known state, launch cwd, last send timestamp, and any bound JSONL pathevents.ndjsonis an append-only event log for launch, send, state changes, and JSONL binding- for Codex and Claude, the helper first tries to bind the session to the agent's JSONL log via the tmux pane process tree and open file descriptors
- if no bound JSONL is available,
tafalls back to pane-based heuristics instead of guessing from prompt characters
Busy detection details:
- Codex:
idlemeans afinal_answerrecord was observed after the last helpersend - Claude:
idlemeans the last assistant record after the last helpersendhasstop_reason=end_turn - pane fallback still looks for recent output such as
Working (...),Churned,Computing,Flowing,• Ran,• Explored,• Searched, or• Called - do not use prompt characters as an idle signal
6. Review And Verification
Review must happen in a fresh session. Do not reuse the implementation worker as the reviewer.
Typical loop:
- implementation worker writes
handoffs/<worker>.md - coordinator inspects the handoff and changed files
- fresh reviewer session reads the brief, handoff, and diff
- reviewer runs actual verification commands
- reviewer writes findings or approval to
reviews/<worker>.md - coordinator records the commands and outcomes in
artifacts/verification.md
Example review task:
cat > "${SESSION_DIR}/tasks/review.md" <<EOF
Read ${SESSION_DIR}/brief.md first.
Read ${SESSION_DIR}/handoffs/ui.md and inspect the diff.
Review for correctness, regressions, missing tests, and scope creep.
Run the verification commands from the brief yourself.
Write findings or approval to ${SESSION_DIR}/reviews/review.md.
Record command output and pass/fail status in ${SESSION_DIR}/artifacts/verification.md.
EOF
${TA_BIN} send "${review_session}" "${SESSION_DIR}/tasks/review.md"
${TA_BIN} wait "${review_session}" 600Worker claims are not verification. The reviewer or coordinator must run the commands.
7. Failure Recovery
Keep recovery tied to observable failures:
- launch failed: inspect
${TA_BIN} read <session> 100, then relaunch - worker never leaves
busy: read the tail, then either wait longer or send one narrowed follow-up - worker went idle with no handoff: ask for the missing artifact, not a full restatement of the task
- conflicting edits: stop parallel work on the shared files and reassign ownership
- claimed completion without evidence: require a handoff with files changed and commands run
- reviewer found concrete issues: send a new bounded task with those findings only
If the same slice fails twice, reduce scope or switch owners.
8. Routing Heuristic
These are heuristics, not laws. Prefer the worker that matches the repo and the observable problem.
| Work shape | Default | Why | Caveat |
|---|---|---|---|
| Backend, infra, debugging, review, verification | Codex | Usually stronger on correctness, systems work, and findings-first review | Keep the task bounded; do not ask for vague polish |
| Frontend UI, docs, copy, readability refactors | Claude | Usually better at presentation, polish, and large wording rewrites | Route technical verification back to Codex or another strict reviewer |
| Full-stack split with clean ownership | Claude for UI, Codex for backend/review | Lets each worker stay inside a real file boundary | Do not let both workers edit the same files concurrently |
| Pure planning with no grounding | Neither by default | Plans drift fast without repo evidence | Write the brief from the actual code and user constraints first |
9. Artifact Contract
After a real run, these artifacts must exist under ${SESSION_DIR}:
brief.mdtasks/<worker>.mdfor every launched workerhandoffs/<worker>.mdfor every implementation workerreviews/<worker>.mdfor every reviewed sliceartifacts/verification.mdwith exact commands and outcomes
Optional artifacts:
artifacts/*.logorartifacts/*.txtfor saved command output- extra handoffs or follow-up tasks when review required another pass
If these files do not exist, the run is not inspectable enough to trust.