[agents]
Sun Apr 5 2026
LLM×8
tmux 3.4
man tmux | head -1
THE TERMINAL OS
In April 2026, the terminal is the primary interface. Every LLM agent, every pipeline, every dev tool has gone CLI. tmux is no longer optional — it's the window manager, process supervisor, session store, and agent orchestration layer all in one. You need to own it completely.
1
server proc
sessions
windows
panes
C-b
default prefix
C-a
power-user prefix

The Object Hierarchy

tmux server ─ one daemon process, survives disconnects ├── session: agents ─ named workspace │ ├── window 0: orchestrator ─ named tab │ │ ├── pane 0 [ACTIVE] ← 60% │ │ └── pane 1 ← 40% │ ├── window 1: workers │ │ ├── pane 0 │ │ ├── pane 1 │ │ └── pane 2 │ └── window 2: logs │ └── pane 0 ├── session: devenv │ └── window 0: editor └── session: monitor └── window 0: htop + kubectl
THE CORE INSIGHT: SESSIONS OUTLIVE YOUR TERMINAL When you close your terminal window, your SSH connection drops, or your laptop lid shuts — the tmux server and all sessions keep running. Detach with C-b d, do anything, reattach later. This is why tmux is non-negotiable for long-running agent jobs — your agent is running inside tmux, not inside your terminal emulator.

Getting Oriented Fast

First 10 commands to learnbash
# ── START / ATTACH ────────────────────────────────────
tmux                          # new unnamed session
tmux new -s agents            # new named session "agents"
tmux attach -t agents        # attach to session "agents"
tmux a                        # attach to most recent session
tmux ls                       # list all sessions

# ── INSIDE TMUX: PREFIX KEY ───────────────────────────
# Default prefix: Ctrl-b (we'll change to Ctrl-a in config)
# Every tmux command: PREFIX then the key

C-b d        → detach (session keeps running!)
C-b c        → create new window
C-b "        → split pane horizontally (top/bottom)
C-b %        → split pane vertically (left/right)
C-b arrow    → move between panes
C-b z        → zoom pane to full window (toggle)
C-b [        → enter scroll/copy mode (q to exit)
C-b ?        → show all keybindings
C-b :        → command prompt (type any tmux command)

# ── POWERFUL COMBOS RIGHT NOW ─────────────────────────
C-b s        → interactive session tree (arrow keys + enter)
C-b w        → interactive window tree
C-b $        → rename current session
C-b ,        → rename current window
PREFIX KEY MUSCLE MEMORY Every single tmux action goes through the prefix key first. The default C-b (Ctrl+b) is uncomfortable — your pinky stretches. Pros remap to C-a (Ctrl+a) — same as GNU Screen. The config section covers this. But first, internalize that EVERY tmux key is: PREFIX → key. That's it.

Why Everything Lives in tmux Now (April 2026)

session persistence
agents don't care about your ssh session

Run claude --agent research-task inside tmux. Disconnect, travel, reconnect. Agent is still running. Without tmux: SSH drops → agent dies → you start over.

parallel visibility
see 8 agents at once

Split into a 4×2 grid. Watch all 8 LLM agents simultaneously. One pane per agent: see their output, status, errors — all without switching contexts.

scripted orchestration
spawn environments in 1 command

tmux new-session -d + send-keys lets you write shell scripts that build entire workspace layouts. One script → 8 panes, 3 sessions, all agents running.

tmux list-keys | wc -l
KEY BINDINGS
The complete reference. Every binding organized by domain. Learn these in order of frequency — sessions first, then panes, then windows, then copy mode.
C-b d
Detach from session (session keeps running)
C-b s
Interactive session switcher (tree view)
C-b $
Rename current session
C-b (
Switch to previous session
C-b )
Switch to next session
C-b L
Switch to last (most recently used) session
C-b $
Rename session
tmux session CLI commandsbash
tmux new-session -s agents           # new session named agents
tmux new-session -s workers -d       # new session, detached (background)
tmux attach-session -t agents        # attach to agents
tmux switch-client -t devenv         # switch to another session
tmux kill-session -t agents          # destroy session + all its windows
tmux kill-server                     # nuke everything
tmux list-sessions                   # ls alias: tmux ls
tmux rename-session -t old new       # rename from outside

# Attach or create (the professional entry point):
tmux attach -t agents || tmux new -s agents
NAMED SESSIONS — THE PROFESSIONAL PATTERN Always name your sessions. tmux new -s agents not tmux. With names: you can attach to the right session by name, script session creation, and glance at tmux ls to understand your workspace instantly. Unnamed sessions are for beginners.

Session Grouping

Grouped sessions — shared windowsbash
# Session groups: two clients viewing same windows
# Use case: pair programming, monitoring from two terminals

# Create first session:
tmux new-session -s main

# Create second session, join the group:
tmux new-session -s monitor -t main

# Now both sessions share windows but can independently:
# - Be focused on different windows
# - Have different sizes (useful: big monitor + laptop)
# Changes in one appear in the other in real time
C-b c
Create new window
C-b ,
Rename current window
C-b n
Next window
C-b p
Previous window
C-b l
Last (most recently used) window
C-b 0–9
Jump to window by number
C-b w
Interactive window picker
C-b &
Kill current window (confirm prompt)
C-b f
Find window by name or content
C-b .
Move window to a different index number
Window management from CLIbash
# Create named window in a session:
tmux new-window -t agents -n "workers"

# Create window and run a command in it:
tmux new-window -t agents -n "logs" -c ~/projects

# Move window from one session to another:
tmux move-window -s agents:2 -t monitor

# Link window (mirror it across sessions):
tmux link-window -s agents:0 -t monitor:0

# Kill a specific window without being inside it:
tmux kill-window -t agents:workers

# Swap two windows:
tmux swap-window -s agents:1 -t agents:3

# Reorder all windows (renumber from 0):
tmux move-window -r
WINDOW NAMING DISCIPLINE Always name windows immediately after creation: C-b ,. In an agent workspace with 8 windows, "agents:0" tells you nothing — "agents:orchestrator" tells you everything. Name for what the window does, not what's running: "logs", "workers", "api", "monitor".
C-b "
Split horizontal (new pane below)
C-b %
Split vertical (new pane right)
C-b ←→↑↓
Navigate between panes
C-b z
Zoom/unzoom current pane (fullscreen toggle)
C-b x
Kill current pane
C-b !
Break pane out into its own window
C-b q
Show pane numbers (type number to jump)
C-b o
Rotate through panes
C-b {
Swap pane with previous
C-b }
Swap pane with next
C-b C-←→↑↓
Resize pane (hold Ctrl, tap arrow)
C-b space
Cycle through built-in layouts
C-b Alt-1–5
Jump to specific built-in layout

Built-in Layouts

even-horizontal
Alt-1
even-vert
Alt-2
main-horiz
Alt-3
main-vert
Alt-4
tile
Alt-5
Pane operations from CLIbash
# Split pane from CLI (great for scripts):
tmux split-window -h           # split horizontal
tmux split-window -v -p 30    # split vertical, new pane 30% tall
tmux split-window -h -c ~/src # split, start in directory

# Move pane to another window:
tmux join-pane -s agents:1.0 -t agents:2

# Resize precisely:
tmux resize-pane -t 0 -x 80   # set pane 0 to exactly 80 cols
tmux resize-pane -Z            # toggle zoom (same as C-b z)

# Apply a layout by name:
tmux select-layout tiled
tmux select-layout main-vertical

Copy Mode — The Terminal Pager

Copy Mode = vim/emacs Inside Terminal Press C-b [ to enter copy mode. You're now in a scrollable buffer of your terminal's entire output history. Navigate with vim keys (or emacs if configured). Select text, copy it, paste with C-b ]. This replaces your mouse for every text operation in the terminal.
C-b [
Enter copy/scroll mode
q
Exit copy mode
Space
Start selection (vi mode)
Enter
Copy selection and exit
C-b ]
Paste buffer
g / G
Jump to top / bottom of history
/ text
Search forward
? text
Search backward
n / N
Next / previous search result
C-b =
Choose from paste buffer list
C-b #
List all paste buffers
vi-mode copy config (put in .tmux.conf)bash
# Enable vi keys in copy mode:
set-window-option -g mode-keys vi

# vi-style selection and copy:
bind-key -T copy-mode-vi v   send-keys -X begin-selection
bind-key -T copy-mode-vi y   send-keys -X copy-selection-and-cancel
bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle

# Mouse: click to select, double-click word, drag to select:
set -g mouse on

# System clipboard integration (macOS):
bind-key -T copy-mode-vi y \
  send-keys -X copy-pipe-and-cancel "pbcopy"

# System clipboard integration (Linux/X11):
bind-key -T copy-mode-vi y \
  send-keys -X copy-pipe-and-cancel "xclip -selection clipboard"

# System clipboard integration (Linux/Wayland):
bind-key -T copy-mode-vi y \
  send-keys -X copy-pipe-and-cancel "wl-copy"

# Increase scrollback buffer (default is only 2000 lines!):
set -g history-limit 50000
SCROLLBACK LIMIT IS 2000 BY DEFAULT The default history limit is laughably small for agent workloads. Set history-limit 50000 or even higher. At 50k lines of terminal output per pane, 8 agent panes = 400k lines in RAM — totally fine on modern hardware. Your agent's 3-hour log output needs to be searchable.
C-b ?
Show all keybindings (searchable)
C-b :
Command prompt — type any tmux command
C-b t
Show a clock in current pane
C-b ~
Show tmux message log
C-b r
Reload config (after bind-key r below)
C-b C-z
Suspend the tmux client
C-b i
Display pane info (index, size, command)
C-b D
Choose client to detach (multi-client)
C-b m
Mark current pane (for join-pane later)
C-b M
Clear the marked pane
show-options — inspect current configbash
# From inside tmux command prompt (C-b :)
# or from shell with tmux prefix:

tmux show-options -g              # all global options
tmux show-options -g prefix       # current prefix key
tmux show-window-options -g       # window-specific options
tmux show-environment             # tmux environment variables
tmux display-message '#{session_name}'  # current session name
tmux display-message '#{window_index}'  # current window index
tmux display-message '#{pane_current_command}'  # running command
tmux display-message '#{pane_pid}'     # PID of shell in pane

# List all format variables:
tmux display-message -a | less    # 200+ variables available
tmux ls
SESSION MASTERY
Sessions are your persistent workspaces. Design them with intent. One session per project, per client, per agent cluster. Name them. Script their creation. Never lose context again.

Session Design Patterns

Professional session layoutbash
# Pattern: one session per project or concern
# tmux ls output of a mature workspace:

$ tmux ls
agents:    3 windows (created Mon Apr  5 09:00:26 2026)
devenv:    2 windows (created Mon Apr  5 08:45:01 2026) (attached)
monitor:   1 window  (created Mon Apr  5 08:45:55 2026)
infra:     4 windows (created Sun Apr  4 22:15:00 2026)

# Switch between sessions instantly:
#   C-b s         → interactive tree
#   C-b (         → previous session
#   C-b )         → next session
#   C-b L         → last used session
#   C-b :switch-client -t agents    → by name

# Quick-switch with fzf (add to shell .zshrc/.bashrc):
alias ts='tmux switch-client -t $(tmux ls -F "#{session_name}" | fzf)'
alias ta='tmux attach -t $(tmux ls -F "#{session_name}" | fzf)'

# The "attach or create" pattern — put in a shell alias:
function t() {
  if [ -z "$1" ]; then
    tmux attach 2>/dev/null || tmux new-session -s main
  else
    tmux attach -t "$1" 2>/dev/null || tmux new-session -s "$1"
  fi
}
# Usage: t         → attach to most recent
#        t agents  → attach or create "agents"

Session Persistence Beyond Reboots

tmux dies on system reboot The tmux server is a process — it survives disconnects but not reboots. For true persistence: use tmux-resurrect (saves/restores session layout) + tmux-continuum (auto-saves every N minutes). The Plugins section covers this. This is critical for long-running agent pipelines.
Session environment + variablesbash
# Set environment variable visible to all panes in session:
tmux set-environment -t agents OPENAI_API_KEY sk-proj-...
tmux set-environment -g LOG_LEVEL debug   # global (all sessions)

# Remove a variable:
tmux set-environment -r OPENAI_API_KEY

# Show session environment:
tmux show-environment -t agents

# Access in shell (new panes inherit at creation time):
$ echo $OPENAI_API_KEY   # works in new panes

# Lock a session (password-protect it):
tmux lock-session -t sensitive

# Set a session-specific working directory:
tmux new-session -s agents -c ~/projects/agents
# All new windows/panes in "agents" start in ~/projects/agents
tmux split-window -h && tmux split-window -v
PANE POWER
Panes are where work happens. Splitting, navigating, synchronizing, and monitoring panes is the core operational skill of the tmux power user. This section covers everything including the killer feature: synchronized panes.

Synchronize Panes — The Killer Feature

SYNCHRONIZE-PANES: TYPE ONCE, RUN EVERYWHERE Enable with C-b : then setw synchronize-panes on. Everything you type goes to ALL panes simultaneously. Use case: deploy the same command to 8 agent processes, run tests in parallel across environments, broadcast a stop signal to all running workers. Toggle off when done.
Synchronize panes — broadcast commandsbash
# Toggle from command prompt:
C-b : setw synchronize-panes on
C-b : setw synchronize-panes off

# Add a keybinding to .tmux.conf (toggle with C-b S):
bind S setw synchronize-panes \; \
  display-message "sync: #{?pane_synchronized,ON,OFF}"

# Practical use: stop all 8 LLM agents at once
# 1. Enter sync mode
# 2. Type: Ctrl+C
# 3. All 8 agents receive SIGINT simultaneously

# Send-keys to all panes WITHOUT sync mode (scripted):
for pane in $(tmux list-panes -t agents:workers -F '#{pane_index}'); do
  tmux send-keys -t agents:workers.$pane "git pull && ./restart.sh" Enter
done

Pane Monitoring

Monitor panes for activity or silencebash
# Monitor for activity (alert when any output appears):
C-b : setw monitor-activity on
# Window tab flashes when background pane has new output
# Perfect for: long-running jobs you need to catch

# Monitor for silence (alert when output stops):
C-b : setw monitor-silence 30
# Alert if pane has no output for 30 seconds
# Perfect for: detecting hung/deadlocked agents

# In .tmux.conf — visual + audible alert:
set -g visual-activity on
set -g visual-bell on
set -g bell-action any   # alert on any window bell

# Pipe pane output to a file (live stream to log):
tmux pipe-pane -t agents:0.0 "cat >> /tmp/agent-0.log"
# Stop piping:
tmux pipe-pane -t agents:0.0   # empty command stops it

Advanced Navigation

Smart pane navigation (vim-tmux-navigator)bash
# Problem: C-b arrow is slow (two keystrokes).
# Solution: use Alt+arrow without prefix.
# Add to .tmux.conf:

bind -n M-Left  select-pane -L   # Alt+← select left pane
bind -n M-Right select-pane -R
bind -n M-Up    select-pane -U
bind -n M-Down  select-pane -D

# Even better: vim-tmux-navigator plugin makes
# Ctrl+h/j/k/l work across vim splits AND tmux panes seamlessly.
# (See Plugins section)

# Resize panes without prefix (Shift+Alt+arrow):
bind -n M-S-Left  resize-pane -L 5
bind -n M-S-Right resize-pane -R 5
bind -n M-S-Up    resize-pane -U 5
bind -n M-S-Down  resize-pane -D 5

# Jump to a specific pane by number (instant):
C-b q   → numbers appear, type the number within 1s

# Display pane addresses for scripting:
tmux list-panes -t agents:0 -F "#{pane_index}: #{pane_current_command} PID=#{pane_pid}"
Custom split keybindingsbash
# Replace confusing " and % with more intuitive bindings:
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
# C-b |  → split vertical (visual: | = vertical line)
# C-b -  → split horizontal (visual: - = horizontal line)
# "pane_current_path": new pane opens in same directory!
# This is the #1 most useful pane config change.

# Also propagate directory on new windows:
bind c new-window -c "#{pane_current_path}"
tmux new-session -d -s agents && tmux send-keys...
SCRIPTING & AUTOMATION
The real power of tmux is scriptability. Every tmux action is a CLI command. Shell scripts can create entire workspaces, spawn processes in specific panes, and orchestrate complex multi-process environments with one command.

The send-keys Pattern

send-keys — the universal orchestration primitivebash
# send-keys sends keystrokes to a pane as if you typed them.
# Target format: session:window.pane
# session:window   → pane 0 of that window (default)
# session:window.N → specific pane N

# Basic: run a command in a specific pane
tmux send-keys -t agents:0.0 "python agent.py --task research" Enter

# Send a key without a command:
tmux send-keys -t agents:0.0 "" C-c   # send Ctrl+C to pane
tmux send-keys -t agents:0.0 q Enter  # type q then Enter

# Send to ALL panes in a window:
for pane in $(tmux list-panes -t agents:workers -F '#{pane_index}'); do
  tmux send-keys -t "agents:workers.$pane" "echo pane $pane ready" Enter
done

# Don't execute yet (no Enter) — populate then review:
tmux send-keys -t agents:0.0 "python dangerous_thing.py"
# User sees the command, presses Enter themselves

# Read output from a pane (capture pane content):
tmux capture-pane -t agents:0.0 -p          # last screenful
tmux capture-pane -t agents:0.0 -p -S -3000 # last 3000 lines
tmux capture-pane -t agents:0.0 -p -e       # include escape codes

# Write pane content to file:
tmux capture-pane -t agents:0.0 -pS -10000 > agent-output.txt

Full Workspace Bootstrap Script

~/scripts/agents.sh — one command to rule them allbash
#!/bin/bash
# Spawn a full 8-agent workspace with monitoring in one shot.
# Usage: ./agents.sh [task_description]

SESSION="agents"
TASK="${1:-default-research-task}"

# Kill existing session if running:
tmux kill-session -t "$SESSION" 2>/dev/null

# ── WINDOW 0: ORCHESTRATOR ────────────────────────────
tmux new-session -d -s "$SESSION" -n "orchestrator" -x 220 -y 50
tmux send-keys -t "$SESSION:orchestrator" \
  "cd ~/agents && python orchestrator.py --task '$TASK'" Enter

# ── WINDOW 1: WORKERS (4 agents in a 2x2 grid) ────────
tmux new-window -t "$SESSION" -n "workers"

# Split into 4 panes:
tmux split-window -t "$SESSION:workers" -h         # pane 0 + pane 1
tmux split-window -t "$SESSION:workers.0" -v       # pane 0 + pane 2
tmux split-window -t "$SESSION:workers.1" -v       # pane 1 + pane 3
tmux select-layout -t "$SESSION:workers" tiled

# Start agent in each pane:
for i in 0 1 2 3; do
  tmux send-keys -t "$SESSION:workers.$i" \
    "python agent_worker.py --id $i --task '$TASK'" Enter
done

# ── WINDOW 2: LOGS + MONITOR ──────────────────────────
tmux new-window -t "$SESSION" -n "monitor"
tmux split-window -t "$SESSION:monitor" -h -p 40

# Left pane: live log aggregation
tmux send-keys -t "$SESSION:monitor.0" \
  "tail -f /var/log/agents/*.log | grep -v DEBUG" Enter

# Right pane: system resources
tmux send-keys -t "$SESSION:monitor.1" \
  "htop -d 5" Enter

# ── FOCUS AND ATTACH ──────────────────────────────────
tmux select-window -t "$SESSION:orchestrator"
tmux attach-session -t "$SESSION"

tmuxinator — YAML-Defined Workspaces

~/.config/tmuxinator/agents.ymlyaml
name: agents
root: ~/projects/agents
socket_name: agents      # isolated tmux server socket

windows:
  - orchestrator:
      layout: main-vertical
      panes:
        - python orchestrator.py
        - tail -f logs/orchestrator.log

  - workers:
      layout: tiled
      panes:
        - python worker.py --id 0
        - python worker.py --id 1
        - python worker.py --id 2
        - python worker.py --id 3

  - monitor:
      layout: even-horizontal
      panes:
        - htop
        - tail -f logs/combined.log

  - shell: # empty pane for ad-hoc commands
tmuxinator commandsbash
# Install:
gem install tmuxinator           # Ruby gem
pip install tmuxinator           # or Python port

# Commands:
tmuxinator start agents         # start workspace
tmuxinator stop agents          # stop workspace
tmuxinator edit agents          # edit YAML config
tmuxinator new agents           # create new config
tmuxinator list                 # list all configs
tmuxinator copy agents dev      # copy a config
tmuxinator doctor               # check dependencies

# With arguments (interpolated in YAML):
tmuxinator start agents task="research openai o3"
# In YAML: <%= @args[:task] %>

# Shell alias for instant access:
alias mux='tmuxinator'
alias ma='tmuxinator start agents'
tmux new -s llm-cluster && python spawn_agents.py --n 8
LLM AGENT ORCHESTRATION
In April 2026, running 8 parallel LLM agents from the command line is standard workflow. tmux is the orchestration layer. This section covers patterns for spawning, monitoring, inter-agent communication, and harvesting results — all without a single GUI.

The 8-Agent Workspace

worker-0 [done]
$ python agent.py --id 0
✓ Task complete. Output: result_0.json
worker-1 [running]
$ python agent.py --id 1
Calling gpt-4o... step 7/12
worker-2 [running]
$ python agent.py --id 2
Searching web... 43 results
worker-3 [ERROR]
$ python agent.py --id 3
RateLimitError: 429
worker-4 [active]
$ python agent.py --id 4
Writing report...
worker-5 [running]
$ python agent.py --id 5
Generating embeddings...
worker-6 [done]
$ python agent.py --id 6
✓ Task complete. Output: result_6.json
worker-7 [running]
$ python agent.py --id 7
Processing 1,847 tokens...

↑ 8 agents running in a 4×2 tiled layout. synchronize-panes for broadcast commands. capture-pane to harvest outputs programmatically.

Python Agent Spawner

spawn_agents.py — Python-controlled tmuxpython
import subprocess, json, time, sys
from dataclasses import dataclass

def tmux(*args) -> str:
    """Run any tmux command, return stdout."""
    result = subprocess.run(
        ["tmux"] + list(args),
        capture_output=True, text=True
    )
    return result.stdout.strip()

class AgentCluster:
    def __init__(self, session: str, n_workers: int = 8):
        self.session = session
        self.n = n_workers

    def spawn(self, task: str):
        # Kill existing session
        tmux("kill-session", "-t", self.session)

        # Create session with first worker window
        tmux("new-session", "-d", "-s", self.session,
             "-n", "workers", "-x", "220", "-y", "50")

        # Create N-1 additional panes
        for i in range(1, self.n):
            tmux("split-window", "-t", f"{self.session}:workers",
                 "-h" if i % 2 == 1 else "-v")

        tmux("select-layout", "-t",
             f"{self.session}:workers", "tiled")

        # Start agent in each pane
        for i in range(self.n):
            tmux("send-keys", "-t", f"{self.session}:workers.{i}",
                 f"python agent.py --id {i} --task '{task}'",
                 "Enter")

    def is_done(self, pane: int) -> bool:
        """Check if agent pane has exited."""
        out = tmux("display-message", "-t",
                   f"{self.session}:workers.{pane}",
                   "-p", "#{pane_dead}")
        return out.strip() == "1"

    def get_output(self, pane: int) -> str:
        """Capture pane output for result collection."""
        return tmux("capture-pane", "-t",
                    f"{self.session}:workers.{pane}",
                    "-p", "-S", "-10000")

    def wait_all(self, poll_interval: float = 5.0):
        while True:
            done = [self.is_done(i) for i in range(self.n)]
            if all(done): break
            time.sleep(poll_interval)

    def broadcast(self, cmd: str):
        """Send command to all agents simultaneously."""
        for i in range(self.n):
            tmux("send-keys", "-t",
                 f"{self.session}:workers.{i}", cmd, "Enter")

# Usage:
cluster = AgentCluster("agents", n_workers=8)
cluster.spawn(task="Analyze 2026 AI landscape")
cluster.wait_all()
outputs = [cluster.get_output(i) for i in range(8)]

Agent Status Dashboard Pane

watch_agents.sh — live status panelbash
#!/bin/bash
# A pane that shows live status of all agent panes.
# Run in a separate tmux pane as your control panel.

SESSION="agents"
WINDOW="workers"

while true; do
  clear
  echo "═══ AGENT STATUS $(date '+%H:%M:%S') ═══"
  echo

  for pane in $(tmux list-panes -t "$SESSION:$WINDOW" \
    -F "#{pane_index}"); do

    # Get pane metadata:
    dead=$(tmux display-message -t "$SESSION:$WINDOW.$pane" \
      -p "#{pane_dead}")
    cmd=$(tmux display-message -t "$SESSION:$WINDOW.$pane" \
      -p "#{pane_current_command}")
    pid=$(tmux display-message -t "$SESSION:$WINDOW.$pane" \
      -p "#{pane_pid}")

    # Get last line of output:
    last=$(tmux capture-pane -t "$SESSION:$WINDOW.$pane" -p \
      | grep -v '^$' | tail -1)

    if [ "$dead" = "1" ]; then
      status="[DONE]  "
    else
      status="[RUN] ⚡"
    fi

    printf "pane %d %s %s\n" "$pane" "$status" "${last:0:60}"
  done

  sleep 3
done
capture-pane — The Programmatic Interface tmux capture-pane -t SESSION:WINDOW.PANE -p -S -N captures the last N lines of a pane's output as text. This is how you harvest agent outputs, check for error strings, build status dashboards, and implement polling loops — all from outside the pane, without interrupting the running agent.
cat ~/.tmux.conf
THE .tmux.conf
A good .tmux.conf transforms tmux from a tool you tolerate into a tool you love. This is a production-grade config with every decision explained — copy it, understand it, adapt it.
~/.tmux.conf — Part 1: Core Settingsbash
# ── PREFIX ────────────────────────────────────────────
# Remap prefix from C-b to C-a (like GNU Screen, more ergonomic)
unbind C-b
set-option -g prefix C-a
bind-key C-a send-prefix   # C-a C-a sends literal C-a to terminal

# ── GENERAL ────────────────────────────────────────────
set -g default-terminal "tmux-256color"
set -ag terminal-overrides ",xterm-256color:RGB"  # true color
set -g history-limit 50000           # scrollback lines per pane
set -g base-index 1                  # windows start at 1 (not 0)
setw -g pane-base-index 1           # panes start at 1
set -g renumber-windows on           # auto-renumber on window close
set -g mouse on                      # enable mouse (click, drag, scroll)
set -sg escape-time 0                # zero delay for vim Escape key
set -g focus-events on               # pass focus events to apps (vim autoread)
set -g display-time 3000            # status messages visible 3s
set -g status-interval 5            # refresh status bar every 5s
set -g automatic-rename on          # auto-rename windows to running command
set -g automatic-rename-format "#{pane_current_command}"

# ── SPLITS (intuitive | and -) ─────────────────────────
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
bind c new-window      -c "#{pane_current_path}"
unbind '"'   # remove old horizontal split
unbind %     # remove old vertical split

# ── PANE NAVIGATION (Alt+arrow, no prefix needed) ──────
bind -n M-Left  select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up    select-pane -U
bind -n M-Down  select-pane -D

# ── PANE RESIZE (prefix + Ctrl+arrow) ──────────────────
bind -r C-Left  resize-pane -L 5
bind -r C-Right resize-pane -R 5
bind -r C-Up    resize-pane -U 5
bind -r C-Down  resize-pane -D 5

# ── WINDOW SWITCHING (prefix + Shift+arrow) ────────────
bind -n S-Left  previous-window
bind -n S-Right next-window
~/.tmux.conf — Part 2: Status Bar + Copybash
# ── COPY MODE (vi keys) ────────────────────────────────
setw -g mode-keys vi
bind-key -T copy-mode-vi v   send-keys -X begin-selection
bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle
bind-key -T copy-mode-vi y   send-keys -X copy-selection-and-cancel
bind-key -T copy-mode-vi Y   send-keys -X copy-end-of-line

# System clipboard (pick ONE for your OS):
# macOS:
bind-key -T copy-mode-vi y \
  send-keys -X copy-pipe-and-cancel "pbcopy"
# Linux X11:
# send-keys -X copy-pipe-and-cancel "xclip -selection clipboard"
# Linux Wayland:
# send-keys -X copy-pipe-and-cancel "wl-copy"

# ── UTILITIES ──────────────────────────────────────────
bind r source-file ~/.tmux.conf \; display-message "Config reloaded!"
bind S setw synchronize-panes \; \
  display-message "sync: #{?pane_synchronized,ON,OFF}"
bind K confirm-before -p "Kill session? (y/n)" kill-session
bind-key / copy-mode \; send-keys "?"  # quick backward search

# ── STATUS BAR ─────────────────────────────────────────
set -g status-position bottom
set -g status-style "bg=colour234 fg=colour136"
set -g status-left-length 40
set -g status-right-length 80

set -g status-left \
  "#[bg=colour64 fg=colour232 bold] #{session_name} \
   #[bg=colour234 fg=colour64]"

set -g status-right \
  "#[fg=colour136] %a %d %b #[fg=colour64 bold] %H:%M \
   #[fg=colour232 bg=colour64 bold] #h "

setw -g window-status-format " #I:#W "
setw -g window-status-current-format \
  "#[bg=colour136 fg=colour232 bold] #I:#W "

# ── PANE BORDERS ───────────────────────────────────────
set -g pane-border-style "fg=colour238"
set -g pane-active-border-style "fg=colour64"

# ── PLUGINS (TPM) ──────────────────────────────────────
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
set -g @plugin 'christoomey/vim-tmux-navigator'

set -g @continuum-restore 'on'
set -g @continuum-save-interval '10'

run '~/.tmux/plugins/tpm/tpm'

Status Bar Format Variables

[agents]
0:orchestrator
1:workers*
2:monitor
sync:ON
Sun 05 Apr
14:22
Key format variables for status-left/rightbash
# Session:   #{session_name}  #{session_windows}  #{session_attached}
# Window:    #{window_name}   #{window_index}     #{window_flags}  (flags: *=active, -=last)
# Pane:      #{pane_index}    #{pane_current_command}  #{pane_pid}  #{pane_width}x#{pane_height}
# Host:      #{host}          #{host_short}
# System:    #{load_average}  (via tmux-cpu plugin)
# Time:      #[fg=colour64]%H:%M#[default]  (strftime format)
# Conditional: #{?pane_synchronized,SYNC ON,}  (? = ternary)
~/.tmux/plugins/tpm/bin/install_plugins
PLUGIN ECOSYSTEM
TPM (tmux Plugin Manager) manages plugins with three keys: install, update, uninstall. These are the essential plugins for 2026 developer and agent workflows.
TPM — installation + managementbash
# Install TPM:
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm

# In .tmux.conf — declare plugins BEFORE run line:
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'    # sane defaults
# ... more plugins ...
run '~/.tmux/plugins/tpm/tpm'                  # MUST BE LAST LINE

# Inside tmux after editing .tmux.conf:
prefix + I   → Install plugins (capital I)
prefix + U   → Update all plugins
prefix + M-u → Remove unneeded plugins

# Then reload config:
prefix + r   → source ~/.tmux.conf

Essential Plugins

PluginWhat it does
tmux-sensibleSane defaults every tmux user wants. The baseline. Always install first.
tmux-resurrectSave and restore sessions across reboots. Saves panes, windows, sessions, and running programs. Critical for long agent runs.
tmux-continuumAutomatic periodic save (every N minutes). Works with resurrect. Set-and-forget persistence.
vim-tmux-navigatorCtrl+h/j/k/l navigates between vim splits AND tmux panes seamlessly. Eliminates the C-b prefix for navigation.
tmux-fzfFuzzy search sessions, windows, panes, commands. Type prefix+F and fuzzy-find anything.
tmux-yankCopy to system clipboard from copy-mode. Handles macOS/Linux/WSL automatically.
tmux-cpuCPU/memory stats in status bar: #{cpu_percentage} #{ram_percentage}
tmux-batteryBattery level in status bar. Adds #{battery_percentage}.
tmux-openOpen URLs and files under cursor. Highlight a URL, press O, it opens in browser.
tmux-sessionistEnhanced session management: move pane to new session, merge sessions.

tmux-resurrect Config

resurrect + continuum setupbash
# In .tmux.conf:
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'

# Resurrect: what to save
set -g @resurrect-capture-pane-contents 'on'  # save pane output too
set -g @resurrect-strategy-vim 'session'       # restore vim sessions
set -g @resurrect-strategy-nvim 'session'      # restore neovim sessions
set -g @resurrect-processes 'ssh psql python3 node'  # restore these processes

# Continuum: auto-save interval
set -g @continuum-restore 'on'         # auto-restore on tmux start
set -g @continuum-save-interval '10'  # save every 10 minutes

# Manual save/restore:
prefix + C-s   → save session
prefix + C-r   → restore session

# Where sessions are saved:
ls ~/.tmux/resurrect/    # last.symlink + timestamped saves

# For agent workloads: continuum saves every 10min.
# System reboots: run tmux, prefix + C-r → entire agent
# workspace back exactly as you left it.

Custom Plugin — Agent Monitor in Status Bar

agents in status bar via shell scriptbash
# ~/scripts/tmux-agent-status.sh
# Shows live agent count in tmux status bar
#!/bin/bash

SESSION="agents"
WINDOW="workers"

total=$(tmux list-panes -t "$SESSION:$WINDOW" 2>/dev/null | wc -l)
if [ "$total" = "0" ]; then
  echo "no agents"; exit
fi

running=$(tmux list-panes -t "$SESSION:$WINDOW" \
  -F "#{pane_dead}" 2>/dev/null | grep -c "^0$")
done=$(( total - running ))

echo "⚡${running}/${total} agents"

# In .tmux.conf status-right:
# set -g status-right "#(~/scripts/tmux-agent-status.sh) | %H:%M"
# set -g status-interval 5   ← refresh every 5s
status-right + Shell Scripts = Live Dashboard Any shell script output can appear in your status bar. Poll tmux capture-pane outputs, check process counts, read files — all refreshed on status-interval. Your status bar becomes a live agent dashboard showing running count, error state, and last update time — without an extra monitoring tool.

The Complete Modern Stack — April 2026

Everything running in one tmux workspacebash
# Session: devenv
#   window 0: editor (nvim with vim-tmux-navigator)
#   window 1: shell (zsh + starship prompt)
#   window 2: git (lazygit)

# Session: agents
#   window 0: orchestrator (LLM pipeline controller)
#   window 1: workers     (8 LLM agents tiled 4x2)
#   window 2: monitor     (htop + log tail)
#   window 3: results     (DuckDB querying agent outputs)

# Session: infra
#   window 0: k8s        (k9s — kubernetes TUI)
#   window 1: db         (pgcli / mycli REPL)
#   window 2: kafka      (kcat consumer watching topics)
#   window 3: flink      (Flink SQL REPL)

# All sessions: auto-restored by tmux-continuum on boot.
# Status bar: shows active agents, time, host.
# Navigation: C-a s → jump anywhere in <2 keystrokes.
# Everything is persistent, scriptable, reproducible.
# This is the CLI-first 2026 workspace.

$ tmux ls
devenv:   3 windows (created Mon Apr  5 08:45:01 2026) (attached)
agents:   4 windows (created Mon Apr  5 09:00:26 2026) ⚡6/8 running
infra:    4 windows (created Sun Apr  4 22:15:00 2026)