I recently learned about terminal multiplexers. They allow you to manage multiple separate terminal sessions within a single terminal window.
Whenever I'm developing for this website I have four tabs open to handle everything. One is running drizzle studio for my database, one is running my files-api service I wrote in Go, and one is running the main Remix application. I also have a fourth open to just do terminal things.
Tabbing around and forgetting which tabs are which is really annoying. So I started playing around with tmux and fzf to create a better workflow in my terminal.
This project is a very simple monorepo. I have two folders for my files-api (Go) and my frontend (Remix). I have a Makefile at the root that has all the commands for both of those services. Then I have a scripts/dev.sh
file that runs the tmux session.
This is the script file:
#!/bin/bash
# Function to switch to a tmux window
switch_window() {
local window_number=$1
tmux select-window -t abyrd-me-dev:$window_number
}
# Function to display the menu and handle selection
show_menu() {
clear # Clear the screen before showing the menu
local selection=$(echo -e "0: DB Studio\n1: Files API\n2: Frontend (Remix)\n3: Interactive Shell\nq: Quit" | fzf --prompt="Select a window: " --height=10 --layout=reverse --border)
case $selection in
"0: DB Studio") switch_window 0 ;;
"1: Files API") switch_window 1 ;;
"2: Frontend (Remix)") switch_window 2 ;;
"3: Interactive Shell") switch_window 3 ;;
"q: Quit")
tmux kill-session -t abyrd-me-dev
exit 0
;;
esac
}
# Start a new tmux session named 'abyrd-me-dev'
tmux new-session -d -s abyrd-me-dev
# Set tmux options
tmux set-option -g prefix C-a
tmux bind-key C-a send-prefix
tmux set-option -g mouse on
tmux set-option -g history-limit 50000
tmux set-window-option -g mode-keys vi
# Set easier window navigation shortcuts
tmux bind-key -n Left select-window -t :-
tmux bind-key -n Right select-window -t :+
# Bind 'Home' key to switch to the menu window
tmux bind-key -n Home select-window -t :=4
# Configure status bar
tmux set-option -g status-style bg=black,fg=white
tmux set-option -g status-left "#[fg=green](#S) "
tmux set-option -g status-right "#[fg=yellow]#(whoami)@#H #[fg=white]%H:%M#[default]"
# Rename the first window to 'db-studio'
tmux rename-window -t abyrd-me-dev:0 'db-studio'
tmux send-keys -t abyrd-me-dev:0 'make db-studio' C-m
# Create a new window for Files API
tmux new-window -t abyrd-me-dev:1 -n 'files-api'
tmux send-keys -t abyrd-me-dev:1 'cd files-api && if [ -f .env ]; then export $(cat .env | xargs); fi && cd ../ && make files-api-dev' C-m
# Create a new window for web:dev (Remix)
tmux new-window -t abyrd-me-dev:2 -n 'web-dev'
tmux send-keys -t abyrd-me-dev:2 'make web-dev' C-m
# Create a new window for interaction
tmux new-window -t abyrd-me-dev:3 -n 'interactive'
tmux send-keys -t abyrd-me-dev:3 'clear; echo -e "\n\n\033[1mWelcome to the interactive shell. Type your commands here.\033[0m\n"' C-m
# Create a new window for the menu
tmux new-window -t abyrd-me-dev:4 -n 'menu'
tmux send-keys -t abyrd-me-dev:4 "while true; do $(declare -f switch_window show_menu); show_menu; done" C-m
# Select the menu window
tmux select-window -t abyrd-me-dev:4
# Attach to the tmux session
tmux attach-session -t abyrd-me-dev
I run a make dev
command and my terminal session shows up:
So now I've got my services and an extra open terminal running in one terminal window. I can get to them through this menu, or pressing the corresponding number, or moving through them with left and right arrow keys. Pressing the home button even sends me back to this menu.
It is significantly better than multiple terminal tabs and it all spins up with one Makefile command. It's really nice.
I'd recommend checking out tmux if you'd like to setup something similar and feel free to copy the snippet I've provided.