3.4 KiB
3.4 KiB
clipsync Protocol v1 (MVP)
This document defines an implementation-friendly first protocol for clipboard sync.
Transport
- Discovery: UDP broadcast on port
45821 - Session: TCP on port
45821 - Payload encoding: UTF-8 JSON frames
- Frame format on TCP: 4-byte big-endian length prefix + JSON bytes
Versioning
Each message includes:
version: protocol version string, initially"1"type: message typerequest_id: unique string per request/response pair where relevantdevice_id: sender stable IDtimestamp_ms: unix epoch milliseconds
Discovery message (UDP)
DISCOVERY_ANNOUNCE
{
"version": "1",
"type": "DISCOVERY_ANNOUNCE",
"device_id": "desktop-uuid",
"device_name": "workstation",
"platform": "linux|windows",
"tcp_port": 45821,
"capabilities": ["clipboard:text"],
"timestamp_ms": 0
}
Android listens for these packets and shows peers.
Pairing flow (TCP)
1) HELLO
Both peers exchange:
- protocol version
- device info
- ephemeral nonce
2) PAIR_REQUEST
Unpaired side sends pairing request including:
- public key
- pairing method (
"pin"or"qr")
3) PAIR_CHALLENGE
Responder sends short code metadata (or QR payload hash) and challenge nonce.
4) PAIR_CONFIRM
Requester returns challenge response.
5) PAIR_ACCEPT
Responder confirms trust and stores remote public key.
After PAIR_ACCEPT, both devices persist:
peer_device_idpeer_public_keypaired_at
Session messages
CLIP_UPDATE
{
"version": "1",
"type": "CLIP_UPDATE",
"request_id": "req-123",
"device_id": "android-uuid",
"timestamp_ms": 0,
"origin_device_id": "android-uuid",
"content_type": "text/plain",
"encoding": "utf-8",
"content_hash": "sha256:...",
"content": "clipboard text",
"sequence": 42
}
Rules:
- Only sync
text/plainin MVP. - Ignore messages with known
content_hashfrom recent history. - Ignore message if
origin_device_idequals local device id (echo prevention).
ACK
Acknowledges accepted request_id.
ERROR
Contains error code and message (UNPAIRED, UNSUPPORTED_VERSION, INVALID_MESSAGE, RATE_LIMITED).
PING / PONG
Keepalive every 15 seconds. Drop and reconnect after timeout.
Security baseline
- Reject non-paired peers for clipboard writes.
- Encrypt session channel (TLS or Noise).
- Enforce max payload size (e.g., 1 MiB for MVP text).
- Apply rate limits per peer.
Current daemon behavior (implemented)
- Server sends
HELLOimmediately on TCP connect. - First client message must be
HELLO(elseERROR: INVALID_MESSAGE). - After
HELLO, server accepts either:PAIR_REQUESTand responds withPAIR_ACCEPT(while persisting peer trust), orCLIP_UPDATEfor already-paired peers.
CLIP_UPDATEfrom unknown peers is rejected withERROR: UNPAIRED.- While connected, server polls local clipboard and emits
CLIP_UPDATEto the connected paired peer when local text changes. - Incoming paired
CLIP_UPDATE(content_type = text/plain) is applied to local OS clipboard. - Inbound
CLIP_UPDATEmessages are deduplicated usingcontent_hash(with a fallback hash for missing values). - Inbound
CLIP_UPDATEmessages are rate-limited per peer; over-limit updates returnERROR: RATE_LIMITED. - Keepalive is implemented: server sends periodic
PING, responds to inboundPINGwithPONG, and drops idle sessions after timeout.