It predated Kick, called Sneedchat Tor-only and listed IRC and Discord as a handful of basics. #238 Co-Authored-By: Claude Opus 5.5 <[email protected]>
5.9 KiB
nobilis
A chat daemon. It speaks IRC, Discord, Matrix, Kick and Sneedchat (SneedChat, the chat built into Kiwi Farms), and translates all of them into one unified JSON model — accounts, buffers, messages — served over a Unix socket.
Frontends talk to that model and never to a protocol. Two exist today: moho, an Electron desktop client, and dms-chat, a Quickshell/QML shell plugin.
Why a daemon
Connections, Tor circuits and Matrix sync are expensive to establish and unpleasant to lose. Keeping them in a long-lived process means a frontend can close, restart, crash or be replaced mid-session without dropping off IRC or resyncing Matrix from scratch. It also means more than one frontend can attach at once — the socket accepts multiple clients, each with its own subscriptions.
src/backend/ one module per protocol (irc, discord, sneedchat, matrix, kick)
src/rpc/ the Unix-socket JSON-RPC server
src/runtime.rs protocol-agnostic connection/buffer/message state
src/store.rs SQLite-backed scrollback persistence
src/accounts.rs account and credential persistence
resources/ assets the protocols need (Sneedchat's smiley table)
Building
cargo build --release
Takes no required arguments. --data-dir and --socket-path override the defaults below.
Wire protocol
Newline-delimited JSON over a Unix socket at $XDG_RUNTIME_DIR/nobilis/nobilis.sock:
request: {"id": 1, "method": "sendMessage", "params": {...}}
response: {"id": 1, "result": {...}} or {"id": 1, "error": "..."}
push: {"event": "message", "data": {...}}
Core methods: listAccounts, listBuffers, listProtocols, addAccount, removeAccount,
setAccountConnected, joinBuffer, partBuffer, sendMessage, editMessage, deleteMessage,
toggleReaction, subscribe/unsubscribe, getBacklog. Each protocol also has its own
account-creation method (addAccount for IRC, addDiscordAccount, addSneedChatAccount,
addMatrixAccount).
Push events: message, messageUpdated, messageDeleted, reactionsChanged, presenceChange,
bufferListChange, connectionState, notification, plus per-protocol login-flow events
(discordLoginQr/discordLoginScanned/discordLoginResult, sneedChatLoginStatus/
sneedChatLoginResult, matrixLoginStatus/matrixLoginResult) and Matrix verification events
(matrixVerificationStatus/matrixVerificationEmoji/matrixVerificationResult).
message, presenceChange, messageUpdated, messageDeleted and reactionsChanged are only
delivered to clients that called subscribe for that buffer; everything else broadcasts.
Notes for frontend authors
- An ordinary message arrives with
kind"chat"from IRC, Discord and Sneedchat, but"message"from Matrix. Treat both as "something a person said"; every other kind (system,join,part,nick,topic,matrixJoin,matrixInvite,matrixKick,matrixQuit) is a log line, and which of those to render is the frontend's choice — nobilis always records them. - Media that nobilis fetched on the client's behalf (Sneedchat avatars and attachments, Matrix
media, shrunk Kick emotes, Discord thumbnails and stickers, the Discord login QR) is handed over as a local
file://path or filesystem path, not a remote URL. This assumes the frontend runs on the same machine. listSneedchatSmiliesreturns a bare filename per smiley, resolved againstresources/sneedchat-smilies/in this repository. A frontend that renders them needs its own copy of that directory.
Protocol backends
A summary; moho's ARCHITECTURE.md has each one in full.
- IRC — TLS with SASL (PLAIN, EXTERNAL, SCRAM-SHA-256), STS, twenty-seven IRCv3 capabilities including chathistory, multiline and message redaction, NickServ, DCC, and image uploads to catbox, postimg, ibb.co or imgur.
- Discord — QR login or Discord's own sign-in page, the user gateway, messages with everything the official client does to them, threads, forums, slash commands, polls, stickers, events and AutoMod. Voice, camera and Go Live streams are its own connections, with DAVE end-to-end encryption, echo cancellation and the soundboard. Nothing Discord puts behind a captcha is attempted.
- Matrix — Client-Server API with full end-to-end encryption (vodozemac-backed Olm/Megolm via
matrix-sdk-crypto), device verification by emoji or QR, cross-signing, key backup, sliding sync, spaces, polls, forwarding, room moderation, and calls including Element Call. - Kick — chat over its Pusher socket with 7TV and BTTV emotes, moderation, polls, predictions and redemptions, and the stream's own HLS playlist, VODs and clips.
- Sneedchat (SneedChat) — on the open internet by default, or over an embedded Tor client (or an external SOCKS5 proxy) at the onion address. Solves the site's proof-of-work anti-bot gate and its login captcha, and holds one persistent websocket per configured room behind a single login. Avatars and attachments are fetched through the same route and cached locally.
Any account on any of the five can be routed through Tor or a SOCKS5 proxy.
On-disk state
| Path | Contents |
|---|---|
~/.config/nobilis/accounts.toml |
account config and credentials |
~/.config/nobilis/scrollback.db |
SQLite scrollback |
~/.config/nobilis/matrix-crypto/ |
Matrix E2EE device keys and Olm sessions |
~/.cache/nobilis/ |
re-derivable media caches |
$XDG_RUNTIME_DIR/nobilis/nobilis.sock |
the control socket |
An flock on the data directory keeps a second instance from racing the first; a second process
notices and exits rather than competing for the socket.
State from when this daemon was called chatd and lived in the moho repository (~/.config/moho,
~/.cache/moho) is moved across automatically on first run.
Licence
GPL-3.0-or-later. See LICENSE.