用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/jleechanorg/claude-commands --skill cmux-steer命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Token-efficient second opinion slash command /advice. Extracts decision point + artifact (≤150 lines), then fans out in parallel: (1) Opus subagent reviewer with fallback chain codex→agy→cursor, (2) /research on the decision topic, (3) /secondo multi-model opinion. Use instead of advisor() which ships the full conversation uncached.
Use this skill when working in repositories managed by Agent Orchestrator or when the user asks how to use `ao` properly. Covers the default AO workflow: bootstrap with `ao start`, dispatch work with `ao spawn`, inspect progress with `ao status` or `ao session ls`, steer sessions with `ao send`, and recover or clean up sessions safely. Includes strict parameter fidelity, pre-spawn cap cleanup, quota-wall fallback, and post-spawn verification.
Generate a full agento PR status report — draft readiness, canonical /green, zero-touch rate, inline display, and Slack summary.
基于 SOC 职业分类
正在显示 SKILL.md
| name | cmux-steer |
| description | Read and steer another cmux terminal tab through the Unix socket. |
REQUIRED (2026-06-09): This skill is deprecated for runtime steering. The bare
cmux send+cmux send-key enterpattern documented here does NOT include proof of submission. Use the canonical wrapper instead:python3 -c "from cmux_client import send_and_submit; print(send_and_submit('workspace:N', 'surface:M', 'text'))"and include the returnedproof+proof_tsin your reply. See~/.hermes_prod/skills/cmux-send-submit/SKILL.md. This skill is preserved for socket read operations (workspace.list,surface.read_text,tree,system.ping) only.
cmux CLI, not raw socket protocolThe raw nc -U $SOCK examples below still work for low-level access, but they
have a name → surface resolution gap that has caused repeated failures
("why do you always get confused when I name a surface"). The canonical recipe
is the cmux CLI, which exposes workspace/surface/tab refs directly.
Always start here when the user names a surface, tab, or workspace:
# 1. MY workspace = caller.workspace_ref, falling back to focused.
# `caller` is populated only when this command runs inside cmux itself;
# from a standalone terminal (and from most skill invocations) it is null,
# and a naive `["caller"]["workspace_ref"]` lookup will KeyError. The
# defensive form below silently falls back to the focused workspace.
WS=$(cmux identify --json | python3 -c '
import sys, json
d = json.load(sys.stdin)
c = d.get("caller") or {}
print(c.get("workspace_ref") or d.get("focused", {}).get("workspace_ref"))
')
# 2. Every pane + tab by name; ◀ here = caller surface, ◀ active = focus.
# Do NOT filter the output — sibling tabs and the ◀ markers are the signal.
cmux tree --all --workspace "$WS"
# 3. Read the target surface. ⚠ Cross-workspace `cmux read-screen
# --workspace X --surface Y` is NOT reliable in current cmux (verified
# bug — see ~/.hermes/skills/cmux/references/surface-read-routing-bug.md):
# it can silently return the currently-focused surface's content even
# when the `result` echoes the requested refs. The reliable recipe for
# reading a non-focused surface is **focus-then-read**:
# a. `cmux focus-surface --workspace "$WS" --surface surface:N` (or the
# JSON-RPC `surface.focus` equivalent) to make surface:N the focused
# surface, then
# b. `cmux read-screen --lines 80` (no --workspace / --surface args —
# the bare invocation reads the focused surface).
# For an already-focused surface, the bare `cmux read-screen --lines N`
# is sufficient and matches what you see on screen.
cmux list-pane-surfaces | grep <name> matches a
same-named tab in another workspace and you steer the wrong agent.cmux tree --all | grep <name> hides sibling
tabs and the ◀ here / ◀ active markers you need to disambiguate.list-pane-surfaces defaults — defaults to ONE pane and omits tabs in
other panes; use cmux tree --all --workspace "$WS" for the full picture.The raw nc -U $SOCK blocks below remain useful for low-level debugging
(system.tree, system.identify, custom JSON-RPC methods) and for
environments where the cmux CLI binary is not on PATH. The CLI recipes
above are the default; fall back to the raw socket blocks only when the
CLI fails or is unavailable.
cmux read-screen --workspace <ws> --surface <surface> can silently
return the focused surface's content instead of the named one (see
~/.hermes/skills/cmux/references/surface-read-routing-bug.md). Use the
focus-then-read recipe above for any non-focused surface.surface.read_text with workspace_ref/surface_ref ignores the ref
params and returns the focused surface's text. Same focus-then-read fix.Usage: Read and follow this skill directly; no /cmux-steer slash command is defined.
Purpose: Read and steer another agent's terminal pane (e.g. a coding agent) from within cmux, without disrupting the user's active workspace navigation.
# Release build
SOCK="$HOME/Library/Application Support/cmux/cmux.sock"
# Dev builds — find via saved path files or lsof:
cat ~/Library/Application\ Support/cmux/dev-may-18-last-socket-path
# → /tmp/cmux-debug-may-18.sock
lsof -p $(pgrep -f "cmux DEV may-18") | grep -E "\.sock"
# Use CMUX_SOCKET_PATH to target a specific build with the CLI:
CMUX_SOCKET_PATH=/tmp/cmux-debug-may-18.sock cmux list-workspaces
The user can switch workspaces at any time, shifting surface indices. Never hardcode an index. Always look up by the workspace's display name:
# List all workspaces with names
printf "list_workspaces\n" | nc -U $SOCK
# Example output:
# 0: D267DC10-... cmux: ubuntu
# * 1: 9075D919-... exp: statusline ← user is here; doesn't matter
# 2: 258EB4B4-... o: mctrl
# Find target workspace UUID by name
WS_UUID=$(printf "list_workspaces\n" | nc -U $SOCK \
| grep "cmux: ubuntu" | grep -oE '[A-F0-9-]{36}')
# List surfaces in that workspace
printf "list_surfaces $WS_UUID\n" | nc -U $SOCK
# Output:
# * 0: 87DB76A9-... supervisor (cmux)
# 1: F05FCE84-... cmux_coder
# Extract coder surface UUID by label (never by index — indices shift)
CODER_UUID=$(printf "list_surfaces $WS_UUID\n" | nc -U $SOCK \
| grep "cmux_coder" | grep -oE '[A-F0-9-]{36}')
The plain-text send_surface command FAILS cross-workspace. Always use the JSON API:
| Method | Cross-workspace? | Notes |
|---|---|---|
surface.send_text (JSON) | ✅ always works | Include \n in text for enter |
send_surface (plain text) | ❌ fails cross-workspace | Only works if workspace is selected |
read_screen | ❌ current workspace only | Use index, not UUID |
# Single command: type + enter (append \n to submit)
printf '{"method":"surface.send_text","params":{"surface_id":"'"$CODER_UUID"'","text":"your instruction here\\n"}}\n' | nc -U $SOCK
This works from any workspace without switching focus. The \n at end acts as Enter.
# Send a harmless probe — if queued=false and ok=true, surface accepted input
result=$(printf '{"method":"surface.send_text","params":{"surface_id":"'"$CODER_UUID"'","text":""}}\n' | nc -U $SOCK)
# Check result.ok and result.queued
# Create workspace
printf '{"method":"workspace.create","params":{"title":"my-workspace"}}\n' | nc -U $SOCK
# Returns workspace_id
# Rename workspace
printf '{"method":"workspace.rename","params":{"workspace_id":"UUID","title":"new name"}}\n' | nc -U $SOCK
# Add a second tab/surface
printf '{"method":"surface.create","params":{"workspace_id":"UUID"}}\n' | nc -U $SOCK
# Returns surface_id
For key combos, fall back to plain text protocol (requires workspace focus):
printf "send_key_surface $CODER_UUID ctrl-c\n" | nc -U $SOCK
printf "send_key_surface $CODER_UUID ctrl-a\n" | nc -U $SOCK
printf "send_key_surface $CODER_UUID ctrl-k\n" | nc -U $SOCK
Available: ctrl-c, ctrl-d, enter, tab, escape, up, down, left, right
read_screen requires a surface index (not UUID) and only works when the target is in the user's currently focused workspace. Obtain the index from list_surfaces output (e.g. 1: F05FCE84-... cmux_coder → index is 1).
# IDX = index from list_surfaces for the focused workspace (replace with actual value)
IDX=1
printf "read_screen $IDX --lines 40\n" | nc -U $SOCK
printf "read_screen $IDX --lines 80 --scrollback\n" | nc -U $SOCK
If the user is in a different workspace, infer state from the filesystem instead:
cd /path/to/project && git log --oneline -5
ls -lt src/ # recently modified files
SOCK="/tmp/cmux-debug-appclick.sock"
# 1. Find coder surface by workspace name
WS_UUID=$(printf "list_workspaces\n" | nc -U $SOCK \
| grep "cmux: ubuntu" | grep -oE '[A-F0-9-]{36}')
CODER_UUID=$(printf "list_surfaces $WS_UUID\n" | nc -U $SOCK \
| grep "cmux_coder" | grep -oE '[A-F0-9-]{36}')
# 2. Send task headlessly (no workspace switch needed)
printf '{"method":"surface.send_text","params":{"surface_id":"'"$CODER_UUID"'","text":"cargo build && cargo test\\n"}}\n' | nc -U $SOCK
# 3. Monitor progress via filesystem (no read_screen needed)
sleep 30
cd /path/to/project && git log --oneline -3
SOCK="/tmp/cmux-debug-appclick.sock"
# Create workspace
WS=$(printf '{"method":"workspace.create","params":{"title":"my-test"}}\n' | nc -U $SOCK \
| python3 -c "import sys,json; print(json.loads(sys.stdin.read())['result']['workspace_id'])")
# Rename it
printf '{"method":"workspace.rename","params":{"workspace_id":"'"$WS"'","title":"test: a/b"}}\n' | nc -U $SOCK
# Add second tab
TAB2=$(printf '{"method":"surface.create","params":{"workspace_id":"'"$WS"'"}}\n' | nc -U $SOCK \
| python3 -c "import sys,json; print(json.loads(sys.stdin.read())['result']['surface_id'])")
# Get first tab
TAB1=$(printf "list_surfaces $WS\n" | nc -U $SOCK | grep "0:" | grep -oE '[A-F0-9-]{36}')
# Send commands to both tabs headlessly
printf '{"method":"surface.send_text","params":{"surface_id":"'"$TAB1"'","text":"echo tab1\\n"}}\n' | nc -U $SOCK
printf '{"method":"surface.send_text","params":{"surface_id":"'"$TAB2"'","text":"echo tab2\\n"}}\n' | nc -U $SOCK
select_workspace — it switches the user's visible workspace.list_workspaces → grep name → get UUID).surface.send_text works headlessly cross-workspace.\n to text — acts as Enter key submission.read_screen requires being in the right workspace; use git/filesystem for cross-workspace monitoring.workspace.create + surface.create for multi-tab setups.