My tmux Setup

Posted on Mar 13, 2021
Last updated Mar 13, 2021

My tmux setup and how it fits into my daily workflow.


What is tmux?

tmux is a “terminal multiplexer”, which basically means that you can run multiple terminal sessions from one window of the terminal emulator (a.k.a terminal application) of your choice. One reason you might want to do this is to be able to run, say, npm install (which could take a long time to finish) and also some other command while you wait. For example, you may be installing the dependencies for a Node.js project and you want to run ls -lah to take a look at the files in the root of the project you just checked out.

Or maybe you want to run a development server and still be able to run git commands without killing the server or switching to a new terminal window. That is exactly how I am using it to run the Hugo development server and commit changes I am making to this very post:

tmux basic

How I Use It

I don’t have much of any customization setup on top of plain old tmux and it is an essential part of my workflow. The keybindings, once committed to memory, are relatively easy to invoke and the power that comes from being able to quickly navigate between multiple shell sessions makes working in the terminal a pleasure.

I have no .tmux.conf to speak of since I do not alter the default behavior of the tool in any way.

However, there is one piece to the puzzle that I had been missing for a long time that I had been using tmux. I have recently (within the last year) begun using a tool that provides session management for tmux, called tmuxp.

tmuxp allows you to “freeze” your tmux session and store that in a file to be able to re-load it again at a later point. This was a game changer for me and is something that I highly suggest.

My Project Workflow

My coworkers and I juggle many different project repositories that all require different versions of Python, Node.js, etc. This also pervades many (if not all) of my personal projects. To give an example of how I might have started work on a given project before I had tmuxp, here is the series of commands I would run to have my development environment ready for me to begin implementing a new feature on an Angular + Django app:

Note: tmux commands are written here, but would otherwise have been executed via keyboard shortcuts.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
tmux -2                 # Start tmux with a new blank session

workon myapp            # Navigate to Django API dir
                        #   and activate the Python virtual environment

tmux new-window         # Create a new window for the running servers

tmux split-window -h    # Split the window vertically into two even panes

./manage.py runserver   # Run the API server

tmux last-pane          # Swap focus back to the first pane

cd ~/projects/myapp-ui  # Angular UI dir
nvm use 14              # Set active Node.js version
npx ng serve            # Run the UI server

tmux last-window        # Swap focus back to the "main" bash window,
                        #   which is ready to run new commands

Throughout the course of a day of development, I might jump back and forth between two or three different tmux sessions, each roughly similar to the setup above. This is obviously quite tedious but it never bothered me too much because once it was setup, I could easily hop between each running session without any extra effort. So it was clumsy and working, but not scalable.

Enter tmuxp

With tmuxp in the picture, I could setup the same session as I had before, take a “snapshot” of it with tmuxp freeze, and then be able to load that later with tmuxp load my-session (simply by storing the “frozen” session config in ~/.tmuxp/my-session.yaml, or json).

This allowed me to configure a tmuxp session config file for each of the projects on which I work and easily call them into existence with a single command.

On top of just configuring the window and pane layout, you can also configure shell commands to run in any given pane in the session. I now have the ability to automate the start of all the development servers I need to run a full-stack web app locally without leaving the terminal.

Here is an example tmuxp session file of just that:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
session_name: my-app

# Common commands run in each new window/pane
shell_command_before:
- workon myapp              # Navigate to Django API dir and activate
                            #   the Python virtual environment
- nvm use 14                # Select the Node.js version needed to run the UI
- clear

windows:

# Default bash window to run any old thing
- focus: 'true'             # Focused window when the session starts
  layout: even-horizontal
  options: {}
  panes:
  - focus: 'true'
  window_name: bash

# Running servers in their own, split window
- layout: even-horizontal   # Split vertically, even
  options:
    automatic-rename: 'off'
  panes:
  - focus: 'true'
    shell_command:
    - ./manage.py runserver
  - shell_command:
    - cd ~/projects/my-app-ui
    - npx ng serve
  window_name: running-servers