cmux Core Control
Use this skill to control cmux topology, terminal I/O (send commands to other panes and read output), notifications, and sidebar metadata.
Environment Detection
cmux sets $CMUX_WORKSPACE_ID and $CMUX_SURFACE_ID in every terminal it spawns. Check before using cmux commands:
if [ -z "$CMUX_WORKSPACE_ID" ]; then
echo "Not running inside cmux — cmux commands unavailable"
fi
If not in cmux, fall back to standard tools (no pane splitting, no cmux notifications).
Core Concepts
- Window: Top-level macOS cmux window.
- Workspace: Tab-like group within a window (sidebar entry).
- Pane: Split container in a workspace.
- Surface: A tab within a pane (terminal or browser panel).
Hierarchy: Window > Workspace > Pane > Surface
Default output uses short refs: window:N, workspace:N, pane:N, surface:N. UUIDs are still accepted as inputs. Request UUID output only when needed: --id-format uuids|both.
Fast Start
Topology
# Always identify first — short refs (pane:1, surface:N) are session-scoped
cmux identify --json # current caller context
cmux list-workspaces # list workspaces
cmux list-panes # list panes in workspace
cmux list-pane-surfaces --pane pane:1 # list surfaces in pane
cmux new-workspace # create workspace
cmux new-split right # split current surface to the right
cmux move-surface --surface surface:7 --pane pane:2 # move surface between panes
cmux trigger-flash --surface surface:7 # visual flash
Terminal I/O (send commands to other panes, read output)
cmux send --surface surface:N "echo hello\n" # send text + Enter (\n = Enter)
cmux send --surface surface:N "npm start\n" # run a command in another pane
cmux send-key --surface surface:N enter # send Enter key separately
cmux send-key --surface surface:N ctrl+c # send Ctrl+C (stop a process)
cmux read-screen --surface surface:N # read visible terminal text
cmux read-screen --surface surface:N --scrollback # include scrollback history
cmux read-screen --surface surface:N --scrollback --lines 200 # last 200 lines only
Notifications & Sidebar
cmux notify --title "Build Complete" --body "All tests passed"
cmux set-status build "Ready" --icon checkmark --color "#34c759"
cmux set-progress 0.75 --label "Running tests"
cmux log --level info --source claude-code "Starting build..."
Terminal I/O Patterns
The core workflow: split a pane, send a command, detect completion, read the output.
Before sending any command, decide how you'll know when it finishes. Claude Code blocks foreground sleep over 2 seconds — pick a completion strategy based on what you're running:
| Command type | Example | Strategy |
|---|---|---|
| Batch (start→finish) | npm run build, pytest |
wait-for signal |
| Long-running service | npm run dev, docker compose up |
Content poll for "ready" text |
| Interactive program | claude, node, psql |
Content poll for prompt marker |
| Instant | echo, ls, cat |
Immediate read-screen |
Batch commands → wait-for
Chain cmux wait-for -S <signal> to the command. Run the wait with run_in_background: true.
cmux new-split right # → surface:9
cmux send --surface surface:9 "npm run build && cmux wait-for -S build-done\n"
# run_in_background: true — notified on completion
cmux wait-for build-done --timeout 120 && cmux read-screen --surface surface:9 --scrollback --lines 50
Services / interactive programs → content poll
Poll read-screen for expected text. Use the bundled helper with run_in_background: true:
# run_in_background: true
$SKILL_DIR/scripts/poll-screen.sh surface:9 "ready|listening|Claude Code" --timeout 60
Common match patterns:
- Server ready:
ready|listening on|started - Claude Code ready:
Claude Code|tips:|❯ - Task complete:
╭─|❯|\\$\\s*$ - Build result:
✓|passed|error|failed
Hybrid example
Server start → wait for ready → then batch work:
cmux send --surface surface:9 "npm run dev\n"
# run_in_background: true — poll for server ready
$SKILL_DIR/scripts/poll-screen.sh surface:9 "ready on" --timeout 30
# (after background notification confirms ready)
cmux send --surface surface:9 "curl localhost:3000/health && cmux wait-for -S health-ok\n"
cmux wait-for health-ok --timeout 10
For detailed patterns (server monitoring, E2E testing, build pipelines, remote Claude Code), read the terminal-io reference.
Sidebar Metadata
# status pill: set-status <key> <value> [--icon name] [--color #hex]
cmux set-status build "Ready" --icon checkmark --color "#34c759"
cmux set-status build "Failed" --icon xmark --color "#ff3b30"
cmux clear-status build
# progress bar (0.0 to 1.0, optional --label)
cmux set-progress 0.75 --label "Running tests"
cmux clear-progress
# log messages (leveled, optional --source)
cmux log --level info --source claude-code "Starting build..."
cmux log --level success "Build complete"
cmux log --level warning "3 deprecation warnings"
cmux log --level error "Test suite failed"
Coexistence
- In cmux: Use
cmux new-splitfor panes,cmux send/cmux read-screenfor terminal I/O,cmux notifyfor notifications. - Outside cmux: These features are unavailable. Use standard terminal workflows.
- Browser automation in cmux: Use the
cmux-browserskill for embedded webview automation. - Markdown viewing in cmux: Use
cmux markdown open <path>directly to open a live-reloading panel. - With
cmux claude-teams: Teams uses its own tmux-shim layer for topology — do not mix directcmuxtopology commands with Teams orchestration.
Gotchas
- cmux commands fail silently outside cmux — always check
$CMUX_WORKSPACE_IDbefore using anycmuxcommand. - Short refs (
surface:7) are session-scoped and may change between sessions — alwayscmux identify --jsonat the start of automation to discover current topology. sendincludes\nfor Enter —cmux send "command\n"sends the command and presses Enter in one call. No need for a separatesend-key enterunless you want explicit timing control.send-keysdoes not exist — the command issend(text) andsend-key(key event). This is different from tmux'ssend-keys.pressdoes not exist — to send Ctrl+C, usecmux send-key --surface surface:N ctrl+c.read-screenreturns the current screen state — if a command is still running, the output may be incomplete. Use--scrollback --lines Nfor history, or use a completion strategy (see Terminal I/O Patterns above).- In Claude Code,
sleepover 2 seconds is blocked in foreground — usewait-forfor batch commands, content polling for interactive programs. Both requirerun_in_background: true. Avoidsleep N && read-screen— it reads too early or too late. - Always plan completion detection before sending a command — decide upfront: is this batch (wait-for), service/interactive (content poll), or instant (immediate read)? Sending without a plan leads to blind retries.
set-status --colorrequires hex values ("#34c759") — named colors likegreenare not supported.set-statusrequires a key (e.g.,build) as the first argument — the key allows multiple independent status pills per workspace.- If
cmux claude-teamsis active, it manages topology through a tmux-compat shim. Direct topology commands (new-split,move-surface) may conflict with Teams orchestration. - Desktop alerts are suppressed when the cmux window is focused and the workspace is active — use
cmux logfor always-visible status updates.
Deep-Dive References
| Reference | When to Use |
|---|---|
| Terminal I/O | Send commands, read output, server monitoring, E2E testing, build pipelines |
| Sync and Automation | wait-for synchronization, buffers, cmux.json custom workspace commands |
| Handles and Identify | Handle syntax, self-identify, caller targeting |
| Windows and Workspaces | Window/workspace lifecycle and reorder/move |
| Panes and Surfaces | Splits, surfaces, move/reorder, focus routing |
| Trigger Flash and Health | Visual flash confirmation and surface health checks |
| Notifications | Notification CLI, sidebar metadata API, hook patterns |