بنقرة واحدة
tmux
Remote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Remote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | tmux |
| description | Remote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output. |
| metadata | {"openclaw":{"emoji":"🧵","os":["darwin","linux"],"requires":{"bins":["tmux"]}}} |
Control tmux sessions by sending keystrokes and reading output. Essential for managing Claude Code sessions.
✅ USE this skill when:
❌ DON'T use this skill when:
exec tool directlyexec with background:trueexec toolexec with tmux new-session| Session | Purpose |
|---|---|
shared | Primary interactive session |
worker-2 - worker-8 | Parallel worker sessions |
tmux list-sessions
tmux ls
# Last 20 lines of pane
tmux capture-pane -t shared -p | tail -20
# Entire scrollback
tmux capture-pane -t shared -p -S -
# Specific pane in window
tmux capture-pane -t shared:0.0 -p
# Send text (doesn't press Enter)
tmux send-keys -t shared "hello"
# Send text + Enter
tmux send-keys -t shared "y" Enter
# Send special keys
tmux send-keys -t shared Enter
tmux send-keys -t shared Escape
tmux send-keys -t shared C-c # Ctrl+C
tmux send-keys -t shared C-d # Ctrl+D (EOF)
tmux send-keys -t shared C-z # Ctrl+Z (suspend)
# Select window
tmux select-window -t shared:0
# Select pane
tmux select-pane -t shared:0.1
# List windows
tmux list-windows -t shared
# Create new session
tmux new-session -d -s newsession
# Kill session
tmux kill-session -t sessionname
# Rename session
tmux rename-session -t old new
For interactive TUIs (Claude Code, Codex, etc.), split text and Enter into separate sends to avoid paste/multiline edge cases:
tmux send-keys -t shared -l -- "Please apply the patch in src/foo.ts"
sleep 0.1
tmux send-keys -t shared Enter
# Look for prompts
tmux capture-pane -t worker-3 -p | tail -10 | grep -E "❯|Yes.*No|proceed|permission"
# Send 'y' and Enter
tmux send-keys -t worker-3 'y' Enter
# Or select numbered option
tmux send-keys -t worker-3 '2' Enter
for s in shared worker-2 worker-3 worker-4 worker-5 worker-6 worker-7 worker-8; do
echo "=== $s ==="
tmux capture-pane -t $s -p 2>/dev/null | tail -5
done
tmux send-keys -t worker-4 "Fix the bug in auth.js" Enter
Reusable orchestration patterns for the /parallel and
/parallel-research skills. Reference these by name instead of
duplicating tmux logic.
Create a session with up to 4 panes per window, tiled layout. Validates pane count before proceeding.
SESSION="myagents"
AGENTS=("agent-1" "agent-2" "agent-3" "agent-4" "agent-5")
PANES_PER_WINDOW=4
tmux new-session -d -s "$SESSION" -x 220 -y 55
pane_index=0
for agent in "${AGENTS[@]}"; do
window_index=$((pane_index / PANES_PER_WINDOW))
slot=$((pane_index % PANES_PER_WINDOW))
if [[ $slot -eq 0 && $pane_index -gt 0 ]]; then
# New window needed
tmux new-window -t "$SESSION"
elif [[ $slot -gt 0 ]]; then
# Split within current window
tmux split-window -t "$SESSION:$window_index"
tmux select-layout -t "$SESSION:$window_index" tiled
fi
# Validate pane exists before sending
if tmux list-panes -t "$SESSION:$window_index" -F '#{pane_index}' | grep -q "^${slot}$"; then
tmux send-keys -t "$SESSION:$window_index.$slot" "echo 'launching $agent'" Enter
else
echo "ERROR: pane $SESSION:$window_index.$slot does not exist"
fi
pane_index=$((pane_index + 1))
done
# Final validation
tmux list-windows -t "$SESSION" -F "#{window_name}: #{window_panes} panes"
Uses wait-for-text.sh to poll each pane for a completion marker.
Blocks until all agents finish or time out.
WAIT="$(dirname "$0")/scripts/wait-for-text.sh"
SESSION="myagents"
TIMEOUT=600 # seconds per agent
MARKER="COMPLETE"
# Build list of all pane targets
PANES=$(tmux list-panes -s -t "$SESSION" -F '#{window_index}.#{pane_index}')
all_done=true
for pane in $PANES; do
target="$SESSION:$pane"
if bash "$WAIT" -t "$target" -p "$MARKER" -T "$TIMEOUT" -i 5; then
echo "Pane $target: DONE"
else
echo "Pane $target: TIMED OUT or FAILED"
all_done=false
fi
done
$all_done && echo "All agents complete." || echo "Some agents failed."
Classify each pane into one of 4 states:
| State | Meaning | Detection |
|---|---|---|
| DONE | Agent finished successfully | COMPLETE marker found in pane output |
| WORKING | Agent still running | Process alive, no COMPLETE, no error patterns |
| FAILED | Agent crashed or hit an error | Process dead without COMPLETE, OR error patterns visible (rate limit, traceback, permission denied, "I'm blocked") |
| UNKNOWN | Pane not accessible | Pane doesn't exist or capture-pane failed |
Quick version (inline, for one-off checks):
SESSION="myagents"
for pane in $(tmux list-panes -s -t "$SESSION" -F '#{window_index}.#{pane_index}'); do
target="$SESSION:$pane"
dead=$(tmux display-message -t "$target" -p '#{pane_dead}')
text=$(tmux capture-pane -p -J -t "$target" -S -50 2>/dev/null)
pid=$(tmux display-message -t "$target" -p '#{pane_pid}')
if printf '%s\n' "$text" | grep -q "COMPLETE"; then
state="DONE"
elif [[ "$dead" == "1" ]]; then
state="FAILED (dead)"
elif printf '%s\n' "$text" | grep -qE "rate limit|Traceback|permission denied|I'm blocked|Error:"; then
state="FAILED (error)"
else
state="WORKING"
fi
echo "=== $target === $state (pid $pid)"
printf '%s\n' "$text" | grep -v '^[[:space:]]*$' | tail -1 | sed 's/^/ /'
echo ""
done
Scripted version (full diagnostics with summary and output file checks):
# Requires: skills/tmux/scripts/diagnose-agents.sh
DIAG="$HOME/Developer/personal_projects/agent-skills/skills/tmux/scripts/diagnose-agents.sh"
# Basic: check all panes in a session
bash "$DIAG" myagents
# With output file check
bash "$DIAG" research "research-agents/*/output.md"
bash "$DIAG" parallel "worktrees/*/run/output.md"
The script prints a per-pane report and a summary line
(N working, N done, N failed, N unknown). See
scripts/diagnose-agents.sh for the full implementation.
When sending text to interactive TUIs (Claude Code, Codex), use -l
(literal) to prevent tmux from interpreting special characters, and
split the text from Enter to avoid paste/multiline edge cases.
# -l sends the string literally (no key-name interpretation)
# sleep gives the TUI time to process the input before Enter
tmux send-keys -t shared -l -- "Please fix the bug in src/auth.ts"
sleep 0.1
tmux send-keys -t shared Enter
Why -l? Without it, tmux interprets words like Enter, Escape,
C-c as special keys. If your prompt text contains these words,
they'll be executed as keystrokes instead of typed as text.
Why separate Enter? Interactive TUIs may have paste detection.
Sending text + Enter in one send-keys call can trigger multiline
paste mode, which many TUIs handle differently from single-line input.
Why NOT send-keys "$(cat file)"? Shell expansion of file contents
through send-keys breaks on quotes, backticks, $, and newlines.
For multi-line prompts, pipe through claude -p instead (see
/parallel-research Phase 4 launcher pattern).
capture-pane -p to print to stdout (essential for scripting)-S - captures entire scrollback historysession:window.pane (e.g., shared:0.0)MECE decompose a research question, run parallel Codex web-research agents via tmux, iteratively deepen via DAG, synthesize findings
Decompose a research question into MECE domains and run parallel Claude agents via tmux
Split implementation tasks into independent workstreams running as parallel agents in git worktrees
Guided learning through Socratic questioning - teaches through discovery, not answers
Extract coding patterns and preferences from session transcripts for CLAUDE.md
Full TDD red-green-refactor cycle with automatic framework detection