How to Orchestrate a Tmux Development Environment
Developing a modern full-stack application often requires running multiple local servers, maintaining a code editor, and having a general terminal available for CLI commands. To prevent terminal clutter and context switching, we orchestrate a highly efficient development environment using Tmux and a Makefile.
The DevX Workflow
We trigger the entire environment using a single command from the project root:
What happens under the hood?
When make dev is run, it executes the dev.sh bash script. This script acts as an orchestrator:
- Cleanup Phase:
- It forcefully kills any pre-existing Tmux session named
Crud-in-the-cloud. -
It runs
lsof -ti:8000,8001,8002 | xargs kill -9to instantly free up the ports used by Django, FastAPI, and MkDocs. This prevents frustrating "Port already in use" errors. -
Session Initialization:
- It creates a new, detached Tmux session and provisions 5 distinct, named windows.
- Window 1 (Main): A blank shell for running git commands or database migrations.
- Window 2 (Nvim): Automatically launches Neovim at the project root (
nvim .). - Window 3 (Django): Runs the
make django-devtarget (Port 8000). - Window 4 (FastAPI): Runs the
make fastapi-devtarget (Port 8001). -
Window 5 (Mkdocs): Runs the
make mkdocs-devtarget (Port 8002). -
Landing:
- The script sets the active window back to
Nvim(Window 2) so you are immediately ready to code. - Finally, it attaches your terminal to the Tmux session.
Navigating the Environment
Once inside the Tmux session, you use the Tmux prefix (usually Ctrl + b) followed by a key to interact:
- Switch to a specific window:
Ctrl + bthen1,2,3,4, or5. - Go to the next window:
Ctrl + bthenn. - Go to the previous window:
Ctrl + bthenp. - Detach from the session:
Ctrl + bthend. This drops you back to your regular terminal, but leaves all servers and Neovim running in the background.
To jump back into the running session later, simply type:
Tearing Down
To completely stop all servers, close Neovim, and destroy the Tmux session, run: