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:

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!

Originally published on June 20, 2011

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.

 
173
Kudos
 
173
Kudos

Now read this

NGINX as a SPDY load balancer for Node.js

Background Recently we wanted to integrate SPDY into our stack at SocialRadar to make requests to our API a bit more speedy (hurr hurr). Particularly for multiple subsequent requests in rapid succession, avoiding that TCP handshake on... Continue →