# 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:**
1. **tmux Basics** (this article) - Core concepts and commands
2. [[2. tmux Configuration with chezmoi]] - Managing configs across machines
3. [[3. TPM - Tmux Plugin Manager]] - Plugin ecosystem
4. [[4. Ghostty + tmux Startup Automation]] - Auto-start workflows
5. [[5. 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
```bash
brew 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:**
```bash
chmod +x ~/.local/bin/dev-session
```
**Usage:**
```bash
dev-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:**
```bash
brew install tmuxinator
```
**Create a project:**
```bash
tmuxinator new myproject
```
**Edit the config** (`~/.config/tmuxinator/myproject.yml`):
```yaml
name: 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:**
```bash
tmuxinator 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:
1. Create `~/.local/bin/start-tmux`:
```bash
#!/bin/bash
tmux attach -t default || tmux new -s default
```
2. Make it executable: `chmod +x ~/.local/bin/start-tmux`
3. 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