tmux – an awesome little tool

If you do a lot of programming from the Linux console, you’ll certainly appreciate the power of tmux. It is a terminal multiplexer, which means that it can create multiple virtual consoles within a single terminal shell. Since these virtual consoles are not bound to a terminal, they will keep running in the background, even if you close the terminal you started it in. This means that you can detach these consoles, and re-attach them in another terminal session.

For example, imagine you are working on some project on a development server. You log into that server over SSH from your office, create a tmux session, and do your coding in vim in there. Then you detach the session, and log out from the server to go home. Back at home, you log into the development server again, and re-attach the tmux session, and you see the vim session back where you left it. Not that I suggest you to work from home, but it is a good example of how you can continue your work or session from anywhere.

Tmux in action. Two vim sessions and a MongoDB console.
Tmux in action. Two vim sessions and a MongoDB console.

Another great thing about tmux is that you can create multiple sessions within the same terminal window, and move between them, something like alt-tabbing between terminal windows, except it is much faster and with less visual distraction. An added bonus is that tmux is able to subdivide the visible portion of your terminal window into parts, so you can have multiple virtual consoles, all visible within one window. Very useful if you have lots of screen estate at your command, so that you can code in vim in one, access a MySQL console in another, and doing a sass --watch in yet another, for example. All the information you need, everything visible in the same window, for optimal productivity.

Installation

To install tmux on Ubuntu, just apt-get it:

$ sudo apt-get install tmux

On MacOSX, get it from homebrew:

$ sudo brew install tmux

Setting up

Terminal multiplexers have a command mode in which you can tell it to do something, such as switching virtual consoles or creating new ones. In tmux the short-cut key to this command mode, called the prefix, is by default Ctrl-b, but because I come from screen, another terminal multiplexer, where it is Ctrl-a, I have the following in my ~/.tmux.conf:

# Set the prefix to ^A
unbind C-b
set -g prefix ^A
 
# So that you can go to the beginning of the line with ^A a
bind a send-prefix

Ctrl-a is in my opinion also easier to reach than Ctrl-b.

However, on the command line, Ctrl-a is also a short-cut for going to the beginning of the line. You can still do that: just hit Ctrl-a a. That is what the last line in the configuration snippet tells tmux what to do when a is hit in command mode, i.e. send the prefix to the shell.

I will use Ctrl-a as the prefix key in the rest of this article. It will be shown as ^A.

Using tmux

Now that you are ready to use tmux, start it up. I make it a habit to give each tmux session a name, so that I can easily re-attach it by using the name:

$ tmux new -s coding

In this example, I have called the tmux session “coding”.

By default, it will look like this:

Starting Tmux for the first time, it looks like this, with information in a status bar
Starting Tmux for the first time, it looks like this, with the name of the session at the bottom left

You can see the name of the tmux session in the bottom left. Then you see that there is one virtual console session running bash. In the bottom right, you see the hostname, time and date. This status bar can easily be configured to allow for a lot of variations. We will come back to the tmux configuration file later, but for the status bar I’ll have to refer you to the man-pages.

Virtual consoles

First, let’s create some virtual consoles. Hit ^A c. In the status bar, you’ll see that you have created another virtual console, with bash running in it. The * means that that one is currently shown. Start vim or your favourite editor.

Running Vim in Tmux
Running Vim in Tmux

See that the currently run process is vim in the status bar?

To switch to the other window, hit ^A p (or ^A n). These letters stand for previous console and next console. As you see, it cycles through the list of consoles, so if you are at the last one in the list, and you do ^A n it will go to the first one.

Split windows

Let’s create split windows. A vertical split is done with ^A % and a horizontal split with ^A ". Personally, these key-bindings do not make any sense, so we will change these later on. To navigate through these split windows, just use ^A and the arrow keys. If you have different programs running in these split windows, you will notice the status bar changing to show you the process name running in the split window you have navigated to.

Three split windows with different processes running in each of them
Three split windows with different processes running in each of them

You can still use ^A n and ^A p to go to the non-visible consoles.

Resizing the split windows is also easy with arrow keys. Hit ^A and while keeping the Ctrl key pressed, use the arrow keys to resize the currently focused split window.

Detaching and reattaching

Let’s try detaching the tmux session. You can do that with ^A d, the d stands for detach. To view a list of tmux sessions running on the computer, do this:

$ tmux list-sessions

The list-sessions command can be shortened to ls:

$ tmux ls

You will see your tmux session listed, with the name you gave it. To re-attach it, simply do:

$ tmux attach -t coding

where “coding” was the name of my tmux session.

You can actually attach your tmux session to multiple terminal windows. There are interesting possibilities here: you could have a mentoring session sharing your tmux session with other programmers, or have some kind of pair programming where the programmers would be communicating by Skype or chat, and working in the same tmux session.

You can have the same tmux session in multiple terminals. Very useful for pair programming or mentoring.
You can have the same tmux session in multiple terminals. Very useful for pair programming or mentoring.

Notice that the size of the tmux windows are the same, and it is restricted to the smallest of the terminal sessions. The smaller one here is the top-right one, and you see the boundaries in the bottom-left one.

Here is where the tmux attach -d option comes in play. The -d option tells tmux to detach that session from any other clients it is currently attached to.

Further customizations

There are so many things you can customize in tmux and for the full list of options, I refer you to its man-page, or the many resources online. But let me list here how you can change the bind keys for split window creation. Personally, I find the | (the pipe) and the - (the dash) more logical for creating vertical and horizontal splits respectively. You can change the bindings by putting the following in your ~/.tmux.conf file:

unbind |
bind | split-window
unbind -
bind - split-window -h

When you are going to configure your .tmux.conf file to your liking, it will be nice to have a short-cut for reloading the .tmux.conf configuration. Put the following in your .tmux.conf:

bind R source-file ~/.tmux.conf \; display-message "Config reloaded..."

Then start your tmux session, and edit your .tmux.conf inside that session. Now, whenever you change the configuration, you can do a ^A R (that is, Ctrl-a Shift-r) to reload the configuration and see the effects of your changes directly!

You can even create different tmux configuration files, and pass them to tmux -f to pre-populate your tmux session with extra sessions, split windows, pre-run programs, etc.

Conclusion

The tmux terminal multiplexer is an awesome little tool that is certainly a must-have for every Linux/Unix/MacOSX programmer or system administrator. You can make such a good use of your screen estate by having one terminal window maximized, and populate it with split windows and hidden consoles you can easily navigate to quickly. If you are using tmux, tell us about your favourite tmux hack!

What are your thoughts?