| name | amux |
| description | Interact with amux, an agent-centric terminal multiplexer. Use this skill whenever the user mentions amux panes, capturing pane output, delegating tasks to agents in panes, monitoring agent progress, typing keys into panes, or managing terminal layouts. Also trigger when AMUX_SESSION is set in the environment and the user wants to interact with other panes or agents. Covers: JSON capture for structured pane inspection, send-keys for delegating to agents (codex, claude, grok), mailbox messaging, wait primitives for monitoring, orchestration scripts, and event streaming.
|
amux — Agent Orchestration Skill
amux is a terminal multiplexer designed for AI agents. It runs a background server that owns PTYs, while clients connect over a Unix socket. This skill covers using amux as an orchestration layer — capturing pane content, delegating tasks, and monitoring agent progress.
Critical Rules
Read before write. Always read pane scrollback (amux capture --history <pane> | grep -v '^$' | tail -30) before sending keys or taking any action on a pane. Never assume a pane's state — check it.
Use wait idle for agent readiness. wait exited checks for child processes, which is useless for persistent agents (codex, claude, grok are always running). wait idle checks if the screen stopped producing output — this works for both shells and agents.
Always start codex with --yolo. Without it, codex stalls at permission prompts that are invisible to the orchestrator.
Use amux list for status sweeps. The branch column shows what workers are working on. Then use wait idle to check which are actively producing output vs sitting screen-quiet.
Resolve pane refs from amux list, not pane-$AMUX_PANE. AMUX_PANE is the numeric pane ID, not a guaranteed pane name. Use the numeric ref directly (amux capture --history 65) or the exact pane name shown in amux list, especially when the visible session is zoomed to another pane and amux capture --format json is showing that pane instead of the worker you need.
Mailbox delivery is passive. amux msg send stores mail out-of-band; it does not type into the recipient's prompt. After sending mail, the sender verifies delivery itself: run amux msg drain-status <recipient> --format json (and/or amux wait msg) to see whether the message is still unread/unacked. That check is read-only and idempotent — do it automatically, and never stop to ask the user whether to check. Only the PTY nudge needs judgment, because it writes into the recipient's prompt: send one short nudge telling the pane to run amux msg drain-status --format json and read+ack its mailbox only when the unread mail is important and the recipient is idle-and-not-replying (a known failure mode). Skip the nudge for a fire-and-forget note, where leaving the mail for the recipient's own drain is the correct terminal state.
Quick Reference
Capture (inspect pane content)
amux capture --format json
amux capture --format json pane-1
amux capture
amux capture pane-1
amux capture --ansi pane-1
amux capture --history pane-1 | grep -v '^$' | tail -30
The JSON capture is the primary interface for agents. It includes pane content lines, cursor position, active/lead/zoomed state, host, task, color, cwd, git branch, and agent-status fields (exited, idle, current_command) as top-level keys on each pane.
Note: JSON capture currently only returns the visible viewport. --history only works with plain text output. See LAB-527 for tracking JSON + history support.
Pane-ref note: when a workflow starts from AMUX_PANE, prefer the numeric ref directly or resolve the real pane name via amux list. Do not assume pane-$AMUX_PANE exists.
Send Input to Panes
amux send-keys pane-1 'ls -la' Enter
amux send-keys pane-1 --via client 'echo hello'
amux send-keys pane-1 --via client Enter
amux wait idle pane-31 --settle 2s --timeout 30s
amux wait idle pane-31 --settle 2s --timeout 30s
amux send-keys pane-31 'Fix the bug in auth.go' Enter
amux send-keys pane-1 --via client Escape
amux send-keys pane-1 --via client C-c
amux send-keys pane-1 --via client C-u
amux send-keys pane-1 --via client C-a
send-keys is the canonical input command. Use the default PTY path for agent delegation, and --via client when you need client-side key translation or keybinding handling.
Wait Primitives
amux wait idle pane-1 --settle 2s --timeout 60s
amux wait exited pane-1 --timeout 300s
amux wait content pane-1 "Tests passed" --timeout 60s
amux wait busy pane-1 --timeout 5s
amux wait layout --after 42 --timeout 3s
Which wait to use:
wait idle — screen stopped changing. Use for: "is the agent at its prompt?", "did it finish rendering?"
wait exited — no child processes. Useless for persistent agent panes (codex/claude are always a child process). Useful for bare shell panes and short-lived commands.
wait content — specific text appeared. Use for: "did the test output PASS?"
wait busy — child processes started. Use for: "did the command begin?"
Event Streaming
amux events
amux events --pane pane-1
amux events --filter idle,busy,exited
Mailbox Messaging
Use mailbox messages when panes need to coordinate without writing into another
pane's PTY. Delivery is out-of-band: the recipient must check or wait on its
mailbox; amux does not paste the body into the prompt. Use mailbox for the real
handoff content, and use send-keys only as a bootstrap/nudge when an idle
agent is not noticing its inbox.
amux msg send --from pane-1 --to pane-2 --subject "Logs ready" --body "See /tmp/run.log"
printf 'multi-line body\n' | amux msg send --from pane-1 --to pane-2 --topic review
amux msg inbox pane-2 --unread --format json
amux msg drain-status pane-2 --format json
amux msg read msg-000001 --for pane-2 --format json
amux msg reply msg-000001 --from pane-2 --body "Ack, looking now." --format json
amux msg reply msg-000001 --from pane-2 --body "Done" --ack ok --ack-note "handled"
amux msg ack msg-000001 --for pane-2 --status seen
amux wait msg pane-2 --topic review --timeout 5m --format json
Sender workflow:
- Resolve pane refs with
amux list.
- Send the task or handoff with
amux msg send --from <sender> --to <recipient>.
- Verify delivery yourself, automatically — this step is read-only, so do not ask the user first. Watch for progress with
amux wait msg <sender> --topic <topic> --timeout <duration> --format json, or check the recipient's amux msg drain-status <recipient> --format json to confirm whether the message is still unread/unacked.
- The PTY nudge is the only part that needs judgment, because it writes into the recipient's prompt. When the mail is important and the recipient is idle with the message still unread/unacked, nudge it once with
amux send-keys <recipient> 'You have amux mailbox work. Run amux msg drain-status --format json, then read and ack pending IDs.' Enter. For a fire-and-forget note that needs no reply, skip the nudge and let the recipient's own drain surface it.
- Avoid repeated PTY nudges; once the agent is working, let the mailbox exchange proceed through
amux msg.
Recipient workflow:
- Run
amux msg drain-status --format json.
- For each pending ID, run
amux msg read <msg-id> --for <recipient> --format json.
- Reply with
amux msg reply <msg-id> --from <recipient> ...; this preserves thread_id, in_reply_to, and topics without manually rebuilding routing.
- Ack handled mail with
amux msg ack <msg-id> --for <recipient> --status seen|ok, or combine reply+ack with amux msg reply ... --ack ok --ack-note "handled".
- Before going idle, rerun
amux msg drain-status --format json and make sure pending is 0.
For agent handoffs, rely on a separate watcher or stop-hook recipe when
available, but do not assume it fired. The sender is responsible for checking
whether important mailbox work is being consumed and nudging an idle recipient
when necessary.
Pane Management
amux list
amux status
amux focus pane-1
amux zoom pane-1
amux spawn --name my-agent
amux kill pane-1
amux spawn --at pane-1 --horizontal
amux equalize
amux equalize --vertical
amux equalize --all
Window Management
amux list-windows
amux new-window
amux select-window 2
amux next-window
amux prev-window
Server Administration
amux reload-server
amux debug goroutines
amux debug heap
amux debug profile --duration 30s > cpu.pprof.gz
amux debug socket
amux debug frames
reload-server re-execs the server from the current binary, preserving all panes and shells via checkpoint/restore. Use after make install or config changes. The debug subcommands (except frames) require [debug].pprof = true in ~/.config/amux/config.toml.
If amux freezes, capture a goroutine dump before killing the server -- the dump is the only evidence for deadlock diagnosis and is destroyed on kill:
amux debug goroutines > /tmp/amux-goroutine-dump-$(date +%s).txt 2>&1
SERVER_PID=$(pgrep -f "amux _server ${AMUX_SESSION:-main}$")
readlink /proc/"$SERVER_PID"/fd/2
kill -QUIT "$SERVER_PID"
Pane Metadata
amux meta set pane-1 issue=LAB-123
amux meta set pane-1 pr=456
amux meta set pane-1 task="fix auth"
amux meta rm pane-1 issue
amux list
Orchestration Scripts
These scripts compose amux primitives for common workflows. They are in the scripts/ directory alongside this SKILL.md file.
Spawn a worker
scripts/spawn-worker.sh --parent pane-109 --issue LAB-499
Does: split pane, create git worktree, start codex --yolo, wait for idle, accept the trust dialog when needed, and set issue metadata. Returns the new pane name.
Delegate a task with verification
scripts/delegate-task.sh pane-47 --issue LAB-468 "Fix the black screen bug"
Does: send task via send-keys, wait for idle to break (output flowing = accepted), report if stuck.
Batch delegation
scripts/batch-delegate.sh tasks.json
Manifest format:
[
{"pane": "pane-47", "issue": "LAB-468", "task": "Fix black screen"},
{"pane": "pane-51", "issue": "LAB-174", "task": "Fix flaky tests"}
]
Worker status dashboard
scripts/worker-status.sh
Shows: pane name, issue, idle/busy/stuck state, PR number, last output line.
Recover a stuck worker
scripts/recover-worker.sh pane-68
Does: detect stuck state, Escape, /exit, codex --yolo resume, select session, send . to continue.
Delegating Tasks to Codex Workers
The read-before-write rule
Before sending anything to a pane, always check what it's doing:
amux capture --history pane-31 | grep -v '^$' | tail -30
Spawning and delegating
amux spawn --at pane-109 --horizontal --name worker-499
Sending a task
amux wait idle pane-31 --settle 2s --timeout 30s
amux send-keys pane-31 "Fix the black screen bug (LAB-468). TDD approach. Open a PR when done." Enter
amux wait idle pane-31 --settle 2s --timeout 5s
Monitoring progress
amux wait idle pane-31 --settle 2s --timeout 3s
amux list
for pane in 47 51 54; do
amux wait idle pane-$pane --settle 2s --timeout 3s 2>&1 | sed "s/^/pane-$pane: /"
done
scripts/worker-status.sh
scripts/check-claude-review.sh --watch
Resuming interrupted codex sessions
If codex was interrupted (Escape, context ran out, error):
amux send-keys pane-31 "." Enter
If codex needs a full restart:
amux send-keys pane-31 Escape
amux wait idle pane-31 --settle 2s --timeout 10s
amux send-keys pane-31 "/exit" Enter
amux wait idle pane-31 --settle 3s --timeout 15s
amux send-keys pane-31 "codex --yolo resume" Enter
amux wait idle pane-31 --settle 3s --timeout 30s
amux send-keys pane-31 Enter
amux wait idle pane-31 --settle 3s --timeout 15s
amux send-keys pane-31 "." Enter
Or use the recovery script: scripts/recover-worker.sh pane-31
Post-Delegation Cleanup
Agents (especially codex) may leave artifacts that need cleanup before a PR:
git diff --cached --name-only | grep -E '\.claude/worktrees/|\.context/'
git reset HEAD .claude/worktrees/ .context/ 2>/dev/null
rm -rf .claude/worktrees/ .context/ 2>/dev/null
Post-PR Protocol
When opening a PR from an amux pane, prefer the shared wrapper so pane PR metadata syncs for any agent:
scripts/gh-pr-create.sh --fill
With make setup active, later git push calls re-sync via the repo pre-push hook. If you already opened the PR with plain gh pr create, repair the pane metadata with:
scripts/sync-pane-pr-meta.sh
JSON Capture Structure
The --format json output looks like:
{
"session": "default",
"window": {"id": 1, "name": "main", "index": 1, "zoomed": false},
"width": 200,
"height": 50,
"panes": [
{
"id": 1,
"name": "pane-1",
"active": true,
"lead": true,
"zoomed": false,
"host": "local",
"task": "",
"color": "rosewater",
"column_index": 0,
"cwd": "/path/to/project",
"git_branch": "main",
"cursor": {"col": 0, "row": 24},
"position": {"x": 0, "y": 0, "width": 100, "height": 25},
"content": ["line 1", "line 2", "..."],
"exited": false,
"current_command": "go test ./...",
"idle": false,
"last_output": "2026-05-26T19:05:00Z"
}
]
}
The agent-status fields are top-level keys on each pane (not nested under an agent_status object). Key fields for agent orchestration:
exited — true when no foreground command is running in the pane (shell sitting at its prompt). Corresponds to wait exited, not wait idle.
exited_since — RFC3339 timestamp of the last busy→exited transition; omitted while busy.
current_command — the foreground process name when busy, or the shell name (e.g. bash) when exited.
idle — true when pane output has been quiet for the settle window. Corresponds to wait idle.
idle_since — RFC3339 timestamp when the pane most recently became screen-quiet; omitted while output is still active. (exited_since and idle_since are both omitted in the example above because the pane is busy.)
last_output — RFC3339 timestamp of the most recent pane output edge.
lead — true for the window's lead pane. (There is no minimized field; minimized panes are simply absent from the visible layout.)
content — array of strings, one per visible line (viewport only, no scrollback)
active — whether this is the focused pane
CI-Style Commands Inside amux
Never run make install from a worker agent. It installs the shared amux binary and can hot-reload unrelated sessions. When running compile checks or tests from within an amux session, strip AMUX_SESSION and TMUX:
env -u AMUX_SESSION -u TMUX go build ./...
env -u AMUX_SESSION -u TMUX go test ./...
Pane References
Panes can be referenced by:
- Name:
pane-1, my-agent, worker-499
- Numeric ID:
1, 31
- Prefix match:
pane- matches pane-1 if unambiguous