# use b as prefix set-option -g prefix C-b unbind-key C-a bind-key C-b send-prefix # enable focus events set-option -g focus-events on # keep stuff going set-option -g exit-unattached off set-option -g destroy-unattached off # Start numbering at 1 set-option -g base-index 1 # Allows for faster key repetition set-option -g escape-time 0 # Set a bigger scrollback buffer size set-option -g history-limit 100000 # status # set-option -g status-left '[#S]' set-option -g status-right '#h %a %d-%b %H:%M' # Rather than constraining window size to the maximum size of any client # connected to the *session*, constrain window size to the maximum size of any # client connected to *that window*. Much more reasonable. set-window-option -g aggressive-resize on # Activity monitoring set-window-option -g monitor-activity on set-option -g visual-activity on # Mouse set-option -g mouse on # for scroll shite, when you have time read https://medium.freecodecamp.org/tmux-in-practice-scrollback-buffer-47d5ffa71c93 # and other stuff in https://github.com/wincent/wincent/blob/main/aspects/dotfiles/files/.tmux.conf # Stay in copy mode on drag end. # (Would use `bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X # stop-selection` but it is a bit glitchy.) unbind-key -T copy-mode-vi MouseDragEnd1Pane # Scroll 3 lines at a time instead of default 5; don't extend dragged selections. bind-key -T copy-mode-vi WheelUpPane select-pane\; send-keys -t'{mouse}' -X clear-selection\; send-keys -t'{mouse}' -X -N 3 scroll-up bind-key -T copy-mode-vi WheelDownPane select-pane\; send-keys -t'{mouse}' -X clear-selection\; send-keys -t'{mouse}' -X -N 3 scroll-down # Make double and triple click work outside of copy mode (already works inside it with default bindings). bind-key -T root DoubleClick1Pane if-shell -Ft'{mouse}' '#{alternate_on}' "send-keys -M" "copy-mode -t'{mouse}'; send-keys -t'{mouse}' -X select-word" bind-key -T root TripleClick1Pane if-shell -Ft'{mouse}' '#{alternate_on}' "send-keys -M" "copy-mode -t'{mouse}'; send-keys -t'{mouse}' -X select-line" # Don't exit copy mode on double or triple click. bind-key -T copy-mode-vi DoubleClick1Pane if-shell -Ft'{mouse}' '#{alternate_on}' "send-keys -M" "copy-mode -t'{mouse}'; send-keys -t'{mouse}' -X select-word" bind-key -T copy-mode-vi TripleClick1Pane if-shell -Ft'{mouse}' '#{alternate_on}' "send-keys -M" "copy-mode -t'{mouse}'; send-keys -t'{mouse}' -X select-line" # Reload config bind r source-file ~/.tmux.conf \; display-message "Config reloaded..." # Enable broadcast input bind ` setw synchronize-panes # auto window rename set-option -g status-interval 5 set-option -g allow-rename off set-option -g automatic-rename on set-option -g automatic-rename-format '#{b:pane_current_path}' # Vi copypaste mode set-window-option -g mode-keys vi # https://github.com/tmux/tmux/issues/754#issuecomment-297452143 bind-key -T copy-mode-vi v send-keys -X begin-selection # bind-key -T copy-mode-vi y send-keys -X copy-nd-selection bind-key -T copy-mode-vi y send-keys -X copy-pipe "if [ \"$(uname)\" = \"Darwin\" ]; then reattach-to-user-namespace pbcopy; elif command -v xclip >/dev/null 2>&1; then xclip -selection clipboard; else cat > /tmp/tmux-paste.txt; fi" # Capture pane into VIM # https://www.reddit.com/r/vim/comments/12eg832/comment/jfcg6p3/ bind V send-keys C-c C-u 'tmux capture-pane -Jp -S- | vim -' Enter # hjkl pane traversal bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R # color # Prefer tmux-256color; fall back to screen-256color on hosts whose # terminfo db lacks it (older RHEL/BSD/minimal containers). set -g default-terminal "screen-256color" # safe default; upgraded below where supported if-shell 'infocmp tmux-256color >/dev/null 2>&1' \ 'set -g default-terminal "tmux-256color"' # set -g default-terminal "xterm-256color" set-option -a terminal-features "$TERM:RGB" set -ag terminal-overrides ",$TERM:Tc" # Tell tmux the outer terminal understands DECSET 2026 (synchronised output), so # it can wrap its own redraws in begin/end-of-frame markers. Alacritty has # supported it since 0.13. Without this, a full-screen TUI repainting inside # tmux tears. (tmux does not pass an *application's* 2026 through, so this is # the only lever we have on flicker under tmux.) set -ag terminal-features ",*:sync" # Advertise OSC 8 hyperlink support so tmux re-emits (rather than strips) # hyperlinks from TUIs inside it. tmux only advertises the feature to inner # apps -- via #{client_termfeatures}, which pi probes at startup -- when the # feature is listed here. Test: `tmux display-message -p # '#{client_termfeatures}'` should list `hyperlinks`, then restart pi. # Clicking: Ghostty/Alacritty open links on a modifier-chord click (e.g. # Cmd/Ctrl depending on capture); a plain click is selection, by design. set -ag terminal-features ",*:hyperlinks" # change selection color set -wg mode-style fg=white,bg="#aaaaaa" # tmux 1.9 decided it was a good idea to ditch default-path... # now every command to create a new pane/window must be rebound bind-key c new-window -c "#{pane_current_path}" bind-key % split-window -h -c "#{pane_current_path}" bind-key '"' split-window -v -c "#{pane_current_path}" # emacs key bindings in tmux command prompt (prefix + :) are better than # # vi keys, even for vim users set -g status-keys emacs # https://github.com/NHDaly/tmux-better-mouse-mode # set -g @plugin 'tmux-plugins/tpm' # # set -g @plugin 'tmux-plugins/tmux-sensible' # set -g @plugin 'nhdaly/tmux-better-mouse-mode' # run '~/.tmux/plugins/tpm/tpm' # set -g @emulate-scroll-for-no-mouse-alternate-buffer "off" # set -g @scroll-down-exit-copy-mode "on" ###########################################33 ### Colors # Guide: # for i in {0..255}; do printf "\x1b[38;5;${i}mcolor%-5i\x1b[0m" $i ; if ! (( ($i + 1 ) % 8 )); then echo ; fi ; done if-shell -b 'test -e ~/.local/share/tmux/color.conf' { source-file "~/.local/share/tmux/color.conf" # run-shell 'tmux source-file "~/.local/share/tmux/color.conf"' } # Disable this section below because it should only apply to macOS systems # # Sessions on this box are local-first; an SSH/mosh attach shouldn't make new # # panes look like remote sessions (e.g. pure prompt showing user@host). # # Default update-environment minus SSH_CONNECTION, keeping SSH_AUTH_SOCK so # # agent forwarding still refreshes on attach. # set-option -g update-environment "DISPLAY KRB5CCNAME SSH_ASKPASS SSH_AGENT_PID SSH_AUTH_SOCK WINDOWID XAUTHORITY" # # Scrub it from whatever environment the server was started with # # (mosh-tmux.sh execs tmux straight from the SSH environment). # set-environment -g -u SSH_CONNECTION # Let OSC escape sequences through to the outer terminal; without this tmux # swallows Claude Code's desktop notifications and progress updates. set -g allow-passthrough on # Modified keys -- Shift+Enter, Ctrl+Enter, Ctrl+J -- reach the apps that ask # for them (pi, Neovim, Claude Code) instead of arriving as a plain Enter. All # three lines are needed: # # - extended-keys on: a pane may request xterm modifyOtherKeys. Not `always`, # which forces it on every pane and hands zsh ESC[13;2u for Shift+Enter. # - extended-keys-format csi-u: the format pi asks for, and the one it can # decode in the misfire below. tmux 3.5 and later; -q lets 3.4 skip it. # - extkeys for Ghostty: tmux asks the outer terminal for modified keys only # when it knows the terminal can send them, and it does not recognise # Ghostty, whose terminfo does not say so either. Without this the two lines # above change nothing there: Shift+Enter still arrives as a bare CR. # # Panes that ask for nothing, shells included, still get plain bytes, pastes # too. One known misfire: in a display-popup tmux re-encodes the newlines of a # paste, so an app there that asked for modified keys sees ESC[106;5u in # their place. Nothing here opens popups. set -g extended-keys on set -gq extended-keys-format csi-u set -as terminal-features 'xterm-ghostty:extkeys' # Caps Lock is F20 (hammerspoon). What reaches tmux for it is read as S-F10 and # passed on as ESC[21;2~, which Neovim takes for F22 and types out as text. Wispr # Flow reads the key before the terminal does, so nothing here needs it: drop it. # This also drops a real Shift+F10. bind-key -n S-F10 {} # Machine-local overrides, where a machine has any: ~/.tmux.conf.local, a real # file in no repo, like ~/.localprofile for the shell. Not under ~/.config/tmux, # which is a link into this repo. Last, so it wins over everything above, # colours included; -q skips it silently where there is none. source-file # rather than `if-shell -b`, which would apply it in the background, after the # rest of the config and in no fixed order. source-file -q ~/.tmux.conf.local