opodze.com/me

Things I keep forgetting about in: tmux

Craftsmen should know how to use their tools. I usually follow this sort of motto. But sometimes, you stop somewhere half-way, or 80% of the way. Bad habits stick instead of the “canonical” way to use the tool. The meme example of it would be using search bar to look up “google.com”, then opening the first link, and using that for your actual search. It is, however, hard to get rid of some of those bad habits, even when you know that there is a better way™️.

This post is something in the middle between a cheat sheet and a confession about things I know are useful, but for some reason keep forgetting about, and usually resort to doing the equivalent in a bad way. My hope that by writing this I can finally push myself to stick to the better solutions instead.

tmux

Let’s start with tmux - one of the tools I refused to learn for 8 years after I was first introduced to it, and deeply regret about not doing so, and resorting to learn all the weird hotkeys to manage sub-terminals in terminator, iTerm, konsole and so on.

I try to keep the shortcuts default for tmux in case I encounter it in remote environment, so this should apply to anyone.

shortcuts with window/pane moving

<prefix> ! moves your current pane into a new window. It sounds useful, but not so much to remember that specifically ! does that. Most reachable symbols with prefix already mean something:

  • " % split current window
  • & kills the window
  • x kills current pane

Additional candidates that seem to be useful, but don’t make sense mnemonically are:

  • . moves the window to a new index. This works weirdly when the renumber-windows is enabled
  • $ renames current session. This can be sometimes useful - but 90% of the time my sessions are just named according to repo I’m working with
  • q displays pane numbers

pane moving

To do this, we need to use join-pane (or joinp) command. This can be a bit confusing. There are at least two ways to do it. The cumbersome way:

  1. C-b m to mark pane you want to move
  2. Focus on the window where you want to move the pane to
  3. C-b :joinp to insert the marked pane into the correct place

The more “intended” way, but usually more error prone also:

C-b :joinp -s <source-pane> -t <target-pane>

In the most simple case, both source and target are integers. However, when moving to a different window, it’s better to use full pane path. So, to move pane 1 from window 3 to window 1, it’s better to use: :joinp -s 3.1 -t 1.1. When using plain integers, tmux will try in order:

  1. find a pane in active window with specified number
  2. only if such pane does not exist, it will use the number as a window index. This part can be surprising and unintuitive, and I don’t see it clearly spelled out in the manual.

Numbers of specific panes can be deduced by using C-b q or C-b w.

It’s possible to omit -s parameter. It will use active pane as the source in this case.

scrolling and navigation

To scroll, search and copy in tmux, you need to enter the “copy mode”, done by C-b [.

After that, this is the only change I’ve made to tmux bindings: I’ve been using vi-mode in config:

set-window-option -g mode-keys vi
bind -T copy-mode-vi v send-keys -X begin-selection
bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard'

What this does is it allows using hjkl for navigation, v for selection, and y yanking, similar to vim. The copying can also be done by pressing Enter.

The copy uses system clipboard, so you can paste it in wherever.

Also, / works in this mode for searching

I suspect that this might be terminal specific, but in ghostty, by default, the links should be clickable. However, tmux can intercept click events (with set -g mouse on command, for example), and this messes with the terminal feature. What helps is that if the terminal allows links to be clickable while holding cmd, tmux allows skipping mouse capturing on shift, so shift+cmd+click should make a link clickable again!

Outside of macOS, replacing cmd with ctrl should also work.

resizing

The simplest rudimentary resizing commands are C-b M-<arrows>. On macOS, M stands for Option. Unfortunately, by default, the Option+left/right on macOS conflicts with these shortcuts. I’m rarely using vertical pane splits, so this is usually not a problem for me.

Also, there are a couple of shortcuts:

  1. C-b z “zooms in” the current pane: makes it full-screen temporarily
  2. C-b E equalizes sizes of panes
  3. C-b {} swaps your current pane with one above/below
  4. C-b M-<number> applies one of the default layouts to your currently opened panes, with 7 options to choose from. A lot of them are useless to me (usually I stop at 2 panes per window), but for sake of completeness I’ll write them out:
    1. “Column” layout: every window takes full height, width split equally
    2. “Row” layout: every window takes full width, height split equally
    3. “Master-Column”: One “master” pane is on top, full width; all other panes are below in column mode
    4. “Master-Row”: One “master” pane is on left, full height; all other panes are to the right in row mode
    5. “Grid” mode: all panes are split into equal sizes into a grid
    6. “Bottom-Master-Row”: same as (3), but master pane is at the bottom
    7. “Right-Master-Row”: same as (4), but master pane is on the right