Skip to content
github-actions[bot] edited this page Oct 19, 2026 · 1 revision

rettui plays two-player games with your contacts over LXMF: Tic-Tac-Toe, Four in a Row and Chess. Each move goes as a message to them, so a game goes wherever messages go (direct, or through a propagation node to someone who's offline) and takes as long as you both like. The moves aren't in your conversation with them: the Games tab shows the games.

The games are LRGP, the Lightweight Reticulum Gaming Protocol from Ratspeak, so you can play against anyone whose client speaks it, not only rettui. Clients that don't see each move as a message like [LRGP Chess] e2e4.

The Games tab

Games have a tab of their own, second in the sidebar, between Messages and Channels (2). It lists your games with everyone, newest first: who with (their face, or their icon), the game, and where it stands ("Your move", "Their move", "They challenged you", "You won by checkmate", …), with a ● on those waiting on you. The tab's badge counts those. Beside the list is the selected game's board, with what you can do now, redrawn as their moves arrive, and how your last move went while it's being sent (or if it failed).

Above the list, All, Active, Pending and Completed filter it (f goes through them): games under way, challenges not yet answered (yours or theirs), and games that are over (won, lost, drawn, declined or expired).

A move that arrives notifies you as a message does (unless the conversation's notifications are off, or it's on screen); opening the notification shows the game.

Starting a game

n in the Games tab (+ New game in the web UI) asks who with (from your conversations), then which game. From a conversation, g (the 🎲 Games button in the web UI) goes to your newest game with them in the Games tab, or starts a new one with them if there's none; the conversation's title (the button, in the web UI) says when a game waits on you.

Your challenge goes as a message. They accept or decline it; whoever challenged moves first (in Chess the colours are drawn when the challenge is accepted, and White moves first).

Playing

In the terminal, ↑↓ pick a game in the list and Enter (or a click on the board) puts you on its board; Esc goes back to the list. On the board, the keys below play; in the list, f filters it, c opens the conversation and x forgets the game. In the web UI, pick a game and click on its board.

Terminal UI Web UI
Tic-Tac-Toe arrows and Enter, or 1–9 (left to right, top to bottom), or click a cell click a cell
Four in a Row ←→ and Enter, or 1–7, or click a column click a column
Chess arrows and Enter on one of your pieces, then on where it goes; or a click on each; t to type a move by its squares (e2e4, e7e8n to promote to a knight) click a piece (the squares it can go to are marked), then where it goes; a pawn reaching the far rank asks what it becomes
Accept / decline a challenge a / d buttons
Offer a draw D button
Answer a draw offered y / n buttons
Resign R (asks first) button (asks first)
Send a move that failed again r ↻ Send again
Forget a game x (asks first) Forget
Back to the list Esc ← (on a phone)

Black sees the chess board turned round, and in the terminal the cursor starts on your e-pawn. Moves that aren't allowed (out of turn, a full column, an illegal chess move) are refused before anything is sent.

How it works

A game's message is an ordinary LXMF message whose text says what it is, with two fields: 0xFB, the protocol's name (lrgp.v1), and 0xFD, the move (a few dozen bytes of msgpack: the game, the command, the session, the move and a random nonce). The players are their LXMF addresses, as other LRGP clients name them, so whose turn it is matches on both sides.

  • Only checked moves are played. A game's move is played only when its signature was checked against the sender's key. One that couldn't be checked (their key isn't known yet) shows in the conversation, as a message with a note, and isn't played. A move in a game from someone who isn't the other player, a copy of one already played, and one read from a paper message aren't played either.
  • Both sides check the rules. If they send a move rettui's copy of the game refuses, it isn't played and they're told (an LRGP error), so the two can't drift apart unnoticed.
  • Sending: your moves go as your messages to them do (by the conversation's delivery mode), never on paper. One that fails is sent again exactly as it was, by r on the board (↻ Send again in the web UI) or, with Resend when they announce on, when they next announce. Other clients may send theirs opportunistically (in one packet, without a Link), which rettui receives as any message.
  • Expiry: a challenge not answered in a day, and a game with no move for a week, expire on each side by its own clock; nothing is sent.
  • Limits: someone can have at most 16 unanswered challenges waiting on you, and everyone together 128; more show in the conversation as messages but aren't played.

Blocked senders' moves are dropped with their messages, and the Unknown senders setting applies to games as to messages.

Where games are kept

In games.json in the data folder, with every game this data folder has played (for each identity it has had), and in backups. The moves themselves are kept with the conversation (only those being sent or that failed, and the newest each way). Forget removes a game and its moves; a game not over isn't ended for the other player, who isn't told. Game moves an earlier version kept in the conversation's history move out of it when rettui starts.

Clone this wiki locally