Streamline Your Development Workflow with TMUX
If you're an experienced coder, you've probably been there: juggling multiple terminal windows running your type checker, frontend server, and multiple local backend services. Keeping track of multiple terminals is tedious, and switching between them interrupts your flow. This pattern is particularly prevalent in the beginning stages of a project while you're still working locally.
Terminal Juggling ๐คนโโ๏ธ
Most modern web development requires running multiple processes simultaneously, such as:
- TypeScript watcher:
tsc --noEmit --watch - Development server:
vite devornpm run dev - Backend services:
npx convex dev,npm run start, etc.
Managing these in separate terminals means constant window switching, and if you close the wrong window, you have to restart everything.
The Solution: TMUX + package.json Scripts
TMUX is a terminal multiplexer that lets you manage multiple terminal sessions within a single window. By combining TMUX with some clever package.json scripts, you can create a development environment that spins up or down with a single command.
Here's the setup:
{
"scripts": {
"dev:all": "SESSION=\"${1:-my-project}\"; tmux kill-session -t $SESSION 2>/dev/null ; tmux new-session -s $SESSION 'npm run typecheck:watch' \\; split-window -h 'npm run backend' \\; split-window -v 'npm run dev' \\; select-pane -t 0",
"dev:kill": "SESSION=\"${1:-my-project}\"; tmux kill-session -t $SESSION 2>/dev/null || echo 'No $SESSION session found'"
}
}
How It Works
Let's break down the dev:all script:
SESSION=\"${1:-my-project}\" # Use first argument or default to "my-project"
tmux kill-session -t $SESSION 2>/dev/null # Clean up any existing session
tmux new-session -s $SESSION 'npm run typecheck:watch' # Create session with first process
\; split-window -h 'npm run backend' # Split horizontally for second process
\; split-window -v 'npm run dev' # Split vertically for third process
\; select-pane -t 0 # Select the first pane
The dev:kill script simply terminates the session when you're done.
Setup Instructions
-
Install TMUX (if not already installed):
# macOS brew install tmux # Ubuntu/Debian sudo apt-get install tmux # Windows (WSL) sudo apt-get install tmux -
Add the scripts to your package.json:
{ "scripts": { "dev:all": "SESSION=\"${1:-my-project}\"; tmux kill-session -t $SESSION 2>/dev/null ; tmux new-session -s $SESSION 'npm run typecheck:watch' \\; split-window -h 'npm run backend' \\; split-window -v 'npm run dev' \\; select-pane -t 0", "dev:kill": "SESSION=\"${1:-my-project}\"; tmux kill-session -t $SESSION 2>/dev/null || echo 'No $SESSION session found'" } } -
Customize the commands to match your project's needs:
- Replace
'npm run typecheck:watch'with your TypeScript watcher - Replace
'npm run backend'with your backend command - Replace
'npm run dev'with your frontend dev server - Change
my-projectto your preferred default session name
- Replace
Usage Examples
Default session name:
npm run dev:all # Starts all processes in "my-project" session
npm run dev:kill # Stops the "my-project" session
Custom session name:
npm run dev:all my-blog # Starts session named "my-blog"
npm run dev:kill my-blog # Stops the "my-blog" session
Essential TMUX Navigation
Once your session is running, use these shortcuts:
Navigation:
Ctrl+Bthenโโโโ- Move between panesCtrl+Btheno- Cycle through panes
Session Management:
Ctrl+Bthend- Detach (leave processes running)tmux attach -t session-name- Reattach to sessiontmux list-sessions- See all active sessions
Pane Management:
Ctrl+Bthenx- Close current pane (with confirmation)Ctrl+Bthen%- Split current pane verticallyCtrl+Bthen"- Split current pane horizontally
Benefits of This Approach
- Single Command Startup: One command starts everything
- Persistent Sessions: Detach and reattach without stopping processes
- Project Isolation: Different projects can run simultaneously with unique session names
- Consistent Workflow: Same setup across all projects
- Easy Cleanup: One command stops all processes
Advanced Customizations
Different Layouts: Modify the split commands for different pane arrangements:
# Stacked layout (three horizontal panes)
tmux new-session -s $SESSION 'cmd1' \; split-window -v 'cmd2' \; split-window -v 'cmd3'
More Processes: Add more processes with additional splits:
tmux new-session -s $SESSION 'cmd1' \; split-window -h 'cmd2' \; split-window -v 'cmd3' \; split-window -v 'cmd4'
Environment Variables: Pass environment variables to your processes:
tmux new-session -s $SESSION 'NODE_ENV=development npm run dev'
Real-World Example
Here's how it looks for a typical React + Node.js project:
{
"scripts": {
"typecheck:watch": "tsc --noEmit --watch",
"backend": "nodemon src/server.js",
"dev": "vite dev --port 3000",
"dev:all": "SESSION=\"${1:-my-app}\"; tmux kill-session -t $SESSION 2>/dev/null ; tmux new-session -s $SESSION 'npm run typecheck:watch' \\; split-window -h 'npm run backend' \\; split-window -v 'npm run dev' \\; select-pane -t 0",
"dev:kill": "SESSION=\"${1:-my-app}\"; tmux kill-session -t $SESSION 2>/dev/null || echo 'No $SESSION session found'"
}
}
Now you can start your entire development environment with npm run dev:all and switch between your type checker, backend server, and frontend dev server seamlessly.
In Conclusion...
This TMUX + package.json approach transforms a messy multi-terminal setup into a clean, manageable workflow. It's especially valuable when working on multiple projects or when you need to quickly start/stop your entire development environment. If you like opening and switching between multiple Ghostty tabs while you work, this workflow is not for you.
Give it a try in your next project - you'll wonder how you ever worked without it!