A script that rebuilds your project workspace in one command saves minutes every day and documents how to run the project.
Every tmux command can be run from a shell script, which lets you build a whole workspace reproducibly.
The pattern:
- Create the session detached with
new-session -d -s name -n firstwindow -c dir. - Add windows with
new-window -t name -n other -c dirand panes withsplit-window -t target. - Start programs by typing into panes with
send-keys -t target 'command' Enter.Enter(orC-m) is a key name; send-lfor literal text. - Finish with
select-windowandattach.
Targets (-t) name what a command acts on: session, session:window (window by index or name), session:window.pane. After split-window, the new pane is the active one, so the next send-keys -t session:window goes to it without needing pane numbers.
Make the script idempotent: if the session already exists, just attach. tmux has-session -t name returns a non-zero exit status when it does not exist.
Alternatives to send-keys: pass the command directly, new-window 'htop', but then the window closes when the program exits (unless remain-on-exit is on). send-keys instead types into a shell, so the shell survives and you can rerun the command. Tools such as tmuxinator and tmuxp generate the same commands from YAML.
Example
#!/usr/bin/env bash
S=dev; DIR=~/code/shop
if tmux has-session -t "$S" 2>/dev/null; then
exec tmux attach -t "$S"
fi
tmux new-session -d -s "$S" -n editor -c "$DIR"
tmux send-keys -t "$S:editor" 'vim .' Enter
tmux new-window -t "$S" -n run -c "$DIR"
tmux send-keys -t "$S:run" 'npm run dev' Enter
tmux split-window -v -t "$S:run" -c "$DIR" # new pane becomes active
tmux send-keys -t "$S:run" 'npm test -- --watch' Enter
tmux select-window -t "$S:editor"
exec tmux attach -t "$S"Remember
- new-session -d builds a session without attaching
- Targets: session:window.pane; windows can be named
- send-keys 'cmd' Enter types into a pane's shell
Watch out for
- Forgetting Enter at the end of send-keys, so the command is typed but never run.