Skip to main content
Settings
Search
Appearance
Theme Mode
About
Jekyll v3.10.0
Environment Production
Last Build
2026-06-26 19:04 UTC
Current Environment Production
Build Time Jun 26, 19:04
Jekyll v3.10.0
Build env (JEKYLL_ENV) production
Quick Links
Page Location
Page Info
Layout article
Collection hacks
Path _hacks/tmux-conf-that-grows-up.md
URL /hacks/tmux-conf-that-grows-up/
Date 2026-06-25
Theme Skin
SVG Backgrounds
Layer Opacity
0.6
0.04
0.08

One .tmux.conf line per real annoyance: the config that grows up

The survival subset ends with a six-line ~/.tmux.conf and a promise: every line earns its place, no theme soup. That config is correct and it is enough to live in tmux.

Then you live in tmux for two weeks, and a few small things start to grate. Not bugs — papercuts. You hit j in copy mode and nothing scrolls. You select an error message, paste it into your browser, and get last week’s clipboard instead. You close window 2 of three and live with a 1 3 gap until you restart. The default status bar glows the same radioactive green it has since 1989.

None of these is worth a config rewrite. Each is worth exactly one line. This is the part-two config — the same “every line earns its place” rule, applied to the annoyances that only show up once tmux is muscle memory. Four annoyances, the lines that remove them, and proof each line does what the comment claims.

We ran every command below against tmux 3.4 on a fresh, isolated server (tmux -L, so none of this touched a real session). Where we couldn’t fully verify something on a headless box — the clipboard line — we say so plainly instead of pretending.

Annoyance 1: copy mode uses the wrong fingers

Copy mode is how you scroll back and select text (prefix [ from the survival subset). Out of the box it uses emacs-style movement keys. If your fingers are vi everywhere else — your editor, less, your shell in vi mode — copy mode is the one place that fights you. You press j to go down and nothing happens.

One line fixes the movement:

# Copy mode should use vi keys like everything else I touch
setw -g mode-keys vi

Ask tmux what it thinks after loading the file, and it agrees:

$ tmux show-options -g mode-keys
mode-keys vi

Now h j k l move, / searches, G jumps to the bottom — the navigation you already know. But movement is only half of it. The selection keys are still not Vim’s, which is the next annoyance.

Annoyance 2: selecting and yanking isn’t Vim’s v / y

With mode-keys vi you can move like Vim, but starting a selection is still Space and copying is still Enter. Your hands expect v to start a visual selection and y to yank it. Two lines teach copy mode those bindings:

# v starts a selection, y yanks it — Vim's visual mode, in tmux
bind -T copy-mode-vi v send -X begin-selection
bind -T copy-mode-vi y send -X copy-selection-and-cancel

These are real bindings in the copy-mode-vi key table, not wishful thinking. Ask tmux to list that table:

$ tmux list-keys -T copy-mode-vi | grep -E ' (v|y) '
bind-key -T copy-mode-vi v                 send-keys -X begin-selection
bind-key -T copy-mode-vi y                 send-keys -X copy-selection-and-cancel

Now the copy-mode dance is pure Vim: prefix [ to enter, v to start selecting, j/k// to extend, y to grab it and drop you back out. The text lands in tmux’s own paste buffer, ready for prefix ]. Which is great until you want it somewhere that isn’t tmux.

Annoyance 3: the yank never leaves tmux

Here’s the one that actually wastes your time. You copy an error in copy mode, switch to your browser to search it, hit paste — and get whatever was on your system clipboard from before. tmux copied to its own internal buffer; the OS clipboard never heard about it. tmux and your desktop keep two separate clipboards and don’t tell you.

One line bridges them:

# Send yanks to the system clipboard too, via the terminal (OSC 52)
set -g set-clipboard on
$ tmux show-options -g set-clipboard
set-clipboard on

How this works is worth thirty seconds, because it changes whether the line helps you. With set-clipboard on, tmux emits an OSC 52 terminal escape sequence — a standard way for a program to hand text to the terminal emulator, which then puts it on the real clipboard. The win: it needs no xclip, no xsel, no pbcopy. It rides the terminal, so it works the same over SSH as it does locally, as long as your terminal emulator supports OSC 52 (recent iTerm2, kitty, WezTerm, Windows Terminal, and Alacritty do; some older or locked-down terminals don’t).

The honest caveat: we verified the option is set (above), but we can’t show you the actual clipboard round-trip here — this was a headless build server with no clipboard and no terminal emulator to receive the OSC 52 sequence. So treat this line as “verified configured, not verified end-to-end.” The real test is yours: load the config, copy something in tmux with y, switch to a GUI app, and paste. If it shows up, your terminal honors OSC 52 and you’re done. If it doesn’t, the fallback is to pipe the selection through a clipboard tool instead — copy-selection-and-cancel becomes copy-pipe-and-cancel "xclip -sel clip" — but that’s a separate, terminal-specific setup, and we’re not pasting a version we didn’t run.

Annoyance 4: closing a window leaves a hole in the numbers

You run 0:edit 1:server 2:logs. The log window’s job is done, so you close it — prefix &. Now you have 0 and 1, fine. But close the middle one and tmux leaves the hole: 0 and 2, with nothing at 1. The numbers stop matching how many windows you have, and prefix 1 jumps to nothing.

Default tmux, watch the gap open:

$ tmux list-windows -t work -F '#{window_index}'
0
1
2
$ tmux kill-window -t work:1     # close the middle one
$ tmux list-windows -t work -F '#{window_index}'
0
2

0 and 2. Window 1 is gone and nothing slid down to fill it. One line tells tmux to close the gap automatically:

# When a window closes, renumber the rest so there are no holes
set -g renumber-windows on

Same test, this time with the line loaded (and base-index 1 from the survival subset, so we count from 1):

$ tmux list-windows -t work -F '#{window_index}'
1
2
3
$ tmux kill-window -t work:2     # close the middle one again
$ tmux list-windows -t work -F '#{window_index}'
1
2

The 3 slid down to 2. The numbers stay dense, prefix 1/prefix 2 always point at something, and you never again squint at a status bar wondering where window 2 went.

Annoyance 5: the status bar is a 1989 eyesore

This is the one that’s pure taste, so it goes last and you should feel free to skip it. The default status bar is black-on-radioactive-green and shows about six things you’ll never read. You don’t need a 200-line “powerline” rig with fonts to install. You need a calmer background, your session name where you can find it, and a clock. Four lines:

# A status bar that informs instead of glows
set -g status-style 'bg=#1d2021 fg=#a89984'
set -g status-left '#[bg=#458588,fg=#1d2021,bold] #S #[default] '
set -g status-right '#[fg=#a89984]%H:%M '
set -g status-left-length 30

tmux stores exactly what you set:

$ tmux show-options -g status-style
status-style "bg=#1d2021 fg=#a89984"
$ tmux show-options -g status-left
status-left "#[bg=#458588,fg=#1d2021,bold] #S #[default] "

You’ll know it took the moment you reload (prefix r): the bar drops from radioactive green to dark grey, your session name lands in a small blue badge on the left, and the clock moves to the right.

Plain-English translation of the format gibberish: status-style paints the whole bar a dark grey with muted foreground text. status-left puts your session name (#S) in a small blue-on-dark badge, then #[default] resets the colors so the window list after it looks normal. status-right shows the time (%H:%M) in the same muted grey. status-left-length only stops tmux from truncating a longer session name. The colors are gruvbox hex values because they’re easy on the eyes; swap them for anything. The point isn’t these specific colors — it’s that four lines get you a readable bar without a plugin or a Nerd Font.

The grown-up config, in one block

Append this to the survival subset. The whole ~/.tmux.conf now reads:

# --- the survival subset (every line earns its place) ---
unbind C-b
set -g prefix C-a
bind C-a send-prefix
set -g mouse on
set -g base-index 1
setw -g pane-base-index 1
bind | split-window -h
bind - split-window -v
bind r source-file ~/.tmux.conf \; display-message "tmux.conf reloaded"
set -g history-limit 10000

# --- the config that grows up (one line per annoyance) ---
# Copy mode should use vi keys like everything else I touch
setw -g mode-keys vi
# v starts a selection, y yanks it — Vim's visual mode, in tmux
bind -T copy-mode-vi v send -X begin-selection
bind -T copy-mode-vi y send -X copy-selection-and-cancel
# Send yanks to the system clipboard too, via the terminal (OSC 52)
set -g set-clipboard on
# When a window closes, renumber the rest so there are no holes
set -g renumber-windows on
# A status bar that informs instead of glows
set -g status-style 'bg=#1d2021 fg=#a89984'
set -g status-left '#[bg=#458588,fg=#1d2021,bold] #S #[default] '
set -g status-right '#[fg=#a89984]%H:%M '
set -g status-left-length 30

Reload it with prefix r (that binding is from the survival subset) and it flashes tmux.conf reloaded.

The part where it breaks

Two things to know before you paste.

set-clipboard on is only as good as your terminal. As covered above, the system-clipboard half rides on OSC 52, which the terminal emulator has to support and, on some, has to be explicitly enabled. If your yank still doesn’t reach the desktop clipboard after loading this, the config isn’t broken — your terminal is declining the handoff. Check your terminal’s settings for an “allow clipboard access” / OSC 52 toggle before you go hunting for a tmux fix that isn’t needed.

mode-keys vi changes more than scrolling. Flipping copy mode to vi keys means the keys you half-remember from emacs copy mode are gone. For the first day you’ll reach for the old ones. That’s the cost of the line, and it pays back the moment your editor and your terminal multiplexer finally agree on what j means.

The honest accounting

The survival subset bought you the one feature that matters: a session that outlives the terminal. None of today’s lines is that important, and that’s the point — these are the second tier, the ones you add only after the first six have earned your trust.

What each line actually buys, stated flatly:

  • mode-keys vi + the two binds: copy mode finally uses the fingers you already trained.
  • set-clipboard on: yanks reach the real clipboard — if your terminal does OSC 52 (verify it yourself; we couldn’t, here).
  • renumber-windows on: closing a window never leaves a hole in the numbering again. Verified, with the gap shown both ways.
  • The status bar: four lines, no plugin, no font — a bar you can read instead of one that glows.

It won’t “10x” your terminal. It removes four specific papercuts, one line each, and leaves the rule from part one intact: if a line can’t name the annoyance it kills, it doesn’t go in the file.