← Back to articles

tmux Basics

Path: Computer Tech/Terminal/tmux/tmux Basics.mdUpdated: 2/3/2026

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. tmux Configuration with chezmoi - Managing configs across machines
  3. TPM - Tmux Plugin Manager - Plugin ecosystem
  4. Ghostty + tmux Startup Automation - Auto-start workflows
  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

KeybindingAction
Ctrl+B DDetach from session
Ctrl+B SList and switch sessions
Ctrl+B $Rename session

Window Management

KeybindingAction
Ctrl+B CCreate window
Ctrl+B ,Rename window
Ctrl+B NNext window
Ctrl+B PPrevious window
Ctrl+B 0-9Jump to window number
Ctrl+B &Kill window

Pane Management

KeybindingAction
Ctrl+B %Vertical split
Ctrl+B "Horizontal split
Ctrl+B ArrowNavigate panes
Ctrl+B XKill pane
Ctrl+B ZZoom pane (fullscreen toggle)
Ctrl+B SpaceCycle layouts
Ctrl+B {Swap pane left
Ctrl+B }Swap pane right

Copy Mode (Scrollback)

KeybindingAction
Ctrl+B [Enter copy mode
SpaceStart selection (in copy mode)
EnterCopy 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

FeaturetmuxGhostty/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 curveHigher (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: