tmux Reference
Core Concepts
Architecture
┌─────────────────────────────────┐
│ Tmux Server │
├─────────────────────────────────┤
│ Session 1 │ Session 2 │
├───────┬───────┼──────┬──────────┤
│Window1│Window2│Window1│Window2 │
├───┬───┼───┬───┼──┬───┼──┬───┬───┤
│P1 │P2 │P1 │P2 │P1│P2 │P1│P2 │P3 │
└───┴───┴───┴───┴──┴───┴──┴───┴───┘
P = Pane, Window = Container, Session = Collection
Session Management
Creating Sessions
tmux new -s dev
tmux new -s background -d
tmux new -s project -n editor
tmux new -s monitoring -c ~/logs 'tail -f app.log'
Window Management
Pane Management
Creating Panes
Ctrl-b %
Ctrl-b "
Ctrl-b :split-window -h -p 30
Ctrl-b :split-window -v -p 25
:split-window -h 'htop'
Pane Operations
Resize panes:
Ctrl-b Ctrl-↑/↓/←/→
Ctrl-b Alt-↑/↓/←/→
Preset layouts:
Ctrl-b Alt-1 # even horizontal
Ctrl-b Alt-2 # even vertical
Ctrl-b Alt-3 # main horizontal
Ctrl-b Alt-4 # main vertical
Ctrl-b Alt-5 # tiled
Ctrl-b z
Ctrl-b !
:join-pane -s 2
:join-pane -t 1
Ctrl-b {
Ctrl-b }
Ctrl-b x
Ctrl-b i
Copy Mode & Scrollback
Configuration (~/.tmux.conf)
Essential Settings
unbind C-b
set -g prefix C-a
bind C-a send-prefix
set -g base-index 1
setw -g pane-base-index 1
set -g mouse on
set -g allow-rename off
set -g history-limit 10000
set -s escape-time 0
setw -g monitor-activity on
set -g visual-activity on
setw -g mode-keys vi
Custom Key Bindings
bind r source-file ~/.tmux.conf \; display "Reloaded!"
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5
bind Tab last-pane
bind C-o rotate-window
bind S setw synchronize-panes
Status Bar Customization
set -g status-style bg=black,fg=white
set -g window-status-current-style bg=white,fg=black,bold
set -g status-left '#[fg=green]#S #[fg=yellow]#I:#P '
set -g status-right '#[fg=yellow]#h #[fg=white]%Y-%m-%d %H:%M'
set -g status-interval 60
set -g status-justify centre
set -g status-left-length 40
set -g status-right-length 60
Advanced Features
Hooks and Commands
Ctrl-b :send-keys -t 2 "ls -la" Enter
:setw synchronize-panes on
:setw synchronize-panes off
set-hook -g after-new-window 'display "New window created!"'
set-hook -g after-kill-pane 'display "Pane killed!"'
Scripting Tmux
#!/bin/bash
# dev-environment.sh
tmux new-session -d -s dev -n editor
tmux split-window -h -t dev:editor
tmux split-window -v -t dev:editor.1
tmux send-keys -t dev:editor.0 'vim' Enter
tmux send-keys -t dev:editor.1 'npm run watch' Enter
tmux send-keys -t dev:editor.2 'git status' Enter
tmux new-window -t dev -n server
tmux send-keys -t dev:server 'npm start' Enter
tmux attach -t dev
Plugins & TPM
Tmux Plugin Manager
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
Add to ~/.tmux.conf:
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'
run '~/.tmux/plugins/tpm/tpm'
Install plugins:
Ctrl-b I
Popular Plugins
Resurrect - Save/restore sessions:
set -g @plugin 'tmux-plugins/tmux-resurrect'
Ctrl-b Ctrl-s # save
Ctrl-b Ctrl-r # restore
Continuum - Automatic save/restore:
set -g @plugin 'tmux-plugins/tmux-continuum'
set -g @continuum-restore 'on'
Yank - Better copy/paste:
set -g @plugin 'tmux-plugins/tmux-yank'
CPU/Memory status:
set -g @plugin 'tmux-plugins/tmux-cpu'
set -g status-right '#{cpu_percentage} #{ram_percentage}'
Better search:
set -g @plugin 'tmux-plugins/tmux-copycat'
Productivity Workflows
Development Setup
#!/bin/bash
# dev-setup.sh
SESSION="dev"
tmux new-session -d -s $SESSION -n code
tmux send-keys -t $SESSION:code "cd ~/project && vim" Enter
tmux new-window -t $SESSION -n test
tmux split-window -h -t $SESSION:test
tmux send-keys -t $SESSION:test.0 "npm test --watch" Enter
tmux send-keys -t $SESSION:test.1 "npm run lint:watch" Enter
tmux new-window -t $SESSION -n server
tmux send-keys -t $SESSION:server "npm run dev" Enter
tmux new-window -t $SESSION -n logs
tmux split-window -v -t $SESSION:logs
tmux send-keys -t $SESSION:logs.0 "tail -f app.log" Enter
tmux send-keys -t $SESSION:logs.1 "tail -f error.log" Enter
tmux new-window -t $SESSION -n git
tmux send-keys -t $SESSION:git "git status" Enter
tmux attach -t $SESSION
Remote Work
ssh server -t "tmux attach || tmux new -s main"
Nested tmux configuration:
bind-key b send-prefix
Monitoring Dashboard
#!/bin/bash
# monitor.sh
tmux new-session -d -s monitor -n system
tmux split-window -h -t monitor:system
tmux split-window -v -t monitor:system.0
tmux split-window -v -t monitor:system.1
tmux send-keys -t monitor:system.0 'htop' Enter
tmux send-keys -t monitor:system.1 'watch -n 1 df -h' Enter
tmux send-keys -t monitor:system.2 'iotop' Enter
tmux send-keys -t monitor:system.3 'watch -n 1 "netstat -tuln"' Enter
tmux new-window -t monitor -n logs
tmux split-window -h -t monitor:logs
tmux send-keys -t monitor:logs.0 'journalctl -f' Enter
tmux send-keys -t monitor:logs.1 'tail -f /var/log/syslog' Enter
tmux attach -t monitor
Troubleshooting
Common Issues
Sessions persist after logout:
tmux kill-server
Can’t create session:
tmux start-server
Colors not working:
export TERM=screen-256color
Or in .tmux.conf:
set -g default-terminal "screen-256color"
Copy/paste with system clipboard:
bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xclip -selection clipboard"
Slow escape time in vim:
set -sg escape-time 0
Mouse scrolling issues:
set -g mouse on
Tips & Tricks
Quick Commands
tmux send-keys -t session:window.pane "command" Enter
tmux capture-pane -t 1 -p > output.txt
tmux list-keys
Ctrl-b ?
tmux list-commands
tmux display -p "#{pane_width}x#{pane_height}"
Ctrl-b Shift-p
Ctrl-b t
Ctrl-b ~
Best Practices
tmux new -s meaningful-name
Additional tips:
-
Use session templates for complex setups
-
Save scrollback for important sessions
-
Use tmux-resurrect for persistence
-
Learn vi-mode for efficient copying
-
Customize status bar for useful info
-
Use pane synchronization for multiple servers
-
Set up different configs for local/remote
Command Reference Card
Learning Path
Real-World Production Scenarios
Kubernetes Multi-Cluster Management
#!/bin/bash
# k8s-monitor.sh
SESSION="k8s-ops"
tmux new-session -d -s $SESSION -n "prod-cluster"
tmux send-keys -t $SESSION:prod-cluster "export KUBECONFIG=~/.kube/prod-config" Enter
tmux split-window -h -t $SESSION:prod-cluster
tmux split-window -v -t $SESSION:prod-cluster.0
tmux split-window -v -t $SESSION:prod-cluster.1
tmux send-keys -t $SESSION:prod-cluster.0 "watch kubectl get pods --all-namespaces" Enter
tmux send-keys -t $SESSION:prod-cluster.1 "kubectl logs -f deployment/api --tail=100" Enter
tmux send-keys -t $SESSION:prod-cluster.2 "kubectl top nodes" Enter
tmux send-keys -t $SESSION:prod-cluster.3 "kubectl get events --watch" Enter
tmux new-window -t $SESSION -n "staging-cluster"
tmux send-keys -t $SESSION:staging-cluster "export KUBECONFIG=~/.kube/staging-config" Enter
tmux split-window -h -t $SESSION:staging-cluster
tmux send-keys -t $SESSION:staging-cluster.0 "kubectl get pods --watch" Enter
tmux send-keys -t $SESSION:staging-cluster.1 "stern ." Enter
tmux new-window -t $SESSION -n "dev-cluster"
tmux send-keys -t $SESSION:dev-cluster "export KUBECONFIG=~/.kube/dev-config" Enter
tmux send-keys -t $SESSION:dev-cluster "kubectl get all" Enter
tmux new-window -t $SESSION -n "helm"
tmux split-window -h -t $SESSION:helm
tmux split-window -v -t $SESSION:helm.0
tmux send-keys -t $SESSION:helm.0 "helm list --all-namespaces" Enter
tmux send-keys -t $SESSION:helm.1 "watch 'helm list | grep -i failed'" Enter
tmux send-keys -t $SESSION:helm.2 "helm repo update" Enter
tmux attach -t $SESSION
Database Operations Center
#!/bin/bash
# db-ops.sh
SESSION="db-ops"
tmux new-session -d -s $SESSION -n "postgres-main"
tmux split-window -h -t $SESSION:postgres-main
tmux split-window -v -t $SESSION:postgres-main.0
tmux split-window -v -t $SESSION:postgres-main.1
tmux send-keys -t $SESSION:postgres-main.0 "psql -U admin -d production -c 'SELECT * FROM pg_stat_activity;'" Enter
tmux send-keys -t $SESSION:postgres-main.1 "watch -n 2 \"psql -c 'SELECT count(*) FROM pg_stat_activity;'\"" Enter
tmux send-keys -t $SESSION:postgres-main.2 "pg_top" Enter
tmux send-keys -t $SESSION:postgres-main.3 "tail -f /var/log/postgresql/postgresql-14-main.log" Enter
tmux new-window -t $SESSION -n "replication"
tmux split-window -h -t $SESSION:replication
tmux send-keys -t $SESSION:replication.0 "watch \"psql -c 'SELECT * FROM pg_stat_replication;'\"" Enter
tmux send-keys -t $SESSION:replication.1 "watch \"psql -c 'SELECT pg_last_wal_receive_lsn() - pg_last_wal_replay_lsn() AS lag;'\"" Enter
tmux new-window -t $SESSION -n "redis"
tmux split-window -h -t $SESSION:redis
tmux split-window -v -t $SESSION:redis.0
tmux send-keys -t $SESSION:redis.0 "redis-cli monitor" Enter
tmux send-keys -t $SESSION:redis.1 "watch redis-cli info stats" Enter
tmux send-keys -t $SESSION:redis.2 "redis-cli --latency" Enter
tmux new-window -t $SESSION -n "mongo"
tmux send-keys -t $SESSION:mongo "mongotop 5" Enter
tmux attach -t $SESSION
CI/CD Pipeline Monitoring
#!/bin/bash
# cicd-monitor.sh
SESSION="cicd"
tmux new-session -d -s $SESSION -n "jenkins"
tmux split-window -h -t $SESSION:jenkins
tmux split-window -v -t $SESSION:jenkins.0
tmux send-keys -t $SESSION:jenkins.0 "jenkins-cli list-jobs" Enter
tmux send-keys -t $SESSION:jenkins.1 "watch 'jenkins-cli queue'" Enter
tmux send-keys -t $SESSION:jenkins.2 "tail -f /var/log/jenkins/jenkins.log | grep ERROR" Enter
tmux new-window -t $SESSION -n "gitlab"
tmux split-window -h -t $SESSION:gitlab
tmux send-keys -t $SESSION:gitlab.0 "glab ci view" Enter
tmux send-keys -t $SESSION:gitlab.1 "watch 'glab pipeline list --per-page 10'" Enter
tmux new-window -t $SESSION -n "argocd"
tmux split-window -h -t $SESSION:argocd
tmux split-window -v -t $SESSION:argocd.0
tmux send-keys -t $SESSION:argocd.0 "argocd app list" Enter
tmux send-keys -t $SESSION:argocd.1 "watch 'argocd app list | grep -v Synced'" Enter
tmux send-keys -t $SESSION:argocd.2 "argocd app get production --refresh" Enter
tmux new-window -t $SESSION -n "docker"
tmux send-keys -t $SESSION:docker "watch 'docker ps --format \"table {{.Names}}\\t{{.Status}}\\t{{.Ports}}\"'" Enter
tmux attach -t $SESSION
Incident Response Command Center
#!/bin/bash
# incident-response.sh
INCIDENT_ID="INC-$(date +%Y%m%d-%H%M)"
SESSION="incident-$INCIDENT_ID"
tmux new-session -d -s $SESSION -n "logs"
tmux split-window -h -t $SESSION:logs
tmux split-window -v -t $SESSION:logs.0
tmux split-window -v -t $SESSION:logs.1
tmux send-keys -t $SESSION:logs.0 "tail -f /var/log/app/error.log | grep -E 'ERROR|CRITICAL'" Enter
tmux send-keys -t $SESSION:logs.1 "journalctl -f -u api-service" Enter
tmux send-keys -t $SESSION:logs.2 "tail -f /var/log/nginx/error.log" Enter
tmux send-keys -t $SESSION:logs.3 "gcloud logging tail \"severity>=ERROR\" --format=json | jq '.'" Enter
tmux new-window -t $SESSION -n "metrics"
tmux split-window -h -t $SESSION:metrics
tmux split-window -v -t $SESSION:metrics.0
tmux send-keys -t $SESSION:metrics.0 "watch 'curl -s localhost:9090/metrics | grep -E \"error_rate|latency_99\"'" Enter
tmux send-keys -t $SESSION:metrics.1 "htop" Enter
tmux send-keys -t $SESSION:metrics.2 "iotop -o" Enter
tmux new-window -t $SESSION -n "network"
tmux split-window -h -t $SESSION:network
tmux send-keys -t $SESSION:network.0 "sudo tcpdump -i any -n 'port 443 or port 80'" Enter
tmux send-keys -t $SESSION:network.1 "watch 'ss -tulpn | grep ESTAB | wc -l'" Enter
tmux new-window -t $SESSION -n "command"
tmux send-keys -t $SESSION:command "echo '=== INCIDENT $INCIDENT_ID ===' > incident.log" Enter
tmux send-keys -t $SESSION:command "echo 'Started: $(date)' >> incident.log" Enter
tmux send-keys -t $SESSION:command "vim incident.log" Enter
tmux new-window -t $SESSION -n "comms"
tmux split-window -h -t $SESSION:comms
tmux send-keys -t $SESSION:comms.0 "slack-term" Enter
tmux send-keys -t $SESSION:comms.1 "echo 'Incident $INCIDENT_ID in progress' | notify-team" Enter
tmux attach -t $SESSION
Performance Testing Dashboard
#!/bin/bash
# perf-test.sh
SESSION="perftest"
TEST_ID="PERF-$(date +%Y%m%d-%H%M)"
tmux new-session -d -s $SESSION -n "jmeter"
tmux split-window -h -t $SESSION:jmeter
tmux split-window -v -t $SESSION:jmeter.0
tmux send-keys -t $SESSION:jmeter.0 "jmeter -n -t load_test.jmx -l results_$TEST_ID.jtl" Enter
tmux send-keys -t $SESSION:jmeter.1 "tail -f jmeter.log | grep -E 'ERROR|WARN'" Enter
tmux send-keys -t $SESSION:jmeter.2 "watch 'wc -l results_$TEST_ID.jtl'" Enter
tmux new-window -t $SESSION -n "app-metrics"
tmux split-window -h -t $SESSION:app-metrics
tmux split-window -v -t $SESSION:app-metrics.0
tmux split-window -v -t $SESSION:app-metrics.1
tmux send-keys -t $SESSION:app-metrics.0 "watch 'curl -s localhost:8080/metrics | grep http_req'" Enter
tmux send-keys -t $SESSION:app-metrics.1 "docker stats" Enter
tmux send-keys -t $SESSION:app-metrics.2 "watch 'ps aux | sort -nrk 3,3 | head -10'" Enter
tmux send-keys -t $SESSION:app-metrics.3 "watch 'ps aux | sort -nrk 4,4 | head -10'" Enter
tmux new-window -t $SESSION -n "db-perf"
tmux split-window -h -t $SESSION:db-perf
tmux send-keys -t $SESSION:db-perf.0 "mysqltuner" Enter
tmux send-keys -t $SESSION:db-perf.1 "watch 'mysql -e \"SHOW PROCESSLIST;\"'" Enter
tmux new-window -t $SESSION -n "network"
tmux split-window -h -t $SESSION:network
tmux send-keys -t $SESSION:network.0 "nload" Enter
tmux send-keys -t $SESSION:network.1 "iftop" Enter
tmux new-window -t $SESSION -n "analysis"
tmux send-keys -t $SESSION:analysis "watch 'tail -20 results_$TEST_ID.jtl | awk -F, \"{print \\\$2,\\\$14}\"'" Enter
tmux attach -t $SESSION
Advanced Tmux Hacks
Auto-Resurrection on System Boot
# /etc/systemd/system/tmux-resurrect@.service
[Unit]
Description=Tmux resurrect for user %i
After=graphical-session.target
[Service]
Type=oneshot
ExecStart=/usr/bin/tmux new-session -d -s saved
ExecStartPost=/bin/bash -c "sleep 2 && tmux run-shell ~/.tmux/plugins/tmux-resurrect/scripts/restore.sh"
User=%i
[Install]
WantedBy=default.target
Enable service:
sudo systemctl enable tmux-resurrect@username
Dynamic Window Creation from Config
#!/bin/bash
# tmux-workspace.sh
# workspace.yaml:
# windows:
# - name: code
# root: ~/project
# panes:
# - vim
# - npm run watch
# - name: git
# panes:
# - git status
python3 -c "
import yaml, os, sys
with open('workspace.yaml') as f:
config = yaml.safe_load(f)
session = config.get('name', 'workspace')
os.system(f'tmux new-session -d -s {session}')
for i, window in enumerate(config['windows']):
name = window['name']
if i == 0:
os.system(f'tmux rename-window -t {session}:0 {name}')
else:
os.system(f'tmux new-window -t {session} -n {name}')
root = window.get('root', '~')
os.system(f'tmux send-keys -t {session}:{name} \"cd {root}\" Enter')
for j, cmd in enumerate(window.get('panes', [])):
if j > 0:
os.system(f'tmux split-window -t {session}:{name}')
if cmd:
os.system(f'tmux send-keys -t {session}:{name}.{j} \"{cmd}\" Enter')
os.system(f'tmux attach -t {session}')
"
Tmux + FZF Integration
# Add to .bashrc/.zshrc
tmux-switch() {
local session
session=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | fzf --height 40%)
[ -n "$session" ] && tmux switch-client -t "$session"
}
tmux-switch-window() {
local window
window=$(tmux list-windows -F "#I: #W" | fzf --height 40%)
[ -n "$window" ] && tmux select-window -t "${window%%:*}"
}
Bind to keys in .tmux.conf:
bind-key C-s run-shell "tmux list-sessions -F '#{session_name}' | fzf-tmux | xargs tmux switch-client -t"
bind-key C-w run-shell "tmux list-windows -F '#I: #W' | fzf-tmux | cut -d: -f1 | xargs tmux select-window -t"
SSH Multi-Server Management
#!/bin/bash
# multi-ssh.sh
SERVERS=("web01" "web02" "web03" "db01" "db02")
SESSION="servers"
tmux new-session -d -s $SESSION
for i in "${!SERVERS[@]}"; do
if [ $i -eq 0 ]; then
tmux rename-window -t $SESSION:0 "${SERVERS[$i]}"
else
tmux new-window -t $SESSION -n "${SERVERS[$i]}"
fi
tmux send-keys -t $SESSION:"${SERVERS[$i]}" "ssh ${SERVERS[$i]}" Enter
done
tmux setw -t $SESSION synchronize-panes on
tmux attach -t $SESSION