Tmux

From Leo's Notes
Last edited on 6 November 2023, at 20:26.

tmux is a terminal multiplexer similar to Screen but with some cool features such as split panes.

Quick Usage

When starting tmux, you create a new session. Each session can have multiple windows (numbered 0..N) and acts like tabs in a web browser. Each window can split into multiple panes and organized in a grid.

Tmux Command Usage:

Command Description
tmux ls Lists all tmux sessions
tmux new -s session-name Creates a new session named session-name
tmux a|attach N Attaches to an existing session
tmux a|attach -t session-name Attaches to an existing session by name
tmux a|attach -dt session-name The -d option detaches any other attached sessions.
tmux kill-session -t session-name Kills a session by name
tmux kill N Kills a session by ID

Tmux Commands

All commands to tmux are prefixed with a key Ctrl-b (as opposed to Ctrl-a in screen). The default key bindings are quite unintuitive but can be changed to something a bit more usable. The tables below will show both the default and modified key bindings.

General commands:

Default Command Modified Command Description
d Detach from this session
$ Rename current session
s Lists all sessions
t Shows a clock in the current pane
? Shows key bindings
: Enters the tmux command prompt, where you can enter commands. Eg. kill-session to quit the current tmux session.
[ / Enter copy mode. You can use Vim key bindings if you set the mode-keys in the settings (see below). Exit copy mode by pressing Enter.
S Synchronize the input to all panes in the current window. Manually done with :setw synchronize-panes.
w Lists windows (it's also displayed at bottom)
` Sends '~.' to stop remote SSH in current pane.

Windows (tab) commands:

Default Command Modified Command Description
c n Creates a new window
n , Go to next window
p . Go to previous window
& X Kills the current window
, r Rename the current window
< > Reorder windows

Panes (split) commands. Enable mouse (see below) to make switching and resizing panes easy.

Default Command Modified Command Description
% b (bisect) Horizontal split (% is like 0/0, splits left/right)
" v Vertical split
x Close pane
! Close all other panes
o JKHL Swap panes (modified bindings swap in the desired direction)
q Show pane numbers
z 'Zooms' or maximizes the selected pane
jkhl Selects pane in direction. (Or use mouse)

Configuration

Configuration can be set in ~/.tmux.conf file. Some useful settings are given below.

# Enable mouse, useful for selecting or resizing panes
set-option -g mouse on

# Enable Vim key bindings in copy-mode
setw -g mode-keys vi

set -g default-terminal screen-256color
set -g history-limit 20000
set -g base-index 1
set-option -g renumber-windows on
set -s escape-time 0
set -ga terminal-overrides ',xterm*:smcup@:rmcup@'

# Pane names on the borders
set -g pane-border-status top
set -g pane-border-format "#P- #{pane_current_command}: #{pane_title}"

# Close ssh connection with .~ as Mod-`
bind ` send-keys "C-m" "~."

# make scrolling with wheels work
bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"
bind -n WheelDownPane select-pane -t= \; send-keys -M

# Reload configuration with Mod-R
bind R source-file ~/.tmux.conf \; display-message "  Config reloaded..".

# Synchronize inputs to all panes with Mod-S
bind S setw synchronize-panes \; display-message " Synchronize panes".

# Better key bindings for common actions
# These are listed as the modified key bindings in the cheat sheet at https://leo.leung.xyz/wiki/Tmux
bind n new-window -c "#{pane_current_path}"
bind . select-window -n
bind , select-window -p
bind < swap-window -t -1
bind > swap-window -t +1
bind Left swap-window -t -1
bind Right swap-window -t +1
bind X confirm-before "kill-window"
bind x confirm-before "kill-pane"
bind v split-window -h -c "#{pane_current_path}"
bind b split-window -v -c "#{pane_current_path}"
bind r command-prompt -I "" "rename-window '%%'"
bind / copy-mode
bind h select-pane -L
bind l select-pane -R
bind k select-pane -U
bind j select-pane -D
bind H run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -L; tmux swap-pane -t $old'
bind J run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -D; tmux swap-pane -t $old'
bind K run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -U; tmux swap-pane -t $old'
bind L run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -R; tmux swap-pane -t $old'

# status bar colors
set -g status-bg black
set -g status-fg white

# Left status session name
set-option -g status-left 'Session: #[bg=black,fg=cyan]#S#[fg=white]  Windows: '
set-option -g status-left-length 35

# window list options
# alignment settings of window list in status line
set-option -g status-justify left
setw -g automatic-rename on
set-window-option -g window-status-format '#[fg=cyan,dim]#I#[fg=blue]:#[default]#W#[fg=grey,dim]#F'
set-window-option -g window-status-current-format '#[bg=blue,fg=cyan,bold]#I#[bg=blue,fg=cyan]:#[fg=colour230]#W#[fg=dim]#F'
set -g base-index 1

# Redraw every second so clock is correct
set -g status-interval 1
set -g status-right '#[fg=yellow]#(whoami)#[fg=default]@#[fg=green]#h#[fg=white]

Tasks

Sharing tmux session with another user

## Create a new session with the socket placed somewhere your other user can access
$ tmux -S /tmp/shared-tmux new -s shared
$ chmod g+rwx /tmp/shared-tmux

## Someone else in your group can now access tmux
$ tmux -S /tmp/shared-tmux attach

Lock a tmux pane

It may be preferable to lock a pane from an accidental ^C on a program. This can be implemented with the following macro in your .tmux.conf file.

# Locking feature. cmd-q to lock, cmd-Q to unlock
bind q run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -t $old -d; tmux select-pane -t $old -T "***** Pane Locked, hit CMD-Q to unlock *****" '
bind Q run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -t $old -e; tmux select-pane -t $old -T "`hostname`" '

You can change the bind keys as desired. This will lock the pane from any inputs and will also update the pane title when locked.

Troubleshooting

Vim in Tmux isn't 256 colors

If applications running within Tmux don't appear to have the right colors, Tmux is likely thinking your terminal isn't able to support 256 colors. The quick fix would be to run tmux -2 where the -2 option forces on the 256 color mode. However, the appropriate fix would be to set the TERM environment variable properly.

If you're working from PuTTY, you will have to set the terminal-type string value under Configuration -> Connection -> Data. You'd likely want to set it to something like putty-256color or xterm-256color. Once your TERM environment variable is set properly, run tput colors to verify how many colors your terminal appears to support. You should see 256 when configured properly.

Tmux is not keeping scrollback

I've encountered issues where tmux stops keeping track of scrollback history properly on some panes for no obvious reason. Symptoms when this happens includes:

  • Scrolling back up past the current frame shows scrollback history from a very long time ago (not what was just displayed in the terminal)
  • If you attempt to clear the scrollback history with ctrl-b : and running clearhist, scrollback breaks completely. Attempting to scrollback will just show [0/0] in the top right of the pane.
  • Running reset to reset the terminal does not help
  • Setting the history-limit from 0 to 20000 again doesn't help (manual says this only applies to new panes, so this likely won't help)

If this is happening to you, try the following:

  • Check: are you in a screen session? If you are, screen is likely going to cut your scrollback history without you knowing.
  • Try to run screen and then detaching/quitting. The act of entering and exiting a screen session seems to reset the terminal back to a good state where scrollback is kept track by tmux once again.

I still don't know the root cause of this behavior. Possibly bad escaped terminal characters being printed at one point? Maybe I was in a screen session that was abruptly terminated?

See Also