Skip to content

Cell - Ta Relay ​

Connect from your phone or another device to your computer's ta serve: both sides establish connections to Relay, which only forwards traffic. Content is end-to-end encrypted, so Relay cannot read it. This is off by default; ta serve only connects to Relay after you pair a device.

text
Mobile (RelaySocket) ──wss──▶ Relay ◀──wss── ta serve (RelayHost) ──ws──▶ localhost /api/ws
          └──────── AES-256-GCM, key only at both ends ────────┘

Pairing ​

bash
ta pair                          # add a device, print pairing link; default Relay is https://relay.cellbang.com
ta pair https://<relay> --name phone   # use your own Relay, name the device
ta pair --list                   # list paired devices
ta pair --remove <device-id>     # unpair, takes effect immediately

Pairing links look like https://<relay>/pair#v=1&h=<host-id>&d=<device-id>&k=<key>. The key is after the #, so the browser won't send it to Relay. Paste the link in the Ta app to connect. You can also pair from the Web client or desktop app: click the gear menu's "Use on your phone…" to show the link as a QR code (shown once only) and list paired devices, whether ta serve is connected to Relay, and allow you to unpair (ta serve's TaRelayServer). Devices are saved in relay.json in the agent directory (file mode 0600); ta serve automatically reads changes as they happen, no restart needed.

Protocol ​

  • /v1/host/<host-id>?secret=<host-secret>: ta serve connects here. Each host ID is claimed by the first host to connect with it; Relay only stores the hash of the secret.
  • /v1/connect/<host-id>: devices connect here. Relay assigns each a channel and forwards it to the host ({t:'open'|'data'|'close', ch, d}).
  • Handshake: the device sends first {t:'hello', v:1, device, nonce}; the host finds the device's key and replies {t:'ready', nonce, proof}. Both sides use HKDF-SHA-256 (device key, salt is both nonces) to derive one AES-256-GCM key for each direction, ensuring every connection has a different key. proof is the host's first encrypted message, proving it has this device's key. After that, every message is encrypted with the IV set to the message sequence number, so Relay's replay, drop, or reorder attempts all fail decryption.
  • The host opens one connection per device to localhost's /api/ws, including the localhost token. Devices never receive or need the token.

Deploying Relay ​

  • Cloudflare Workers: apps/ta-relay (Durable Objects, sleep when idle).
  • Your own machine: ta relay [--host 0.0.0.0] [--port 8080], behind an HTTPS reverse proxy. Host ID ownership exists only in memory; after restart, the first host to connect reclaims it.

Known Limitations ​

  • When going through Relay, only WebSocket calls work. Local file preview in the Web client (/api/files) is not available.
  • Device keys are long-term with no forward secrecy: if a key leaks, old traffic in recordings can be decrypted. Unpairing invalidates the key.