Mastering tmux‘s Scrollback and Copy Mode
If you spend a lot of time in the terminal, you‘ve likely encountered tmux – the ubiquitous terminal multiplexer. tmux allows you to manage multiple terminal sessions within a single window, detach and re-attach to sessions, and customize your terminal environment.
One aspect of tmux that often trips up new users is how it handles scrollback compared to a regular terminal. In this guide, we‘ll take an in-depth look at tmux‘s scrollback behavior, learn how to make it more intuitive, and pick up some handy tips and tricks along the way. Let‘s dive in!
Understanding tmux‘s Scrollback Buffer
A typical terminal emulator implements a scrollback buffer to allow you to view output that has disappeared off-screen. For example, you can scroll up in your terminal using keyboard shortcuts like Shift-PageUp or your mouse wheel to access the scrollback history.
tmux, on the other hand, runs in the alternate screen buffer of your terminal. This is a special mode that applications can enable to gain more control over what is displayed. For example, when you launch vim, it switches to the alternate screen to show the editor interface.
The alternate screen has the same dimensions as your terminal window. Any output that exceeds the visible area is not accessible via the regular terminal scrollback. In effect, tmux is like a "window manager for your terminal" – it takes over the entire screen and implements its own scrollback buffer.
This behavior has a few important consequences:
-
Output that gets scrolled off-screen in tmux is not added to the terminal‘s scrollback history. If you exit tmux, that output is lost forever.
-
You can‘t access tmux‘s scrollback using the typical terminal shortcuts or your mouse wheel. tmux uses a separate mechanism called copy mode.
-
When you detach from a tmux session, the contents of the tmux window are not dumped into the terminal‘s history. You pick up right where you left off when you re-attach.
So while tmux‘s scrollback system might feel foreign at first, it‘s really just a consequence of how tmux interacts with the terminal. Luckily, tmux provides a rich set of features for working with its scrollback buffer.
Navigating tmux‘s Scrollback with Copy Mode
To access tmux‘s scrollback buffer, you use a special mode called copy mode. To enter copy mode, press Prefix [
(that‘s Ctrl-b then [). You‘ll see a message like [0/55]
at the top, indicating your current position and the size of the scrollback buffer.
Once in copy mode, you can navigate the scrollback using these keys:
Up
ork
: Scroll up one lineDown
orj
: Scroll down one lineCtrl-u
: Scroll up half a pageCtrl-d
: Scroll down half a pagePageUp
orCtrl-b
: Scroll up a full pagePageDown
orCtrl-f
: Scroll down a full page
To exit copy mode and return to the current pane, press q
or Enter
.
These keybindings follow the vi-style and are enabled by default in tmux 2.4 onwards. If you‘re on an older version, it uses emacs-style keybindings. You can customize the keys used in copy mode with the bind-key -T copy-mode
command.
Making tmux‘s Copy Mode More Intuitive
One gripe I have with tmux‘s default copy mode keys is that Prefix [
feels clunky to type. Since I use iTerm2, I‘m used to the Cmd-UpArrow shortcut to enter scroll mode. We can replicate that in tmux by adding this to our ~/.tmux.conf
file:
# Use Alt-UpArrow to enter copy mode
bind -n M-Up copy-mode
Now when we press Alt-UpArrow, we enter copy mode with our cursor at the bottom ready to scroll up. We can keep hitting Alt-Up to scroll line-by-line, or use any of the other navigation shortcuts.
Next up, I find tmux‘s default scroll speed too fast – each tick of the mouse wheel scrolls 5 lines at a time. Here‘s how we can slow it down to a more manageable 2 lines per tick:
bind -T copy-mode-vi WheelUpPane select-pane \; send-keys -X -N 2 scroll-up
bind -T copy-mode-vi WheelDownPane select-pane \; send-keys -X -N 2 scroll-down
Selecting and Copying Text
Copy mode isn‘t just for scrolling through output – you can also use it to select and copy text. First, make sure mouse mode is enabled:
set -g mouse on
This allows you to select text by dragging with your mouse. However, the default behavior is a bit odd:
- When you finish dragging with the mouse button, tmux drops you out of copy mode
- The selected text is immediately copied to tmux‘s internal buffer
- Your scroll position resets to the bottom
I prefer to stay in copy mode after selecting text with the mouse, so I can continue scrolling if needed. We can override the default like so:
# Stay in copy mode when dragging with mouse
unbind -T copy-mode-vi MouseDragEnd1Pane
bind -T copy-mode-vi MouseDown1Pane select-pane \; send-keys -X copy-pipe "pbcopy" \; send-keys -X clear-selection
Now dragging with the mouse selects text but keeps us in copy mode. To actually copy the text, just click with the mouse – this copies the current selection to the clipboard and clears the selection.
Pasting Copied Text
When you copy text in tmux using copy mode, it gets added to a paste buffer. tmux maintains a stack of buffers, so you can copy multiple things and paste them later.
To paste the most recently copied text, use the paste-buffer
command:
bind p paste-buffer
To view a list of all copied buffers, use the choose-buffer
command:
bind C-p choose-buffer
This opens an interactive list of buffers that you can select from:
Accessing tmux Scrollback from iTerm2
Ideally, you‘d be able to use the same keybindings to access tmux‘s scrollback as you use in plain iTerm. For example, I‘d love to keep using Cmd-UpArrow to enter scroll mode, even from inside tmux.
This is possible using iTerm2‘s ability to bind keys to send hex codes. Essentially, we configure iTerm to send the same M-Up
sequence that we bound to tmux‘s copy mode earlier when we press Cmd-UpArrow.
Here are the steps:
- Open iTerm2 preferences and create a new profile for tmux
- In the Keys section, click the + icon to add a new keymapping
- Set the shortcut to Cmd-UpArrow (⌘↑)
- Select "Send Hex Code" and enter
0x1b 0x5b 0x31 0x3b 0x35 0x41
- Repeat for Cmd-DownArrow (⌘↓) with code
0x1b 0x5b 0x31 0x3b 0x35 0x42
Now when you press Cmd-Up/DownArrow in iTerm2 while inside tmux, it sends the right sequence to activate tmux‘s copy mode and you can keep using all your muscle memory for scrolling!
Note this only works for scrolling – to select text you‘ll still need to use tmux‘s built-in selection mechanism that we set up earlier. A small price to pay for the convenience of familiar scroll keys.
Quickly Copying to the Clipboard
Even with all these tweaks, selecting text in tmux with the mouse can feel a bit fiddly. Sometimes you just want to make a quick copy without entering copy mode.
Here‘s a handy trick: hold Option while dragging with the mouse to bypass tmux‘s mouse handling. The selection will happen in iTerm2 instead, so you can quickly copy to the clipboard.
This is a good fallback for those times when you don‘t need tmux‘s more advanced copy mode features and just want to grab some text in a hurry.
Persisting tmux‘s Scrollback
By default, tmux only keeps around 2000 lines of scrollback. If you want to save more, you can adjust the history-limit
setting:
set -g history-limit 10000
This tells tmux to keep 10,000 lines of history per pane. You can tweak this number depending on your needs and how much memory you‘re willing to dedicate to tmux.
An alternative approach is to use a terminal logging tool like script
to record all your tmux sessions to disk. You can then search through the logs later if you need to dig up some output.
Conclusion
tmux‘s scrollback system is a powerhouse once you learn how to use it effectively. With a few tweaks, you can mould it to fit your workflows and build muscle memory for quickly navigating and copying output.
The configuration examples we‘ve covered are just the tip of the iceberg – there‘s so much more you can do to customize tmux to your liking. I encourage you to explore the official docs, read through other people‘s configs, and experiment to see what works for you.
Hopefully this deep-dive has given you a solid foundation for making the most of tmux‘s scrollback features. Feel free to hit me up in the comments if you have any other neat tricks to share!