Notes on Using Tmux
A collection of notes around how I (ab)use and configure tmux: this is a live document, edited as I refine my workflows.
This is not an introduction to tmux, but more a set of workflows of using it. I assume a familiarity with what tmux is, and perhaps that you already use it.
Some Terms
I always find myself somewhat befuddled when reading the man page for tmux; here's a list of the most important words:
- Sessions: different workspaces, generally identified by numbers
- Windows: one tab inside a session
- Panes: the parts of windows, each representing one shell instance
Dual Wielding Tmuxes (tmuxen?)
I generally work in a shell on my laptop and as well as on development servers; and occasionally multiple devservers. To reduce the number of keyboard shortcuts I need to remember, I prefer to use a simple Terminal Emulator and rely on Tmux to manage all state for me.
To be able to send share run commands with some sanity, I bind
Ctrl-b
as my prefix-key for laptop tmux; and Ctrl-a
as the prefix
for all devserver tmuxes.
In general this flow has worked out remarkably well for me: I only need to remember one style of keyboard shortcuts to manipulate and add terminals, and my sessions persist against X-server restarts.
The fact that tmux works as a very sane window-manager is a
significant bonus. I use dwm
as my non-terminal window manager, and
things work out fairly smoothly.
Emacs integration
I used to rely heavily on emamux to have a shell in parallel to my emacs session, but that doesn't work from a graphical emacs session.
Instead, I've written my own custom snippet to run commands on the
last active tmux pane using tmux send-keys
:
(setq tr--last-command nil) (defun tr (command) "Run the specified command in the currently active tmux pane" (interactive "sCommand: ") (setq tr--last-command command) (call-process "tmux" nil nil nil "send-keys" command "Enter")) (defun trr () "Re-run the previous command" (interactive) (if tr--last-command (call-process "tmux" nil nil nil "send-keys" tr--last-command "Enter") (message "No available previous command!"))) (global-set-key (kbd "C-c x") 'tr) (global-set-key (kbd "C-c r") 'trr)
It's fairly trivial, but remarkably speeds up iteration because I can easily trigger tests, builds and other shenanigans without having to navigate away from emacs: and I can use it in any scenario without having to go through a complex set up process first.
My current configuration
I've customized tmux a little bit to make it more convenient: it started out as a direct copy from a blog post , and I've tweaked it significantly over the years.
I'll only describe my additional customization:
Mouse support
Tmux has excellent mouse support: I've even used it to surprise my co-workers on occasion.
Round trip time was a little bit high while I was trying to resize a pane – so it looked more as if I wished something existed, and he started laughing. A few seconds later it actually resized, and he was astonished.
set-option -g mouse on
Vim Bindings
As the title says: being able to use v
in copy mode or /
to search
forwards and ?
to search backwards feels normal.
Similarly, using C-b h/j/k/l
for navigating windows just works in my
head; to the point I no longer consciously think about it.
set -g status-keys vi set -g mode-keys vi # Better window navigation bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R
Minimalist UI
I prefer a line on the top with minimal formatting, including no visible "-" and "|" in the separators.
# Custom status line set-option -g status-left '-- #[fg=colour253]#S - ' set-window-option -g window-status-format '#[fg=colour244]#I/#[fg=colour253] #W ' set-window-option -g window-status-current-format '#[fg=colour244]#I/#[fg=colour253,bg=colour238] #W ' set-option -g status-right '#[fg=colour250] %Y-%m-%d #[fg=colour254]%H.%M' set-option -g status-bg colour234 set-option -g status-fg colour007 set-option -g status-position top # Custom split colours set -g pane-active-border-style bg=colour234,fg=colour234 set -g pane-border-style bg=colour234,fg=colour234
Large scroll back
For me, one of tmux's super powers is to be able to scroll back
through output easily, particularly while looking at something with
fairly spammy logs and forgetting to pipe it through less
, tee
,or saving it
to a file.
# More scroll back! set-option -g history-limit 10000
Nicer colors
To be perfectly honest I'm not sure if this is required anymore, but it did help emacs within tmux work better for me.
# Force 256 colours set -g default-terminal screen-256color
Always stay in the same directory
I believe I copied from this from Stack Overflow a few years ago: but this lets me easily navigate splits without constantly having to change directories.
# Maintain the current path bind '%' split-window -h -c '#{pane_current_path}' # Split panes horizontal bind '"' split-window -v -c '#{pane_current_path}' # Split panes vertically bind c new-window -c '#{pane_current_path}' # Create new window
Always renumber windows
Before using this option I would end up with windows going beyond 9, which are a mess to navigate – and then I'd end up closing several windows and cleaning up my sessions.
With automatic renumbering my shortcuts stay consistent. This might not be the best choice if you're a stickler about what goes into which window – I tend to do this opportunistically.
set-option -g renumber-windows on
The full configuration
# Stolen from http://mutelight.org/articles/practical-tmux # and then heavily modified over the last several years. # Make pbcopy and pbpaste work from tmux # set-option -g default-command "reattach-to-user-namespace -l zsh" # C-a C-a to jump to the last active window bind-key C-b last-window # Windows from 1 set -g base-index 1 # Resize based on smallest client actually active at the moment setw -g aggressive-resize on # Faster key repetition set -s escape-time 0 # Mouse support! set-option -g mouse on # vi everywhere set -g status-keys vi set -g mode-keys vi # Custom status line set-option -g status-left '-- #[fg=colour253]#S - ' set-window-option -g window-status-format '#[fg=colour244]#I/#[fg=colour253] #W ' set-window-option -g window-status-current-format '#[fg=colour244]#I/#[fg=colour253,bg=colour238] #W ' set-option -g status-right '#[fg=colour250] %Y-%m-%d #[fg=colour254]%H.%M' set-option -g status-bg colour234 set-option -g status-fg colour007 set-option -g status-position top # Better window navigation bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R # More scroll back! set-option -g history-limit 10000 # Force 256 colours set -g default-terminal screen-256color # Custom split colours set -g pane-active-border-style bg=colour234,fg=colour234 set -g pane-border-style bg=colour234,fg=colour234 # Maintain the current path bind '%' split-window -h -c '#{pane_current_path}' # Split panes horizontal bind '"' split-window -v -c '#{pane_current_path}' # Split panes vertically bind c new-window -c '#{pane_current_path}' # Create new window # Automatically fill holes set-option -g renumber-windows on
Frequently used, somewhat obscure commands
Ctrl-b z
: Zoom the current window: particularly useful for copying multi-line content.Ctrl-b space
: Quickly toggle between window layouts.Ctrl-b :
detach-clients -a
: This one is useful to kill all other clients attached to the current session; good to clean up in case you got disconnected or have a terminal emulator lost in the labyrinth of your desktop window manager.Ctrl-b :
kill-pane
: Useful when things are truly, completely, absolutely FUBAR. I've used it in cases my shell has become completely unresponsive (and yes, I also double checked that I hadn't accidentally hitCtrl-S
/ ranCtrl-Q
).
References
- A tmux introduction
- My original source for configuring tmux
- man tmux: The reference for tmux.
History
- 2020-07-07: First version.
- 2020-07-08: Fleshed it out a little.