tmux Basics
tmux Basics
tmux (terminal multiplexer) is the missing piece in most developers' workflows. It solves the "I wish I could save my terminal layout" problem and makes your development environment persistent and portable.
This is part 1 of a series:
- tmux Basics (this article) - Core concepts and commands
- tmux Configuration with chezmoi - Managing configs across machines
- TPM - Tmux Plugin Manager - Plugin ecosystem
- Ghostty + tmux Startup Automation - Auto-start workflows
- tmux Session Presets - Project-specific layouts
What Problem Does tmux Solve?
Without tmux:
- Close your terminal β Everything dies (servers, editors, log tails)
- Want a 3-pane layout? β Create it manually every time
- SSH to a server β Session dies if connection drops
- Switch projects β Manually recreate your window layout
With tmux:
- Close terminal β Sessions keep running
- Create layouts once β Save and restore them
- SSH sessions survive disconnects
- Switch projects β Just
tmux attach -t project-name
Core Concepts
Sessions
A tmux session is a collection of windows that persist even when you close your terminal.
bash# Create a session named "dev" tmux new -s dev # Detach from session (keeps running) Ctrl+B D # List sessions tmux ls # Reattach to session tmux attach -t dev # Kill session tmux kill-session -t dev
The key insight: Sessions are the persistence layer. This is Layer 2 in the Dev Environment Stack.
Windows
A tmux window is like a tab. Each session can have multiple windows.
bash# Inside tmux: Ctrl+B C # Create new window Ctrl+B , # Rename window Ctrl+B N # Next window Ctrl+B P # Previous window Ctrl+B 0-9 # Jump to window by number Ctrl+B & # Kill window
Panes
A tmux pane is a split within a window.
bash# Inside tmux: Ctrl+B % # Split vertically (left/right) Ctrl+B " # Split horizontally (top/bottom) Ctrl+B Arrow # Navigate between panes Ctrl+B X # Kill pane Ctrl+B Z # Zoom pane (toggle fullscreen) Ctrl+B Space # Cycle through layouts
Quick Start
Installation
bashbrew install tmux
Basic Workflow
bash# 1. Create a new session tmux new -s myproject # 2. Split into panes Ctrl+B % # Vertical split Ctrl+B " # Horizontal split # 3. Navigate Ctrl+B Arrow # Move between panes # 4. Detach Ctrl+B D # Session keeps running # 5. Close terminal, go to lunch, whatever # 6. Later: Reattach tmux attach -t myproject # Everything is exactly as you left it!
Creating Preset Layouts
This is the answer to "I want certain terminal windows open when I press Cmd+T".
Method 1: Shell Script
Create ~/.local/bin/dev-session:
bash#!/bin/bash # Create session in detached mode tmux new-session -d -s dev -n editor # Split window into panes tmux split-window -h -t dev tmux split-window -v -t dev:0.1 # Send commands to each pane tmux send-keys -t dev:0.0 'nvim' C-m tmux send-keys -t dev:0.1 'npm run dev' C-m tmux send-keys -t dev:0.2 'git status' C-m # Select first pane tmux select-pane -t dev:0.0 # Attach to session tmux attach -t dev
Make it executable:
bashchmod +x ~/.local/bin/dev-session
Usage:
bashdev-session # Creates your preset layout instantly!
Result:
βββββββββββββββββββ¬ββββββββββββββββββ
β β npm run dev β
β nvim β (server logs) β
β βββββββββββββββββββ€
β β git status β
βββββββββββββββββββ΄ββββββββββββββββββ
Method 2: tmuxinator (Session Manager)
tmuxinator lets you define layouts in YAML.
Install:
bashbrew install tmuxinator
Create a project:
bashtmuxinator new myproject
Edit the config (~/.config/tmuxinator/myproject.yml):
yamlname: myproject root: ~/Code/myproject windows: - editor: layout: main-vertical panes: - nvim . - npm run dev - git status - logs: - tail -f logs/development.log - shell: - # Empty pane for commands
Usage:
bashtmuxinator start myproject # Creates entire layout tmuxinator stop myproject # Kills session tmuxinator list # Show all projects
Method 3: Tmux Resurrect (Save Any Layout)
Save and restore tmux sessions automatically.
Install: (requires TPM - Tmux Plugin Manager)
bash# First install TPM git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm # Add to ~/.tmux.conf: set -g @plugin 'tmux-plugins/tpm' set -g @plugin 'tmux-plugins/tmux-resurrect' set -g @plugin 'tmux-plugins/tmux-continuum' # Auto-save # Initialize TPM run '~/.tmux/plugins/tpm/tpm' # Reload tmux config tmux source ~/.tmux.conf # Inside tmux: Install plugins Ctrl+B I
Usage:
bash# Create any layout you want manually # Then save it: Ctrl+B Ctrl+S # Save session # Later, restore: Ctrl+B Ctrl+R # Restore session
Auto-save setup:
bash# Add to ~/.tmux.conf set -g @continuum-restore 'on' set -g @continuum-save-interval '15' # Save every 15 minutes
Essential Keybindings
Note: Default prefix is Ctrl+B. You can change it to Ctrl+A (more ergonomic):
bash# Add to ~/.tmux.conf unbind C-b set -g prefix C-a bind C-a send-prefix
Session Management
| Keybinding | Action |
|---|---|
Ctrl+B D | Detach from session |
Ctrl+B S | List and switch sessions |
Ctrl+B $ | Rename session |
Window Management
| Keybinding | Action |
|---|---|
Ctrl+B C | Create window |
Ctrl+B , | Rename window |
Ctrl+B N | Next window |
Ctrl+B P | Previous window |
Ctrl+B 0-9 | Jump to window number |
Ctrl+B & | Kill window |
Pane Management
| Keybinding | Action |
|---|---|
Ctrl+B % | Vertical split |
Ctrl+B " | Horizontal split |
Ctrl+B Arrow | Navigate panes |
Ctrl+B X | Kill pane |
Ctrl+B Z | Zoom pane (fullscreen toggle) |
Ctrl+B Space | Cycle layouts |
Ctrl+B { | Swap pane left |
Ctrl+B } | Swap pane right |
Copy Mode (Scrollback)
| Keybinding | Action |
|---|---|
Ctrl+B [ | Enter copy mode |
Space | Start selection (in copy mode) |
Enter | Copy selection |
Ctrl+B ] | Paste |
Recommended Configuration
Create ~/.tmux.conf:
bash# ============================================ # Basic Settings # ============================================ # Change prefix to Ctrl+A (more ergonomic) unbind C-b set -g prefix C-a bind C-a send-prefix # Enable mouse support set -g mouse on # Start windows and panes at 1, not 0 set -g base-index 1 setw -g pane-base-index 1 # Renumber windows when one is closed set -g renumber-windows on # Enable 256 colors set -g default-terminal "screen-256color" # Increase scrollback buffer set -g history-limit 50000 # ============================================ # Better Keybindings # ============================================ # Split panes using | and - bind | split-window -h bind - split-window -v unbind '"' unbind % # Reload config bind r source-file ~/.tmux.conf \; display "Config reloaded!" # Vim-like pane navigation bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R # Vim-like copy mode setw -g mode-keys vi bind -T copy-mode-vi v send -X begin-selection bind -T copy-mode-vi y send -X copy-selection-and-cancel # ============================================ # Status Bar # ============================================ set -g status-position bottom set -g status-bg colour234 set -g status-fg colour137 set -g status-left '#[fg=colour233,bg=colour245,bold] #S ' set -g status-right '#[fg=colour233,bg=colour245,bold] %Y-%m-%d %H:%M ' # ============================================ # Plugins (requires TPM) # ============================================ set -g @plugin 'tmux-plugins/tpm' set -g @plugin 'tmux-plugins/tmux-sensible' set -g @plugin 'tmux-plugins/tmux-resurrect' set -g @plugin 'tmux-plugins/tmux-continuum' # Auto-restore sessions set -g @continuum-restore 'on' # Initialize TPM (keep at bottom) run '~/.tmux/plugins/tpm/tpm'
Auto-start tmux on Terminal Open
Option 1: Always use tmux
Add to ~/.zshrc:
bash# Auto-attach to tmux if not already in tmux if command -v tmux &> /dev/null && [ -z "$TMUX" ]; then # Try to attach to 'default' session, or create it tmux attach -t default || tmux new -s default fi
Option 2: Only for Cmd+T
If you're using Ghostty, configure it to run a script on new tabs:
-
Create
~/.local/bin/start-tmux:bash#!/bin/bash tmux attach -t default || tmux new -s default -
Make it executable:
chmod +x ~/.local/bin/start-tmux -
In Ghostty preferences, set shell to:
/Users/yourusername/.local/bin/start-tmux
Common Workflows
Development Session
bash# Create project-specific session tmux new -s myapp # Window 1: Editor nvim . # Create new window for server Ctrl+B C npm run dev # Create new window for git Ctrl+B C git status # Create new window for logs Ctrl+B C tail -f logs/development.log # Switch between windows Ctrl+B 0 # Editor Ctrl+B 1 # Server Ctrl+B 2 # Git Ctrl+B 3 # Logs
Remote Development
bash# SSH to server ssh user@server # Create/attach to session tmux attach -t work || tmux new -s work # Do your work... # Connection drops? No problem! # Just SSH again and reattach: ssh user@server tmux attach -t work # Everything is still there!
Pair Programming
bash# Person 1: Create session tmux new -s pairing # Person 2: SSH to same machine and attach ssh user@server tmux attach -t pairing # Both see the same screen!
Troubleshooting
Colors look wrong
bash# Add to ~/.tmux.conf set -g default-terminal "screen-256color"
Mouse doesn't work
bash# Add to ~/.tmux.conf set -g mouse on
Can't scroll back
bash# Enter copy mode Ctrl+B [ # Now use arrow keys, Page Up/Down, or Vim keys (if configured)
Clipboard doesn't work
bash# macOS: Install reattach-to-user-namespace brew install reattach-to-user-namespace # Add to ~/.tmux.conf set -g default-command "reattach-to-user-namespace -l $SHELL"
Comparison: tmux vs Terminal Native Splits
| Feature | tmux | Ghostty/iTerm2 Native |
|---|---|---|
| Persistence | β Survives closing terminal | β Dies with terminal |
| Remote sessions | β Works over SSH | β No remote support |
| Scriptable | β Full automation | β οΈ Limited |
| Cross-platform | β Works everywhere | β Terminal-specific |
| Learning curve | Higher (new keybindings) | Lower (familiar) |
Bottom line: Use tmux if you want persistence, remote work, or scripted layouts. Use terminal-native splits for quick temporary splits.
Related:
- Dev Environment Stack - Understanding the four layers
- Terminal Keyboard Shortcuts - Shell-level shortcuts (different layer)
- Neovim/LazyVim Workflows/File Navigation in LazyVim - Editor navigation inside tmux