tmux
Scannednpx machina-cli add skill zebbern/icron/tmux --openclawtmux Skill
Use tmux only when you need an interactive TTY. Prefer exec background mode for long-running, non-interactive tasks.
Quickstart (isolated socket, exec tool)
SOCKET_DIR="${icron_TMUX_SOCKET_DIR:-${TMPDIR:-/tmp}/icron-tmux-sockets}"
mkdir -p "$SOCKET_DIR"
SOCKET="$SOCKET_DIR/icron.sock"
SESSION=icron-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
icron_TMUX_SOCKET_DIRenvironment variable. - Default socket path:
"$icron_TMUX_SOCKET_DIR/icron.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(usesicron_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)
Overview
This tmux skill lets you control interactive CLIs remotely by sending keystrokes and scraping pane output. It relies on a private tmux socket, enabling isolated sessions for tasks like coding agents in parallel and monitoring REPLs. It also includes helper scripts and clear targeting conventions to manage multiple panes.
How This Skill Works
You create a detached tmux session bound to a private socket with tmux -S SOCKET. Commands are sent to a specific session:window.pane using tmux -S SOCKET send-keys, while pane output is captured with capture-pane. You can monitor prompts with wait-for-text scripts and reattach for live viewing, all while isolating sessions per socket and session naming.
When to Use It
- When you need an interactive TTY for CLIs or REPLs and want isolation from the main terminal
- When orchestrating multiple coding agents in parallel (e.g., running several Codex/Claude Code tasks in separate tmux sessions)
- When you must monitor and capture pane output for prompts or results without blocking the terminal
- When spawning long-running, multi-step tasks that should not disrupt ongoing work
- When managing sessions across a private socket and performing safe cleanup (kill-session/kill-server)
Quick Start
- Step 1: Define a private socket and session: SOCKET_DIR="${icron_TMUX_SOCKET_DIR:-${TMPDIR:-/tmp}/icron-tmux-sockets}"; mkdir -p "$SOCKET_DIR"; SOCKET="$SOCKET_DIR/icron.sock"; SESSION=icron-python
- Step 2: Start a detached session: tmux -S "$SOCKET" new -d -s "$SESSION" -n shell
- Step 3: Send a command and capture output: 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
Best Practices
- Use a dedicated socket dir via the icron_TMUX_SOCKET_DIR environment variable to keep sessions isolated
- Keep session/pane names short and avoid spaces to simplify targeting (session:window.pane defaulting to :0.0)
- Prefer literal sends with -l when sending exact commands and use -c for control keys like C-c
- Print monitor commands after starting a session to simplify later attach/monitor workflows
- Use tmux -S SOCKET list-sessions and list-panes -a to discover targets before sending input
Example Use Cases
- Create multiple sessions and launch agents: 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
- Poll for completion by checking prompts: for sess in agent-1 agent-2; do tmux -S "$SOCKET" capture-pane -p -t "$sess" -S -3 | grep -q "❯" && echo "$sess: DONE"; done
- Get full output from a finished session: tmux -S "$SOCKET" capture-pane -p -t agent-1 -S -500
- Monitor a session live by attaching: tmux -S "$SOCKET" attach -t agent-1; detach with Ctrl-b d