Skip to content

Instantly share code, notes, and snippets.

@burke
Last active September 26, 2023 11:04
Show Gist options
  • Save burke/5960455 to your computer and use it in GitHub Desktop.
Save burke/5960455 to your computer and use it in GitHub Desktop.
This sets up keybindings in tmux that allow you to copy/paste to/from your OS X clipboard from tmux running inside an SSH connection to a remote host. Partially borrowed from http://seancoates.com/blogs/remote-pbcopy

Local (OS X) Side

~/Library/LaunchAgents/pbcopy.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
     <key>Label</key>
     <string>localhost.pbcopy</string>
     <key>ProgramArguments</key>
     <array>
         <string>/usr/bin/pbcopy</string>
     </array>
     <key>inetdCompatibility</key>
     <dict>
          <key>Wait</key>
          <false/>
     </dict>
     <key>Sockets</key>
     <dict>
          <key>Listeners</key>
               <dict>
                    <key>SockServiceName</key>
                    <string>2224</string>
                    <key>SockNodeName</key>
                    <string>127.0.0.1</string>
               </dict>
     </dict>
</dict>
</plist>

~/Library/LaunchAgents/pbpaste.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
     <key>Label</key>
     <string>localhost.pbpaste</string>
     <key>ProgramArguments</key>
     <array>
         <string>/usr/bin/pbpaste</string>
     </array>
     <key>inetdCompatibility</key>
     <dict>
          <key>Wait</key>
          <false/>
     </dict>
     <key>Sockets</key>
     <dict>
          <key>Listeners</key>
               <dict>
                    <key>SockServiceName</key>
                    <string>2225</string>
                    <key>SockNodeName</key>
                    <string>127.0.0.1</string>
               </dict>
     </dict>
</dict>
</plist>

~/.ssh/config

Host myhost
    HostName 192.168.1.123
    User myname
    RemoteForward 2224 127.0.0.1:2224
    RemoteForward 2225 127.0.0.1:2225

After adding the PLists above, you'll have to run:

launchctl load ~/Library/LaunchAgents/pbcopy.plist
launchctl load ~/Library/LaunchAgents/pbpaste.plist

Remote (Linux) Side

~/.tmux.conf

if-shell 'test "$(uname)" = "Linux"' 'source ~/.tmux-linux.conf'

~/.tmux-linux.conf

bind C-c run "tmux save-buffer - | pbcopy-remote"
bind C-v run "tmux set-buffer $(pbpaste-remote); tmux paste-buffer"

~/bin/pbpaste-remote

#!/bin/sh
nc localhost 2225

~/bin/pbcopy-remote

#!/bin/sh
cat | nc -q1 localhost 2224

~/.vimrc

function! PropagatePasteBufferToOSX()
  let @n=getreg("*")
  call system('pbcopy-remote', @n)
  echo "done"
endfunction

function! PopulatePasteBufferFromOSX()
  let @+ = system('pbpaste-remote')
  echo "done"
endfunction

nnoremap <leader>6 :call PopulatePasteBufferFromOSX()<cr>
nnoremap <leader>7 :call PropagatePasteBufferToOSX()<cr>
@jclosure
Copy link

@jclosure
Copy link

jclosure commented Jul 29, 2019

Incidentally, this approach has problems with multibyte chars like, ü. Seem pbcopy encodes w/ MacRoman.

Example 1:
From Linux->Mac, I send:

Grüssen

In Mac, I get:

Grüssen

Example 2:
From Mac->Linux, I send:

Grüssen

In Linux, I get:

Gr\237ssen

Example 3:
From Linux->Mac->Linux, I send:

Grüssen

In the 2nd Linux box, I get:

Grüssen

My shells in all systems have:

LC_CTYPE=en_US.UTF-8
LANG=en_US.UTF-8

The Linux boxes are using UTF-8 and I think the Mac's pasteboard by default is using MacRoman encoding.

This seems to show that I'm right:
After sending a multibyte char from Linux->Mac, do:

pbpaste | textutil -convert txt -stdin -stdout -encoding 30 | pbcopy

You get:

Grüssen

I've tried doing this conversion in the plist ProgramArguments, but so far no luck. Wonder if anyone else has a better approach to normalize the encoding differences.

Thanks.

@jclosure
Copy link

jclosure commented Jul 30, 2019

Alright, here's a workaround for the encoding issue. Note this makes the assumption that our clipboard server is speaking UTF-8.

pbcopy

	<string>localhost.pbcopy</string>
	<key>ProgramArguments</key>
	<array>
	    <string>/bin/sh</string>
	    <string>-c</string>
	    <string>LC_CTYPE=en_US.UTF-8 pbcopy</string>
	</array>

pbpaste

        <string>localhost.pbpaste</string>
	<key>ProgramArguments</key>
	<array>
	    <string>/bin/sh</string>
	    <string>-c</string>
	    <string>LC_CTYPE=en_US.UTF-8 pbpaste</string>
	</array>

IANA character sets

FYI, you can always debug this using a local file, e.g.:

pbcopy cmd

/bin/sh -c "cat /dev/stdin > /tmp/clipboard.txt; cat /tmp/clipboard.txt | pbcopy"

pbpaste cmd

/bin/sh -c "pbpaste > /tmp/clipboard.txt; cat /tmp/clipboard.txt"

@Midren
Copy link

Midren commented Dec 26, 2021

If you are using tmux-yank, you could just add set -g @override_copy_command 'nc localhost 2224', as mentioned here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment