Have Vim / Emacs / Tmux use System Clipboard

(even in remote sessions!)

Justin Chips
3 min readJan 11, 2021

Background

Like any recipe writeup nowadays I’m going to start with needless background on my workflow and why this tip is great, but if you just skip to the bottom for the solution I will forgive you. Ahem, now then…

My entire workflow is currently performed on a remote machine, like many of you in this quarantine era. I’ve tried various ways to access my remote machine like getting remote windows (RDP) or (X11 forwarding) but I was never satisfied with the latency or resolution quality. I’ve also tried solutions related to file syncing (like rsync and (sshfs) never seemed to work in all cases. So I do everything from a terminal emulator (I’m also one of those crazy people that runs Emacs inside Tmux 🥵).

One of the biggest downfalls of performing work inside a terminal emulator is the constant need to copy text from the terminal session and paste into another application (logs, links, test output, code snippets, etc.).

I gave up on bridging the copy buffers of my various terminal programs (namely in Emacs, affectionately called the “kill ring”) with my system clipboard using xclip/xsel/pbcopy, especially since supporting remote sessions requires more work (e.g., network listeners for piping information back to your local machine).

One clipboard solution to rule them all™️…

I put up with no solution for a few years and just fumbled about whenever I had to copy text from Emacs to another GUI application. But then…Last Friday, I sat down on the floor and decided I wouldn’t work and instead read HN articles or something.

Pictured: Me. Criss-cross applesauce’d reading Hacker News articles

That’s when I randomly stumbled upon a unique category of terminal escape codes called “Operating System Controls” (OSC). Interestingly enough, one of these sequences ( \033]52) is meant for interacting with the system clipboard. To test if your terminal supports this sequence, simply run:

$ printf “\033]52;c;$(printf “Hello, world” | base64)\a”

Now paste from your system clipboard (“⌘V” in Mac or “ctrl-v” for Linux). If it pastes the text “Hello, world”, then you’re terminal is good to go!

(Note this specific command will not work inside Tmux b/c it swallows the sequence. We’ll fix that later…)

So…What?

The greatest part of using terminal escape codes is…It just works. Even for remote sessions. No dependencies required. As long as you use a terminal emulator that supports the escape sequence, which I’ve found is true for both iTerm2 and OS X’s terminal emulator.

How

Solutions all stem from the above line where copy text is converted to base64 and printed to terminal using the OSC 52 escape sequence.

Examples (Emacs)

  • If you do not ever run Emacs inside Tmux:
  • This OSC 52 plugin for Emacs supported by the Chromium project should do fine
  • Emacs 25.1+ seems to have added support for OSC 52
  • If you do run Emacs inside Tmux: Here is a function that will ‘yank’ whatever you last added to your killring into your system clipboard. Supports SSH, Tmux, or SSH + Tmux.
  • There is also this plugin I stumbled upon that claims to add support for Tmux, Tmux +SSH, and other terminal emulators/multiplexers.

Example (Tmux)

Tmux actually supports this feature now out-of-the-box (at least since version 2.6). You just set the option in your .tmux.conf:

set -g set-clipboard on # you can also set this value to ‘external’

Example (Vim)

OSC 52 plugin for Vim supported by the Chromium project: https://chromium.googlesource.com/apps/libapps/+/master/hterm/etc/osc52.vim

Limitations

  • Max copy limit of 74,994 bytes: The maximum length of an OSC 52 escape sequence is 100,000 bytes. Subtracting the header/footer and accounting for the remaining bytes to contain base64-encoded text, you’re left with 74,994 bytes. That is plenty for my use-case, but it depends on your workflow.
  • Terminal emulator support: While most emulators support OSC 52, it appears the GNOME terminal does not. But it seems to be close.

Resources

--

--