Comprehensive cmux CLI toolkit for AI agents to orchestrate parallel tasks, manage workspaces/panes, read/send terminal I/O, use browser surfaces, show sidebar progress, and coordinate multi-agent workflows. Use when: (1) running parallel commands in separate panes, (2) creating isolated workspaces for tasks, (3) reading output from other terminals, (4) sending commands to surfaces, (5) showing progress/status in sidebar, (6) browser automation in cmux, (7) inter-agent synchronization via wait-for/notify, (8) monitoring and collecting results from multiple panes. Triggers on: cmux, parallel tasks, multi-pane, split terminal, workspace management, terminal orchestration, browser automation in cmux.
Control cmux topology, execute parallel tasks, and coordinate multi-agent work.
| Entity | Description | Ref format |
|---|---|---|
| Window | macOS window | window:N |
| Workspace | Tab-like group in a window | workspace:N |
| Pane | Split container in a workspace | pane:N |
| Surface | Terminal or browser tab within a pane | surface:N |
Hierarchy: Window > Workspace > Pane > Surface. Commands accept refs, UUIDs, or indexes.
Most cmux mutation commands return plain text, not JSON:
OK surface:7 pane:10 workspace:1
The --json flag only works reliably on identify. Other commands (new-pane, new-workspace, etc.) ignore it or error. Parse output with text tools:
# Extract surface ref from new-pane output
OUTPUT=$(cmux new-pane --direction right)
SURF=$(echo "$OUTPUT" | grep -o 'surface:[0-9]*')
# new-workspace returns UUID, not ref — use list-workspaces to find ref
cmux new-workspace
cmux list-workspaces # find the new workspace:N ref
CMUX_WORKSPACE_ID — default --workspaceCMUX_SURFACE_ID — default --surfaceCMUX_SOCKET_PATH — socket path (default: /tmp/cmux.sock)cmux identify --json # current context (window, workspace, pane, surface) — JSON works here
cmux list-workspaces # all workspaces
cmux list-panes # panes in current workspace
cmux list-pane-surfaces --pane pane:1 # surfaces in a pane (add --workspace for cross-workspace)
# Create panes and extract surface refs
P1=$(cmux new-pane --direction right | grep -o 'surface:[0-9]*')
P2=$(cmux new-pane --direction down | grep -o 'surface:[0-9]*')
# Send commands
cmux send --surface "$P1" "npm run test\n"
cmux send --surface "$P2" "npm run lint\n"
# Collect results later
cmux read-screen --surface "$P1" --scrollback --lines 50
cmux read-screen --surface "$P2" --scrollback --lines 50
# Create panes for agents
P1=$(cmux new-pane --direction right | grep -o 'surface:[0-9]*')
P2=$(cmux new-pane --direction down | grep -o 'surface:[0-9]*')
# Launch Claude agents in parallel
cmux send --surface "$P1" "claude --print 'Analyze the auth module'\n"
cmux send --surface "$P2" "claude --print 'Review the API routes'\n"
# Track progress
cmux set-status agent1 "auth review" --icon hammer --color "#ff9500"
cmux set-status agent2 "API review" --icon hammer --color "#34c759"
# Collect results after completion
sleep 30
cmux read-screen --surface "$P1" --scrollback --lines 100
cmux read-screen --surface "$P2" --scrollback --lines 100
# Cleanup
cmux close-surface --surface "$P1"
cmux close-surface --surface "$P2"
cmux clear-status agent1
cmux clear-status agent2
Note: new-workspace returns a UUID, not a ref. Use list-workspaces to find the ref. Surfaces in non-selected workspaces may show in_window=false and reject send commands until the workspace is selected at least once.
# Create and find workspace ref
cmux new-workspace
cmux list-workspaces # find new workspace:N ref
# Create a pane in it (panes in the current workspace always work)
cmux new-pane --workspace workspace:N --direction right
# Select it to activate surfaces
cmux select-workspace --workspace workspace:N
# ... do work ...
cmux close-workspace --workspace workspace:N
# Pane A waits:
cmux wait-for build-done --timeout 120
# Pane B signals:
cmux wait-for --signal build-done
# Read
cmux read-screen # current surface viewport
cmux read-screen --surface surface:3 --scrollback --lines 200
# Send text (\n = Enter, \t = Tab)
cmux send "echo hello\n"
cmux send --surface surface:3 "npm run build\n"
# Send keys
cmux send-key ctrl-c
cmux send-key --surface surface:3 enter
# Pipe output to command
cmux pipe-pane --command "grep ERROR" --surface surface:3
Gotcha: send and send-key only work on terminal surfaces that are in_window=true. Use cmux surface-health to check. Surfaces in non-selected workspaces may be in_window=false.
# Status pills (key-based, each tool manages its own key)
cmux set-status build "compiling" --icon hammer --color "#ff9500"
cmux clear-status build
# Progress bar
cmux set-progress 0.5 --label "Building..."
cmux set-progress 1.0 --label "Done"
cmux clear-progress
# Log entries (levels: info, progress, success, warning, error)
cmux log "Build started"
cmux log --level success --source build "All tests passed"
cmux log --level error --source deploy "Connection refused"
cmux list-log --limit 20
cmux notify --title "Task Complete" --body "All 42 tests passed"
cmux list-notifications
cmux clear-notifications
Important: Browser commands require --surface to specify which browser surface to target.
# Open browser
cmux browser open https://example.com # reuses pane if available
cmux browser open-split https://example.com # creates new split
# All subsequent commands need --surface
cmux browser --surface surface:N snapshot # DOM snapshot
cmux browser --surface surface:N snapshot --interactive # with clickable refs
cmux browser --surface surface:N snapshot --compact # minimal output
cmux browser --surface surface:N get title
cmux browser --surface surface:N get url
cmux browser --surface surface:N navigate https://other.com
cmux browser --surface surface:N click "#btn"
cmux browser --surface surface:N fill "#input" "text"
cmux browser --surface surface:N eval "document.title"
See references/browser-commands.md for full browser automation docs.
| Reference | When to read |
|---|---|
| references/parallel-patterns.md | Complex multi-pane orchestration, fan-out/fan-in, result collection, progress tracking |
| references/browser-commands.md | Browser surface automation: navigate, click, snapshot, eval, forms, cookies, network |
| references/topology-management.md | Window/workspace/pane/surface CRUD, move, reorder, focus, drag, rename |
| references/tmux-compat.md | tmux-compatible commands: swap-pane, break-pane, join-pane, resize, buffers, hooks |
These were confirmed through testing (March 2025):
| Feature | Status | Notes |
|---|---|---|
identify --json | Works | Returns proper JSON |
new-pane --json | Broken | Ignores flag, returns plain text |
new-workspace --json | Broken | Unknown flag error |
new-workspace output | UUID only | Returns UUID, not ref — use list-workspaces |
send to other workspace | Fragile | Surfaces must be in_window=true (select workspace first) |
list-pane-surfaces cross-workspace | Needs flag | Must pass --workspace for panes in other workspaces |
browser commands | Need --surface | Won't auto-detect browser surface |
browser open | Reuses pane | placement=reuse — may not create new pane |
new-split --panel | Works | Alias for --surface, not --pane |
wait-for sync | Works | Tested with timeout, signal delivery confirmed |
set-status/progress/log | Works | All sidebar features functional |
send + read-screen | Works | Core I/O loop reliable in current workspace |
| Parallel Claude agents | Works | claude --print in multiple panes, collect with read-screen |
| Form automation | Works | fill, check, click, get value, is checked all functional |
is checked returns | 1/0 | Not true/false |