UniClipboard

Sync content

Payload types that flow through the clipboard pipeline.

Edit on GitHub

A "clip" in UniClipboard isn't a single blob — it's a small bundle of representations describing the same logical copy. Some apps copy both rich and plain text; some only ever produce text; an image copy yields the encoded bytes plus a fallback path. The receiver picks the richest representation it understands when you paste.

Supported representations

TypeNotes
Plain textUTF-8. Always present as a fallback when richer types exist.
RTF / HTMLCarried alongside text so rich pastes survive the wire.
ImagesPNG / JPEG / WebP, transferred by content hash.
FilesSingle or multi-file selections, reconstructed at the receiver.

Each representation is a distinct payload on the wire. The dispatcher waits until every representation is delivered before flagging the clip as fully synced — partial deliveries are surfaced in the history.

Small payloads

Text, RTF, HTML, and small images travel inline inside an encrypted envelope (V3 wire format). Each envelope carries its own random 24-byte XChaCha20-Poly1305 nonce; nonce reuse is structurally impossible. The envelope is signed by the sender's node identity and verified before decryption.

Large payloads (files & big images)

Anything past the inline-size threshold is published as a blob:

  1. The sender chunks the payload, encrypts each chunk under the space MasterKey, and seeds the chunks into the local blob store.
  2. A short blob ticket — content hash + access metadata — is sent to the receiver via the same encrypted channel as small payloads.
  3. The receiver streams the blob back. Already-cached chunks short circuit; only missing chunks are pulled.

This means:

  • Files don't have to fit in memory. Both ends stream chunks to and from disk.
  • Resumable across reconnects. A laptop closing mid-file resumes on the next session, picking up at the last completed chunk.
  • Deduplication is automatic. Re-copying the same file pays only metadata overhead — the chunks are already on disk on both ends.

Local storage

Every received payload (and every payload you generate) lands in the local clipboard history:

  • Encrypted SQLite database under the platform-specific app data directory (see Install).
  • A separate encrypted full-text search index for the dashboard search box and uniclip search. The index is encrypted on disk too — "stored locally" is not the same as "stored safely."
  • Blob chunks live under a sibling directory and are garbage-collected according to your retention settings.

If you switch spaces (uniclip join --switch with another sponsor's invitation), the existing history is re-encrypted under the new space's MasterKey before the daemon reports the switch as complete. There is no plaintext window during the transition.

Per-device sync gates

Every paired device exposes a small set of toggles that bound what this machine will send to and receive from that peer:

  • Send to this device — outbound master switch, per peer. When off, clips produced here never leave for that peer.
  • Receive from this device — inbound master switch, per peer. When off, future clips from that peer do not enter this machine's history or system clipboard.
  • Content-type allowlists — for each direction, you can disable individual types (text, image, link, file, HTML/rich text) per peer.

Send toggles are enforced at the sending side's dispatcher, so a disabled type never leaves this machine. Receive toggles are enforced locally before accepted content reaches history, the system clipboard, or re-broadcast. See the Devices page in the GUI; equivalent CLI config commands are on the roadmap.

Mobile sync (companion mode)

Paired mobile devices flow through a separate HTTP path rather than the iroh wire format described above. The desktop daemon exposes the SyncClipboard JSON protocol; the iOS Shortcut and any SyncClipboard-compatible Android client read and write through it.

What works:

  • Bidirectional text, images, and files between desktop and the paired mobile client.
  • Per-device credentials — username and password are minted at pairing and bound to a single registered mobile device.
  • Password rotation without re-pairing the device.

Known limits compared to desktop ↔ desktop sync:

  • Not P2P on the mobile side. The mobile client never does iroh, NAT hole-punching, or relay — it's a plain HTTP client. On the same LAN it works out of the box; to reach it across networks, run a headless server node (a public HTTPS endpoint) or put both ends on a Tailscale / VPN overlay.
  • No mobile-to-mobile sync. Two phones don't talk directly to each other; both talk to the desktop.
  • No per-direction or per-content-type gates yet for mobile pairings.
  • Not part of the space's encrypted history mesh. Mobile clients read and push the latest clipboard item via HTTP rather than participating in the space database.

For the full protocol surface, see Mobile LAN API. For the pairing UI, see Pairing & sync — Mobile companion.

What sync does not do

  • No "history merge" across devices. Each device keeps its own encrypted history. Copying on A delivers to B's history live; B doesn't retroactively receive A's pre-pairing history.
  • No cross-space leakage. Two spaces on the same machine use independent MasterKeys; switching spaces re-encrypts but doesn't share.
  • No clipboard polling. UniClipboard listens for native clipboard events from the OS — there's no busy-wait loop reading the pasteboard.

On this page