The relay

relay.seshi.sh forwards sealed frames by fingerprint and holds them for whoever is offline. What it sees, what it never sees, and how to run your own.

Nobody has to run one

The first command you run says so, once:

  Using Jiffi's relay at wss://relay.seshi.sh.
  It carries sealed frames between paired people. It sees two fingerprints and
  ciphertext, never content. To use a box of your own:  seshi use wss://<host>

The hosted relay runs on one small machine in Sydney. It holds state in memory, so exactly one machine runs it, and a check every thirty minutes confirms it answers the signed hello. A default relay does make Jiffi the metadata sink for everyone who installs: two routing fingerprints and frame timing per conversation, never content. If that is a problem for you, run your own; it is one command.

What it sees, and never sees

Sees: your connection’s address; both public keys and the fingerprint derived from them; the recipient fingerprint on every frame; the ciphertext and its size; timing; and, for up to fifteen minutes during pairing, the mailbox bundle, which is public keys, a display name and the relay address, base64 and not encrypted.

Never sees: a headline, a body, an act, a ledger state, or who signed a frame. The signature is inside the ciphertext. Every turn is signed with Ed25519 and sealed with ChaCha20-Poly1305 under a fresh key for every single message, using Node’s built-in cryptography and nothing else.

Registering with the relay needs your private key: the relay hands each connection a nonce, the client signs it and presents both public keys, and the relay derives the fingerprint itself. A stranger who knows your fingerprint cannot sit on it or swallow your queued frames.

The caps

Limit Value
Frame size 256 KB
Queued frames per recipient 500, then the oldest is dropped and the sender is told
Queued frames per sender 64
Queue lifetime for an absent recipient 6 hours
Pairing mailbox lifetime 15 minutes, one claim

A thousand active pairs at ten conversations a month is about 25 GB a month, which is a small VPS.

Your own relay

Point both machines at it. The joiner never needs to, because the link carries the host:

seshi use wss://your-host

To run one from a laptop, with a tunnel:

seshi serve

It starts a relay on port 8787, looks for cloudflared or ngrok, waits up to 45 seconds for a public hostname, checks it answers, points this machine at it, and prints:

  ──────────────────────────────────────────────────────────────────
  Relay live at wss://<host>
  Already set as yours. Start talking, in another terminal:

      seshi start "what you want to settle"
  ──────────────────────────────────────────────────────────────────

  This relay forwards encrypted frames between two paired people and
  queues them when one side is offline. It sees ciphertext and two
  fingerprints. It cannot read anything either of you says.

  Leave this running. Ctrl-C stops the relay and the tunnel.

Hosting is the one thing that needs a package, because Node ships a WebSocket client but not a server. Run npm install once in the seshi directory on the hosting machine only; everyone joining needs nothing. Without a tunnel tool it says so and suggests brew install cloudflared.

The tunnel URL dies when you Ctrl-C, which is right for a conversation between two people at their desks. For anything ongoing, put the relay on a host you own with node packages/relay/src/main.ts and a PORT, or the Dockerfile in the repository, and both of you seshi use wss://your-host.

every command on this page is the real one, from the source as shipped