Copying text to clipboard when working on a remote machine via SSH can be tricky. While you can usually highlight text with your mouse to copy it to the primary selection clipboard (and paste with middle-click), this approach has limitations.

Two common scenarios where this falls short for me are:

I configure my n(vim) to show whitespace characters for clarity:

vim.opt.listchars = {
  tab = '🡒 ',
  space = '·',
  nbsp = '␣',
  extends = '⟩',
  precedes = '⟨'
}

and the results look something like:

Visual representation of whitespace characters in Neovim

While these visualization characters are helpful, I don’t want them copied to my clipboard. Vim handles this correctly when using yank commands, but mouse selection in the terminal emulator copies everything - including the whitespace characters.

Similarly, copying from tmux sessions can be frustrating. While tmux has basic mouse support, selecting text becomes challenging when you need scrolling and/or are using split panes:

Mouse selection issues in tmux

Using OSC-52 for Remote Clipboard Access

OSC-52 is an escape code that instructs terminals to copy text into the system clipboard. While not an official standard, it’s widely supported by modern terminals like kitty.

The basic format is:

\033]52;c;BASE64_ENCODED_PAYLOAD\007

When a terminal receives this sequence with base64-encoded text, it copies the decoded content to the system clipboard.

Kitty ships a kitten clipboard utility that handles clipboard integration using OSC-52. For simpler needs, I wrote this minimal bash script saved as clipwrite that I use on remote machines:

#!/usr/bin/env bash

printf "\033]52;c;%s\007" "$(base64 -w0 < /dev/stdin)"

Usage is straightforward:

echo "foobar" | clipwrite

Configuring neovim to use OSC-52

You can configure neovim to use OSC 52 for both primary (*) and clipboard (+) registers:

vim.g.clipboard = {
  name = 'OSC 52',
  copy = {
    ['+'] = require('vim.ui.clipboard.osc52').copy '+',
    ['*'] = require('vim.ui.clipboard.osc52').copy '*',
  },
  paste = {
    ['+'] = require('vim.ui.clipboard.osc52').paste '+',
    ['*'] = require('vim.ui.clipboard.osc52').paste '*',
  },
}

This allows you to use normal Neovim clipboard operations (like “+y to copy or “+p to paste) and have them work across SSH.

Configuring tmux to use OSC-52

Enable OSC 52 in your tmux.conf:

set -g set-clipboard on

(See tmux documentation for more details.)

For quickly copying entire tmux buffers, which is often what I want to do, I use this shell alias:

alias tmux2clip='tmux capture-pane -pS - | clipwrite'