Tmux Manual

Until recently, I used tmux occasionally, only if I had to run some experiments on a remote server and later see the results of the execution. Basically, I used it only as a mean to execute commands in the background. If I needed to run several commands on a remote server parallelly, I used to open several terminals, connect each of them to the remote host and then switch between them.

Recently, I started working with a remote server through ssh more often and the routine, I used to, became very operation consuming. So, to improve my effectiveness, I spend several hours reading articles, watching videos and trainings how to use tmux. This article combines the knowledge I have acquired. It is also a crib for me if I forget something in the future.

Tmux is one of the most popular Terminal MUltipleXers. Terminal multiplexer is a tool that enables you to mingle several terminal sessions on one screen and effectively navigate between them, access and control them. This kind of tools is especially useful if you need to run several commands simultaneously on a remote machine and see the results alongside. Without a multiplexer you would have to log in to a remote host many time opening each time a new terminal window and issuing a connect command. Terminal multiplexer allows you to open only connection to a remote host, create there several sessions and work with them concurrently. Moreover, if for some reason the connection is torn down, you would be able to connect to the remote host lately and continue from the point when the connection is lost.
Table of Contents

Introduction

I am not a professional user of tmux, so in this article I provide only the basics in order to start using this tool in your everyday work. Moreover, I will describe and explain only some basic tmux settings, so that you can easily configure tmux on a remote machine without copying/writing complicated config files.

Usually, tmux is not installed by default, therefore we need to install it at first. In Ubuntu-based distributives, you can install this utility firing the following command:

$ sudo apt install tmux 

In order to start tmux, invoke the binary:

$ tmux

If you run this command in your terminal you will notice almost no change: only a green line (by default) in the bottom part of the window with some information will appear.

Tmux Concepts

In order to understand how to use tmux, we need to learn what components this tool consists of and what concepts it operates on. Figure 1 presents the main concepts related to this tool.

Tmux Concepts
Tmux Concepts

Tmux is a client-server application. When we execute tmux command, we start a client part that interacts with the server through a socket connection. This command creates a new session with one window and one pane on the server, and attach a client application to it. A user can create later several sessions, windows and panes. Note that multiple clients can be attached to the same server and session.

Let’s consider how tmux components look like on an example. Figure 2 shows a tmux client window of my current session.

Tmux Elements
Tmux Elements

A pane is a visually separate part where you execute terminal commands and see their output. For instance, on Figure 2 there are three panes (marked with large red circles with numbers): the first pane I use to run atomic commands (e.g., open VSCode to edit a post, commit changes to a git repository or push the modification remotely); the second pane is used to run hugo server that builds and serves my static website during the development; the third pane shows the current load in my system (it runs the htop command). Splitting one screen into multiple panes is very helpful, because this allows me to see the output of multiple commands at the same time without switching between different terminal instances. A pane can be imagined as a separate application window. You can have several programs’ windows placed aside to each other in order to see their results at the same time.

A set of panes on one screen constitutes a window. You can have several tmux windows and switch between them, each of which would have its own layout of panes. Tmux windows are similar to virtual desktops: only one desktop is shown at a time; however applications on other, even not visible desktops, are executed at the same time. On Figure 2, there are two windows: their labels in the status bar (see bottom left part of the figure) are highlighted with pink rectangles, number 4 (1:bash-) and number 5 (0:hugo*). By default, tmux assigns labels to the windows automatically using the name of the program that runs in the currently active pane of the window. For instance, in the window 0:hugo* pane 2 is currently active that is used to run hugo server, therefore the label of the window includes this program’s name. The number before the column corresponds to the window index. Window indices are used as a “part of address” that enables one to send commands to the right window.

You could also spot some auxiliary characters after the window labels, e.g., * after 0:hugo and - after 1:bash. These symbols provide additional information about the window. For instance, * means that the window with this symbol is currently active. Tmux manual provides the following meanings of these characters:

  • * denotes the current window;
  • - marks the last window (previously selected);
  • # means that the window is monitored and activity has been detected;
  • ! means that a bell has occurred in the window;
  • + designates that the window is monitored for content and it has appeared;
  • ~ shows that the window has been silent for the monitor-silence interval.

Tmux windows are run within a session on the server. A session can be considered as a set of windows united by one goal. It resembles a user session if we continue considering the analogue with operating system interface elements. There can be several users working with different applications on one machine; similarly, several tmux sessions can be run simultaneously with their own set of windows and panes.

Some developers prefer to consider a session as a separate project that unites several windows where one performs different tasks related to the same project. For instance, first window may unite front-end development tasks (one pane to modify the code, second pane to install necessary front-end dependencies), the second window may bind together backend development tasks (one pane to start a server using docker, while the second pane can be used to watch the logs). Both these windows are related to one project. If a developer works simultaneously with several projects, s/he can use sessions to switch between them easily: just by attaching to the corresponding tmux session.

For instance, on Figure 2 you can see that my session is called website (the session label is highlighted with a blue rectangle and circle with number 6) because it is related to my website development project. If I need to write a new blog post or modify something on my webpage, I run tmux and activate this session.

Each session is persistent and will survive accidental disconnection, e.g., if an ssh connection to a remote server is dropped. Later, you can reattach to this session using a special command and continue from the point where you have been interrupted. A user can kill a session, if it is not required anymore. After a user closes the last pane of the last window in a tmux session, the session also finishes automatically.

Unfortunately, if you restart a tmux server (e.g., if you develop locally and reboot your machine, or if you develop remotely and reboot your remote host) tmux sessions will not survive. Therefore, you would need to create your sessions and layouts from scratch again in such case. Luckily, you can automate these tasks by interacting with tmux through its commands, which we consider in the following section.

Tmux Commands

As we have mentioned before, tmux is a client-server application. Server is responsible for multiplexing the terminals and representing them as sessions, windows and panes. The client is used to interact with these server abstractions of separate terminals.

You can use tmux to send commands to tmux server. In order to do this, you need to execute the tmux <command> <parameters> command in a terminal. If you are already inside a tmux session, you can also press prefix : — the tmux status bar will show the : (column) invitation, and there you can enter a tmux command with parameters.

In order to interact with a particular terminal in tmux server, you need to know its address (or target). Usually, it has the following format: <session_name>:<window_index>.<pane_index> (however, the format may be changed). Using the address, it is possible to send commands to a particular terminal.

Tmux commands are often used in bash scripts to prepare a working environment. For instance, the following bash script can be used prepare the environment similar to the one shown on Figure 2:

#!/bin/bash

# check if the session called exactly 'website' exist
if ! tmux has-session -t=website; then
  # if it does not exist
  # create a new session (new -s) called 'website' detached (-d flag)
  tmux new -s website -d

  # split the 0th pane of the 0th window of the 'website' vertically
  tmux split-window -v -t website:0.0
  # split the 1st pane of the 0th window of the 'website' horizontally
  tmux split-window -h -t website:0.1

  # send-keys (change directory command) in the 0th window and 0th pane
  tmux send-keys -t website:0.0 'cd "/home/yury/PROJECTS/PERSONAL/zyrikby_webpage/website/"' Enter
  # run vscode editor in the content/ directory in the target pane website:0.0
  tmux send-keys -t website:0.0 'code .' Enter
  # send-keys (change directory command) in the 1st pane of the 0th window  
  tmux send-keys -t website:0.1 'cd "/home/yury/PROJECTS/PERSONAL/zyrikby_webpage/website/"' Enter
  # run hugo server there
  tmux send-keys -t website:0.1 'hugo serve -e production -D -F' Enter
  # run htop command inside the 2nd pane
  tmux send-keys -t website:0.2 'htop' Enter
fi

# attach to the session called 'website'
tmux a -t=website

In this script, we check if a session called website (exact match) exists. If it does not, we create a new detached one. Then, in this session we split our window into three panes and run the commands there. In the end of the script, we attach to the session named website (newly created or existing one).

Note if you change the value of the base-index and pane-base-index parameters in the configuration, you would need to modify the script, because the indices of the window and panes would be changed accordingly.

If you want to develop a script that does not depend on window and pane indices, then you need to create named windows and interact with panes using their relative positions. However, this may considerably complicate the script.

Such scripts are very useful if you repeat the same set of actions regularly. They allow you to create a working environment using only one command even after your computer is rebooted.

Note that you can run several clients simultaneously to interact with the same session. This functionality can be used, e.g., to allow several users to attach to the same session and work simultaneously. For instance, this can facilitate teaching new developers how to do something on a server instead of using screen sharing.

Tmux Hotkeys

Although tmux commands are very useful, true tmux power concludes in the extensive usage of hotkeys when you are inside a tmux session.

When you run something in tmux, by default all keypress events are sent to the terminal of the currently active pane. Therefore, it is obvious that in order to interact with tmux server itself, we need to prepend them with a special “escape” sequence. This sequence is called prefix. This key chord tells that the following keypresses should be interpreted by tmux server. By default, the prefix correspond to Ctrl+b. However, so as it is not very convenient to press these two keys together, some developers rebind them, e.g., to Ctrl+a or to Ctrl+s.

Note that tmux uses special characters to designate some control keys:

  • C for Ctrl;
  • M for Alt (Meta);
  • S for Shift.

This control keys go in the beginning of a key sequence, so you should not confuse them with the capital c, m and s keys.

In what follows, we will use these shortcuts. For instance, instead of writing Ctrl+b, we will further use C-b.

Note that keys are register-dependent. Therefore, C-d and C-D are two different hotkeys (in the latter case, you also need to press Shift key together with d).

Tmux Actions

Now, we are ready to consider what you can do using tmux. In this section, we will consider the most common actions that you can perform with the help of tmux. how to perform the most common actions in tmux that I face in my work. For the complete list of all possible actions, you can refer to a tmux online man page or run man tmux to read the manual in your terminal.

In case of most common actions, usually we can achieve the same goal using both tmux hotkeys and tmux commands. However, the correspondence between tmux commands and hotkeys is not one-to-one. Tmux is very flexible in configuration: you can bind a tmux command, a sequence of tmux commands, or even shell commands to a particular key. Below, we consider the default key bindings and most often used tmux commands (in parenthesis, we give an alias for a command).

Note that tmux analyzes commands in a prefix manner, so you can use shorter versions of the commands if the prefix is unique. For instance, instead of writing tmux attach, you can shorten the command to tmux at or even tmux a because there is no other tmux command starting with a.
List of Tmux Actions
Tmux CommandTmux ShortcutExplanation
General Actions
detach-client (detach)prefix dDetach the current client
detach-client (detach) -t <client_name>prefix DChoose a client to detach
command-promptprefix :Enter the tmux command prompt
list-keys (lsk)prefix ?List all key bindings
bind-key (bind) <key> <command>Bind key to a command
unbind-key (unbind) <key>Unbind the command bound to the key
list-commands (lscm)List all tmux commands
show-options (show)Show tmux options
source-file (source) <path>Execute commands from a file
Session Actions
attach-session (attach) -t <session_name>Attach to a session
new -s <session_name>Create new session with the name
list-sessions (ls)List sessions
rename-session (rename)prefix $Rename the current session
switch-client (switchc) -t <session_name>prefix sSelect a new session for the attached client interactively
kill-session -t <session_name>Kill session
Window Actions
new-windowprefix cCreate a new window
select-window (selectw) -t <0 to 9>prefix <0 to 9>Select windows from 0 to 9
select-window (selectw) -t <target_window>prefix wChoose the current window interactively
rename-window (renamew)prefix ,Rename the current window
kill-window (killw)prefix &Kill the current window
select-window (selectw) -lprefix lMove to the previously selected window
select-window (selectw) -nprefix nChange to the next window
select-window (selectw) -pprefix pChange to the previous window
Pane Actions
split-pane -vprefix "Split the current pane vertically into two: top and bottom
split-pane -hprefix %Split the current pane horizontally into two: left and right
select-pane (selectp) -l OR last-paneprefix ;Move to the previously active pane
select-pane (selectp) -D/-U/-L/-Rprefix Up/Down/Left/RightSelect the pane below/above/to the left/to the right
resize-pane (resizep) -D/-U/-L/-Rprefix C-Up/C-Down/C-Left/C-RightResize the current pane in steps of one cell
resize-pane (resizep) -Zprefix zToggle zoom state of the current pane
kill-pane (killp)prefix x OR C-dKill the current pane
display-panes (displayp)prefix qBriefly display pane indexes
swap-pane (swapp) -Uprefix {Swap the current pane with the previous pane
swap-pane (swapp) -Dprefix }Swap the current pane with the next pane
break-pane (breakp)prefix !Break the current pane out of the window

Copy Mode

Unfortunately, when you work with a terminal in tmux, it does not always behave as you expect. For instance, if you would try to scroll up to see the output, you would not be able doing this. This is because tmux window may be in one of two modes. The default permits direct access to the terminal attached to the window (this mode and its actions we considered in the previous section). The other is copy-mode, which permits a section of a window or its history to be viewed or copied so that it can be inserted later in another window.

In the table below, I provide the set of keys used in copy-mode:

List of Tmux Copy-Mode Related Actions
Tmux CommandTmux ShortcutExplanation
Copy-Mode Related Actions
copy-modeprefix [Enter copy mode
paste-buffer (pasteb)prefix ]Paste the most recently copied buffer of text
list-buffers (lsb)prefix #List all paste buffers
choose-bufferprefix =Choose which buffer to paste interactively from a list
delete-buffer (deleteb)prefix -Delete the most recently copied buffer of text

Inside the copy-mode, you can use two different key layouts to navigate: emacs or vi. In the configuration file, you need to change the mode-keys option to choose what layout to use. By default, the emacs layout it used.

Copy-Mode Shortcuts
vi shortcutemacs shortcutExplanation
SpaceC-SpaceBegin selection
qEscapeEscape
EnterM-wCopy selection and cancel
kUpMove cursor up
jDownMove cursor down
hLeftMove cursor left
lRightMove cursor right
/C-sSearch forward
?C-rSearch backward
nnSearch next result
NNSearch previous result
:gGo to line

Configuration

It is possible that you would need to adjust some tmux settings. For the current user, tmux configuration is usually stored in the ~/.tmux.conf file. Once you have modified this file, you can load the made changes into tmux using the following command (this command will execute all the commands in the file):

$ tmux source-file ~/.tmux.conf

Tmux is a highly customizable tool. After extensive configurations it may look and behave completely different way compared to its default configuration. In the Internet, you can find many different useful configurations, e.g., check out this one. However, development of such configuration requires quite a lot of time. Moreover, if you do not have access to the Internet it would be difficult to type all these commands in an isolated environment. Therefore, in this section we will consider only the most useful configuration options.

First of all, as I have already mentioned, a lot of people do not like to use Ctrl+b as a prefix. They have two choices: either rebind prefix to a new key chord, or configure the second prefix:

# remap prefix from 'C-b' to 'C-a'
unbind-key C-b
set-option -g prefix C-a
bind-key C-a send-prefix

# bind prefix2 to 'C-s'
set-option -g prefix2 C-s
bind-key C-s send-prefix -2

In these lines, we at first unbind default prefix C-b so that we can use it later. Then, we are binding prefix to the C-a key chord globally (-g) using the set-option command. The following configuration line allows one to send C-a to the terminal if this combination is pressed twice. Similarly, we configure the prefix2 binding to C-s.

Now, let’s consider some options that improve user experience:

# set mode keys
set-option -wg mode-keys vi

# mouse behavior
set-option -wg mouse on

# increase history size
set-option -g history-limit 5000
# faster command sequences that involve 'Escape' key press
set-option -g escape-time 20
# increase repeat timeout
set-option -g repeat-time 600      

The history-limit option increases the size of the history buffer size to 5000 lines; escape-time reduces the time tmux waits if ‘Escape’ key is pressed; repeat-time increases the time tmux waits for repeated key press events (the keys bound using the command bind-key with the flag -r): if you press a key within the repeat-time there is no need to prepend it again with prefix.

So as it is quite hard to press 0 to activate first window (or pane), it is recommended to start numbering windows (and panes) from 1; if you close a window, tmux should renumber windows:

# start windows numbering from 1
set-option -g base-index 1
# start pane numbering from 1        
set-option -wg pane-base-index 1     

# rename window automatically to reflect what program is running
set-option -wg automatic-rename on
# renumber windows when a window is closed
set-option -g renumber-windows on

Some people do not like the default keys assigned to split windows horizontally and vertically because signs % and " do not remind vertical and horizontal lines. Instead, they prefer to use more descriptive characters:

# split panes using | and -
bind-key | split-window -h
bind-key - split-window -v
unbind-key '"'
unbind-key %

Finally, with the default shortcut layouts it is not convenient to move between the panes: you need at first press the prefix and then move your hand and press arrows. Some people prefer to use vim keys (h,j,k and l) to move between panes. However, personally I prefer to use arrow keys pressed together with Alt (Meta - M) key without prepending them with tmux prefix. Similarly, to change the size of panes I use Shift+Alt+Arrow shortcut:

# switch panes using Alt-arrow without prefix
bind-key -n M-Left select-pane -L
bind-key -n M-Right select-pane -R
bind-key -n M-Up select-pane -U
bind-key -n M-Down select-pane -D

# resize panes using Shift-Alt-arrow without prefix
bind-key -n S-M-Left resize-pane -L 2
bind-key -n S-M-Right resize-pane -R 2
bind-key -n S-M-Up resize-pane -U 2
bind-key -n S-M-Down resize-pane -D 2

Conclusion

Tmux is a very powerful tool. Unfortunately, I use only a small fraction of its functionality until recently. One of the reason to abandon this tool was that it was not easy to grasp the concepts behind tmux and remember its keys. However, I could say that the time investment worth it. Hopefully, this article may help others to discover the potential of this utility.

Related