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>
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
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)
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

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
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

ProblemCauseFix
Colours look wrong in NeovimTrue colour not enabledAdd set-option -sa terminal-overrides ",xterm*:Tc"
Escape key is slow in Neovimescape-time too highSet set-option -sg escape-time 10
Clipboard not workingtmux yank not configuredInstall tmux-yank plugin; ensure xclip/xsel/wl-clipboard is installed
Session won’t attachSocket permissions issueCheck /tmp/tmux-<uid>/ permissions
Pane splits open in home dirNo path inheritanceUse -c "#{pane_current_path}" on split commands
Plugin not loadingTPM run line not lastrun '~/.tmux/plugins/tpm/tpm' must be the final line
Config changes not taking effectStale serverRun tmux source ~/.config/tmux/tmux.conf inside session
Mouse not workingMouse not enabledAdd set -g mouse on
Status bar shows garbageMissing Nerd FontInstall 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