Tmux
tmux is a terminal multiplexer. It lets you run multiple terminal sessions – windows, split panes, background jobs – inside a single shell. More importantly, it decouples your terminal session from the process that spawned it. Drop an SSH connection, lose power to your laptop, close the tab by accident: the session on the remote machine keeps running. You reconnect and find everything exactly where you left it.
Think of it like a mycelium network. The visible terminals are just fruiting bodies. The actual organism – the tmux server – lives below the surface, persisting without your direct presence, passing state between every point of contact.
tmux runs a server in the background. Clients (your terminal emulators) connect to that server. Sessions are containers the server manages. You can have as many sessions as you like, attach and detach from them freely, share them across multiple clients, or pipe output from one pane into another. All of this without spawning a new process per terminal window.
1. Installation
Alpine Linux
apk add tmux
Arch Linux
sudo pacman -S tmux
Ubuntu / Debian
sudo apt update && sudo apt install tmux
Rocky Linux / RHEL / Fedora
sudo dnf install tmux
macOS
brew install tmux
Verify the install:
tmux -V
# Expected: tmux 3.x
2. Core Concepts
The Server-Client Model
When you run tmux, it starts a server process if one isn’t already running, then connects a client to it. The server manages all sessions. The client is what you interact with – your terminal window. Detaching a client doesn’t kill the server or any session. Everything keeps running.
Sessions, Windows, Panes
These three concepts form the tmux hierarchy:
- Session – the top-level container. A tmux server can hold many sessions. Each session is independent. Named sessions let you organise work by project or context.
- Window – what most applications call a “tab”. Each session holds one or more windows. Only one window is visible at a time per session. Each window runs its own shell.
- Pane – what most applications call a “split”. A window can be divided into multiple panes. All panes in a window are visible simultaneously. Each pane runs its own process.
The naming trips everyone up once: window ≠ what your OS calls a window. Window = tab. Pane = split. After a day, it stops mattering.
The Prefix Key
Every tmux keybinding begins with the prefix key. The default is Ctrl+B. Press it, release it, then press the command key. Two-stroke chord, not simultaneous.
Ctrl+B → release → command key
Do not remap this. The default is documented everywhere, works on every fresh install, and is already in muscle memory for anyone who uses tmux seriously. A custom prefix only works on machines you control. SSH into someone else’s box and you are suddenly recalling the default under pressure. The default is Ctrl+B. Learn it once.
3. Sessions
Sessions are persistent. They survive detach, disconnection, and client death. They die only when explicitly killed or when the server shuts down.
Starting Sessions
Start an unnamed session:
tmux
Start a named session:
tmux new -s <name>
tmux new-session -s <name>
Start a session with a specific window name:
tmux new -s <session-name> -n <window-name>
Start a session in the background (detached):
tmux new -s <name> -d
Start a session running a specific command:
tmux new -s monitor -d 'htop'
Attaching and Detaching
Detach from current session (session keeps running):
prefix + d
Detach all other clients from a session:
prefix + D
List all running sessions:
tmux ls
tmux list-sessions
Attach to the most recent session:
tmux attach
tmux a
Attach to a specific session by name:
tmux attach -t <name>
tmux a -t <name>
Attach and detach any other clients currently on the same session:
tmux attach -t <name> -d
Switch between sessions inside tmux:
prefix + s # interactive session tree
prefix + $ # rename current session
prefix + ( # switch to previous session
prefix + ) # switch to next session
prefix + L # switch to last (previously used) session
Killing Sessions
Kill a specific session:
tmux kill-session -t <name>
Kill all sessions except the current one:
tmux kill-session -a
Kill the tmux server entirely (terminates all sessions):
tmux kill-server
Listing and Inspecting Sessions
tmux ls # list all sessions
tmux list-sessions -F '#{session_name} #{session_windows} windows'
4. Windows
Windows are the tab layer. Each session has at least one window. Windows are numbered from 0 by default (configurable to 1 – recommended).
Creating and Closing Windows
Create a new window in the current session:
prefix + c
Create a new window with a specific name:
tmux new-window -n <name>
Close the current window (prompts for confirmation):
prefix + &
Close without prompt (from command line):
tmux kill-window -t <session>:<window-number>
Navigating Windows
prefix + n # next window
prefix + p # previous window
prefix + l # last (previously active) window
prefix + 0-9 # jump to window by number
prefix + w # interactive window list (whole session tree)
prefix + ' # prompt for window number to jump to
prefix + f # find window by name/content
Managing Windows
Rename the current window:
prefix + ,
Rename from command line:
tmux rename-window -t <index> <new-name>
Move a window to a different index:
prefix + . # prompt for new index
Move a window from command line:
tmux move-window -s <src-session>:<src-window> -t <dst-session>:<dst-window>
Swap two windows:
tmux swap-window -s <index1> -t <index2>
Link a window from another session (shared window, same underlying shell):
tmux link-window -s <src-session>:<window> -t <dst-session>
List all windows in a session:
tmux list-windows -t <session-name>
5. Panes
Panes are the split layer. A single window can hold many panes. Each pane runs its own process. All panes in a window are visible at the same time.
Splitting Panes
Split horizontally (creates top/bottom panes):
prefix + "
Split vertically (creates left/right panes):
prefix + %
Split from command line:
tmux split-window -h # horizontal split (left/right)
tmux split-window -v # vertical split (top/bottom)
tmux split-window -h -p 30 # open new pane at 30% width
tmux split-window -c '#{pane_current_path}' # split, inherit current directory
Navigating Between Panes
prefix + arrow key # move to pane in direction
prefix + o # cycle through panes
prefix + ; # toggle to last active pane
prefix + q # show pane numbers briefly (press number to jump)
Navigate panes with vim-style keys (requires config – see §12):
prefix + h / j / k / l # left / down / up / right
Resizing Panes
prefix + Ctrl + arrow key # resize in direction (hold to repeat)
prefix + Alt + arrow key # resize in larger increments
prefix + z # toggle zoom (fullscreen for current pane)
Resize from command line:
tmux resize-pane -D 5 # down 5 cells
tmux resize-pane -U 5 # up 5 cells
tmux resize-pane -L 10 # left 10 cells
tmux resize-pane -R 10 # right 10 cells
tmux resize-pane -x 80 # set exact width
tmux resize-pane -y 24 # set exact height
Closing and Managing Panes
Close the current pane (prompts for confirmation):
prefix + x
Close without prompt:
exit
Convert a pane into its own window:
prefix + !
Join a window into the current window as a pane:
tmux join-pane -s <session>:<window> -t <current-window>
Swap two panes:
prefix + { # swap with previous pane
prefix + } # swap with next pane
Swap from command line:
tmux swap-pane -s <pane1> -t <pane2>
Rotate panes within the window:
prefix + Ctrl + O # rotate all panes
prefix + Alt + O # rotate in reverse
Pane Layouts
tmux has five built-in pane layouts, cyclable with a single key:
prefix + Space # cycle through: even-horizontal, even-vertical,
# main-horizontal, main-vertical, tiled
Apply a layout directly:
tmux select-layout even-horizontal
tmux select-layout even-vertical
tmux select-layout main-horizontal
tmux select-layout main-vertical
tmux select-layout tiled
6. Copy Mode
Copy mode lets you scroll back through terminal output, search it, and copy text – without leaving tmux.
Enter copy mode:
prefix + [
Exit copy mode:
q (or Escape)
Navigation in Copy Mode
Arrow keys # move cursor
Ctrl + F / B # page forward / back
g # go to top
G # go to bottom
/ # search forward
? # search backward
n / N # next / previous search result
Selecting and Copying Text (vi mode – recommended)
Enable vi copy mode in config (see §12):
set-window-option -g mode-keys vi
In copy mode with vi keys:
Space # begin selection
v # begin selection (vi visual mode)
V # select entire line
Ctrl + V # rectangle selection
y # yank (copy) selection
Enter # copy and exit copy mode
Paste copied text:
prefix + ]
Show paste buffers:
prefix + = # list all paste buffers, select to paste
Piping and Saving Buffers
Save the tmux paste buffer to a file:
tmux save-buffer buffer.txt
Pipe pane content directly:
tmux capture-pane -pS -3000 > pane_output.txt # last 3000 lines
Delete a paste buffer:
tmux delete-buffer
tmux delete-buffer -b <buffer-name>
7. Command Mode and the Command Prompt
You can run any tmux command from within a session using the command prompt.
Open the command prompt:
prefix + :
Useful things to run from the prompt:
:source ~/.config/tmux/tmux.conf # reload config
:split-window -h # split horizontally
:new-window -n logs # open new window named logs
:kill-session -t old-project # kill session by name
:set -g mouse on # toggle an option live
:display-message "hello" # debug/display a string
:list-keys # list all keybindings
:list-commands # list all tmux commands
8. Targeting: Sessions, Windows, and Panes
Many tmux commands accept a -t target to specify exactly what to act on.
Target syntax:
<session>:<window>.<pane>
Examples:
tmux send-keys -t work:1.0 "ls -la" Enter # send command to pane 0, window 1, session "work"
tmux select-pane -t work:2.1 # focus pane 1 in window 2 of session "work"
tmux kill-pane -t work:1.2 # kill pane 2 of window 1
Shorthand targets:
tmux send-keys -t work "htop" Enter # targets active pane in session "work"
tmux send-keys -t :2 "ls" Enter # targets window 2 in current session
9. send-keys and Scripting
send-keys lets you send keystrokes to any pane programmatically – essential for scripting tmux-based automation.
tmux send-keys -t <target> "command" Enter
Examples:
# Start a dev environment in a new session automatically
tmux new-session -d -s dev
tmux rename-window -t dev:1 editor
tmux send-keys -t dev:1 "nvim ." Enter
tmux new-window -t dev -n server
tmux send-keys -t dev:2 "python -m http.server 8000" Enter
tmux new-window -t dev -n logs
tmux send-keys -t dev:3 "tail -f /var/log/syslog" Enter
tmux attach -t dev
Send keys without Enter (just type characters):
tmux send-keys -t <target> "partial text"
Send a literal Ctrl sequence:
tmux send-keys -t <target> "C-c" # send Ctrl+C
tmux send-keys -t <target> "C-l" # send Ctrl+L (clear)
10. Hooks
Hooks let you run commands automatically when tmux events fire.
# Run a command after a new session is created
tmux set-hook after-new-session "run-shell 'notify-send tmux session started'"
# Automatically rename windows based on running command
set-option -g automatic-rename on
set-option -g automatic-rename-format '#{b:pane_current_command}'
# Log all pane output to a file when a window is created
tmux set-hook after-new-window "pipe-pane -o 'cat >> /tmp/tmux-#{session_name}-#{window_index}.log'"
List available hooks:
tmux show-hooks -g
11. Plugins and TPM
TPM (Tmux Plugin Manager) is the standard way to install and manage tmux plugins.
Installing TPM
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
Add to the bottom of tmux.conf (must be last):
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
run '~/.tmux/plugins/tpm/tpm'
Inside a tmux session:
prefix + I # install plugins
prefix + U # update plugins
prefix + Alt + U # uninstall plugins not in plugin list
Recommended Plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible' # sane defaults
set -g @plugin 'tmux-plugins/tmux-resurrect' # save/restore sessions across reboots
set -g @plugin 'tmux-plugins/tmux-continuum' # automatic session saving
set -g @plugin 'tmux-plugins/tmux-yank' # clipboard integration
set -g @plugin 'tmux-plugins/tmux-open' # open files/URLs from copy mode
set -g @plugin 'tmux-plugins/tmux-pain-control' # consistent pane keybindings
set -g @plugin 'catppuccin/tmux' # catppuccin theme
tmux-resurrect
Save and restore the full session layout – windows, panes, working directories, and running commands – across reboots.
prefix + Ctrl + S # save session
prefix + Ctrl + R # restore session
tmux-continuum
Automatic session saving (runs resurrect save on a timer):
set -g @continuum-restore 'on' # auto-restore on tmux server start
set -g @continuum-save-interval '15' # save every 15 minutes
12. Configuration Reference
tmux configuration lives at ~/.config/tmux/tmux.conf or ~/.tmux.conf. The former is preferred.
Recommended modular structure:
~/.config/tmux/
├── tmux.conf # entry point, sources all others
└── conf/
├── opts.conf # behaviour options
├── keys.conf # custom keybindings
└── skin.conf # theme and status bar
tmux.conf (entry point)
source-file ~/.config/tmux/conf/opts.conf
source-file ~/.config/tmux/conf/keys.conf
source-file ~/.config/tmux/conf/skin.conf
# Plugins (must be last)
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 'tmux-plugins/tmux-yank'
set -g @plugin 'catppuccin/tmux'
run '~/.tmux/plugins/tpm/tpm'
opts.conf
# True colour passthrough
set-option -sa terminal-overrides ",xterm*:Tc"
set-option -g default-terminal "tmux-256color"
# Mouse support
set -g mouse on
# Start windows and panes at 1, not 0
set -g base-index 1
set -g pane-base-index 1
set-window-option -g pane-base-index 1
set-option -g renumber-windows on
# Escape time (critical for Neovim)
set-option -sg escape-time 10
# Increase scrollback buffer
set-option -g history-limit 50000
# Status bar at top
set-option -g status-position top
# Aggressive resize (resize to smallest *active* client, not smallest connected)
set-window-option -g aggressive-resize on
# Focus events (needed for Neovim autoread)
set-option -g focus-events on
# Activity monitoring
set-window-option -g monitor-activity on
set -g visual-activity off
# Vi mode for copy mode
set-window-option -g mode-keys vi
# Word separators (useful for double-click word selection)
set -g word-separators ' @"=()[]'
# Automatic window rename
set-window-option -g automatic-rename on
set-option -g automatic-rename-format '#{b:pane_current_command}'
# Status refresh interval
set -g status-interval 5
keys.conf
# Reload config
bind r source-file ~/.config/tmux/tmux.conf \; display-message "Config reloaded"
# Vi-style pane navigation
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
# Split panes keeping current directory
bind '"' split-window -v -c "#{pane_current_path}"
bind '%' split-window -h -c "#{pane_current_path}"
bind c new-window -c "#{pane_current_path}"
# Vi-style copy mode
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
# Easier resize
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
# Move windows
bind -r '<' swap-window -d -t -1
bind -r '>' swap-window -d -t +1
# Kill without confirmation
bind X kill-pane
bind Q kill-window
skin.conf (Catppuccin)
set -g @catppuccin_flavour 'mocha'
set -g @catppuccin_window_left_separator ""
set -g @catppuccin_window_right_separator " "
set -g @catppuccin_window_middle_separator " █"
set -g @catppuccin_window_number_position "right"
set -g @catppuccin_window_default_fill "number"
set -g @catppuccin_window_default_text "#W"
set -g @catppuccin_window_current_fill "number"
set -g @catppuccin_window_current_text "#W"
set -g @catppuccin_status_modules_right "directory session"
set -g @catppuccin_status_left_separator " "
set -g @catppuccin_status_right_separator ""
set -g @catppuccin_status_fill "icon"
set -g @catppuccin_status_connect_separator "no"
set -g @catppuccin_directory_text "#{pane_current_path}"
Reload the config from inside tmux:
tmux source ~/.config/tmux/tmux.conf
# or from within a session:
# prefix + : source ~/.config/tmux/tmux.conf
13. Status Bar and Formats
tmux uses a format string system for status bar content. Variables are referenced with #{}.
Useful Format Variables
#{session_name} current session name
#{window_index} window number
#{window_name} window name
#{pane_index} pane number
#{pane_current_path} current directory in pane
#{pane_current_command} command running in pane
#{pane_pid} PID of process in pane
#{host} hostname
#{host_short} hostname without domain
#{b:pane_current_path} basename of current path
#{client_width} terminal width
#{client_height} terminal height
Manual Status Bar Configuration (without Catppuccin)
set -g status-left-length 30
set -g status-right-length 80
set -g status-left '#[fg=colour232,bg=colour154,bold] #S #[bg=default,fg=colour154]'
set -g status-right '#[fg=colour154]#[fg=colour232,bg=colour154] %H:%M %d %b '
set -g status-style 'bg=colour235 fg=colour255'
set -g window-status-current-style 'fg=colour154 bold'
set -g window-status-current-format ' #I:#W '
set -g window-status-format ' #I:#W '
Display a message in the status bar:
tmux display-message "Custom message"
tmux display-message "#{pane_current_path}"
14. Sharing Sessions
Multiple clients can connect to the same tmux session simultaneously – useful for pair programming or live demos.
Same Machine
# Person A creates a session
tmux new -s shared
# Person B attaches to the same session (both see and can control the same terminal)
tmux attach -t shared
Over SSH (same user)
# On the remote machine, user starts a session
tmux new -s collab
# From a different SSH connection, same user attaches
tmux attach -t collab
Grouped Sessions (independent focus, shared windows)
Two clients see different windows of the same session – each can navigate independently but share the window pool.
tmux new -s base
tmux new-session -t base -s view2 # new session linked to "base"
15. Environment Variables
tmux maintains its own environment. Variables set in .bashrc may not propagate into new panes if tmux was started before sourcing them.
Show the tmux environment:
tmux show-environment
tmux show-environment -g # global environment
Set a variable in the tmux environment:
tmux set-environment EDITOR nvim
tmux set-environment -g PROJECT_ROOT /home/dil/projects
Remove a variable:
tmux set-environment -r EDITOR
Update the shell environment from tmux (run inside a pane):
eval "$(tmux show-environment -s)"
16. Logging and Monitoring
Log all output from a pane to a file:
# From command line
tmux pipe-pane -t <target> 'cat >> /tmp/tmux-log.txt'
# From inside tmux (command prompt):
# prefix + :
pipe-pane -o 'cat >> ~/tmux-pane.log'
# Stop logging
pipe-pane
Capture pane output to stdout:
tmux capture-pane -pt <target> # current visible content
tmux capture-pane -pt <target> -S -3000 # last 3000 lines of scrollback
Monitor a window for activity:
tmux set-window-option monitor-activity on
Monitor for silence (no activity for N seconds):
tmux set-window-option monitor-silence 30
17. Automation Scripts
Dev Environment Bootstrap
#!/bin/bash
# bootstrap-dev.sh -- launch a full dev layout in one command
SESSION="dev"
tmux kill-session -t $SESSION 2>/dev/null
tmux new-session -d -s $SESSION -n editor -x 220 -y 50
tmux send-keys -t $SESSION:1 "cd ~/projects && nvim ." Enter
tmux new-window -t $SESSION -n terminal
tmux send-keys -t $SESSION:2 "cd ~/projects" Enter
tmux new-window -t $SESSION -n monitor
tmux split-window -h -t $SESSION:3
tmux send-keys -t $SESSION:3.0 "btop" Enter
tmux send-keys -t $SESSION:3.1 "journalctl -f" Enter
tmux select-window -t $SESSION:1
tmux attach -t $SESSION
Incus Container Monitoring Layout
#!/bin/bash
SESSION="incus-ops"
tmux new-session -d -s $SESSION
# Pane 0: container list
tmux send-keys -t $SESSION "watch -n 2 'incus list'" Enter
# Pane 1: logs
tmux split-window -v -t $SESSION
tmux send-keys -t $SESSION "journalctl -u incus -f" Enter
# Pane 2: resource monitor
tmux split-window -h -t $SESSION
tmux send-keys -t $SESSION "btop" Enter
tmux select-pane -t $SESSION:1.0
tmux attach -t $SESSION
18. Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| Colours look wrong in Neovim | True colour not enabled | Add set-option -sa terminal-overrides ",xterm*:Tc" |
| Escape key is slow in Neovim | escape-time too high | Set set-option -sg escape-time 10 |
| Clipboard not working | tmux yank not configured | Install tmux-yank plugin; ensure xclip/xsel/wl-clipboard is installed |
| Session won’t attach | Socket permissions issue | Check /tmp/tmux-<uid>/ permissions |
| Pane splits open in home dir | No path inheritance | Use -c "#{pane_current_path}" on split commands |
| Plugin not loading | TPM run line not last | run '~/.tmux/plugins/tpm/tpm' must be the final line |
| Config changes not taking effect | Stale server | Run tmux source ~/.config/tmux/tmux.conf inside session |
| Mouse not working | Mouse not enabled | Add set -g mouse on |
| Status bar shows garbage | Missing Nerd Font | Install a Nerd Font in your terminal emulator |
Check if tmux server is running:
tmux info
List all options currently set:
tmux show-options -g # global options
tmux show-window-options -g # global window options
19. Quick Reference
Sessions
tmux new -s <name> # new named session
tmux ls # list sessions
tmux a -t <name> # attach to session
tmux kill-session -t <name> # kill session
tmux kill-server # kill everything
Inside tmux (prefix = Ctrl+B)
prefix + d detach
prefix + s session list
prefix + $ rename session
prefix + c new window
prefix + , rename window
prefix + n / p next / previous window
prefix + 0-9 jump to window
prefix + w window/session tree
prefix + " split horizontal
prefix + % split vertical
prefix + arrow move between panes
prefix + z zoom pane
prefix + x close pane
prefix + ! pane → window
prefix + [ enter copy mode
prefix + ] paste
prefix + r reload config (if bound)
prefix + : command prompt
prefix + ? list all keybindings
prefix + t show clock
prefix + ~ show previous messages
Copy Mode (vi)
Space / v begin selection
y yank
q / Escape exit
/ ? search forward / backward
g / G top / bottom