diagram of 4 panes open on a terminal

At work, I have to develop a service that has an API server, a web server that serves UI, and a Slack bot. This uses a database. I can either run it locally via podman, or connect to one which already runs in a development cluster.

The web server requires the API server to provide some basic functionality, so even if I'm only developing the web service, I need both the API server and the database available, and vice versa.

Silly ’ol me was creating multiple tabs in my terminal, going to them manually, and running the setup commands via shell history. After the 90th time of doing this, I realised that I’m a programmer and such toil deserves to be scripted. So here we are.

Enter tmux

tmux, as many of you already know, is a terminal multiplexer, sort of a window manager for terminal processes. You can create a session and either interact with it by pressing key sequences from your keyboard, or you can send those key sequences from the terminal to automate some setup.

Here’s a script I created to set up all of the services.

Create a tmux session

#!/usr/bin/env zsh

WORK="$HOME/work" # Or wherever your WORK directory is

tmux kill-session -t devops-buddy
tmux new-session -d -s devops-buddy

We create a detached session with whatever name we want, and we kill a session with that name if it already exists. I don’t really care about persisting state manually because that’s what the database is for.

First service

# Pane 1: make watch
tmux send-keys "cd $WORK/backend" C-m
tmux send-keys "make watch" C-m

We cd to the repository of the first service and run whatever command we want. send-keys sends whatever text we enclose in quotes literally, and C-m means CTRL+m, which is the code for Enter. This actually executes the command. We can do it all in one line if we want but it looks cleaner this way.

Splitting the window and running the second process

tmux split-window -h -t 0 -c $WORK/frontend \; send-keys -t "$pane2" "npm run dev" C-m

You can split commands to tmux with an escaped semicolon: \;. split-window -h splits the window (tmux terminology for a single screen with multiple panes, sort of like a desktop) horizontally. The -c flag sents the current directory of the new pane, so we don’t have to execute cd manually. send-keys by default sends the keys to the active pane, which is, in this case, the newest one created.

Do this twice more

If you want to run four processes, you’d have to do the same thing again, twice, but with different arguments to split-window and send-keys

Attach to the session

tmux attach-session -t devops-buddy

This puts the tmux session in the foreground, split between your four panes. The good thing about this being a shell script is that you can do all sorts of setup interspersed with your tmux calls.

For instance, to connect to the database instance, I first connect to the kubernetes cluster it’s running in, and only then create the tmux pane that port-forwards to it.

How to use it

Just like a shell script! Since I’ve given all of the paths as absolute, I can run this script from any directory and get the same results. You can put something like this in your $PATH to not have to remember where you put it.