Use System Clipboard for Vi Copy Mode in Tmux in macOS and Linux
Since I sync my dotfiles through GitHub, I wanted to implement something that will work on both macOS and Linux. Enter if-shell
, which is documented in tmux’s man page:
if-shell [-bF] [-t target-pane] shell-command command [command]
(alias: if)
Execute the first command if shell-command returns success or the second command otherwise. Before being executed, shell-command is expanded using the rules specified
in the FORMATS section, including those relevant to target-pane. With -b, shell-command is run in the background.
If -F is given, shell-command is not executed but considered success if neither empty nor zero (after formats are expanded).
In short, you can run a command conditionally, based on whether your “if” condition returns true. Interestingly, you can also run an “else” command without saying “else.”
Since we want to determine whether we’re on macOS or Linux, we can use the uname
command. It returns Darwin
for macOS and Linux
for Linux.
The system-dependent commands to access the system clipboard are pbcopy
on macOS and xclip
on Linux. In addition, on macOS only, we must use the reattach-to-user-namespace utility to access the system clipboard in tmux.
One final note: we must wrap the commands that follow our “if” condition in quotes or braces. If braces, we don’t have to worry about escaping things, and we can specify multiple commands on multiple lines.
Here’s what I’ve put in my .tmux.conf
, so that I can copy the selection, when in vi mode, into the system clipboard:
if-shell "uname | grep -q Darwin" {
bind-key -T copy-mode-vi 'y' send -X copy-pipe-and-cancel 'reattach-to-user-namespace pbcopy'
bind-key -T copy-mode-vi Enter send -X copy-pipe-and-cancel 'reattach-to-user-namespace pbcopy'
} {
bind-key -T copy-mode-vi 'y' send -X copy-pipe-and-cancel 'xclip -in -selection clipboard'
bind-key -T copy-mode-vi Enter send -X copy-pipe-and-cancel 'xclip -in -selection clipboard'
}
If uname returns “Darwin,” we run the settings in the first set of braces. If not, we run the second set.
Note: This is on tmux 3.0a (Linux) and tmux 3.1b (macOS). I’m not sure if this will work on other versions of tmux. You can get your tmux version by running tmux -V
.
I’ve found that this works in iterm but not Kitty.
Interesting. Since writing this post, I switched to Kitty and its windowing instead of tmux on Linux. I’m still on iTerm + tmux on MacOS, but I plan to switch there, too, once I get around to it.
It somehow started working. Maybe I was doing something dumb. But in any case I realized that OhMyTmux which I’ve been using has this option pre-configured (had to turn it on) and it works with Mac, Windows, and Linux. I was having a problem where copying was appending to the clipboard rather than orverwriting it and I think it had to do with the ohmytmux and your solution above conflicting.
Also found this capability build in to tmux: https://github.com/tmux/tmux/wiki/Clipboard
Good finds!