# 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