One clipboard across Linux, macOS, and iPhone. Copy on any of them, paste on Linux. Copy on Linux, paste on the Mac. Text and photos, no keystroke, no app on the phone.
iPhone ──(Universal Clipboard)──▶ Mac ◀──(SSH, both ways)──▶ Linux (Wayland)
The Mac is the gateway. Linux is the client. The iPhone needs nothing installed: Apple's own Universal Clipboard delivers to the Mac, and clipsync carries it the rest of the way. Works with any clipboard manager, or none.
- Linux ⇄ Mac, text and PNG images, both directions, ~1s.
- iPhone → Linux, text and photos, automatic. Copy on the phone, a toast pops on Linux a few seconds later, paste.
- Photos are downscaled on the Mac to a 2560px long edge before crossing (a 12-megapixel JPEG becomes ~4MB instead of a 34MB PNG). Set
MAX_EDGE=0for full resolution. - Every transfer, error, and offline/online transition is logged.
clipsync-statusshows health at a glance. clipsync-restore-imageputs the last incoming photo back if something on your desktop replaced it before you pasted.
Linux → iPhone goes through the Mac: copy on Linux, then paste on the iPhone while it is near the Mac. Each new outgoing text or image briefly asserts Mac user activity before setting its clipboard, because an awake but idle Mac can suspend Handoff advertising. This can wake the Mac's display; it does not unlock it or change its sleep settings. The phone fetches the clipboard when you paste; clipsync does not write directly to iOS.
Linux: a Wayland session, wl-clipboard (wl-copy/wl-paste), OpenSSH, coreutils, systemd user services. Optional: libnotify for toasts, ImageMagick for dimensions in the log.
Mac: stock macOS. Remote Login enabled (System Settings → General → Sharing) with key-based SSH from the Linux box. The Mac must be awake with the user logged in — Universal Clipboard only resolves in the GUI session.
iPhone: signed into the same Apple ID as the Mac, with Handoff on (Settings → General → AirPlay & Handoff), Bluetooth and Wi-Fi on, within range of the Mac.
Set up an SSH alias for the Mac with connection multiplexing — clipsync polls every second, and this makes each poll ~50ms instead of ~200ms:
# ~/.ssh/config
Host mac
HostName 192.168.1.20 # or a Tailscale name/IP
User you
ControlMaster auto
ControlPath ~/.ssh/cm/%r@%h:%p
ControlPersist 10m
ServerAliveInterval 30
mkdir -p ~/.ssh/cm
ssh mac true # confirm key auth works non-interactively
Then:
git clone https://github.com/nixfred/clipsync
cd clipsync
./install.sh mac # Linux side: ~/.local/bin + systemd --user, starts the daemon
mac/install-mac.sh mac # Mac side: the pull agent, installed over SSH — nothing to click
That's it. Copy something on the Mac and wl-paste on Linux.
Many Wayland setups run wl-paste --primary --watch wl-copy so mouse-highlighted text is available to Ctrl+V. That one-liner has a side effect: the moment you click into an app to paste a photo, the click touches the primary selection and the mirror replaces the photo with whatever was highlighted — the photo "pastes once, then it's gone."
primary-mirror is a drop-in with two guards: it never mirrors an empty selection, and it never overwrites an image. Install it with ./install.sh mac --mirror (a systemd user unit) and remove the old one-liner from your compositor's autostart. Trade-off: while an image is on the clipboard, highlighting text won't replace it — Ctrl+C will.
~/.config/clipsync/config (shell syntax; environment variables override):
| key | default | meaning |
|---|---|---|
MAC_HOST |
— | ssh alias of the Mac (required) |
POLL_SECS |
1 |
seconds between ticks |
MAX_EDGE |
2560 |
downscale phone photos to this long edge; 0 = full resolution |
MAX_BYTES |
67108864 |
hard cap on one clip (64MB); anything larger toasts and is skipped |
TOAST |
1 |
desktop notification when an image arrives |
Restart after changes: systemctl --user restart clipsync.
Start here — the log names the cause:
journalctl --user -u clipsync -n 30 -o cat
clipsync-status
Lines look like mac->linux furl-image 4769259B 0520b2b75d1f 1440x2560 and phone furl: IMG_1234.jpeg. SKIP, ERROR, and UNREACHABLE mean what they say.
Phone copies never reach the Mac. On the iPhone: toggle Handoff off and on, and Bluetooth off and on. This is the single most common fix; the Mac's sharingd can start rejecting the phone's advertisements as replays until the phone re-announces. Confirm the Mac is awake and unlocked. You can watch the Mac's side with UC_PULL_DEBUG=1 in the agent's plist (/tmp/ucpull.log on the Mac).
Photo arrives but is gone after one paste. Something on your desktop is retaking the clipboard — usually a primary-selection mirror (see above) or a clipboard manager that re-copies. clipsync-restore-image brings it back; the mirror replacement fixes it for good.
Pasted early and got the old clip. A full-resolution photo takes a few seconds (Universal Clipboard handoff, then the transfer). Wait for the toast.
Mac asleep. clipsync backs off 15s and resumes on its own; nothing to do.
Clipboard disappeared after a service restart or an app closed. The bridge checks whether Wayland still has a clipboard owner and restores the Mac's current content if it does not. The saved hash and image caches alone must not suppress that recovery. This also means clearing the local clipboard while sync is running restores the remote clipboard.
Each tick:
- Fetch the Mac's clipboard fingerprint (
osascript -e 'clipboard info'). - Phone first. An iPhone photo lands on the Mac as a file URL (
«class furl») into Universal Clipboard's ephemeral shared-pasteboard folder, which macOS purges the instant the Mac clipboard changes. If a fresh one is present, resolve the path on the Mac,sipsit to PNG atMAX_EDGE, and ferry it to Linux — before looking at the Linux side, so a busy Linux clipboard can't stomp it. Freshness is keyed on the file path (every copy gets a new UUID folder), because the fingerprint alone is just the URL's byte length and consecutive photos (IMG_6829,IMG_6830) collide. - Linux side: if the clipboard holds something with a hash we haven't ferried, push it to the Mac (
pbcopyfor text,osascript«class PNGf»for images). - Mac side: same in reverse for direct images and text.
A single last-synced hash prevents ping-pong. Nothing on the Mac writes the clipboard except when Linux pushes.
The Mac agent (mac/uc-pull.sh) exists because a pasteboard read over SSH does not trigger Apple's lazy Universal Clipboard fetch — only a read from the logged-in GUI session does. It runs as a LaunchAgent in gui/<uid>, reads the pasteboard every 1.5s (text and PNG, so photos resolve too), and never writes it.
- Wayland only on Linux (
wl-clipboard). X11 would needxclip/xselin three places — PRs welcome. - One Mac, one Linux box. Not a mesh.
- The Mac has to be awake and logged in; Universal Clipboard does not work from a locked or sleeping Mac.
- Linux → iPhone requires the phone to fetch the Mac clipboard when pasting (see above); it is not a background write to iOS.
MIT