Remote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.
Install
Documentation
tmux Skill (Clawdbot)
Use tmux only when you need an interactive TTY. Prefer bash background mode for long-running, non-interactive tasks.
Quickstart (isolated socket, bash tool)
SOCKET_DIR="${CLAWDBOT_TMUX_SOCKET_DIR:-${TMPDIR:-/tmp}/clawdbot-tmux-sockets}"
mkdir -p "$SOCKET_DIR"
SOCKET="$SOCKET_DIR/clawdbot.sock"
SESSION=clawdbot-python
tmux -S "$SOCKET" new -d -s "$SESSION" -n shell
tmux -S "$SOCKET" send-keys -t "$SESSION":0.0 -- 'PYTHON_BASIC_REPL=1 python3 -q' Enter
tmux -S "$SOCKET" capture-pane -p -J -t "$SESSION":0.0 -S -200
After starting a session, always print monitor commands:
To monitor:
tmux -S "$SOCKET" attach -t "$SESSION"
tmux -S "$SOCKET" capture-pane -p -J -t "$SESSION":0.0 -S -200
Socket convention
- -Use
CLAWDBOT_TMUX_SOCKET_DIR(default${TMPDIR:-/tmp}/clawdbot-tmux-sockets). - -Default socket path:
"$CLAWDBOT_TMUX_SOCKET_DIR/clawdbot.sock".
Targeting panes and naming
- -Target format:
session:window.pane(defaults to:0.0). - -Keep names short; avoid spaces.
- -Inspect:
tmux -S "$SOCKET" list-sessions,tmux -S "$SOCKET" list-panes -a.
Finding sessions
- -List sessions on your socket:
{baseDir}/scripts/find-sessions.sh -S "$SOCKET". - -Scan all sockets:
{baseDir}/scripts/find-sessions.sh --all(usesCLAWDBOT_TMUX_SOCKET_DIR).
Sending input safely
- -Prefer literal sends:
tmux -S "$SOCKET" send-keys -t target -l -- "$cmd". - -Control keys:
tmux -S "$SOCKET" send-keys -t target C-c.
Watching output
- -Capture recent history:
tmux -S "$SOCKET" capture-pane -p -J -t target -S -200. - -Wait for prompts:
{baseDir}/scripts/wait-for-text.sh -t session:0.0 -p 'pattern'. - -Attaching is OK; detach with
Ctrl+b d.
Spawning processes
- -For python REPLs, set
PYTHON_BASIC_REPL=1(non-basic REPL breaks send-keys flows).
Windows / WSL
- -tmux is supported on macOS/Linux. On Windows, use WSL and install tmux inside WSL.
- -This skill is gated to
darwin/linuxand requirestmuxon PATH.
Orchestrating Coding Agents (Codex, Claude Code)
tmux excels at running multiple coding agents in parallel:
SOCKET="${TMPDIR:-/tmp}/codex-army.sock"
Create multiple sessions
for i in 1 2 3 4 5; do
tmux -S "$SOCKET" new-session -d -s "agent-$i"
done
Launch agents in different workdirs
tmux -S "$SOCKET" send-keys -t agent-1 "cd /tmp/project1 && codex --yolo 'Fix bug X'" Enter
tmux -S "$SOCKET" send-keys -t agent-2 "cd /tmp/project2 && codex --yolo 'Fix bug Y'" Enter
Poll for completion (check if prompt returned)
for sess in agent-1 agent-2; do
if tmux -S "$SOCKET" capture-pane -p -t "$sess" -S -3 | grep -q "❯"; then
echo "$sess: DONE"
else
echo "$sess: Running..."
fi
done
Get full output from completed session
tmux -S "$SOCKET" capture-pane -p -t agent-1 -S -500
Tips:
- -Use separate git worktrees for parallel fixes (no branch conflicts)
- -
pnpm installfirst before running codex in fresh clones - -Check for shell prompt (
❯or$) to detect completion - -Codex needs
--yoloor--full-autofor non-interactive fixes
Cleanup
- -Kill a session:
tmux -S "$SOCKET" kill-session -t "$SESSION". - -Kill all sessions on a socket:
tmux -S "$SOCKET" list-sessions -F '#{session_name}' | xargs -r -n1 tmux -S "$SOCKET" kill-session -t. - -Remove everything on the private socket:
tmux -S "$SOCKET" kill-server.
Helper: wait-for-text.sh
{baseDir}/scripts/wait-for-text.sh polls a pane for a regex (or fixed string) with a timeout.
{baseDir}/scripts/wait-for-text.sh -t session:0.0 -p 'pattern' [-F] [-T 20] [-i 0.5] [-l 2000]
- -
-t/--targetpane target (required) - -
-p/--patternregex to match (required); add-Ffor fixed string - -
-Ttimeout seconds (integer, default 15) - -
-ipoll interval seconds (default 0.5) - -
-lhistory lines to search (integer, default 1000)
Launch an agent with Tmux on Termo.