end-to-end encrypted · six games · chat
Pull up a chair, play a friend.
kibitz is chess, backgammon, checkers, reversi, Connect Four, and provably-fair Battleship — with a chat alongside — over one end-to-end-encrypted session. You get a code phrase like lion-42-maple, a share link, and a QR; the first friend to join sits down as your opponent, everyone after that kibitzes. The relay that carries it all can never read a move or a message.
what's on the table
Six games, one encrypted session.
Games start on demand from a picker and run side by side — play a chess game and a backgammon game at once, chatting the whole time. Every rules engine is pure Go, compiled to WebAssembly, and runs identically on both screens.
Chess
The full ruleset — castling, en passant, promotion, draws and resignation — via the maintained corentings/chess engine. Kibitzers watch and heckle in chat.
Backgammon
With a commit-reveal dice roll: each roll is committed then revealed, so neither side — nor a spectator — can doctor the dice. Forced moves and bear-off, all validated both sides.
Checkers
American draughts with forced captures — the engine walks every capture chain, so a jump you're owed is a jump you must take.
Reversi
Othello, flips and all. Legal moves and passes are computed by the shared engine, never asserted — so both boards always agree on the count.
Connect Four
Drop, connect, gloat. A quick one between the longer games — with the disc-drop animation and a hover ghost showing where your piece will land.
Battleship
Provably fair: each cell of your fleet is a cryptographic commitment made before the first shot. "Sunk" becomes a public derivation — there's no message left to lie in. No hidden server; nobody cheats.
how it's private
The relay is blind.
Your code phrase never reaches the server — it seeds a PAKE handshake between you and each friend. From that, everyone shares a group key; every move, dice roll, and chat line is sealed with XChaCha20-Poly1305 before it leaves the tab. The relay only forwards opaque frames between participants: it sees connection counts and a session id that's a one-way hash of the phrase, and nothing else. Self-host the one-binary relay or use the hosted one — either way it can't read a thing.
// the phrase is the secret — it never // travels; the session id is a hash sessionID = SHA-256("kibitz/v1" ∥ phrase)[:16] // PAKE → pairwise key → group key key = HKDF(pake.SharedKey()) seal = XChaCha20Poly1305(key, frame, AD: sessionID ∥ version ∥ sender)
# what the relay can see session a1b2c3… (hash, not the phrase) members 2 players + 3 kibitzers frames ▓▓▓ opaque ciphertext ▓▓▓ # what it can never see moves · dice · chat · names ✗ sealed
Games sync both-sides-validate — each client runs the same deterministic engine and checks a state hash, so there's no authoritative server to trust or to breach. Read the full threat model ↗.