Cmux Terminal Multiplexer

reason-machines/trending-skills/skills/cmux-terminal-multiplexer

by reason-machines2384a003145aNo license83 starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 3 months ago

AI-native terminal multiplexer with programmable socket API, full Playwright-equivalent browser automation, and agent team coordination — built for Claude Code and autonomous agent workflows

AI-generated overview

Guides agents in using the cmux terminal multiplexer CLI for splits, browser automation, status reporting and agent teams.

What it does
This skill documents how to drive the cmux terminal multiplexer from an AI agent: creating terminal splits, sending commands to specific surfaces, capturing pane output, and managing panes and workspaces. It also covers cmux's embedded headless Chromium automation, including navigation, snapshots with element refs, form interaction, waits, JavaScript evaluation, cookies and saved browser state. Additionally it describes sidebar status, progress bars, logs, OS notifications, and patterns for coordinating parallel subagents, each with its own visible split.
When to use it
Use it when an agent needs to run commands in separate visible terminal panes, automate a browser without external Chrome, or coordinate several subagents in parallel workspaces. It fits workflows that want live progress and status shown to the user while long tasks run.
Requirements
Requires the cmux CLI to be installed and running, with its socket API available; browser automation uses cmux's embedded headless Chromium. Some examples use python3 for JSON parsing and shell utilities such as sleep and tail. No scripts ship with the skill; it is instructions only.

cmux — AI-Native Terminal Multiplexer

Skill by ara.so — Daily 2026 Skills collection

cmux is a terminal multiplexer with a programmable socket API designed for AI coding agents. It provides full Playwright-equivalent browser automation, real-time terminal split management, sidebar status reporting, and agent team coordination — all via a simple CLI.


What cmux Does

  • Terminal splits — create side-by-side or stacked panes, send commands, capture output
  • Browser automation — full headless Chromium with snapshot-based element refs (no CSS selectors)
  • Status sidebar — live progress bars, log messages, and icon badges visible to the user
  • Notifications — native OS notifications from agent workflows
  • Agent teams — coordinate parallel subagents, each with their own visible split

Orient Yourself

bash
cmux identify --json          # current window/workspace/pane/surface contextcmux list-panes               # all panes in current workspacecmux list-pane-surfaces --pane pane:1  # surfaces within a panecmux list-workspaces          # all workspaces (tabs) in current window

Environment variables set automatically:

  • $CMUX_SURFACE_ID — your current surface ref
  • $CMUX_WORKSPACE_ID — your current workspace ref

Handles use short refs: surface:N, pane:N, workspace:N, window:N.


Terminal Splits

Create splits

bash
cmux --json new-split right   # side-by-side (preferred for parallel work)cmux --json new-split down    # stacked (good for logs)

Always capture the returned surface_ref:

bash
WORKER=$(cmux --json new-split right | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")

Send commands and read output

bash
cmux send-surface --surface surface:22 "npm run build\n"cmux capture-pane --surface surface:22              # current screencmux capture-pane --surface surface:22 --scrollback  # with full history
cmux send-key-surface --surface surface:22 ctrl-c  # send keycmux send-key-surface --surface surface:22 enter

Golden rule: never steal focus. Always use --surface targeting.

Worker split pattern

bash
WORKER=$(cmux --json new-split right | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")cmux send-surface --surface "$WORKER" "make test 2>&1; echo EXIT_CODE=\$?\n"sleep 3cmux capture-pane --surface "$WORKER"cmux close-surface --surface "$WORKER"   # clean up when done

Pane management

bash
cmux focus-pane --pane pane:2cmux close-surface --surface surface:22cmux swap-pane --pane pane:1 --target-pane pane:2cmux move-surface --surface surface:7 --pane pane:2 --focus truecmux reorder-surface --surface surface:7 --before surface:3

Browser Automation

cmux embeds a full headless Chromium engine with a Playwright-style API. No external Chrome required. Every command targets a browser surface by ref.

Workflow pattern

navigate → wait for load → snapshot --interactive → act with refs → re-snapshot

Open and navigate

bash
cmux --json browser open https://example.com        # opens browser split, returns surface refcmux browser surface:23 goto https://other.comcmux browser surface:23 backcmux browser surface:23 forwardcmux browser surface:23 reloadcmux browser surface:23 get urlcmux browser surface:23 get title

Capture the surface ref:

bash
BROWSER=$(cmux --json browser open https://docs.example.com | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")

Snapshot and element refs

Instead of CSS selectors, snapshot to get stable element refs (e1, e2, ...):

bash
cmux browser surface:23 snapshot --interactive              # full interactive snapshotcmux browser surface:23 snapshot --interactive --compact     # compact outputcmux browser surface:23 snapshot --selector "form#login" --interactive  # scoped

Refs are invalidated after DOM mutations — always re-snapshot after navigation or clicks. Use --snapshot-after to auto-get a fresh snapshot:

bash
cmux --json browser surface:23 click e1 --snapshot-after

Interact with elements

bash
# Click and hovercmux browser surface:23 click e1cmux browser surface:23 dblclick e2cmux browser surface:23 hover e3cmux browser surface:23 focus e4
# Text inputcmux browser surface:23 fill e5 "[email protected]"   # clear + typecmux browser surface:23 fill e5 ""                      # clear inputcmux browser surface:23 type e6 "search query"          # type without clearing
# Keyscmux browser surface:23 press Entercmux browser surface:23 press Tabcmux browser surface:23 keydown Shift
# Formscmux browser surface:23 check e7          # checkboxcmux browser surface:23 uncheck e7cmux browser surface:23 select e8 "option-value"
# Scrollcmux browser surface:23 scroll --dy 500cmux browser surface:23 scroll --selector ".container" --dy 300cmux browser surface:23 scroll-into-view e9

Wait for state

bash
cmux browser surface:23 wait --load-state complete --timeout-ms 15000cmux browser surface:23 wait --selector "#ready" --timeout-ms 10000cmux browser surface:23 wait --text "Success" --timeout-ms 10000cmux browser surface:23 wait --url-contains "/dashboard" --timeout-ms 10000cmux browser surface:23 wait --function "document.readyState === 'complete'" --timeout-ms 10000

Read page content

bash
cmux browser surface:23 get text body        # visible textcmux browser surface:23 get html body        # raw HTMLcmux browser surface:23 get value "#email"   # input valuecmux browser surface:23 get attr "#link" --attr hrefcmux browser surface:23 get count ".items"   # element countcmux browser surface:23 get box "#button"    # bounding boxcmux browser surface:23 get styles "#el" --property color
# State checkscmux browser surface:23 is visible "#modal"cmux browser surface:23 is enabled "#submit"cmux browser surface:23 is checked "#agree"

Locators (Playwright-style)

bash
cmux browser surface:23 find role buttoncmux browser surface:23 find text "Sign In"cmux browser surface:23 find label "Email"cmux browser surface:23 find placeholder "Enter email"cmux browser surface:23 find testid "submit-btn"cmux browser surface:23 find first ".item"cmux browser surface:23 find last ".item"cmux browser surface:23 find nth ".item" 3

JavaScript evaluation

bash
cmux browser surface:23 eval "document.title"cmux browser surface:23 eval "document.querySelectorAll('.item').length"cmux browser surface:23 eval "window.scrollTo(0, document.body.scrollHeight)"

Frames and dialogs

bash
cmux browser surface:23 frame "#iframe-selector"   # switch to iframecmux browser surface:23 frame main                  # back to main framecmux browser surface:23 dialog acceptcmux browser surface:23 dialog dismisscmux browser surface:23 dialog accept "prompt text"

Cookies, storage, and state

bash
# Cookiescmux browser surface:23 cookies getcmux browser surface:23 cookies set session_token "abc123"cmux browser surface:23 cookies clear
# Local/session storagecmux browser surface:23 storage local getcmux browser surface:23 storage local set myKey "myValue"cmux browser surface:23 storage session clear
# Save/restore full browser state (cookies + storage + tabs)cmux browser surface:23 state save ./auth-state.jsoncmux browser surface:23 state load ./auth-state.json

Authentication flow

bash
BROWSER=$(cmux --json browser open https://app.example.com/login | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")cmux browser $BROWSER wait --load-state complete --timeout-ms 15000cmux browser $BROWSER snapshot --interactivecmux browser $BROWSER fill e1 "[email protected]"cmux browser $BROWSER fill e2 "my-password"cmux browser $BROWSER click e3cmux browser $BROWSER wait --url-contains "/dashboard" --timeout-ms 20000
# Save auth for reusecmux browser $BROWSER state save ./auth-state.json
# Reuse in a new surfaceBROWSER2=$(cmux --json browser open https://app.example.com | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")cmux browser $BROWSER2 state load ./auth-state.jsoncmux browser $BROWSER2 goto https://app.example.com/dashboard

Diagnostics

bash
cmux browser surface:23 console list     # JS console outputcmux browser surface:23 console clearcmux browser surface:23 errors list      # JS errorscmux browser surface:23 errors clearcmux browser surface:23 highlight "#el"  # visual highlightcmux browser surface:23 screenshot       # capture screenshot

Script and style injection

bash
cmux browser surface:23 addscript "console.log('injected')"cmux browser surface:23 addstyle "body { background: red; }"cmux browser surface:23 addinitscript "window.__injected = true"  # runs on every nav

Sidebar Status and Progress

Show live status to the user without interrupting their flow:

bash
cmux set-status agent "working" --icon hammer --color "#ff9500"cmux set-status agent "done" --icon checkmark --color "#34c759"cmux clear-status agent
cmux set-progress 0.3 --label "Running tests..."cmux set-progress 1.0 --label "Complete"cmux clear-progress
cmux log "Starting build"cmux log --level success "All tests passed"cmux log --level error --source build "Compilation failed"

Notifications

bash
cmux notify --title "Task Complete" --body "All tests passing"cmux notify --title "Need Input" --subtitle "Permission" --body "Approve deployment?"

Agent Teams with cmux

Use cmux splits to give each agent teammate a visible workspace. Coordinate via SendMessage and task lists — never via reading each other's terminal output.

The pattern

  1. Create splits for each teammate
  2. Spawn teammates via Agent tool — pass each their cmux surface ref
  3. Teammates run commands in their split via cmux send-surface
  4. Teammates report status via cmux set-status and cmux log
  5. User sees all work side-by-side

Example: 3-agent team

bash
# Create visible splits for each teammateSPLIT_1=$(cmux --json new-split right | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")SPLIT_2=$(cmux --json new-split down | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")SPLIT_3=$(cmux --json new-split down | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")

Then in each teammate's prompt:

You have a cmux terminal split at surface:42.Run commands:  cmux send-surface --surface surface:42 "command\n"Read output:   cmux capture-pane --surface surface:42Set status:    cmux set-status myagent "working" --icon hammerLog progress:  cmux log "message"Never steal focus — always use --surface targeting.

Mixed layout: terminals + browsers

bash
BUILD=$(cmux --json new-split right | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")DOCS=$(cmux --json browser open https://docs.example.com | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")TEST=$(cmux --json new-split down | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")

Key rules

  • Never spawn claude -p in splits — use the Agent tool with team_name instead
  • Create splits before spawning teammates — pass refs in their prompts
  • One split per teammate — each owns their visible workspace
  • Coordinate via SendMessage, not by reading each other's terminal output
  • Clean up: cmux close-surface --surface <ref> when done

Quick Reference

TaskCommand
Where am I?cmux identify --json
Split rightcmux --json new-split right
Split downcmux --json new-split down
Send commandcmux send-surface --surface <ref> "cmd\n"
Read outputcmux capture-pane --surface <ref>
Open browsercmux --json browser open <url>
Page snapshotcmux browser <ref> snapshot --interactive
Click elementcmux browser <ref> click e1
Fill inputcmux browser <ref> fill e1 "text"
Wait for loadcmux browser <ref> wait --load-state complete --timeout-ms 15000
Read page textcmux browser <ref> get text body
Evaluate JScmux browser <ref> eval "expression"
Find by rolecmux browser <ref> find role button
Save authcmux browser <ref> state save ./auth.json
Load authcmux browser <ref> state load ./auth.json
Set statuscmux set-status <key> "text" --icon <name>
Progress barcmux set-progress 0.5 --label "Working..."
Log messagecmux log "message"
Notifycmux notify --title "T" --body "B"
Close splitcmux close-surface --surface <ref>
Screenshotcmux browser <ref> screenshot

Common Patterns

Run build in background split, tail logs

bash
LOG=$(cmux --json new-split down | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")cmux send-surface --surface "$LOG" "cargo build --release 2>&1 | tee /tmp/build.log\n"# ... do other work ...cmux capture-pane --surface "$LOG" --scrollback | tail -20

QA test flow

bash
BROWSER=$(cmux --json browser open https://myapp.vercel.app | python3 -c "import sys,json; print(json.load(sys.stdin)['surface_ref'])")cmux browser $BROWSER wait --load-state complete --timeout-ms 15000cmux browser $BROWSER snapshot --interactive# Interact using e1, e2, e3 refs...cmux browser $BROWSER screenshotcmux browser $BROWSER errors listcmux close-surface --surface $BROWSER

Status-driven long task

bash
cmux set-status task "starting" --icon clock --color "#ff9500"cmux set-progress 0.0 --label "Initializing..."
# ... step 1 ...cmux set-progress 0.33 --label "Building..."
# ... step 2 ...cmux set-progress 0.66 --label "Testing..."
# ... step 3 ...cmux set-progress 1.0 --label "Done"cmux set-status task "complete" --icon checkmark --color "#34c759"cmux clear-progresscmux notify --title "Task complete" --body "All steps passed"

Source and attribution

Source:reason-machines/trending-skillsinskills/cmux-terminal-multiplexerat commit2384a00

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal