env.dev

tmux: Sessions, Panes, .tmux.conf, and Neovim Integration

tmux is the BSD-licensed terminal multiplexer (3.6a, 2026) that survives SSH drops and reboots. Sessions, panes, .tmux.conf, scripting, and the Neovim handshake.

Last updated:

tmux is a terminal multiplexer that turns a single SSH or local shell into many. Nicholas Marriott released it in 2007 as a portable, BSD-licensed alternative to GNU Screen, and the current 3.6a build — with OSC 8 hyperlinks, mode-2 extended keys, and a 10-millisecond default escape-time since 3.5 — is what every Linux server, Mac dev machine, and remote pair-programming session relies on. Without it, a flaky Wi-Fi blip kills your tail -f, your kubectl logs, and the half-finished vim buffer; with it, tmux attach puts you back exactly where you left off, even after the laptop slept and the VPN rotated. Zellij arrived in 2022 with a friendlier UX and a WebAssembly plugin model, but tmux still wins on the things that matter on a real fleet — it's pre-installed nearly everywhere, its .tmux.conf is portable across two decades of machines, and the vim-tmux-navigator handshake with Neovim splits is still unmatched.

TL;DR

  • tmux new -s work starts a session; Ctrl-b d detaches; tmux attach -t work comes back. Sessions survive SSH drops, sleep, and reboots if you use tmux-resurrect.
  • tmux is a client-server architecture; one server process per user, many clients can attach to the same session — this is the killer feature Screen never matched.
  • Three layers of containers: session (a workspace) → window (a tab) → pane (a split). Most users only need two of the three.
  • Set escape-time 10, mouse on, and rebind the prefix from C-b to C-a or C-Space. Those three lines fix tmux's biggest defaults.
  • Pair tmux with vim-tmux-navigator to navigate Neovim splits and tmux panes with the same Ctrl-h/j/k/l chord.

What Is tmux and How Is It Different From Screen?

tmux runs as a daemon (the server) in the background. Every tmux command you type is a client that talks to that server over a Unix socket at /tmp/tmux-$UID/default. Sessions, windows, and panes live inside the server, not the terminal — that's why closing iTerm or losing SSH doesn't kill anything.

GNU Screen, released 1987, predates tmux by twenty years and ships with most distros for backwards compatibility. tmux superseded it for three reasons that still matter in 2026:

FeaturetmuxGNU Screen
Vertical splitsBuilt in (default since 1.0)Added late, awkward keybindings
Multiple clients per sessionFirst-class — attach from two terminals at onceSingle client only
ConfigurationTree of options via set -g, scriptable from inside tmux.screenrc with a less consistent grammar
LicenseBSD (permissive)GPL
Active development3.6a in 2026, regular releasesMaintenance mode; major releases years apart
Mouse supportSmooth out of the boxRequires xterm-mouse-mode toggle
Plugin ecosystemTPM + 100+ pluginsEffectively none

Stick with Screen only when you SSH into a locked-down server where you cannot apt-get install tmux. Otherwise, tmux is the default in 2026, and the tmux cheatsheet has every keybinding you'll need to memorise.

How Do tmux Sessions, Windows, and Panes Work?

Three nested concepts. Most muscle-memory wins come from getting the names right and never confusing them.

Session

A named workspace, persisted by the server. One project, one branch, one task = one session. Detach and reattach freely.

tmux new -s api

Window

A tab inside a session. Switch with prefix + number (0–9) or prefix + n / p. Each window has its own working directory.

prefix + c (create), prefix + , (rename)

Pane

A split inside a window. Horizontal or vertical, freely resizable, can run any program. Layouts can be saved.

prefix + " (split horiz), prefix + % (split vert)

The default prefix is Ctrl-b. Every tmux command begins by pressing the prefix, releasing it, then pressing the action key. So "split horizontally" is Ctrl-b then ", not Ctrl-b-". The prefix exists so tmux doesn't collide with readline shortcuts inside the panes.

The 12 commands that get you 95% of the way
tmux new -s work        # start a new session called "work"
tmux ls                 # list sessions
tmux attach -t work     # attach to "work"
tmux kill-session -t x  # kill session "x"

# Inside a session — prefix is Ctrl-b by default:
prefix d                # detach (process keeps running)
prefix c                # create new window
prefix ,                # rename current window
prefix 0..9             # jump to window N
prefix n / p            # next / previous window
prefix "                # split current pane horizontally
prefix %                # split current pane vertically
prefix arrow            # move focus to pane in that direction
prefix x                # kill current pane (with confirm)
prefix z                # zoom current pane (toggle full-screen)

What Should Go in Your .tmux.conf?

The default tmux config works, but four changes pay off the moment you make them. This is the minimum-viable ~/.tmux.conf — drop it on every new machine and your reflexes follow you.

~/.tmux.conf — opinionated minimum
# 1. Faster ESC handling — fixes vim insert-mode lag.
#    tmux 3.5 made 10 ms the default; older versions still ship 500 ms.
set -sg escape-time 10

# 2. Mouse support — scroll, click panes, drag dividers.
set -g mouse on

# 3. 256-color + true-color so vim/nvim themes render correctly.
set -g default-terminal "tmux-256color"
set -ga terminal-overrides ",*256col*:Tc"

# 4. Rebind prefix to Ctrl-Space (or Ctrl-a if you grew up on screen).
#    Ctrl-b clashes with Emacs-style readline back-one-char.
unbind C-b
set -g prefix C-Space
bind C-Space send-prefix

# Quality-of-life tweaks
set -g base-index 1                 # windows start at 1, not 0 (matches keyboard row)
setw -g pane-base-index 1
set -g renumber-windows on          # close window 2 of {1,2,3} → renumber to {1,2}
set -g history-limit 50000          # bigger scrollback
setw -g mode-keys vi                # vi-style motion in copy mode

# Reload config without restarting tmux
bind r source-file ~/.tmux.conf \; display-message "config reloaded"

# Better split keybindings — | and - mirror what they look like
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
unbind '"'
unbind %

Three things to know about applying a config. set -g is global, set -s is server-wide, and most options work both ways — escape-time is one of the rare -s-only options. prefix r reloads but doesn't restart the server, so default-terminal changes still require killing the server with tmux kill-server. And tmux 3.2 added -N for binding descriptions that show up in prefix ?; use it generously, your future self will thank you.

How Do You Integrate tmux With Neovim?

Two integrations are worth installing. vim-tmux-navigator unifies Ctrl-h/j/k/l across Neovim windows and tmux panes, and tmux-yank bridges the tmux copy buffer to your system clipboard so "+y in Neovim and prefix [ ... y in tmux end up in the same place.

~/.tmux.conf — Neovim-aware navigation
# vim-tmux-navigator: pass Ctrl-h/j/k/l to vim if vim is the focused process,
# otherwise switch tmux panes. The pattern is the recommended one from the
# upstream README.
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
        | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"

bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h'  'select-pane -L'
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j'  'select-pane -D'
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k'  'select-pane -U'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l'  'select-pane -R'
lazy.nvim — matching Neovim side
-- ~/.config/nvim/lua/plugins/tmux.lua
return {
  {
    'christoomey/vim-tmux-navigator',
    cmd = {
      'TmuxNavigateLeft', 'TmuxNavigateDown',
      'TmuxNavigateUp',   'TmuxNavigateRight',
    },
    keys = {
      { '<C-h>', '<cmd>TmuxNavigateLeft<cr>' },
      { '<C-j>', '<cmd>TmuxNavigateDown<cr>' },
      { '<C-k>', '<cmd>TmuxNavigateUp<cr>' },
      { '<C-l>', '<cmd>TmuxNavigateRight<cr>' },
    },
  },
}

For clipboard, Neovim 0.10+ has built-in OSC 52 support — set vim.g.clipboard = 'osc52' and "+y writes to your local clipboard even over SSH, no plugin required. tmux 3.2 added the set-clipboard on option so the same escape sequences flow through tmux untouched. Combined, these mean: yank in Neovim on a remote box → paste in your local browser, with no xclip, no pbcopy, no clipboard manager. For more on the editor side, see the Neovim guide and the Neovim Lua config guide.

How Do You Script tmux Layouts?

tmux is fully scriptable. Every keybinding is a tmux command you can run from a shell, which means the layout you build by hand can be checked in as a startup script. This is how teams turn "I open three panes, run X in one, Y in another, Z in the third" into ./dev.sh.

dev.sh — opinionated dev session for a Node project
#!/usr/bin/env bash
set -euo pipefail

SESSION="api"

# If the session already exists, just attach.
if tmux has-session -t "$SESSION" 2>/dev/null; then
  exec tmux attach -t "$SESSION"
fi

# Window 1: editor
tmux new-session -d -s "$SESSION" -n editor -c "$PWD"
tmux send-keys -t "$SESSION":editor 'nvim .' C-m

# Window 2: dev server + tests in two panes
tmux new-window -t "$SESSION" -n run -c "$PWD"
tmux send-keys -t "$SESSION":run 'pnpm dev' C-m
tmux split-window -h -t "$SESSION":run -c "$PWD"
tmux send-keys -t "$SESSION":run.2 'pnpm test --watch' C-m

# Window 3: shell
tmux new-window -t "$SESSION" -n shell -c "$PWD"

# Drop into the editor
tmux select-window -t "$SESSION":editor
exec tmux attach -t "$SESSION"

For more elaborate layouts, two community tools take over. tmuxinator (Ruby) reads a per-project YAML file and builds the session — battle-tested, but adds a Ruby dependency. tmuxifier is the same idea in pure shell. Either is a fine wrapper, but raw scripts like the one above stay readable for teammates who don't use tmux.

Which tmux Plugins Are Actually Worth Installing?

The plugin ecosystem is enormous. Three plugins move the needle for almost everyone; the rest is taste. Install them via the Tmux Plugin Manager (TPM).

PluginWhat it doesWhy it matters
tmux-resurrectSave and restore sessions, windows, panes, and (optionally) running programsReboots and crashes stop costing you state
tmux-continuumAuto-saves resurrect snapshots every 15 minutesSet-and-forget version of resurrect
tmux-yankSends copy-mode selections to the system clipboardCross-platform clipboard without xclip / pbcopy in your config
vim-tmux-navigatorUnifies Ctrl-h/j/k/l between Neovim and tmuxSingle mental model for split navigation
tmux-sensibleA short list of sane defaultsSkip if you already have a curated .tmux.conf
Bottom of ~/.tmux.conf — TPM bootstrap
# Plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
set -g @plugin 'tmux-plugins/tmux-yank'
set -g @plugin 'christoomey/vim-tmux-navigator'

set -g @resurrect-capture-pane-contents 'on'
set -g @continuum-restore 'on'   # auto-restore on tmux server start

# Keep this LAST. Initializes TPM.
run '~/.tmux/plugins/tpm/tpm'

Bootstrap once with git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm, then prefix I inside tmux to fetch the plugins listed in .tmux.conf. Use prefix U to update them.

tmux vs. Zellij vs. Screen — How Should You Pick?

ToolReleasedStrengthPick when
tmux2007Universal availability, scriptable, leanYou SSH into anything other than your laptop
Zellij2022 (Rust)Discoverable UI, Wasm plugins, layouts as dataYou want a multiplexer that teaches itself
GNU Screen1987Pre-installed on every Unix since foreverYou cannot install software on the box

Practical take: tmux is still the right default in 2026. Zellij is genuinely better at first contact — keybindings shown in the status bar, a built-in file picker, layouts as Kubernetes-style YAML — and if you only multiplex on your local laptop, it's a defensible choice. But the moment your workflow involves SSHing into anything you don't own (a CI runner, a teammate's box, a bare-metal server in a colo), you want the multiplexer that's already there. That's tmux.

When Should You Not Use tmux?

  • For a single long-running command. Use nohup cmd & or systemd-run --user --unit=foo cmd — they're what those tools exist for. tmux is overkill if you're never going to attach.
  • Inside a container that already has process supervision. Docker, Kubernetes, and systemd-nspawn already provide log capture and restart. Running tmux inside a container hides logs from the orchestrator.
  • As a poor-man's window manager. If you find yourself cloning windows because you're really running a desktop UI, switch to a proper tiling WM (i3, Sway, AeroSpace) — tmux panes can't host browser tabs.
  • For multi-user collaboration. Two clients on one tmux session works for pair programming, but you both have full shell access. For real shared sessions with read-only observers, use tmate (a tmux fork) or VS Code Live Share.
  • When ssh -t is enough. If you just need to run an interactive command and disconnect cleanly, ssh -t host 'cmd' with no multiplexer is simpler and faster.

Frequently Asked Questions

What is the latest version of tmux?

tmux 3.6a, the bug-fix follow-up to 3.6. The 3.5 release shipped in late 2024 and brought OSC 8 hyperlinks, mode-2 extended keys (matching xterm), and a default escape-time of 10 ms — fixing the long-standing vim insert-mode lag. Check github.com/tmux/tmux/releases for the canonical list.

How do I detach from a tmux session without killing it?

Press the prefix (Ctrl-b by default), then d. The session keeps running on the server; the processes inside it keep running. Reattach with `tmux attach` or `tmux attach -t name` if you have multiple sessions.

Why does my tmux session lose state when the server reboots?

The tmux server is a user process. A reboot kills it. Install tmux-resurrect plus tmux-continuum, set @continuum-restore "on", and snapshots are saved every 15 minutes and restored automatically when tmux starts. Note this saves the layout and (optionally) running shell commands — it does not snapshot vim or psql state.

Should I rebind the tmux prefix?

Yes if Ctrl-b clashes with anything you use — Emacs-style readline back-one-char is the most common collision. Ctrl-Space is a good neutral choice (no native shell binding); Ctrl-a is the screen default and easy to type, but it conflicts with readline beginning-of-line. Pick one and stick with it across all your machines.

How do I copy text from tmux to my system clipboard?

Easiest path: install tmux-yank and pair it with tmux 3.2+ `set -g set-clipboard on`. In copy mode (prefix [), select with v (in vi mode), copy with y, and the selection lands in your OS clipboard via OSC 52. Works over SSH if your terminal emulator supports OSC 52 (iTerm2, kitty, Alacritty, WezTerm all do).

Can I share a tmux session with a teammate?

Yes if you're on the same machine — both users attach with `tmux -S /tmp/shared attach`, after `chmod 777` on the socket. For remote pair programming, use tmate (a tmux fork that exposes a public SSH endpoint), or VS Code Live Share if your teammate isn't a terminal user.

References

  • tmux/tmux on GitHub — canonical source repo, releases, issue tracker, and CHANGES log
  • tmux Wiki — getting started, advanced configuration recipes, and FAQ from the maintainers
  • tmux CHANGES — full release-by-release changelog from 0.6 to 3.6a
  • Tmux Plugin Manager (TPM) — install, update, and remove plugins from inside tmux
  • tmux-resurrect — restore sessions, windows, and panes after a reboot
  • vim-tmux-navigator — Ctrl-h/j/k/l navigation across Neovim splits and tmux panes
  • Zellij — Rust-based modern alternative with a discoverable UI and Wasm plugins
  • tmux Cheatsheet (env.dev) — every keybinding and the most common config snippets, on one page
Was this helpful?

Read next

jq: Filter and Transform JSON From the Command Line

jq is the C-based JSON processor (1.8.1, 2025) that filters, reshapes, and pipes JSON inside shell scripts. Real-world recipes for kubectl, GitHub API, and AWS CLI.

Continue →

Frequently Asked Questions

What is the latest version of tmux?

tmux 3.6a, the bug-fix follow-up to 3.6. The 3.5 release shipped in late 2024 and brought OSC 8 hyperlinks, mode-2 extended keys (matching xterm), and a default escape-time of 10 ms — fixing the long-standing vim insert-mode lag. Check github.com/tmux/tmux/releases for the canonical list.

How do I detach from a tmux session without killing it?

Press the prefix (Ctrl-b by default), then d. The session keeps running on the server; the processes inside it keep running. Reattach with `tmux attach` or `tmux attach -t name` if you have multiple sessions.

Why does my tmux session lose state when the server reboots?

The tmux server is a user process. A reboot kills it. Install tmux-resurrect plus tmux-continuum, set @continuum-restore "on", and snapshots are saved every 15 minutes and restored automatically when tmux starts. Note this saves the layout and (optionally) running shell commands — it does not snapshot vim or psql state.

Should I rebind the tmux prefix?

Yes if Ctrl-b clashes with anything you use — Emacs-style readline back-one-char is the most common collision. Ctrl-Space is a good neutral choice (no native shell binding); Ctrl-a is the screen default and easy to type, but it conflicts with readline beginning-of-line. Pick one and stick with it across all your machines.

How do I copy text from tmux to my system clipboard?

Easiest path: install tmux-yank and pair it with tmux 3.2+ `set -g set-clipboard on`. In copy mode (prefix [), select with v (in vi mode), copy with y, and the selection lands in your OS clipboard via OSC 52. Works over SSH if your terminal emulator supports OSC 52 (iTerm2, kitty, Alacritty, WezTerm all do).

Can I share a tmux session with a teammate?

Yes if you're on the same machine — both users attach with `tmux -S /tmp/shared attach`, after `chmod 777` on the socket. For remote pair programming, use tmate (a tmux fork that exposes a public SSH endpoint), or VS Code Live Share if your teammate isn't a terminal user.

Stay up to date

Get notified about new guides, tools, and cheatsheets.