< Back to Posts

Remote Clipboard Integration With Vim

Joe Ellis

2020-11-13

Most of my day-to-day dev work is done on a remote machine. I use Vim and tmux.

Something I find myself doing often is copy-pasting code snippets. For local development this is no issue; Vim has clipboard integration. But this won’t work if you want to write to the clipboard from a remote machine.

It would be nice if there was an easy way to write to my local clipboard from a remote Vim session. I’ve searched a bit, and the majority of answers are about disabling mouse reporting any copying the contents of the terminal screen directly. A fine suggestion, but this breaks down for anything other than single lines; line numbering, tmux panes, etc, will clobber what you’re trying to copy.

Turns out you can get remote clipboard integration using two standard Unix tools: netcat and ssh. We use netcat to host a simple server that accepts text and pipes it to the clipboard, and we use ssh to create a reverse tunnel so that the development machine can send information to our netcat server.

Now… this is a little bit of a hack. But it actually works very well.

Basic recipe is:

  1. Set up a netcat server on a local socket:

    while [[ 1 ]]; do rm -f /tmp/clipboard.sock && nc -lU /tmp/clipboard.sock | pbcopy; done

    (I use macOS, hence pbcopy – if you’re on a different system you will have to search piping to the clipboard and use the relevant command)

  2. Forward the Unix socket (to as many development machines as you need!) with ssh:

    ssh -nNT -R /tmp/clipboard.sock:/tmp/clipboard.sock <dev_machine_1> & ssh -nNT -R /tmp/clipboard.sock:/tmp/clipboard.sock <dev_machine_2> & … and so on

Then, on the remote machine, try this:

echo "Hello, world!" | nc -NU /tmp/clipboard.sock

Now try pasting. If all went well, you should have pasted Hello, world!.

To integrate this with Vim, you can drop this snippet into your .vimrc:

let g:clipboard_nc_invocation = "nc -NU"
let g:clipboard_socket_file = "/tmp/clipboard.sock"
function! LocalClipboardCopy()
  silent! execute "'<,'>:w !" . g:clipboard_nc_invocation . " " . g:clipboard_socket_file
  echo "Copied to local clipboard."
endfunction
vnoremap <leader>d :<C-u>call LocalClipboardCopy()<cr>

Now, if you have a visual selection in Vim, hit <leader>d. It should copy to your local clipboard!