Scripting tmux

I spend quite a bit of time on the shell, more often than not inside a tmux session. For those of you not familiar with tmux, it is a terminal multiplexer (akin to GNU screen) allowing you to split your terminal into multiple windows and panes. Its a tool that offers man conveniences such as being able to start a session on a server, detach from it and to come back to later (in a different SSH session) or even having multiple people sharing a single session without having to physically be in the same place.

When developing with Ruby I tend to program using Vim in a tmux session. In my setup I usually have a window per project which has three panes: one for Vim, a second to run processes in (such as a rails web server) and a third as a console to run ad-hoc commands or an application console. With my configuration this setup looks something like the below screenshot:

While you can easily create the above panes with a few keystrokes, you can also script tmux to setup this up for you with a single key combination. This is what I will be diving into in this article.

The basics of configuring tmux

To configure tmux you need to edit the file .tmux.conf in your home directory, if this file does not yet exist you can create it as an empty file and start adding settings as desired. If you are editing the configuration file from within in a tmux session the changes will not take effect until you either reload the configuration file or restart tmux entirely.

Restarting tmux will require you to exit all the windows and panes of your session, taking you out of tmux (detaching and attaching won’t do, because the settings are loaded within the session). This is rather inconvenient if you are working in your session (and not just tweaking settings).

Reloading the settings is done by having tmux source the configuration file, you can do this through the tmux command prompt. The command prompt is started using by pressing the tmux command prefix followed by the : key. The default command prefix is CTRL+b (which means pressing the b key while holding down the CTRL key) which is how I will refer to it in this article.

Once you start the tmux command prompt by pressing CTRL+b : you will see a colon in the bottom if your screen where the status bar normally resides:

To reload the configuration file you enter the command source-file ~/.tmux.conf and press enter.

After entering the command the status bar will be shown again and your changed settings will be applied.

For convenience you can bind this to a key combination by putting the following line in your configuration file:

bind r source-file ~/.tmux.conf\; display "tmux configuration reloaded"

The bind command indicated adds a key binding for CTRL+b followed by the character (or character combination) you entered, the rest of the line is what is executed when the key combination is pressed. In case of the above line it binds CTLR+b r to reload your tmux configuration and echo the text “tmux configuration reloaded”:

The three pane setup

Setting up the three panes like in the initial image is done by a series of tmux commands:

# Rename the window to the last part of the current path
rename-window "#{b:pane_current_path}"
# Split horizontally and change the directory of the new pane to the current path
split-window -h -c "#{pane_current_path}"
# Split vertically and change the directory of the new pane to the current path
split-window -c "#{pane_current_path}"
# Select the first pane
select-pane -t 1
# Start vim
send-keys 'vim' C-m

You can bind these commands in your tmux configuration file to a shortcut on one line and separate each command by \; like so:

bind C-d rename-window "#{b:pane_current_path}" \; split-window -h -c "#{pane_current_path}" \; split-win
dow -c "#{pane_current_path}" \; select-pane -t 1 \; send-keys 'vim' C-m                                 

This is however rather long winded and hard to read, also if you want to change this script slightly you will have to reload your tmux configuration each time after you changed it. I personally find it easier to put this script into a separate file and bind the source-file command to load that instead:

bind C-d source-file ~/.tmux/tmux-develop.conf

In the file ~/.tmux/tmux-develop.conf you can place each command on a new line and add comments as desired without having to smash it together on a single line, so you can in fact copy the set of commands (including the comments) from the start of this section into this file.

Once you have this all set up pressing CTLR+b CTRL+d will create the panes you saw at the start of the article.

Asking for input and using it in a command

When working on multiple Rails projects I often have to start the rails web server on different ports. I have a shortcut setup to have tmux ask me for the port number and then start the Rails web server on said port in my right top pane:

bind C-r command-prompt -p 'port' "send-keys -t 2 'bundle exec rails s -p %1' C-m"

The above binding will respond to CTRL+b CTRL+r, when this combination is pressed you will be prompted at the bottom of the screen to enter a value for “port”. Pressing CTRL+c at this prompt will cancel the command. If you enter a value and hit enter the value will be passed to the quoted command instead of %1, the command is a send-keys command which targets pane two without switching to it.

Switching to a pane and starting a command in it

Another often used shortcut is for me to start the Rails console in the right bottom pane (number three):

bind C-c select-pane -t 3\; send-keys 'bundle exec rails c' C-m

The above binding responds to CTRL+b CTRL+c and will activate the third pane and run the Rails console there.

In conclusion

Tmux is an amazingly useful utility that I use on a daily basis, if this article has piqued your curiosity about it I recommand that you have a look at the documentation (which is quite extensive) to explore it further.

If you have feedback on this article or have questions based on its contents then feel free to reach out to me on Twitter or through e-mail.