The tmux Keymap
Every key binding in Cole's tmux config: stock prefix keys, one-chord Alt keys for windows and sessions, Alt-a for an instant agent window, SSH-aware splits, phone-friendly control keys and the mouse.
f. 12rThe ShellCapitula · contents
Cole’s tmux keymap keeps the stock bindings worth keeping, adds one-chord Alt keys for moving between windows and sessions, and gives agents keys of their own: Alt+a opens a Claude Code window on the spot, and a new window opened from an SSH pane lands on the same server. This page is the full reference for every binding in tmux’s config file, with the reason each one exists.
StudiumThe tmux keymap
Choose a layer, then point at a key, tap it, or focus the drawing and press the chord.
Point at a key
Sanguine keys do something in this layer. On a Mac, Alt is the Option key: Cole’s Ghostty makes the left Option key act as Alt (macos-option-as-alt = left), and Termius has the same switch on the phone.
| Do | With | Why |
|---|---|---|
| Scroll | Wheel | Scrolls five lines a notch; scrolling up enters copy mode on its own. |
| Copy a selection | Drag, release | Copies and stays in copy mode at the same place, instead of snapping back to the bottom. |
| Switch window or session | Click the status bar | The first row lists windows, the second every session; clicking either switches to it. |
Every binding, as a list
| Keys | Does | Line in tmux.conf |
|---|---|---|
| Alt+H | Previous window | bind -n M-h previous-window |
| Alt+L | Next window | bind -n M-l next-window |
| Alt+S | Next session | bind -n M-s switch-client -n |
| Alt+Shift+S | Previous session | bind -n M-S switch-client -p |
| Alt+1 | Window 1 | bind -n M-1 select-window -t 1 |
| Alt+2 | Window 2 | bind -n M-2 select-window -t 2 |
| Alt+3 | Window 3 | bind -n M-3 select-window -t 3 |
| Alt+4 | Window 4 | bind -n M-4 select-window -t 4 |
| Alt+5 | Window 5 | bind -n M-5 select-window -t 5 |
| Alt+6 | Window 6 | bind -n M-6 select-window -t 6 |
| Alt+7 | Window 7 | bind -n M-7 select-window -t 7 |
| Alt+8 | Window 8 | bind -n M-8 select-window -t 8 |
| Alt+9 | Window 9 | bind -n M-9 select-window -t 9 |
| Alt+A | New agent window | bind -n M-a new-window -a -n yolo -c "#{pane_current_path}" 'exec zsh -lic "claude --dangerously-skip-permissions"' |
| Alt+Y | Kill window | bind -n M-y kill-window |
| Alt+C | Capture scrollback | bind -n M-c capture-pane -S - -E - \; display-message 'captured scrollback to tmux buffer' |
| Alt+Shift+C | Capture to the clipboard | bind -n M-C run-shell -E "~/.dotfiles/base/tmux-copy-buffer.sh" |
| Ctrl+K | Clear scrollback | bind -n C-k clear-history |
| Ctrl+B then C | New window, same host | bind c run-shell "~/.dotfiles/base/tmux-ssh-inherit.sh window #{pane_id}" |
| Ctrl+B then Ctrl+C | New local window | bind C-c new-window -a -c "#{pane_current_path}" |
| Ctrl+B then Shift+| | Split side by side | bind | run-shell "~/.dotfiles/base/tmux-ssh-inherit.sh hsplit #{pane_id}" |
| Ctrl+B then - | Split top and bottom | bind - run-shell "~/.dotfiles/base/tmux-ssh-inherit.sh vsplit #{pane_id}" |
| Ctrl+B then A | New agent window | bind a new-window -a -n yolo -c "#{pane_current_path}" 'exec zsh -lic "claude --dangerously-skip-permissions"' |
| Ctrl+B then Shift+A | New Claude window that says hi | bind A new-window -a -n claude -c "#{pane_current_path}" 'exec zsh -lic "claude \"hi\""' |
| Ctrl+B then K | Send Ctrl+C | bind k send-keys C-c |
| Ctrl+B then Q | Send Ctrl+D | bind q send-keys C-d |
| Ctrl+B then Z | Send Ctrl+Z | bind z send-keys C-z |
| Ctrl+B then L | Send Ctrl+L | bind l send-keys C-l |
| Ctrl+B then R | Reload the config | bind r source-file ~/.tmux.conf \; display-message "Config reloaded" |
| Ctrl+B then Shift+M | Toggle the mouse | bind M set -g mouse \; display-message "mouse: #{?mouse,on,off}" |
| Ctrl+B then S | Session tree | bind s set -gF @chooser-session '#{session_id}' \; choose-tree -Zs -F '#{E:@tree-fmt}' |
| Ctrl+B then W | Window tree | bind w set -gF @chooser-session '#{session_id}' \; choose-tree -Zw -F '#{E:@tree-fmt}' |
| Ctrl+B then B | Toggle the status bar | bind b if -F "#{==:#{status},off}" "set -g status 2" "set -g status off" |
| Ctrl+B then Shift+B | Toggle the sessions row | bind B if -F "#{==:#{status},2}" "set -g status on" "set -g status 2" |
| Ctrl+B then Ctrl+S | Save the layout | set -g @plugin 'tmux-plugins/tmux-resurrect' |
| Ctrl+B then Ctrl+R | Restore the layout | set -g @continuum-restore 'off' |
| Ctrl+B then D | Detach (tmux default) | (tmux default) |
| Ctrl+B then X | Kill pane (tmux default) | (tmux default) |
| Ctrl+B then [ | Copy mode (tmux default) | (tmux default) |
| Ctrl+B then ] | Paste the buffer (tmux default) | (tmux default) |
The keyboard above is drawn from the same file the tables below come from, base/tmux.conf. Pick a key to see what it does on its own and after the prefix.
How to read the bindings
tmux has two kinds of keys. Prefix keys take two steps: press the prefix, Ctrl+b by default,
let go, then press the key. Root keys fire on their own, with no prefix, and tmux catches them before the program
in the pane ever sees them. The config writes root keys as bind -n.
tmux’s own notation shows up in the config: C-b is Ctrl+b, and M-h is
Alt+h (M for Meta, the old name for Alt). An uppercase letter means Shift, so M-S is
Alt+Shift+s.
Cole keeps the stock prefix. Windows and panes are numbered from 1, not 0, so the first window sits under the 1 key,
and renumber-windows closes the gaps when a window goes away.
No-prefix Alt bindings
These are the everyday movement keys. Each one is a single chord, which matters on a phone keyboard in Termius, where every extra keystroke is a tap.
| Keys | What it does | Why |
|---|---|---|
| Alt+h | Previous window | One chord, phone-friendly, h is left in vim |
| Alt+l | Next window | One chord, l is right in vim |
| Alt+s | Next session, wrapping around | Hop between projects without a picker |
| Alt+Shift+s | Previous session | The reverse of Alt-s |
| Alt+1 to Alt+9 | Jump to window 1 to 9 | Direct jumps; windows start at 1 |
| Alt+a | New window named yolo running Claude Code with permission prompts off |
An agent, right now, in this directory |
| Alt+y | Kill the current window, no confirmation | Faster than the stock &, which asks first |
| Alt+c | Capture the whole pane’s scrollback into tmux’s paste buffer | Paste it into any pane with prefix ] |
| Alt+Shift+c | Copy the whole scrollback to the system clipboard | Works on macOS, WSL, Wayland, X11, and over SSH |
| Ctrl+k | Clear the pane’s scrollback history | A clean slate before a noisy command |
The config block for the movement keys, exactly as written:
# Quick window switching with Alt+number
bind -n M-h previous-window # Alt+h = previous window (mobile-friendly)
bind -n M-l next-window # Alt+l = next window (mobile-friendly)
bind -n M-s switch-client -n # Alt+s = next session (cycles, wraps)
bind -n M-S switch-client -p # Alt+Shift+s = previous session
The two copy keys differ in where the text goes. Alt+c runs capture-pane -S - -E -, which
grabs everything from the top of the history to the bottom, and keeps it inside tmux. The shifted version runs a small
helper,
tmux-copy-buffer.sh, that picks whichever
clipboard tool exists (pbcopy on a Mac, clip.exe in WSL, wl-copy, xclip or xsel on Linux desktops)
and, inside an SSH session with none of those, hands the text to tmux, which sends it to your local terminal as an
OSC 52 escape sequence. That last path is how a whole agent transcript on a server ends up on the laptop’s clipboard.
Prefix bindings
Windows and splits
| Keys | What it does |
|---|---|
| prefix c | New window right after the current one, in the current directory. If the pane is running ssh, the new window is already connected to the same host |
| prefix Ctrl+c | New window, always local, even from an SSH pane |
| prefix | | Split side by side (SSH-aware, like prefix c) |
| prefix - | Split top and bottom (SSH-aware) |
The stock prefix c opens a window at the next free number, usually the end of the list, in the session’s
working directory. Cole’s version inserts it right after the current window (-a), in the directory you are in, which
keeps related windows next to each other.
The SSH part is the clever bit. When the pane is running ssh, the binding calls
tmux-ssh-inherit.sh, which reads the ssh
command line back from the process table, keeps the connection options, drops any remote command, and opens the new
window already logged in to the same host. If the remote shell reports its working directory (Cole’s zsh does, with an
OSC 7 escape sequence on every prompt), the new window even lands in the same remote directory. The window is named for
the host and pinned, so it does not get renamed to a useless ssh. Before this, every new window from a server pane
meant retyping the ssh and the cd. For non-SSH panes the helper does exactly what the plain binding would. The
SSH page covers the details, including why it only looks at direct children of the pane’s shell (a jump host
starts a second ssh that must not be replayed).
Prefix Ctrl+c is the escape hatch, in the config’s own words:
# Escape hatch: always a LOCAL window, even from an ssh'd pane. Same key as the
# stock new-window, plus Ctrl — mnemonically "c, but don't be clever".
bind C-c new-window -a -c "#{pane_current_path}"
Cole’s description of the keymap puts it this way: “custom tmux bindings like Alt-H and Alt-L, in addition to the standard ones like Ctrl-B and Ctrl-C to start new windows or Alt-A to start an agentic window off the bat”.
Agent windows
| Keys | What it does |
|---|---|
| prefix a | New window named yolo running claude --dangerously-skip-permissions in the current directory |
| Alt+a | The same, without the prefix |
| prefix Shift+a | New window named claude running Claude Code with a first message of “hi”, permission prompts on |
“Yolo” is the nickname for running Claude Code with its permission prompts switched off, the same mode the yu and the Claude Launchers launcher uses. Here is the binding:
bind a new-window -a -n yolo -c "#{pane_current_path}" 'exec zsh -lic "claude --dangerously-skip-permissions"' \; setw automatic-rename off
Two details make it work. First, setw automatic-rename off keeps the name yolo, so the window stands out in the
status line instead of turning into claude or a directory name. Second, the command runs inside
zsh -lic, a login, interactive zsh. The comment in the config explains why: without it, tmux runs the command through
a bare sh -c that inherits the tmux server’s environment, frozen at whatever moment the server started. An API key
or cloud token that rotated since then is stale in that snapshot, and the agent fails with an authentication error. The
zsh -lic wrapper reads the shell startup files, which load the current credentials from ~/.env_secrets. That is
also why typing claude by hand in a fresh window always worked while a raw command binding did not.
Since agent windows open in the current directory, the natural move is to cd into a repository or a
worktree and hit Alt+a. For many agents at once, the
Parallel Worktrees launcher creates the windows and types the launch commands itself.
Mobile-friendly control keys
| Keys | Sends | Normally means |
|---|---|---|
| prefix k | Ctrl+c | Interrupt the running program |
| prefix q | Ctrl+d | End of input, exits a shell |
| prefix z | Ctrl+z | Suspend the program |
| prefix l | Ctrl+l | Clear the screen |
# Mobile-friendly bindings (after Ctrl+B prefix)
bind k send-keys C-c # Ctrl+B then k = Ctrl+C (kill/interrupt)
bind q send-keys C-d # Ctrl+B then q = Ctrl+D (exit/EOF)
bind z send-keys C-z # Ctrl+B then z = Ctrl+Z (suspend)
bind l send-keys C-l # Ctrl+B then l = Ctrl+L (clear)
On a phone, the control keys live in an extra row above the on-screen keyboard. Once the prefix is a key you can reach, every other control character becomes the prefix plus a plain letter, typed on the normal keyboard.
The bar, the mouse and the config
| Keys | What it does |
|---|---|
| prefix s | Session chooser, colored like the status bar |
| prefix w | Window chooser, colored like the status bar |
| prefix b | Hide the status bar, or bring it back (with its second row on tmux 3.7 and newer) |
| prefix Shift+b | Switch between a one-row and a two-row bar (tmux 3.7 and newer) |
| prefix Shift+m | Turn mouse mode on or off |
| prefix r | Reload the config and say “Config reloaded” |
The choosers are tmux’s stock choose-tree with a color wrapper: the current session in bold gold, every window in its
activity color, a handoff badge on windows whose agent handed off. The The tmux Status Line page explains the colors.
Keys from the plugins
The config loads three plugins through the Tmux Plugin Manager, and they bring keys of their own.
| Keys | From | What it does |
|---|---|---|
| prefix Shift+i | TPM | Install the plugins listed in the config |
| prefix Shift+u | TPM | Update plugins |
| prefix Alt+u | TPM | Remove plugins no longer listed |
| prefix Ctrl+s | tmux-resurrect | Save every session, window and pane layout |
| prefix Ctrl+r | tmux-resurrect | Restore the saved layout |
| prefix Ctrl+p / Ctrl+n | tmux-sensible | Previous and next window, holding Ctrl |
| prefix Shift+r | tmux-sensible | Reload the config (a second way) |
tmux-sensible only binds a key that is still free, so Cole’s own bindings win. That matters for prefix b, which sensible would otherwise turn into “last window”.
Restore is manual on purpose (@continuum-restore 'off'). After a restore, two hooks Cole added put every agent back:
the save hook records which Claude Code or Codex conversation ran in which pane, and the restore hook types
claude --resume <id> or codex resume <id> into each one. The tmux page
covers how that works and the gap it closes.
Stock keys that still matter
Everything not overridden keeps its default. The ones worth knowing:
| Keys | What it does |
|---|---|
| prefix d | Detach: tmux and everything in it keeps running |
| prefix [ | Copy mode, to scroll and select with the keyboard |
| prefix ] | Paste the most recent tmux buffer |
| prefix , | Rename the window |
| prefix $ | Rename the session |
| prefix n / p | Next and previous window |
| prefix ( / ) | Previous and next session |
| prefix 1 to 9 | Jump to a window |
| prefix arrow keys | Move between panes |
| prefix o | Next pane |
| prefix x | Kill the pane, after a yes or no |
| prefix & | Kill the window, after a yes or no |
| prefix “ / % | Stock splits, top and bottom or side by side, without the SSH inheritance |
| prefix ? | List every binding, the quickest way to check this page against a live server |
| prefix : | The tmux command prompt |
Keys Cole gave up
Rebinding a stock key means losing what it did. The trades in this config:
| Key | Stock meaning | Now |
|---|---|---|
| prefix z | Zoom the pane to full window | Sends Ctrl-Z |
| prefix q | Show pane numbers | Sends Ctrl-D |
| prefix l | Last window | Sends Ctrl-L |
| prefix - | Delete the newest paste buffer | Split top and bottom |
| prefix Shift+m | Clear the marked pane | Toggle the mouse |
| prefix r | Redraw the client | Reload the config |
Zoom is the one people miss. It is still a command away: prefix : then resize-pane -Z, or bind it to a
free key of your own.
The mouse
Mouse mode is on. Clicking a pane focuses it, dragging selects text, and clicking a window name on the first status row, or a session name on the second, switches to it. Prefix Shift+m turns the mouse off when you would rather the outer terminal own selection.
Two mouse behaviors are deliberate changes:
- Selecting does not throw you back to the bottom. Stock tmux copies a selection when you release the button and then leaves copy mode, which snaps the view to the live end of the output and loses your place. Cole’s config copies and stays put, at the same scroll position, until you press q or Esc or scroll back down.
- The scroll wheel is inverted on purpose. A Termius update flipped which wheel events a finger swipe on the
phone sends. Rather than relearn, Cole re-inverted tmux so a finger-up swipe again reveals older output, and flipped
the desktop to match so both feel the same. Each wheel tick moves five lines, and scrolling past the bottom leaves
copy mode. Programs that capture the mouse themselves, like vim with
mouse=a, get the raw events and are not inverted.
Two sharp keys
Ctrl+k never reaches your programs. It is a root binding, so tmux eats it in every pane. That
includes the shell, where Ctrl+k normally deletes from the cursor to the end of the line. If you
copy this config and miss that shortcut, drop the bind -n C-k clear-history line.
Alt+y does not ask. It kills the window and every pane in it at once. An agent’s conversation
survives on disk, so cr or yur from the yu and the Claude Launchers page can resume it, but whatever a shell was running is gone.
Making Alt keys work
Alt bindings only work if the terminal sends Alt as a modifier. Two settings make that true:
- On a Mac, the Option key types accented characters by default (Option-h is ˙), and tmux never sees an Alt key.
Cole’s Ghostty config sets
macos-option-as-alt = left, so the left Option key acts as Alt and the right one still types accents. - Inside tmux, the config turns on extended keys in the CSI u format (
extended-keys on,extended-keys-format csi-u). Without it, Ghostty’s encodings for Alt and Ctrl combinations leak into panes as literal escape characters instead of reaching the program.
On the phone, Termius has Alt in its extra key row. On a board like Cole’s mechanical keyboard, the Mac and Windows switch remaps the modifier row: Option and Command for the Mac, Alt and the Windows key for a PC.
Copy the keymap
The whole file is public: take the parts you like from
base/tmux.conf. The SSH-aware keys need
tmux-ssh-inherit.sh next to it, and the bindings check for that script and fall back to plain splits when it is
missing. After an edit, prefix r reloads. The rest of the setup is on the tmux page, the session picker
that sits in front of it is tm, the Session Picker, and the Dotfiles page explains how the file gets onto every machine.