documentation
Two keys, and they are not the same key.
Almost every confusing thing about end-to-end encryption comes from mixing up two jobs: proving who you are, and hiding what you said. Clawdline keeps them in separate keys, with separate lifetimes, and only one of them ever exists on our side.
key one
Device authentication keypair
- job
- proves "I am device B of account X" by signing a challenge
- who makes it
- each device, for itself — on a Mac it lives in the Keychain; in a browser it is a non-extractable WebCrypto key
- can we see it
- the public half, yes — it is in the machine list by design
- revocation
- the cloud stops routing to that device at the next entitlement refresh — normally inside a minute, and up to 24 hours if our control plane is unreachable. Limit 2 has the whole of it
key two
Account master secret
- job
- encrypts and decrypts every payload you ever send
- who makes it
- your first Mac, once. That machine is the root of trust
- can we see it
- never. That sentence is the entire definition of end-to-end encryption, and it is the reason this page exists
- rotation
- lazy, named by key_id so a new generation needs no new format
How a second device gets the content key
The pattern is the one you already used the first time you opened WhatsApp on a laptop, and it is chosen for exactly that reason.
- First Mac: install, sign in with a device code, and the app generates the master secret locally. Nothing about that step involves us holding it.
- Every device after that: signing in gets you authentication and nothing else. The screen says so plainly — it shows a QR code and asks you to scan it with a device you already have.
- The handover: the master secret travels through that QR channel — either encoded in the code itself, or encrypted under a one-time key derived from a nonce inside it, in which case what passes our servers is still ciphertext. Pairing checks public-key fingerprints at the same moment, so a malicious server cannot insert its own key in the middle.
- Recovery: one recovery code, held by you, in the shape a password manager's secret key already taught. We run no server-side escrow, because "not even we can read it" and "we keep a copy for emergencies" cannot both be true.
Losing every device is not a catastrophe here
This is the structural advantage of encrypting this product rather than a chat app. The source of truth was never in the cloud: your transcripts, your code and your sessions are on your Mac. Lose every key and you lose the optional encrypted history vault — the live content simply flows out of the Mac again the next time you connect. A messaging app that loses its keys loses the conversation; we lose a backup.
What actually travels
One JSON envelope, for everything. The relay routes it by the fields on the left and can do nothing whatsoever with the striped one.
ct is XChaCha20-Poly1305 under the account master secret. sig is Ed25519 by the sending device's authentication key, over the routing fields and the ciphertext — sender is routed by, not signed over. Two keys, two jobs, one envelope — and the cloud holds neither private half.
Commands are encrypted too, and that is the point
It would be possible to encrypt content and still let the server compose commands. We do not: a command from a viewer is signed by that device's key and encrypted under the content key, and the Mac checks both before it injects a single character. This is why "your account was stolen" and "your Mac was taken over" are different sentences in this product.
Two design choices, and why
- One account master secret, not a per-device key-wrapping hierarchy. The hierarchy revokes more cleanly and is a level more complex; v1 takes the simpler one and leaves key_id in the format so the upgrade needs no new wire shape.
- Encryption changes nothing about billing or routing. Concurrency is countable from channel names; push payloads are already end-to-end encrypted by the standard and are sent from your Mac, not through us. Nothing here creates a reason to peek.
The limits of all this — the browser client, lazy content-key rotation, and the metadata that is visible by construction — are written out on the security page rather than left for you to find.