Using iTerm2, I start an interactive SSH session to a remote Linux machine (where pbcopy is not available). On the remote Linux machine I would like to capture the output of some arbitrary command (e.g. ls *.foo), and have it magically appear in my OSX clipboard, so that when I hit +v it appears in whatever OSX application I've just pasted into. Is this possible? I've tried the escape codes mentioned on the iTerm2 doc page and can't make them work.

  • @klanomath -- thanks, I'll consider that (I'm not sure I want to setup access back to my machine via SSH keys, though it could be passcode-protected, of course.). Oct 17, 2016 at 16:54
  • It does require X on the remote server, which isn't there, and XQuartz running on the local server, which makes my machine run hot. But it might be my best bet -- thanks! Oct 17, 2016 at 17:09
  • then nbren12's comment to the second answer! ;-)
    – klanomath
    Oct 17, 2016 at 17:11
  • Looked at that already -- it still requires SSH keys be set up, and it's the only way I'd be able to do it, since one use case has me SSH'ing into the remote machine from a VPN connection, so no static IP or hostname. Another problem is that I have different user account names on my two primary local machines, but I could solve that in an environment variable or something. Thanks for the effort, though, I really appreciate it. Oct 17, 2016 at 17:16

4 Answers 4



Piecing together lots of information from several different sources, here's what I came up with.

Local Daemon

From the local computer (OSX), setup a daemon to listen on a specific port, via launchd (see links below). The daemon process will simply call pbcopy, which will take anything passed in via STDIN and put it on the clipboard. To do this you need to setup a launchd plist file. Mine looked like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

By convention, the plist file name should be the label name with .plist appended, so for the above example, it would be local.pbcopy.9999.plist. If you wish to use a port other than 9999, just change it everywhere (keeping in mind that it should be something above 1024 and should not be a well-known port that you might already be using). Once you have things working, you can remove the StandardOutPath and StandardErrorPath keys and strings, as they're only needed for debugging.

In order to load the daemon, run the following command:

$ launchctl load local.pbcopy.9999.plist

You can see that it's loaded or remove it with the following commands:

$ launchctl list local.pbcopy.9999
$ launchctl remove local.pbcopy.9999

If you would like this to load every time you login, place the plist file into the ~/Library/LaunchAgents directory.

Note: you will need to set this up on each local host you want this to work on.

SSH Port-Forwarding

Because I could be accessing the remote machine from several different local computers, I can't hard-code the sending of the data on the remote machine to a specific host. To make this as painless and dynamic as possible, I've used SSH port-forwarding to create a dynamic link from the remote machine back to the local computer (the how's and why's of this are beyond this answer; see below for more information). Specifically, I create a link from the remote machines's port 9997 to the local computer's port 9999, which now has a daemon listening on it, thanks to the launchd stuff above. I could use port 9999 on both the remote machine and the local computer, but I don't need to.

To setup this tunnel, execute the following command:

$ ssh -R 9997:localhost:9999 user@remote.com

You can remote into multiple different remote machines with the same command and all will function as expected. You can remote into the same remote machine multiple times with the same command, and it will sort of work as expected; see note below.

If you don't feel like typing the -R 9997:localhost:9999 on every SSH invocation you make, you can put the remote forwarding definition in the SSH config file to do it automatically. Here's an example from my ~/.ssh/config file:

Host ufo*
  RemoteForward 9997 localhost:9999

With that, any time that I SSH to a host whose name starts with 'ufo', the remote forwarding from 9997 to localhost:9999 will automatically be set up. See the config file man page link below for more options.

Sending Data

On the remote end I use netcat to send the desired content back to the listening daemon.

$ date | nc localhost 9997

You can get as complicated as you'd like:

$ nc localhost 9997 <<EOF
> `ls -ld *`
> `date`

You can even dynamically decide whether or not to send any data, based on whether or not anyone is listening (there's probably a more efficient way to do this, but it works):

cnt=`(netstat -lnptu 2>/dev/null) | grep | grep -v grep | wc -l`
if [[ $cnt -eq 1 ]]; then
    date | nc localhost 9999

Observations & Caveats

Things I noted:

  • pbcopy plays nicely with Copy'em Paste
  • if you initiate more than one SSH session with the same remote port forwarding to the same remote machine, only the first one will have any effect; no "duplicate port" type errors will be reported on either end
  • similarly, if you remote in from several different local computers to the same remote machine using the same remote port (e.g. 9997), only the first one will have any effect

Reference Links

  • 1
    If you don't havenc on your remote host, this works--at least on RHEL: echo "howdy" > /dev/tcp/localhost/9997 Dec 7, 2018 at 18:47
  • I have used this solution for more than 1 year, recently noticed that it does not support unicode. For example, clipboard was filled with test‚ûú abc after echo "test➜ abc"|nc -w 0 localhost 9999, which means is converted into ‚ûú in the progress, anyone has an idea about this?
    – brook hong
    Oct 17, 2019 at 10:02

remote pbcopy for iTerm2 seems to be a piece of software made especially for this problem.


If you use iTerm2, there is an easier way. This functionality is built into iTerm2's Shell Integration capabilities via the it2copy command:

Usage: it2copy
          Copies to clipboard from standard input
       it2copy filename
          Copies to clipboard from file

To make it work, choose iTerm2-->Install Shell Integration menu item while logged into the remote host, to install it to your own account. Once that is done, you'll have access to it2copy, as well as a bunch of other aliased commands that provide cool functionality.

The other solutions here are good workarounds but this one is so painless in comparison.


You can do this

ssh -ttt user@location "ksh -c 'ls *'" | pbcopy
  • I need a solution for an interactive shell session -- I'll clarify above. Oct 17, 2016 at 13:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .