tmux Tutorial

Why a terminal window manager?

As a web developer, most of my time is spent in a command prompt banging away at web code. One of the greatest discoveries I have made to my productivity is the use of GNU Screen. It’s hard to distill the many benefits of a terminal window manager like this into a few bullet points, so here is my best shot:

  • Ability to quickly switch between multiple command prompts or editor windows.
  • Persistence, so if the connection is lost between client and server, server maintains the state it was in exactly prior to disconnection. This also means you can just close your terminal window, reopen it, reattach, and everything is just as you left it.
  • Ability to copy-paste and perform other operations across command prompts or editor windows without the use of the mouse.
  • Visual alerts to things happening in other “windows” not in the foreground.

Some quick Googling will provide a more exhaustive list, but these are my main favorites. For anyone curious, here is my .screenrc file on GitHub

But GNU Screen is just one of many programs that accomplish the same task. I found that tmux was another terminal window manager, thought I’d give it a shot!

Why try tmux when I’m a happy GNU Screen user?

I’ve been a happy GNU Screen user for about 2.5 years, but I am always looking for ways to improve my development process. I came across an article linked on HackerNews discussing tmux as a GNU Screen Killer. I’m not a fan of such a sensationalist title, but I thought it was worth evaluating.

I figured I would also document my experience here because I often find a lack of beginner documentation for many *nix based command line utilities. Most hardcore nerds just reply, “Just read the man pages n00b!” which I find to be disappointing as a first-time user. If I spend my first hour using some new technology just trying to get it set up and learn the ropes, I am liable to simply give up on it and decide it’s not worth my time – and I am a persistent bugger. If I can help one new user get up to speed a bit faster, using my first-time experiences as a stepping stone, mission accomplished.

Installation

My primary development machine is a Mac, and I use the fantastic HomeBrew as my package manager of choice. (Highly recommended over MacPorts!) This makes my installation very easy:

$ brew install tmux

And that’s it! Typing tmux in the command line launches it.

Initial Configuration

My first step was to get my initial configuration all set up. To do so, I first create a file called .tmux.conf in my home directory:

$ touch ~/.tmux.conf

Now, I jump in with my favorite editor (go emacs!) and set up a few basics. Through some experimentation and playing, I got my initial file set up which I’ll paste here then explain:

set -g status on
set -g status-keys emacs

set -g history-limit 1000000

set -g prefix C-t

set -g status-bg green
setw -g window-status-current-bg cyan
setw -g window-status-current-attr bold

set -g status-right '#7H | %F %s'

bind-key C-t last-window

setw -g monitor-activity on
set -g visual-activity on

The first couple lines turn the status bar on and set my keybindings to emacs. There are also vi keybindings available. The status bar is one of the main benefits of using tmux. In GNU Screen, it was quite a task to get the status bar working. Below I’ve pasted the .screenrc configuration line to get the status bar working:

hardstatus string '%{= kG}[ %{G}%H %{g}[%{=kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%= %{g}][%{B}%Y-%m-%d %{W}%c %{g}]'

God help me if I ever had to change anything there! I can barely decipher what it’s doing! In contrast, the bit of my tmux config that accomplishes the same thing:

set -g status on

Ahhhhh. So, with tmux, just turning it on was much simpler and the default works exactly as I’d like so no customization was necessary.

The set -g history-limit 1000000 line sets the history limit very high so tmux remembers everything I have done. The set -g prefix C-t line changes the keybinding to have Control-t be the keyboard command for all of tmux’s commands. This had been my keybinding in GNU Screen and I liked it because it didn’t conflict with anything I use in emacs. I rarely use the transpose function and t is on my homerow (go Dvorak!). The default GNU Screen C-a conflicted with the jump-to-beginning-of-line command in emacs which I had frequently used. The default in tmux is C-b. More on this prefix command below.

The next 3 lines set the colors. I want the background of the status bar to be green and the currently active one to be cyan so it stands out.

The set -g status-right '#7H | %F %s' line sets some attributes for the status bar. I found it a bit difficult to get a straightforward enumeration of what all possibilities were, but the \#7H shows the name of the machine I am using, the %F is the date in the form Y-M-D, and the %s puts the unix time, which is seconds since 1970. This is always useful for database and other things which use that. There are many other things which could be added to this status bar, but these are a few I found useful.

The bind-key C-t last-window line makes it so when I just type C-t twice, it jumps to the last window I was using for easy switching and the last 2 lines set visual activity on so when something happens in a window other than my current one, I get a visual notification.

There are many more things that could go in a configuration file, but this gets me set up and going quickly and easily with my familiar keybindings.

Assorted tips

Naming the session

First, you can just start tmux by typing the command and hitting enter:

$ tmux

But then your session has no name. This is ok, but it makes it more difficult to reattach later. To start a session with a name, start it with the following command:

$ tmux new-session -s {session-name}

Where {session-name} is any name you want to give to your session. Then, to reattach it later, if you disconnect from the server running tmux or just decide to detach it for any other reason, just run:

$ tmux attach-session -t {session-name}

To attach the session which was previously open. Try it. Open a terminal window, run tmux new-session -s test, type some stuff into the command prompt, then close the terminal window. Don’t worry, it’s not gone. Open up another terminal window and run tmux attach-session -t test and you’ll be back up and running with your commands still entered.

Prefix command, typing commands

Above, I rebound my prefix to C-t. The default in tmux is C-b. This means you type it and, regardless of what program or window you are in, anything that follows is a global command to tmux, superseding the underlying window. This is why I chose C-t, because C-b is frequently used by me in emacs and I didn’t want to change it. If you look at the man page for tmux, you can see a full list of commands. They all assume the prefix command has come first. This confused me a bit at first because I thought those were all commands I could type from tmux, but they all needed the prefix command first, then the command. Note, from here on out, I’ll use C-b to denote the prefix command because it’s the default and likely more useful to most people than my C-t rebinding.

So to use any of those keybindings from the man page, type your prefix command (C-b) then the key. For example, when it says t – Show the time. it actually means C-b, t which is typing Control-b (or your rebound prefix key) then the t key.

On that same man page, further down, there are a bunch of word commands such as source-file and list-commands. These can be bound to keys, but they can also be called ad-hoc. This is like M-x in emacs or vi’s :. Simply type your prefix command such as C-b, then type a colon (:) and, where the status bar was, these arbitrary commands can now be typed. For example:

C-b, :, list-commands

Will show you all of the available commands. These arbitrary commands can also be bound by adding the following to the .tmux.conf file:

bind-key C-l list-commands

This will bind C-l to the list-commands command. So, typing your prefix key C-b then that C-l will launch the list of commands without the need to type it out. (this command, by default, is already bound to ? so this is a bit of an unnecessary example)

Detaching the session

In the subsection above about attaching a session, I suggested that you close your terminal window to detach the session. That is however unnecessary. It is easy to just detach a session from within tmux without closing the terminal window by typing:

C-b, d

d for Detach.

Creating, removing windows

So you’ve started tmux, but you only have a single window. Much of the discussion above assumes multiple active windows. To create a new window, just type:

C-b, c

c for create. A new window is created and currently active. Look at the status bar and there is now a new numbered window. There is no (reasonable) limit to the number of windows created. Now, to kill the currently selected one, just type:

C-b, &

Then confirm.

Moving between windows

Select Window by Number

There are many ways to jump between currently active windows. The first is just to type the prefix command, C-b, then a number. This will jump to the selected window. For example, C-b, 1 jumps to window 1, C-b, 0 jumps to window 0.

C-b, {number}

Last Selected Window

To jump to the last selected window:

C-b, l

That’s l as in lion. In my configuration, I rebound it to my prefix command so I just type my prefix twice. This is my most frequently used command, so I gave it the easiest shortcut.

Next, previous

The commands:

C-b, n
C-b, p

n for next, p for previous. Jump between the next and previous windows respectively. It wraps so if the last window is currently selected and the next command is issued, it will jump to the first window.

List of windows

It is also possible to get a list of all windows and choose between them:

C-b, w

w for windows. This is great if there are many windows opened. The status bar can only show so many titles, so this view is often useful if titles are long or there are many open windows.

Find text

This is one of my favorite features in tmux that I have discovered. This command actually allows for finding text in a given window and switching to that window. If multiple windows contain that text, a dialog is displayed for choosing the window.

C-b, f, {search string}

f for find. Any search string can be entered and tmux will search each of the windows for the appearance of that string and jump to the window that contains that string.

Windows vs. Panes

In tmux, there is a distinction made between windows and panes. Windows are what appear along the bottom status bar. However, there is also talk of panes in the man file. So is a pane different from a window one may wonder?

Yes. The difference however is quite simple. Each thing along the status bar is a window. Each window consists of one or more panes, just like a real physical window. By default, it is a single pane, but it could have more. One of the strong benefits of tmux is the ability to split a window into multiple panes and work with each of them. More detailed discussion on panes below. Killing a pane kills just that pane and does not kill the window unless it is the last remaining pane in that window.

q dismisses tmux dialogs

If you want to see a list of commands available to you, type C-b, :, list-commands and hit enter. To make that list disappear and go back to where you were, just hit the q key. This use of the q key to jump out of any tmux dialog is consistent, so it also works for any other commands. To try another, type C-b, t to view the current time. Typing q closes the time.

Reloading the configuration without leaving the session.

When I first tried using tmux and getting my configuration set up, I was entering it using tmux, seeing how it looked, quitting it with the exit command, editing the configuration file, then relaunching it. I thought, “there has got to be a better way, like source for tmux” There is. Just run:

C-b, :, source-file, ~/.tmux.conf

And the configuration is reloaded in place! Now there is no reason to leave tmux to reload it.

Copy-paste buffer

One of the things I always found a bit kludgy was the way GNU Screen dealt with copy-past between buffers. I have a cheat sheet taped to my monitor for just this. In tmux, things seem a bit more straightforward and more powerful as tmux maintains a buffer so you can copy multiple things and access each thing you copied later! So you can copy Thing A, Thing B, Thing C, then go paste Thing B, Thing A, Thing C if you want. Very cool.

So, to jump into copy mode, type:

    C-b, [

You’ll see now you can move your cursor up and down the current window using your keybindings of choice (for emacs, it’s C-p for previous line, C-n for next line, M-v for page up, C-v for page down). When you get the cursor to where you want to start copying, hit the space bar to start the selection. Then move to the end of what you want to copy and use the command to wipe in emacs (C-w) and the text is copied! Now is where the magic starts. To paste the last thing copied, just type:

C-b, ]

But, to get to the whole buffer of what has previously been copied, type:

C-b, =

The copy buffer is now displayed. Just highlight the thing to be pasted and hit enter to paste it. As with any dialog in tmux, q will also just dismiss the dialog.

Split window into panes

So, you want to split your window to have an editor in the top and a command prompt in the bottom. No problem with tmux!

In any window, just type:

C-b, "

That’s a double-quote and it’ll split that window into 2 panes! Now, to move the cursor between the panes:

C-b, o

To kill a pane, just type:

C-b, x

It’s easy to open an editor in one and use the other like a terminal. There are many advanced features in tmux for getting the panes specifically configured a certain way, but that would merit its own treatment entirely. My favorite little trick though is to create a few panes and use:

C-b, space

This jumps through a set of default pane configurations, one of which almost always suits my needs.

Conclusion

This is just the tip of the iceberg, there are many other features in tmux, but at the start, I see a lot I like. It seems a lot like the next generation of GNU Screen which, sadly, has been mostly stagnant for many years. tmux gets a lot of things right like the configuration, the status bar and its use of panes. All of these things, while technically possible in GNU Screen, require a PhD in GNU Screen configuration, a task for which mere mortals are unequipped. I’ll keep using tmux for awhile to see how it goes, but it already has all the functionality of GNU Screen with basically the same keybindings (with a bit of conf file tweaking) and it has many additional features without dropping anything I use from the feature set of GNU Screen.

Thus far, I have to give tmux a big thumbs up!

Update September 25, 2014: If you enjoyed this, I expanded upon it greatly into a whole book on tmux! It’s called Getting Started with tmux and is available through Packt Publishing.

Published 20 Jun 2011

Scaling and leading engineering and data teams to solve the world's problems
Victor Quinn on Twitter