Oct 24, 2026 • 4 min read
Automating Development Environments with Nix and Custom Tmux Scripts
Introduction
Setting up terminal development environments often requires repetitive manual steps: opening splits, launching dev servers, and setting up environment variables. Doing this manually every time you start work leads to context switching overhead and inconsistent layouts. To make environment setup seamless and reliable, combine Nix with a custom Tmux script.
Instead of manually setting up panes and dependencies, this approach builds an isolated development workspace automatically upon entering a Nix shell.
The full source code for this environment is available in the rosera/nix-shell-pack repository on GitHub.
The Custom Tmux Script (dev.tmux)
The first step is defining a shell script that handles session creation and pane layouts.
This script checks for an existing session or automatically generates a unique session name using random adjective-noun pairs. It then creates a three-pane window layout and attaches to it:
#!/usr/bin/env bash
# DEFAULT_PORT
DEFAULT_PORT=8080
# Detect OS shell
if [[ "$OSTYPE" == "darwin"* ]]; then
SHELL_CMD="zsh"
else
SHELL_CMD="bash"
fi
# Generate random Docker-like name
generate_session_name() {
ADJECTIVES=(happy brave calm eager fancy gentle jolly kind lucky nice proud quick shiny witty bold clever)
NOUNS=(tiger panda eagle otter fox whale lion falcon wolf bear koala shark)
adj=${ADJECTIVES[$RANDOM % ${#ADJECTIVES[@]}]}
noun=${NOUNS[$RANDOM % ${#NOUNS[@]}]}
echo "${adj}-${noun}-dev"
}
SESSION=${2:-$(generate_session_name)}
echo "Using SESSION=$SESSION"
# Check if the session already exists
tmux has-session -t "$SESSION" 2>/dev/null
# Create new session if it doesn't exist
if [ $? != 0 ]; then
tmux new-session -d -s "$SESSION" "$SHELL_CMD"
tmux split-window -h -t "$SESSION" "$SHELL_CMD"
tmux split-window -v -t "$SESSION" "$SHELL_CMD"
# Optional: Send commands to specific panes
# tmux send-keys -t "$SESSION":0.0 "hugo serve -p $DEFAULT_PORT" C-m
tmux send-keys -t "$SESSION":0
fi
tmux attach-session -t "$SESSION"Wrapping the Script in Nix (shell.nix)
Once your script (dev.tmux) is ready, use Nix to bundle the script into an executable package (dev-tmux) and construct the environment shell.
Using pkgs.writeShellScriptBin, Nix turns the local script file into a binary available in the PATH inside the shell context:
with import <nixpkgs> {};
let
# External Script: Reads './dev.tmux' and creates a binary executable 'dev-tmux'
tmuxLayout = pkgs.writeShellScriptBin "dev-tmux" (builtins.readFile ./dev.tmux);
in
pkgs.mkShell {
name = "tmux-dev";
nativeBuildInputs = with pkgs; [
tmux
tmuxLayout
];
LANGUAGE = "Tmux";
VERSION = "tmux -V";
shellHook = ''
# Environment startup info
echo "Welcome to $LANGUAGE Development Environment"
$VERSION
# Trap: Kills the tmux session as soon as you exit the nix-shell
trap "tmux kill-session -t go-dev" EXIT
# Execute the custom Tmux layout
exec dev-tmux
'';
}Running the Environment
You can spin up this development environment either from a local clone or directly from the remote repository.
Option 1: Running Locally
If you have cloned the repository locally, navigate to the directory containing shell.nix and dev.tmux, then execute:
nix-shellOption 2: Running Directly from GitHub
Nix allows running shell expressions directly from a remote Git URL without needing to manually clone the repository first:
nix-shell https://github.com/rosera/nix-shell-pack/archive/main.tar.gz -A development.nix-tmuxUpon executing either command, Nix fetches tmux, constructs the dev-tmux wrapper binary, executes the layout script, and attaches you directly to your configured terminal session.
The Isolated Workspace Loop
When combining Nix and Tmux, your terminal lifecycle becomes fully deterministic and self-contained.
[ nix-shell ]
/ \
/ \
v v
[ Dependencies ] [ dev-tmux Binary ]
\ /
\ /
v v
[ Managed Tmux Workspace ]- Instantiation: Running
nix-shellevaluatesshell.nix, downloadstmux, and compilesdev.tmuxinto an ephemeral binary executable. - Execution: The
shellHooktriggersexec dev-tmux, instantly dropping you into your split-pane workspace. - Cleanup: Once you exit the shell, the
traphook cleans up background sessions, leaving no orphan processes behind.
Conclusion
Combining Nix with custom Tmux layout scripts turns interactive environment creation into a repeatable software pattern. By packaging your layouts directly within your project’s declarative environment, onboarding developers or resuming work becomes a single-command process.