Skip to content

Instantly share code, notes, and snippets.

@Micka33
Created August 29, 2025 13:24
Show Gist options
  • Save Micka33/dd77056a95268436b7b2cd063b5c9ff7 to your computer and use it in GitHub Desktop.
Save Micka33/dd77056a95268436b7b2cd063b5c9ff7 to your computer and use it in GitHub Desktop.
A simple TMUX script to run (`bin/rails s`, `bin/vite dev` and `sidekiq` in 3 separate top panes and have a bottom pane with a shell)
#!/usr/bin/env bash
set -euo pipefail
# PS4='+ ${BASH_SOURCE}:${LINENO}:${FUNCNAME[0]:-main}() '
# set -x
# -- Add to your ~/.tmux.conf --
# set -g mouse on
# or run
# echo "set -g mouse on" >> ~/.tmux.conf
# --- Config (override via env if needed) ---
BOTTOM_PERCENT="${BOTTOM_PERCENT:-60%}" # bottom row height percentage
RIGHT_PERCENT="${RIGHT_PERCENT:-35%}" # top right column width percentage (eg: takes 35% of the top row)
MIDDLE_PERCENT="${MIDDLE_PERCENT:-15%}" # top middle column width percentage (eg: takes 15% of the width left in the left column)
SESSION_NAME="${SESSION_NAME:-$(basename "$PWD")}"
# --- Commands to run ---
CMD_LEFT_PANE="${CMD_LEFT_PANE:-bin/rails s}"
CMD_MIDDLE_PANE="${CMD_MIDDLE_PANE:-bin/vite dev}"
CMD_RIGHT_PANE="${CMD_RIGHT_PANE:-sidekiq}" # or "bundle exec sidekiq"
require_tmux() {
if ! command -v tmux >/dev/null 2>&1; then
echo "tmux is required. Install with: brew install tmux" >&2
exit 1
fi
}
# Build layout in a specific target window (format: <session>:<window-index>)
# and start commands. This function runs tmux commands server-side; it doesn't
# depend on the interactive client being attached.
build_layout_in_window() {
local TARGET="$1"
# Ensure we are operating on the right window
tmux select-window -t "$TARGET"
# Start from a single pane: kill all other panes in that window
# (safe even if there's only one)
tmux kill-pane -a -t "$TARGET" || true
# Capture the top pane id (the only pane right now)
local P_TOP
P_TOP="$(tmux display-message -p -t "$TARGET" '#{pane_id}')"
# Create bottom free shell
tmux split-window -v -l "$BOTTOM_PERCENT" -t "$TARGET"
# Go back to the captured TOP pane explicitly
tmux select-pane -t "$P_TOP"
# Split TOP into three columns: left (P_TOP), new right (P_RIGHT1),
# then split the left again to create the middle (P_MID)
tmux split-window -h -l "$RIGHT_PERCENT" -t "$P_TOP"
local P_RIGHT
P_RIGHT="$(tmux display-message -p -t "$TARGET" '#{pane_id}')"
tmux split-window -h -l "$MIDDLE_PERCENT" -t "$P_TOP"
local P_MID
P_MID="$(tmux display-message -p -t "$TARGET" '#{pane_id}')"
local P_LEFT="$P_TOP"
# Fire up commands in precise panes
tmux send-keys -t "$P_LEFT" "$CMD_LEFT_PANE" C-m
tmux send-keys -t "$P_MID" "$CMD_MIDDLE_PANE" C-m
tmux send-keys -t "$P_RIGHT" "$CMD_RIGHT_PANE" C-m
# Put focus on the bottom shell (the one that was created by split-window -v)
# Easiest: select the last pane (bottom) by direction from any top pane
tmux select-pane -t "$P_LEFT"
tmux select-pane -D -t "$TARGET" 2>/dev/null || true
}
main() {
require_tmux
if [ -n "${TMUX-}" ]; then
# Already inside tmux: operate on the current window
local CUR_SESSION CUR_INDEX TARGET
CUR_SESSION="$(tmux display-message -p '#S')"
CUR_INDEX="$(tmux display-message -p '#I')"
TARGET="${CUR_SESSION}:${CUR_INDEX}"
build_layout_in_window "$TARGET"
else
# Not in tmux: create or reuse a session (no new iTerm2 window is spawned)
if ! tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
tmux new-session -d -s "$SESSION_NAME" -n dev
fi
# Build in window 0 of that session
build_layout_in_window "${SESSION_NAME}:0"
# Attach in THIS terminal window
tmux attach -t "$SESSION_NAME"
fi
}
main "$@"
@Micka33
Copy link
Author

Micka33 commented Aug 29, 2025

Usage :

Move to your Rails folder and run the script above.

# Don't forget to make that file executable: `chmod +x start_rails.sh`
# I personally like to locate it to the parent folder of my rails project(s)
cd my_rails_app
../start_rails.sh
Screenshot 2025-08-29 at 15 29 44

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment