Skip to main content

Peer-to-peer clipboard sync for Windows, macOS, and Linux

Project description

ClipSync

Peer-to-peer clipboard sync for Windows, macOS, and Linux. Copy on one machine, paste on another. No account, no cloud, no central server. The data never leaves your devices.

Verified working across Windows, macOS, and Linux, across different networks.

Why this exists

Every other cross-platform clipboard tool I found falls into one of three buckets:

  1. Same-LAN only - needs mDNS or a discovery broadcast, so it breaks the moment you're on a different network (or a corporate one that blocks multicast).
  2. Needs a signaling server - even the "peer-to-peer" modes usually still need a relay or a server you host somewhere, which means one more thing to maintain and one more thing that can go down.
  3. Reinvented the networking stack - custom libp2p, custom NAT traversal, custom encryption. Which means custom bugs.

The design choice here is to reuse Syncthing instead of inventing anything. Syncthing has already solved peer discovery, NAT traversal, TLS with forward secrecy, and relay fallback for millions of users. By treating a single file (clipboard.txt) inside a shared Syncthing folder as the transport, you inherit all of that for free, including cross-WAN sync that just works, without Tailscale, without port forwarding, and without a VPN.

Two loops sit on top:

  • OUT polls the local clipboard and writes changes to the file.
  • IN watches the file with filesystem events and applies remote changes to the clipboard.

A shared-last-value guard prevents ping-pong when both sides see the same write. Newlines are normalized to LF so Windows CRLF doesn't look like a real change and retrigger sync.

At-rest encryption

Syncthing already encrypts data in transit. For defense-in-depth, in case someone gains read access to the sync folder on one device, you can set a passphrase in Settings. Payloads are then encrypted with Fernet (AES-128-CBC + HMAC-SHA256) using a PBKDF2-SHA256 key derivation, and prefixed with a CSENC magic header so peers can detect ciphertext and refuse to paste it raw.

Every device in the group needs the same passphrase. A mismatch logs a clear "decrypt failed (passphrase mismatch?)" message rather than silently pasting ciphertext.

Install

pip install -r requirements.txt
python -m clipsync

Python 3.11+. The correct Syncthing binary for your platform is downloaded on first run from the official Syncthing GitHub release.

Linux setup notes

pystray picks its tray backend at import time: PyGObject + AppIndicator if available, XEmbed otherwise. KDE Plasma and several other modern desktops no longer render XEmbed icons; they only speak StatusNotifierItem, which AppIndicator provides. If the tray icon silently never appears, install the system packages and make them visible to your venv.

Debian / Ubuntu / Mint

sudo apt install python3-gi gir1.2-ayatanaappindicator3-0.1 xclip

Fedora

sudo dnf install python3-gobject libayatana-appindicator-gtk3 xclip

Arch

sudo pacman -S python-gobject libayatana-appindicator xclip

If you use a virtualenv, set include-system-site-packages = true in its pyvenv.cfg so the system-installed PyGObject is importable. xclip is the X11 backend pyperclip uses for clipboard access; on Wayland install wl-clipboard instead. GNOME users typically also need the AppIndicator extension for the icon to actually show up.

Pairing

  1. Tray icon -> Add Device.
  2. On the second machine, do the same.
  3. Scan the QR code with the webcam, or paste the device ID shown below it.
  4. Both sides auto-accept and start syncing.

Settings

  • Start on login (HKCU Run on Windows, LaunchAgent on macOS, XDG autostart on Linux).
  • Show notifications.
  • Pause sync.
  • Sync folder path.
  • Encryption passphrase.
  • View Syncthing logs.
  • Reset / unpair all devices.
  • Check for updates (compares against the latest GitHub release and opens the download page, no auto-install, no phone-home on startup).

Settings changes from the UI take effect immediately; hand-editing settings.json is also picked up, the file is watched for changes.

How it compares

Tool Cross-WAN No signaling server E2E encrypted Tray UI
ClipSync yes (via Syncthing relays) yes yes yes
p2p-clipboard partial yes yes yes
ClipCascade yes no (self-host required) yes yes
cross-clipboard no (LAN mDNS) yes yes no
macOS Universal Clipboard yes (iCloud) no N/A built-in
Windows Cloud Clipboard yes no (Microsoft account) N/A built-in

Project layout

Module Purpose
config.py Paths, settings with on-disk watch, logging.
syncthing.py Binary download, config generation, REST API client, subprocess lifecycle.
clipboard.py OUT poll + IN watcher, loop guard, optional Fernet encryption.
pairing.py QR generation, webcam scan, auto-accept of pending devices.
ui.py CustomTkinter windows for pairing, devices, and settings.
autostart.py Cross-platform "run at login" toggle.
main.py Tray icon, orchestration, shutdown ordering.

Status

Fully tested and working on Windows, macOS, and Linux.

License

MIT. See LICENSE. You can fork, modify, and redistribute (including commercially), but the copyright notice must travel with the code.

Support

This project is free and I don't ask for anything. If it's useful to you, a star on the repo is appreciated, and if you want to follow along with other things I'm building, you can find them under @offbyonebit.

If you'd like to support development, you can sponsor me on GitHub.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

offbyonebit_clipsync-0.2.2.tar.gz (57.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

offbyonebit_clipsync-0.2.2-py3-none-any.whl (55.1 kB view details)

Uploaded Python 3

File details

Details for the file offbyonebit_clipsync-0.2.2.tar.gz.

File metadata

  • Download URL: offbyonebit_clipsync-0.2.2.tar.gz
  • Upload date:
  • Size: 57.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.3","id":"zena","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for offbyonebit_clipsync-0.2.2.tar.gz
Algorithm Hash digest
SHA256 e30c7e355447c83756a3f5f66877d34a8001c1e23b7cbf64016446a4f2a5b78a
MD5 72aae6773a49e5a62736018d8eff65d3
BLAKE2b-256 67f2cc69c56ab9c47e9ff5215ce0807f33643db22ea0006dd0456a5376a40ef7

See more details on using hashes here.

File details

Details for the file offbyonebit_clipsync-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: offbyonebit_clipsync-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 55.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.3","id":"zena","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for offbyonebit_clipsync-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d11ccfa453bb18aa24aa4173cac0e6e20ead799d10043db4dc119f4526fc9d7e
MD5 85148ab43b571a187c5c2ff8ca55b8e5
BLAKE2b-256 22c81c5ed4fb5fded83f77273358413af528b88da00654ce42f4c1d4a311fcb7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page