├── .github └── FUNDING.yml ├── README.md ├── pbcopy ├── pbpaste └── pbproxy /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: arghzero 2 | github: nikvdp 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pbproxy - send your clipboard anywhere you can ssh to 2 | 3 | **TL;DR:** `pbcopy` and `pbpaste` from any (mac or linux) machine you can ssh to 4 | 5 | This is a simple tool to make it easy to interact with clipboards on remote 6 | machines. The "ui" mimics macOS's `pbcopy` and `pbpaste` commands using the 7 | original `pbcopy` and `pbpaste` on macOS, and wrapping `xsel` on Linux boxes. 8 | On linux boxes where xsel is not available (eg headless servers that don't have 9 | X) it falls back to storing clipboard contents in a temp file 10 | 11 | In other words, you can `pbcopy` and `pbpaste` from any remote machines you 12 | have ssh access to. The special sauce is that you can put a server name from 13 | your ssh config on the end of a pbcopy or pbpaste command so you can do stuff 14 | like run `echo hello | pbcopy server2` on server1, after which doing `pbpaste` 15 | from server2 would print 'hello'. You can also do this in the other direction 16 | with pbpaste, eg from server2 you can run `pbpaste server1` and it'll print out 17 | the contents of server1's clipboard. 18 | 19 | ## Prereqs: 20 | 21 | For best results: 22 | 23 | - make sure you have `pbproxy` installed at `~/.pbproxy` on all machines you'll 24 | be copying/pasting to/from. 25 | - **make sure you have key-based ssh authentication set up** (otherwise you'll 26 | have to enter your password each time you copy or paste) 27 | 28 | ## Usage: 29 | 30 | - Print the contents of another machine's clipboard to your local machine's stdout: 31 | ``` 32 | pbpaste 33 | ``` 34 | - Insert data into another machine's clipboard: 35 | 36 | ``` 37 | echo hello there | pbcopy 38 | ``` 39 | 40 | You can also use this to send the contents of your current machine's 41 | clipboard to another machine: 42 | 43 | ``` 44 | pbpaste | pbcopy 45 | ``` 46 | 47 | - Print the contents of your local clipboard to stdout: `pbpaste` 48 | - Insert data into your local clipboard: `echo some data | pbcopy` 49 | 50 | **NOTE**: This tool works the same way regardless of whether it's running on a 51 | macOS or a linux machine. On macs it wraps the native pbcopy and pbaste commands, 52 | and on linux it uses `xsel` or a temp file 53 | 54 | ## Installation 55 | 56 | - Clone this repo to your local machine 57 | - Add the folder you cloned it to to your `PATH` through your 58 | `~/.bashrc`/`~/.zshrc` files (**NOTE**: on macOS, make sure it comes BEFORE 59 | `/usr/bin` on your PATH, otherwise the native `pbcopy` and `pbpaste` will 60 | take precedence) 61 | - restart your shell (or on zsh do `hash -r`) and try it out. 62 | 63 | For the lazy (read: efficient), copy/pasting this quick and dirty shell snippet should get the job done: 64 | 65 | ```bash 66 | git clone https://github.com/nikvdp/pbproxy ~/.pbproxy 67 | ps | grep $$ | grep -q zsh && echo 'export PATH="$HOME/.pbproxy:$PATH"' | tee -a ~/.zshrc 68 | ps | grep $$ | grep -q bash && echo 'export PATH="$HOME/.pbproxy:$PATH"' | tee -a ~/.bashrc 69 | export PATH="$HOME/.pbproxy:$PATH" 70 | hash -r 71 | ``` 72 | 73 | ## Alternatives 74 | 75 | If you know of any other tools in this space feel free to open a PR to include them here! 76 | 77 | - [marcopaganini/clipsync](https://github.com/marcopaganini/clipsync) - conceptually similar, but runs as a background daemon. Unlike pbproxy, this means it can sync automatically in realtime over the cloud, whereas pbproxy only connects to other clipboards on demand. Linux only for now though. 78 | 79 | -------------------------------------------------------------------------------- /pbcopy: -------------------------------------------------------------------------------- 1 | pbproxy -------------------------------------------------------------------------------- /pbpaste: -------------------------------------------------------------------------------- 1 | pbproxy -------------------------------------------------------------------------------- /pbproxy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # this is used to emulate a clipboard on machines where xsel and/or 4 | # pbcopy/pbpaste aren't present (eg a headless linux box with no X server) 5 | PBPROXY_TEMPFILE="$HOME/.pbproxy/pbproxy-tempfile" 6 | 7 | main() { 8 | case "$1" in 9 | --help | -h) 10 | show-usage 11 | return 0 12 | ;; 13 | esac 14 | 15 | local remote_host="$1" 16 | 17 | if [[ -n "$remote_host" ]]; then 18 | case "$SCRIPT_NAME" in 19 | pbcopy | *copy*) 20 | exec cat | ssh "$remote_host" '~/.pbproxy/pbcopy' 21 | ;; 22 | pbpaste | *paste*) 23 | exec ssh "$remote_host" '~/.pbproxy/pbpaste' 24 | ;; 25 | esac 26 | 27 | return 0 28 | fi 29 | 30 | if [[ "$CUR_PLATFORM" == "Darwin" ]]; then 31 | 32 | # run the system pbcopy/pbpaste 33 | exec "/usr/bin/$SCRIPT_NAME" 34 | elif [[ "$CUR_PLATFORM" == "Linux" ]]; then 35 | 36 | if quiet which xsel && quiet timeout 1 xsel --clipboard --output; then 37 | case "$SCRIPT_NAME" in 38 | pbcopy | *copy*) 39 | cat | exec xsel --clipboard --input 40 | ;; 41 | pbpaste | *paste*) 42 | exec xsel --clipboard --output 43 | ;; 44 | esac 45 | else 46 | # Fall back to storing clipboard contents in a tempfile if xsel is 47 | # not available 48 | case "$SCRIPT_NAME" in 49 | pbcopy | *copy*) 50 | exec cat >"$PBPROXY_TEMPFILE" 51 | ;; 52 | pbpaste | *paste*) 53 | [[ -f "$PBPROXY_TEMPFILE" ]] && exec cat "$PBPROXY_TEMPFILE" 54 | ;; 55 | esac 56 | 57 | fi 58 | fi 59 | 60 | } 61 | 62 | show-usage() { 63 | cat < below can be any hostname your machine can reach via ssh 71 | (including host aliases set in ~/.ssh/config) 72 | 73 | Usage: 74 | 75 | Print the data in another machine's clipboard: 76 | 77 | pbpaste 78 | 79 | Copy data to another machine's clipboard: 80 | 81 | echo hi | pbcopy 82 | 83 | EOF 84 | return 0 85 | } 86 | 87 | quiet() { 88 | "$@" &>/dev/null 89 | } 90 | 91 | abspath() { 92 | local dir= 93 | local file= 94 | if quiet pushd "$1"; then 95 | pwd 96 | quiet popd 97 | else 98 | dir="$(dirname "$1")" 99 | file="$(basename "$1")" 100 | quiet pushd "$dir" 101 | echo "$PWD/$file" 102 | quiet popd 103 | fi 104 | } 105 | 106 | SCRIPT_NAME="$(basename "$0")" 107 | CUR_PLATFORM="$(uname)" 108 | 109 | main "$@" 110 | --------------------------------------------------------------------------------