| name | tmux |
| description | Minimal tmux workflow for running long-lived commands in named sessions: create a session, send commands, inspect recent output, stop a process, kill a session, and keep names consistent for search and cleanup. Use when an agent needs a durable terminal session for servers, watchers, REPLs, or commands that may need later inspection.
|
tmux
Use tmux for durable terminal work: dev servers, file watchers, REPLs, or long-running
commands whose output you need to inspect later.
Variables
| Variable | Value | Notes |
|---|
NAME_PREFIX | agent | Stable prefix for easy search and cleanup |
TASK_SLUG | short lowercase kebab-case | Project/task label, e.g. api-dev-server |
SESSION_NAME | NAME_PREFIX-TASK_SLUG | Full tmux session name |
PANE_SHELL | detected from tmux pane | Usually bash, zsh, fish, or nu |
TAIL_LINES | 80 | Default output lines to inspect |
Knowledge
Naming convention
Use predictable names so sessions are easy to find and clean up:
agent-<task-slug>
Examples:
agent-api-dev-server
agent-vitest-watch
agent-rails-console
Keep names lowercase, kebab-case, and specific enough to identify the task. Reuse the
same name for the same task so reruns replace stale sessions instead of accumulating
near-duplicates.
Core commands
tmux list-sessions -F '#S' | rg '^agent-'
tmux new-session -d -s "$SESSION_NAME" -c "$PWD" '<command>'
tmux new-session -d -s "$SESSION_NAME" -c "$PWD"
tmux display-message -p -t "$SESSION_NAME" '#{pane_current_command}'
tmux send-keys -l -t "$SESSION_NAME" '<command>'
tmux send-keys -t "$SESSION_NAME" C-m
tmux send-keys -l -t "$SESSION_NAME" $'first command\rsecond command'
tmux send-keys -t "$SESSION_NAME" C-m
tmux capture-pane -p -t "$SESSION_NAME" -S -"$TAIL_LINES"
tmux capture-pane -p -t "$SESSION_NAME" -S -
tmux send-keys -t "$SESSION_NAME" C-c
tmux send-keys -l -t "$SESSION_NAME" exit
tmux send-keys -t "$SESSION_NAME" C-m
tmux kill-session -t "$SESSION_NAME"
Procedures
Start a durable command
-
Choose TASK_SLUG and set SESSION_NAME="agent-$TASK_SLUG".
-
Check whether that session already exists:
tmux has-session -t "$SESSION_NAME" 2>/dev/null
-
If it exists and belongs to the same task, either reuse it or kill it before starting a fresh run:
tmux kill-session -t "$SESSION_NAME"
-
Start the command in a detached session from the current working directory:
tmux new-session -d -s "$SESSION_NAME" -c "$PWD" '<command>'
-
Capture recent output to confirm it started:
tmux capture-pane -p -t "$SESSION_NAME" -S -80
Detect the pane shell
Run this before sending shell-specific commands or examples to an idle tmux shell:
PANE_SHELL="$(tmux display-message -p -t "$SESSION_NAME" '#{pane_current_command}')"
printf 'tmux pane shell: %s\n' "$PANE_SHELL"
Treat PANE_SHELL as the syntax target for commands sent into the pane. Do not assume
bash: zsh, fish, and nu differ for variables, arrays, conditionals, multiline
strings, and command substitution.
Inspect output later
-
Confirm the session exists:
tmux list-sessions -F '#S' | rg '^agent-'
-
Tail recent output:
tmux capture-pane -p -t "$SESSION_NAME" -S -80
-
Increase the line count if the relevant output scrolled off the recent tail:
tmux capture-pane -p -t "$SESSION_NAME" -S -200
Interact with a running session
-
Detect the shell actually running in the pane before sending shell-specific syntax:
PANE_SHELL="$(tmux display-message -p -t "$SESSION_NAME" '#{pane_current_command}')"
printf 'tmux pane shell: %s\n' "$PANE_SHELL"
-
Prefer send-keys -l for commands or pasted blocks so tmux treats text as
literal UTF-8 instead of looking up key names. Send control keys like C-m
separately:
tmux send-keys -l -t "$SESSION_NAME" '<command>'
tmux send-keys -t "$SESSION_NAME" C-m
-
For multi-command shell input from a bash/zsh caller, use shell quoting or another
command-builder that preserves carriage returns, then send Enter separately if the
final line should run:
tmux send-keys -l -t "$SESSION_NAME" $'first command\rsecond command'
tmux send-keys -t "$SESSION_NAME" C-m
-
Use C-c to interrupt a foreground process:
tmux send-keys -t "$SESSION_NAME" C-c
-
Capture output after each interaction before deciding the next step.
Clean up sessions
-
List agent-owned sessions:
tmux list-sessions -F '#S' | rg '^agent-'
-
Politely exit sessions that are just shells:
tmux send-keys -l -t "$SESSION_NAME" exit
tmux send-keys -t "$SESSION_NAME" C-m
-
Kill sessions that are no longer needed or did not exit:
tmux kill-session -t "$SESSION_NAME"
-
Bulk cleanup only the names you own:
tmux list-sessions -F '#S' | rg '^agent-' | xargs -r -n1 tmux kill-session -t
Constraints
- Never use vague session names like
test, server, or tmp.
- Never kill sessions that do not match the agreed
agent- naming pattern unless the user explicitly identifies them.
- Always capture output after starting, interrupting, or sending input to a session.
- Always detect
PANE_SHELL before sending syntax that differs across bash, zsh, fish,
or nushell.
- Prefer polite shutdown (
C-c, then exit) before kill-session when preserving logs or graceful process cleanup matters.
- Do not leave long-running sessions behind unless the user needs them for follow-up inspection.
Validation