| name | pi-cmux |
| description | Control cmux terminal multiplexer from pi — read other terminal screens, send commands to other workspaces, manage panes/splits, set sidebar status/progress, send notifications, and open browser surfaces. Use when asked to: check what's running in another terminal, send a command to another pane, split the workspace, show progress in the sidebar, notify the user, open a URL in a browser pane, orchestrate multi-workspace workflows, or interact with cmux in any way. Triggers on: 'cmux', 'other terminal', 'other workspace', 'read screen', 'send command to', 'split pane', 'sidebar status', 'progress bar', 'notify', 'browser pane', 'terminal multiplexer'. |
| disable-model-invocation | true |
cmux Integration for Pi
Pi runs inside cmux with full access to the cmux CLI via three extension tools: cmux, cmux_status, and cmux_notify. The cmux extension also automatically manages sidebar status (Running/Idle/Needs input) through pi lifecycle hooks.
Naming discipline
When starting meaningful work or pivoting the core workstream, use the cmux-workspace-naming skill. Name the broad workspace theme in short Human Case, optionally with one useful emoji. Do not rename for tiny substeps.
For multi-tab, multi-session, or multi-subagent workspaces:
- Workspace/session name = umbrella theme shared by all lanes.
- Tab/surface/child-session name = stable lane/role, only when helpful.
- Parent/orchestrator owns workspace naming; child agents should not clobber it.
- Use sidebar status/progress/log rows for live state instead of renaming tabs every time something starts/stops.
- Keep the sidebar calm: avoid bouncy
Running, Checking, Fixing, Almost Done title churn.
- For 4-10 agents, boring is good:
Parent, Research 1, Research 2, Reviewer, Worker, CI Watch.
- Split into a new workspace/session when the lane becomes an independent workstream.
Required flow:
cmux action="identify"
cmux action="rename-workspace" args=["--workspace", "workspace:45", "🧭 cmux Naming Rules"]
cmux action="focus-panel" args=["--workspace", "workspace:45", "--panel", "surface:80"]
cmux action="tree" args=["--workspace", "workspace:45"]
Use the discovered refs, not guessed refs. Do not type rename commands into the active Pi terminal with send; that turns into user input instead of an operator command. Use the cmux tool or run the cmux CLI from a shell tool.
Concepts
Refs — cmux uses short refs to identify objects: workspace:1, pane:2, surface:3, window:1. Run cmux identify for the caller/focused refs, or cmux tree for layout discovery, before targeting specific surfaces.
Surfaces — a surface is a single terminal or browser tab inside a pane. Each pane can have multiple surfaces (shown as tabs). Each workspace has one or more panes (splits).
Environment — cmux auto-sets CMUX_WORKSPACE_ID, CMUX_SURFACE_ID, and CMUX_SOCKET_PATH in local terminal surfaces. In cmux ssh remote sessions, Pi subprocesses may not inherit those variables; the extension discovers ~/.cmux/bin/cmux and the relay socket automatically. Commands default to the caller's workspace/surface when flags are omitted where cmux exposes caller context.
Tools
cmux — Workspace, Pane, and Surface Control
The main tool for multiplexer operations. Takes an action and optional args array.
Discover layout
cmux action="tree"
cmux action="tree" args=["--all"]
cmux action="identify"
cmux action="remote-status"
cmux action="diagnose"
cmux action="capabilities"
cmux action="list-workspaces"
cmux action="current-workspace"
cmux action="list-panes"
cmux action="list-panes" args=["--workspace", "workspace:2"]
Read another terminal's screen
cmux action="read-screen" args=["--surface", "surface:1", "--lines", "50"]
cmux action="read-screen" args=["--surface", "surface:3", "--scrollback"]
cmux action="read-screen" args=["--workspace", "workspace:2"]
Use --scrollback to include scrollback buffer. Use --lines N to limit output. Without --surface, reads the focused surface of the specified workspace (or caller's workspace).
Send text or keys to another terminal
cmux action="send" args=["--surface", "surface:1", "npm run build\n"]
cmux action="send-key" args=["--surface", "surface:1", "Enter"]
cmux action="send-key" args=["--surface", "surface:2", "C-c"]
Important: Append \n to text to "press Enter". Use send-key for special keys: Enter, C-c (Ctrl+C), C-d, Up, Down, Left, Right, Tab, Escape, BSpace (backspace).
Create workspaces, panes, splits
cmux action="new-workspace" args=["--cwd", "/path/to/project"]
cmux action="new-split" args=["right"]
cmux action="new-split" args=["down", "--workspace", "workspace:1"]
cmux action="new-pane" args=["--type", "terminal", "--direction", "right"]
cmux action="new-pane" args=["--type", "browser", "--url", "http://localhost:3000"]
Split directions: left, right, up, down.
Navigate and manage
cmux action="select-workspace" args=["--workspace", "workspace:3"]
cmux action="rename-workspace" args=["--workspace", "workspace:3", "🚢 Course Builder Deploys"]
cmux action="focus-pane" args=["--pane", "pane:2"]
cmux action="close-surface" args=["--surface", "surface:5"]
cmux action="close-workspace" args=["--workspace", "workspace:4"]
cmux_status — Sidebar Status, Progress, and Logs
Control the cmux sidebar for the current workspace. In cmux ssh remote relay mode, current stable cmux may support notifications and remote status but not sidebar mutation commands (set-status, set-progress, log). If unsupported, the tool returns a clear error and lifecycle status writes no-op instead of failing the Pi session. Use cmux action="diagnose" first when local/remote behavior looks odd.
Status entries
cmux_status action="set-status" key="build" value="Compiling..." icon="hammer.fill" color="#FF9500" priority=10
cmux_status action="set-status" key="tests" value="14/20 passing" icon="checkmark.circle" color="#34C759" priority=10
cmux_status action="clear-status" key="build"
cmux_status action="sidebar-state"
Icons are SF Symbol names. Common ones:
bolt.fill — running/active
pause.circle.fill — idle/paused
checkmark.circle — success
xmark.circle — error/failure
hammer.fill — building
magnifyingglass — searching
arrow.down.circle — downloading
bell.fill — attention needed
circle.dashed — pending
Colors are hex: #4C8DFF (blue), #34C759 (green), #FF3B30 (red), #FF9500 (orange), #8E8E93 (gray).
priority controls sidebar ordering. Higher appears first; use negative priority for low-priority background rows.
Progress bar
cmux_status action="set-progress" value="0.45" label="Deploying..."
cmux_status action="set-progress" value="1.0" label="Complete"
cmux_status action="clear-progress"
Value is 0.0 to 1.0.
Log entries
cmux_status action="log" value="Build started" level="info"
cmux_status action="log" value="Test failed: auth.test.ts" level="error"
cmux_status action="log" value="Deprecated API usage" level="warn"
cmux_status action="clear-log"
cmux_notify — Native Notifications
Send macOS notifications via cmux. Appears in Notification Center.
cmux_notify title="Build Complete" body="All 47 tests passing" subtitle="my-project"
cmux_notify title="Deploy Failed" body="Error: connection timeout on staging"
cmux_notify title="pi" body="Task finished — ready for review"
Common Patterns
Check what's running in another workspace
# 1. Find the workspace
cmux action="tree"
# 2. Read its screen
cmux action="read-screen" args=["--workspace", "workspace:2", "--lines", "30"]
Run a command in another terminal and check output
# Send the command
cmux action="send" args=["--surface", "surface:1", "npm test 2>&1\n"]
# Wait a moment, then read the result
cmux action="read-screen" args=["--surface", "surface:1", "--lines", "50"]
Multi-workspace orchestration
# Create a new workspace for the task
cmux action="new-workspace" args=["--cwd", "/path/to/project"]
# Split it for parallel work
cmux action="new-split" args=["right"]
# Run frontend in one pane, backend in the other
cmux action="send" args=["--surface", "surface:7", "npm run dev\n"]
cmux action="send" args=["--surface", "surface:8", "npm run api\n"]
# Show progress
cmux_status action="set-progress" value="0.5" label="Starting services..."
# Open browser to preview
cmux action="new-pane" args=["--type", "browser", "--url", "http://localhost:3000"]
Long task with progress tracking
# Set status at start
cmux_status action="set-status" key="task" value="Processing..." icon="bolt.fill" color="#4C8DFF"
cmux_status action="set-progress" value="0.0" label="Step 1/5"
# Update as you go
cmux_status action="set-progress" value="0.4" label="Step 3/5"
cmux_status action="log" value="Completed migration step 3"
# Finish
cmux_status action="set-progress" value="1.0" label="Done"
cmux_status action="set-status" key="task" value="Complete" icon="checkmark.circle" color="#34C759"
cmux_notify title="Task Complete" body="All 5 steps finished successfully"
# Clean up
cmux_status action="clear-progress"
cmux_status action="clear-status" key="task"
Open a browser pane for preview
cmux action="new-pane" args=["--type", "browser", "--url", "http://localhost:3000"]
Automatic Lifecycle Status
The cmux extension automatically manages Pi sidebar metadata:
pi_model — current provider/model/thinking level
pi_usage — context usage, token totals, and cost
- pane stack rows — active cmux panes/surfaces, with the running Pi pane annotated
- lifecycle status — Idle/Running/Needs input shown on the active pane row
| Pi Event | Sidebar Status | Icon | Color | Tab Indicator |
|---|
| Session start | Idle + session name (if resuming) | pause.circle.fill / text.bubble | gray | mark-read, clear notifications |
| Agent starts working | Running | bolt.fill | blue | mark-read, clear notifications |
| Tool execution | Live activity (e.g. "Reading ~/.zshrc") | bolt.fill | blue | — |
| Agent turn complete | Needs input + turn summary | bell.fill | blue | mark-unread + notification |
| Session shutdown | all cleared | — | — | mark-read, clear notifications |
Session naming is opt-in via PI_CMUX_SESSION_NAMING=1. When enabled, the session name appears as a sidebar status entry — the workspace label is never modified by the extension and is left to the operator.
Live tool activity: Every tool execution updates the active pane row with what pi is doing (e.g. "Reading ~/.zshrc", "Running grep", "Editing auth.ts"). This is always on and visible from other workspaces — useful for monitoring pi while focused elsewhere.
Attention cycle: When the agent finishes a turn, the workspace tab is marked unread (lights up) and a cmux notification fires. When the user provides input and the agent starts working again, the tab is marked read and notifications are cleared. This gives a clean read/unread signal across workspaces.
Allowed Actions
The cmux tool allows these actions: tree, identify, list-workspaces, current-workspace, read-screen, send, send-key, new-workspace, new-split, new-pane, new-surface, select-workspace, close-surface, close-workspace, list-panes, list-pane-surfaces, focus-pane, rename-workspace, surface-health.
For browser control, use new-pane with --type browser to create browser surfaces. For advanced browser automation, use the agent-browser skill or cmux browser subcommands via bash.
Extension Safety: Fork-Bomb Prevention
The cmux extension spawns helper pi -p subprocesses for session naming and turn summaries. Without proper guards, each child process loads the cmux extension again, fires the same hooks, and spawns another child — exponential process explosion.
Three-layer defense (all required):
-
--no-extensions flag on every pi -p spawn — prevents the child from loading any extensions, including cmux itself. This is the critical flag; --no-tools/--no-skills alone are not enough.
-
--no-session flag — prevents the child from creating session files, which would compound the recursion with disk I/O.
-
PI_CMUX_CHILD env guard — the extension sets PI_CMUX_CHILD=1 in the child's environment and bails out at the top of cmuxExtension() if that var is set. Belt-and-suspenders defense in case --no-extensions is somehow bypassed.
if (process.env[CMUX_CHILD_ENV] === "1") return;
spawn("pi", [
"-p",
"--model", NAMING_MODEL,
"--no-session",
"--no-extensions",
"--no-tools",
"--no-skills",
"--no-prompt-templates",
"--system-prompt", "...",
], {
env: { ...process.env, [CMUX_CHILD_ENV]: "1" },
});
State resets on lifecycle events:
session_start: reset _pendingSessionName and _hasNamedSession
session_shutdown: reset both to prevent stale state across /continue sessions