A network clipboard for files and text, between your Mac and Linux machines.
ccp copy a file — or a snippet of text — on one machine, ccp paste on
another — that's it. cross-copy discovers your machines automatically over mDNS
and transfers everything directly between them over your LAN. No cloud, no
account, no config: your data never leaves your network. Want to hand a file
to one machine in particular? ccp send offers it AirDrop-style — nothing
transfers until the other side accepts.
# On your Mac
$ ccp copy notes.pdf
Copied 1 file (2.4 MB) to the network clipboard.
# On your Linux box
$ ccp paste
Pasted notes.pdf (2.4 MB) from sayeed-macbook.Text works exactly the same way:
# On your Mac
$ ccp copy "meeting at 5"
Copied text (12 chars) to the network clipboard.
# On your Linux box
$ ccp paste
meeting at 5ccp paste prints text to stdout, so it pipes — and stdin works too:
cat log.txt | ccp copy # copy a command's output as text
ccp paste > out.txt # paste it into a file on the other machineWorks with multiple files and whole directories too: ccp copy photos/ report.docx.
The clipboard is a pull model — whoever pastes first gets it. ccp send is
a push: you pick the target machine, and nothing transfers until someone
there says yes.
# On your Mac
$ ccp send report.pdf --to linux-box
📨 Offered 1 file (2.4 MB) to linux-box — waiting for them to accept...
✅ linux-box accepted — 1 file delivered# Meanwhile on linux-box, a desktop notification pops up:
# 📥 sayeed-macbook wants to send 1 file (2.4 MB)
$ ccp offers
ID FROM CONTENTS AGE
3f9c1a2b sayeed-macbook 1 file, 2.4 MB 4s
Accept with: ccp accept [id] [dir] · Decline with: ccp decline [id]
$ ccp accept
📥 Accepted 1 file (2.4 MB) from sayeed-macbook
/home/you/Downloads/cross-copy/report.pdfGood to know:
--totakes a device name or id, and is optional when there's exactly one other device on the network.- Text works too —
ccp send "the wifi password" --to macbook— with the same path-vs-text rules asccp copy(-t/--textforces text, and piped stdin works:ccp send --to macbook < notes.txt). Accepted text prints to stdout, so it pipes. - Offers expire after 5 minutes if nobody answers (Ctrl-C while waiting doesn't cancel the offer — it stays acceptable until it expires). The sender is told whether you accepted or declined.
- Accepted files land in
~/Downloads/cross-copyby default — change that with thereceive_dirconfig key, or per-accept:ccp accept [id] ~/dir.
One-liner:
curl -fsSL https://raw.githubusercontent.com/UNILOOP/cross-copy/main/install.sh | bashOr from source:
git clone https://github.com/UNILOOP/cross-copy.git
cd cross-copy
./install.shThe installer prefers pipx if you have it, otherwise it
creates a self-contained venv and links ccp into ~/.local/bin. It also
enables daemon autostart at login by default (systemd user unit on Linux,
launchd agent on macOS) — pass --no-service to skip that, and enable it later
with ccp daemon install. To remove everything: ./uninstall.sh.
- Two or more machines on the same LAN (macOS and/or Linux)
- Python 3.9+
- That's it — the daemon auto-starts on first use
| Command | What it does |
|---|---|
ccp copy <path...|text> |
Put files/dirs on the network clipboard (stays valid for repeated pastes). If no argument is an existing path, the arguments are copied as text; --text/-t forces text. echo foo | ccp copy copies stdin |
ccp move <path...> |
Like copy, but source files are deleted after a successful paste (a text move clears the source clipboard) |
ccp paste [dir] |
Paste the newest peer clipboard into dir (default: current dir); a text clipboard is printed verbatim to stdout instead (pipeable: ccp paste > out.txt). --from <name|id> to pick a machine |
ccp send <path...|text> --to <name|id> |
Offer files or text to one specific device and wait for them to accept (AirDrop-style). Same path-vs-text rules as ccp copy; --to is optional when there's exactly one other device |
ccp offers |
List pending incoming offers (id, sender, contents, age) |
ccp accept [id] [dir] |
Accept an offer — newest one if no id (a short id prefix is enough). Text prints to stdout; files go to dir, or your receive_dir if omitted |
ccp decline [id] |
Decline an offer (newest if no id) — the sender is notified |
ccp devices |
List machines on the LAN with their clipboard contents (alias: ccp list) |
ccp status |
Show daemon status and your current local clipboard |
ccp clear |
Clear your local clipboard |
ccp add <host> [port] |
Manually add a peer by IP (when mDNS doesn't work) |
ccp name <newname> |
Rename this device (defaults to hostname) |
ccp daemon run|start|stop|status |
Manage the background daemon directly |
ccp daemon install |
Set up start-at-login (systemd user unit / launchd agent) and start the daemon now. install.sh runs this by default (--no-service to opt out) |
ccp daemon uninstall |
Stop, disable, and remove the start-at-login service |
ccp ui |
Open the web UI in your browser |
ccp widget |
Run the menu-bar / system-tray companion in the foreground (see below) |
ccp widget install|uninstall |
Start the tray widget now and at every login / remove that. install.sh runs install by default in graphical sessions |
ccp update |
Update cross-copy to the latest version (and restart the daemon) |
ccp update --check |
Only check whether a newer version is available |
ccp version |
Print the version |
cross-copy keeps itself up to date by default: the daemon checks for a new version shortly after it starts and every 6 hours, installs it, and restarts itself. You don't have to do anything.
- Turn auto-update off by setting
"auto_update": falsein~/.crosscopy/config.json. You'll still see an update notice inccp statusand the web UI when a new version is out. - Update manually any time with
ccp update(or just see what's out there withccp update --check).
Everything lives in ~/.crosscopy/config.json (created on first run; edit
and restart the daemon to apply):
| Key | Default | What it does |
|---|---|---|
device_name |
your hostname | How this machine appears to others — or just run ccp name <newname> |
receive_dir |
~/Downloads/cross-copy |
Where files from accepted offers (ccp send → ccp accept) are saved; ~ is expanded. Override per-accept with ccp accept [id] <dir> |
notifications |
true |
Desktop notifications (macOS Notification Center, notify-send/D-Bus on Linux) for incoming offers, declines, and finished transfers. Set to false to silence them |
auto_update |
true |
Let the daemon update itself automatically (see Updates) |
ccp uiOpens http://localhost:7373 — see every device on your network and what each
one is sharing, live: the page updates the moment something changes, no
refreshing needed. Drag & drop files into the browser to share them from
this device without touching the terminal, or use "Share text" to share a
snippet. On the other machine, hit "Save to this device" to receive files
(pick the folder with "Save into folder") or "Get text" to grab shared text
— it lands right there and goes onto the browser clipboard as well. Done
sharing? Hit "Stop sharing".
ccp widget install # start now + at every login (install.sh does this by default)
ccp widget # or run it in the foreground oncePuts cross-copy in your menu bar (macOS) / system tray (Linux): send
files or your clipboard text to any device in a couple of clicks, and accept
or decline incoming offers without opening a terminal. "Open panel" pops
a compact panel with the same controls, live-updating — a native floating
window on macOS (WKWebView), a compact app window on Linux. Remove the
autostart with ccp widget uninstall.
Ubuntu/GNOME note: tray icons render through AppIndicator — the installer builds its venv with
--system-site-packagesso the widget can use the system's PyGObject. If the icon doesn't appear, check that the "Ubuntu AppIndicators" GNOME extension is enabled andgir1.2-ayatanaappindicator3-0.1is installed.
The widget needs two optional dependencies (pystray and Pillow) —
install.sh includes them by default; for manual installs they're the
widget extra:
pip install "cross-copy[widget]"
# pipx users:
pipx install cross-copy && pipx inject cross-copy pystray PillowDesktop notifications don't need the extra: on macOS and Linux the daemon fires them natively whenever an offer arrives, is declined, or a transfer finishes.
- Each machine runs a small daemon (started at login by the installer, and
auto-started on first use otherwise) that announces itself via mDNS as
_crosscopy._tcp, so machines find each other with zero config. ccp copyjust records a manifest — nothing is transferred yet.ccp pastefinds the newest clipboard on the network and downloads the files (or fetches the text) directly from the source machine over HTTP. Nothing ever leaves your LAN.ccp moveis safe: the source files are only deleted after the receiving machine confirms a fully successful paste.ccp sendworks the other way around: the sender posts an offer (just metadata) to the target, and accepting it pulls the files straight from the sender — nothing is transferred until then, and unanswered offers expire after 5 minutes.
-
A device doesn't show up in
ccp devices— some networks (corporate Wi-Fi, VLANs, some routers) block mDNS. Add the peer manually by IP:ccp add 192.168.1.5. -
One-way visibility (machine A sees B, but B doesn't see A) — as of v0.3 this self-heals: machines that can reach each other introduce themselves directly, so as long as either machine can reach the other, both show up within about a minute. If neither direction works, fall back to
ccp add <ip>on one side. -
Devices see each other but transfers fail — a firewall is likely blocking the daemon port. Open TCP 7373 (or your
CROSSCOPY_PORT) on both machines. -
Want to try it on a single machine? Run two instances side by side:
# Terminal 1 CROSSCOPY_HOME=/tmp/a CROSSCOPY_PORT=7373 CROSSCOPY_NO_MDNS=1 ccp daemon run # Terminal 2 CROSSCOPY_HOME=/tmp/b CROSSCOPY_PORT=7474 CROSSCOPY_NO_MDNS=1 ccp daemon run # Terminal 3 — wire them together and use them CROSSCOPY_HOME=/tmp/b CROSSCOPY_PORT=7474 ccp add 127.0.0.1 7373
v0.4.3 trusts your LAN. There is no authentication or encryption yet: any device on your network can read your cross-copy clipboard (files and text) and offer you files. Use it on networks you trust (home, small office) — not on public or untrusted Wi-Fi. Pairing codes and TLS are on the roadmap.
MIT — see LICENSE.
An open source initiative by UNILOOP LLC