an icon composed of a laptop, paperclip, and two servers

Like many bioinformatics engineers, I spend a lot of time in the terminal connected to remote servers. I’ve long been frustrated by how often I have to stop and copy text out of the terminal, either to paste back into the same terminal, a different terminal, or an application running on my Mac. I’ve always wanted a more efficient way of getting text copied to my clipboard from the terminal without having to manually select it.

The Mac has two CLI utilities, pbcopy and pbpaste, that enable access to the clipboard from the CLI. These work great, but are of course limited to when you are working in your local terminal. When you are connected via SSH to a remote server, those tools aren’t available and you can only interact with your clipboard by pasting directly into the terminal and manually selecting text to copy.

One solution I considered was to build a simple tool modeled after pbcopy and pbpaste that could at least mimic a local clipboard on each remote server. While it wouldn’t be ideal, as I would only be able to paste copied text within terminal sessions attached to the same server, it would have at least some utility for situations when I want to capture the output of a command and use it later on the same server.

After giving it some thought over the course of a few days, I came up with a solution that I think is flexible enough to cover a wide range of use cases. I’m excited to announce that it is now released as a Python package called remoclip, short for remote clipboard! I hope you find it as useful as I do.

For those who prefer videos, I made a short (less than 4 minute) screen recording that walks through the installation and major features. View it below, or skip it and read more in the rest of this blog post.

remoclip

remoclip works using a simple client-server setup. On your local workstation, you run the remoclip_server, which by default listens on a localhost port accessible only from processes running on your workstation. The server uses the pyperclip package to interface with your local clipboard (Linux, Mac, and Windows are supported).

With the server running, you then use the remoclip copy and remoclip paste subcommands to manipulate the clipboard. This CLI tool talks to the remoclip_server over HTTP to send and receive clipboard data. Both subcommands use standard in and standard out, so they fit right in with normal Unix shell workflows. For example, you can send the output of any command to the clipboard by piping it to remoclip copy, which will also echo back the content as standard out:

$ find ~/Documents -name "mynotes.txt" | remoclip copy
/Users/jeff/Documents/Misc/mynotes.txt

Now you can paste the resulting file path into any app on your local workstation. You can also retrieve it as standard out by running remoclip paste.

Remote access

So where does the remote part of remote clipboard come in? Since the remoclip_server is listening on a port, you can forward the port when you connect to a remote server via SSH:

$ ssh -R 35612:127.0.0.1:35612 myremotehost
jeff@myremotehost$ remoclip paste
/Users/jeff/Documents/Misc/mynotes.txt
jeff@myremotehost$ echo Hello from a remote host. | remoclip copy
Hello from a remote host.

Now, back on your local workstation, you should have Hello from a remote host. in your clipboard!

The usage section of the documentation covers other scenarios as well, such as cluster environments where SSH port forwarding is not available.

Security

Exposing your clipboard data to potentially untrusted processes on remote systems is not a good idea! In the SSH example above, nothing prevents other users and processes on myremotehost from interacting with the remoclip_server via the localhost port 35612. For this reason, I added a security token option to remoclip’s configuration and highly recommend you use it. The token ensures that only authorized clients can talk to the remoclip_server. The Quick Start guide in the docs includes instructions for creating and using a secure token.

Other features

remoclip’s other features include:

  • Event logging on the server, accessible from the client with remoclip history
  • Requesting a specific history entry with remoclip paste --id n
  • Deletion of sensitive history entries (say if you accidentally copy a password)
  • Unix domain socket support with SSH forwarding (if you don’t want to expose a remote port)
  • Client HTTPS support if you put remoclip_server behind a reverse proxy

This is my first public Python package, and I learned quite a bit during the process. Managing package builds, releases, documentation hosting, and PyPI submissions is a complex endeavor! I have a new level of respect for anyone who manages an open-source project, and find it inspiring that we have so many amazing tools and resources available to us for free. Please consider giving back to the open-source community in whatever way you can.