John Terenz.io

My Guide to tmux

JT on 20160319

This guide was originally written in August of 2013 for a class I taught at Airbnb. I recently uncovered it and am publishing it here with some minor updates.

Introduction

What is tmux?

Why should I use it?

How do I install it?

How do I use it?

Configuration

The main configuration file lives in ~/.tmux.conf. To start, here are some sane defaults:

set -g default-terminal 'screen-256color' # match your local terminal capabilities (this is for os x) set -g base-index 1 # start window index at 1 instead of 0 setw -g pane-base-index 1 # start pane index at 1 and instead of 0 set -g prefix C-a # make the prefix key Ctrl-a instead of Ctrl-b bind C-a send-prefix # Ctrl-a twice to send Ctrl-a to the underlying program

IMPORTANT NOTE: it's popular with tmux users to remap the prefix key from "b" to "a". This guide assumes you are using "a", but if you stay with the default, keep that in mind when you see Ctrl-a from here on out.

You also might want to get Bash autocompletion working for tmux. Download this file and then source that in your .bashrc.

Managing sessions

Just type tmux. By default it will create a session and attach you to it. Now let's detach from it with Ctrl-a d. Now you're back in bash. Want to reattach? tmux attach-session will by default attach to the first (and only in this case) session.

If you're going to use more than one session, we should learn basic session management. To create a session with a name try tmux new-session -s mysesh. Now you have given this session a name. Let's detach from it with Ctrl-a d and then list it with tmux list-sessions. You should see one line that says something like: mysesh: 1 windows (created Mon Aug 19 11:45:41 2013) [364x94]. Now reattach with tmux attach-session -t mysesh. The -t stands for target and can apply to sessions, windows, and panes.

Managing windows

We're back inside mysesh. Let's talk about windows. A window is what fills the screen in tmux. Your session can have many windows and they always take up the entire terminal. You have to have at least one window or the session will die. You are now looking at your session's default window. Down in the lower right of the status bar you will see [mysesh] 1:bash*. The session name, and what command the first window (or rather that window's only pane) is running. Windows normally start at index 0, but we changed them to start at 1, this makes keyboard navigation between windows easier as we'll see later. Keep in mind you are not actually interacting with the window itself, a window always has at least one pane. When there is only one pane, it occupies the entire window.

Creating more windows

Let's create a second window in your session. There are three ways to do this. The quick way is Ctrl-a c. This creates a new window at the next index with the default command. If you want to be fancier you can type tmux new-window. When you're inside tmux, and you type tmux <command> it acts on the current session, window, and pane depending on the command. Let's create another new window running Vim with tmux new-window vim. This new window is no longer running Bash underneath, it's "natively" Vim. When you exit Vim, the window will die. Try it!

Running tmux commands in tmux

When you're inside Tmux, everything is scriptable with tmux <command>. But tmux also has a command line similar to Vim. Do Ctrl-a : and it will come up. If you want to cancel out do Ctrl-c. Down here you can pretty much type the same stuff as before, but without prefixing with tmux. Try new-window vim. It's usually faster to use this method when running command by hand, but if you want to script tmux, then you have to use the first form.

Navigating between windows

To navigate between windows there are two main ways. Ctrl-a p and Ctrl-a n move to the previous and next respectively. You can also do Ctrl-a <n> where n is the number of the window and you will go there! This is why we indexed windows starting at 1, since 0 is a big reach across the keyboard, especially if you're using "a" as the prefix and you want to use one hand.

Renaming windows

Your windows each have an index and a name. By default, the name is the command running in the window (in the focused pane). You can rename your windows to be more descriptive though, so they aren't all just called "bash", "vim", etc. To do this type Ctrl-a ,, fill out the new name and hit return. Alternatively you can do type tmux rename-window <name>.

Moving windows

You can swap windows with swap-window -t <n> where n is the window index you want to swap with ("t" stands for target). You can move a window to an empty index with move-window -t <n> or just run move-window to move it to the lowest available index.

Killing windows

If your window only has one pane, then killing that pane will kill the window too. Alternatively, you can do Ctrl-a &. This will prompt you at the bottom of the screen to kill the window and all it's panes. Type y to proceed.

Managing panes

Creating more panes

Now that we know how to manage windows, let's talk about panes. A window is by default one pane, but can be divided into many panes. The two most basic commands are Ctrl-a % which splits the pane horizontally, and Ctrl-a " which splits the pane vertically. These will create new panes with the default command (bash).

If you want to create more interesting panes, you can use the split-window command and pass it options plus a command to run. If the command is more than one word, use quotes. Here are some examples:

split-window # splits vertically, same as Ctrl-a " split-window -h # splits horizontally, same as Ctrl-a % split-window -h vim # splits horizontally, but uses "vim" as the command split-window "ssh mainframe" # splits vertically, and uses "ssh mainframe" as the command split-window -p 10 # splits vertically, the new window is 10% of the total height

Remember, these commands can be run in the tmux command line or in bash by prefixing each line with tmux. In case it's not clear yet, this is where huge power lies in tmux since we can script the creation of panes. More on this later.

Navigating between panes

What good are all these panes if you can't go into them? There are a few ways to move between panes. The most basic is Ctrl-a o. This will basically cycle through the panes in order. What order you ask? Like windows, panes have indices too. To see them do Ctrl-a q. For a brief moment large numbers will appear in the middle of each pane telling you what index it is.

A more efficient way to navigate is with the arrow keys. Ctrl-a Left for example will move to the pane to the left of the current pane, or wrap around. By default all the arrow keys when prefixed with Ctrl-a will move easily between panes. If you are a Vim user, you might think about remapping these to hjkl or something like that. I will provide my full .tmux.conf so you can see what a hard-core Vim user might do.

There are more precise ways to navigate, you can do stuff like this:

select-pane -t 2 # select pane at index 2 select-pane -U # same as Ctrl-a Up

Rearranging panes

Like windows, you can swap panes. By default you can do Ctrl-a { which is an alias for swap-pane -U. This will swap the current pane with the one above it, or to the side if nothing is above. I never really liked these because I get confused. I usually just type out swap-pane -s <m> -t <n> where s is the current pane, and n is the pane I want to swap with. It's a pain, but I don't really do this very often. When you swap panes, the contents move, but the layout stays fixed.

Resizing panes

Yes, you can resize panes. By default the keyboard shortcuts for this are hard to get to in OS X because they use the meta key. The first thing to do is to go into your Terminal preferences and go Settings -> Keyboard and make sure "Use option as meta key" is checked. Once this is done you can resize a pane down by doing Ctrl-a Option-Down and likewise, up, left and right. I strongly recommend remapping these to something easier. If you use hjkl to move, you could use HJKL to resize. Of course, you can also resize via the command line:

resize-pane -D 5 # resize the pane down by 5 rows resize-pane -R 5 # resize the pane right by 5 rows

Scrolling panes

tmux might have mouse support, but we're not interested in that if we're using tmux, right? If you need to scroll up inside a pane, then pipe your command to less. Just kidding, there's another way. If you do Ctrl-a [ you will enter "copy mode". We'll cover what this means later, but for now just know that when in copy mode you can navigate the pane's buffer in a manner similar to less. Arrows will bring you slowly up and down, but you can also use Ctrl-u and Ctrl-d and gg and G to move the the top and bottom of the buffer respectively.

Layouts

tmux has some built in layouts. You can access these by doing Ctrl-Space. They will arrange your existing panes in random ways. I hate this feature because I used to accidentally hit Ctrl-a Space and it would mess up my layout. I unbound this mapping entirely, but you might find it useful.

Zooming in on a pane

tmux 1.8 brought and amazing new feature called zoom. Let's say you have a small pane, but things are getting pretty crowded in there and you temporarily want to make it full-screen. While inside that pane, do Ctrl-a z and it will "zoom" in on that pane, making it take up the whole window. When you're done, you can do Ctrl-a z again and you will return to the former layout.

Breaking panes

Sounds destructive, but it's actually quite useful. Let's say you're in a window with a few panes, and you want to take one of those panes and promote it to it's own window. The command is Ctrl-a ! or break-pane.

Scripting tmux

The old-fashioned way

There are enormous scripting capabilities with tmux. Take for example a basic script to create a workspace for you. This is a simplified version of what I use to load up a coding project, for example.

tmux rename-window Personal tmux split-window -d -c ~/Documents # new shell in Documents tmux split-window -d -h -t 2 -c ~/Documents # new shell in Documents tmux split-window -d -h -c ~/Documents vim # new vim, with pwd = Documents tmux resize-pane -D 25 # resize things tmux select-pane -t 4 # select the lower left pane tmux kill-pane -t 1 # kill the original pane

The full version I use is two parts. I created a bash function called tri_pane. Given a name and a path, it will open a large Vim and two smaller Bashes underneath all with their pwd set to the same path.

#!/bin/sh function tri_pane { name=$1 path=$2 tmux rename-window $name tmux split-window -d -c $path tmux split-window -d -h -t 2 -c $path if [[ -n command -v reattach-to-user-namespace ]]; then tmux split-window -d -h -c $path 'bash -c "sleep 0.1; while true; do reattach-to-user-namespace vim; done"' else tmux split-window -d -h -c $path 'bash -c "sleep 0.1; while true; do vim; done"' fi tmux resize-pane -D 25 tmux select-pane -t 4 tmux kill-pane -t 1 }

#!/bin/sh source ~/.tmux/tri_pane.sh tri_pane MyProject ~/Documents/myproject

Then I have an alias called win that does this:

win () { sh ~/.tmux/"$*".sh; }

So all I have to do in the morning is create a new window and type win myproject and it will pull up my project "IDE".

Tmuxinator

I'm an old-school purist when it comes to this stuff, but someone created an awesome program called Tmuxinator. It's built in Ruby and uses YAML files to specify layouts. Definitely something to look into rather than struggle with the scripts I put above.

Copying and pasting

Within tmux

Copy and pasting within tmux is relatively straightforward. To select text, first you need to enter copy mode (remember from when we scrolled). Once in copy mode move to the beginning of the text you want to copy and hit Space. Now move to the end of the text, you'll see it getting highlighted, and hit Enter. This will copy the selected text into a tmux buffer. To paste this, go to the pane you want to paste into and do Ctrl-a ]. This buffer by default won't interact with the system clipboard, or with vim, but there are ways around it.

Keep in mind that everything in tmux can be re-bound to different keys. I have a more Vim-like set of mapping for this that makes it almost the same as yanking in Vim.

Between tmux and OS X

An annoying issue that tmux presents on OS X is that it breaks compatibility with the system clipboard. In a normal Bash session on OS X (outside tmux) you can do something like ls | pbcopy. This will copy the output of the ls command into the OS X system clipboard for usage elsewhere. Due to reasons that are hard to explain, this no longer works inside tmux. Instead what you copy goes into a black hole. Fortunately, someone has a fix for this. It's a small program with a big name that wraps commands like bash and vim such that they are properly scoped and will work with the OS X system clipboard. It's called reattach-to-user-namespace and can be found here or installed with brew install reattach-to-user-namespace.

Once you have this, the fix for OS X will be something like adding a line in your .tmux.conf changing the default command to this:

set -g default-command 'reattach-to-user-namespace bash'

And also setting up aliases for other programs that access the system clipboard and might run on their own, not as a child of your reattached bash session, and only inside tmux.

if [ -z "$TMUX" ]; then if command -v reattach-to-user-namespace &> /dev/null; then alias bash='reattach-to-user-namespace bash' alias sudo='reattach-to-user-namespace sudo' alias vim='reattach-to-user-namespace vim' fi fi

Talk to me if you need help on this, it took me forever to figure this out but now my workflow is more or less seamless now.

Themes / customization

tmux's colors and status bar can be fully customized. I have my colors match solarized and my status bar show the current battery level of my Macbook. There is a link to my full configuration below. Here's my status bar config:

set -g status-right '#(date +"%a %b %d %I:%M %p") #(command -v battery &> /dev/null && battery)'

Copy this to /usr/local/bin and call it "battery" (and make it executable):

#!/bin/sh if command -v pmset &> /dev/null; then pmset -g batt | egrep -o '[0-9]+\%' fi

Multi-user tmux

By the way, multiple users can connect to a tmux session. That is something that we're not going to cover here, but talk to me if you have questions or check the resources below.

Resources

Tutorials:

Software: