Architecture
Technical overview of repartee's internal design.
Technology stack
| Component | Technology |
|---|---|
| Language | Rust 2024 edition |
| TUI framework | ratatui 0.30.2 with crossterm backend + ratatui-image 11.1.0 |
| Web frontend | Leptos 0.7 (WASM CSR) + Axum 0.8 + rustls (aws_lc_rs) + beamterm-renderer 1.0 |
| Async runtime | tokio (full features) |
| IRC protocol | irc-repartee crate v1.5.2 |
| Scripting | Lua 5.4 via mlua 0.12.2 |
| Storage | SQLite via rusqlite 0.40.2 (bundled, WAL + FTS5) |
| Encryption | AES-256-GCM via aes-gcm 0.11.1 (log storage) + Ed25519 / X25519 / XChaCha20-Poly1305 (RPE2E v1) |
| Error handling | color-eyre + thiserror |
| Config | TOML via serde |
TEA architecture
repartee follows The Elm Architecture (TEA) pattern:
Model → Message → Update → View
- Model:
AppState-- all application state (buffers, connections, config) - Message: Events from IRC, keyboard, mouse, timers, web sessions, shell PTYs
- Update: Event handlers that transform state
- View: ratatui rendering functions that read state (and broadcast snapshots for web clients)
State is UI-agnostic -- the state/ module has no ratatui imports.
Module structure
src/
main.rs # Entry point, fork, terminal setup, CLI subcommands
app/ # Main event loop, App struct, event dispatch
constants.rs # APP_NAME and global constants
config/ # TOML config loading & validation
state/ # Application state (buffers, connections, sorting, typing, act)
session/ # Detach/reattach infrastructure
mod.rs # Socket paths, session listing, PID liveness
protocol.rs # Shim ↔ backend message types (bincode framing)
shim.rs # Terminal shim (relay loop, splash, input)
writer.rs # SocketWriter (impl Write for socket output)
irc/ # IRC connection, event handling, formatting
events.rs # IRC message → state update
mod.rs # Connection setup, CAP negotiation, SASL, bouncer probe
cap.rs # IRCv3 CAP framework (30+ capabilities)
isupport.rs # ISUPPORT + draft/extended-isupport parsing
batch.rs # IRCv3 BATCH (netsplit/netjoin, chathistory, multiline, search)
sasl.rs # SASL PLAIN, EXTERNAL, SCRAM-SHA-1/256/512, ECDSA, OAUTHBEARER
extban.rs # Extended ban types ($a:account, etc.)
flood.rs # Flood protection & CTCP rate limiting
netsplit.rs # Netsplit detection
ignore.rs # Ignore list matching
formatting.rs # IRC formatting helpers
whox.rs # WHOX (extended WHO) tracking
dcc/ # DCC CHAT protocol (active & passive)
e2e/ # RPE2E v1 end-to-end encryption (Ed25519, X25519, XChaCha20-Poly1305)
translate/ # Inline message translation (Lingva, Google, MyMemory, LibreTranslate)
shrink/ # Automatic URL shrinking (is.gd)
emote/ # Text emote dictionary & expansion
image_preview/ # Inline & popup image rendering (Kitty, iTerm2, Sixel, halfblocks)
shell/ # Embedded PTY terminal sessions (vt100 screen parser)
spellcheck/ # Multi-language Hunspell spellchecker
web/ # Embedded HTTPS/WebSocket server, WebPush (RFC 8291), WASM bundle
ui/ # TUI rendering
layout.rs # Screen layout + regions
tree_list.rs # Tree & flat buffer sidebar
nick_list.rs # Right sidebar
chat_view.rs # Message display + inline image thumbnails
bare_view.rs # Bare mode (stripped chrome for clean text selection)
shell_view.rs # Embedded terminal PTY view
settings_modal.rs # Interactive /wizard & /config modal
window_overlay.rs # Searchable /window list popup overlay
input.rs # Command input + tab completion + multiline paste guard
status_line.rs # Bottom status bar (+typing, [E2E], [TR], [LAG], Act)
topic_bar.rs # Top topic display
message_line.rs # Single message rendering
styled_text.rs # Format string → ratatui spans
theme/ # Theme loading + irssi-compatible format string parser
scripting/ # Lua scripting engine
engine.rs # ScriptEngine trait + ScriptManager
api.rs # Event names & Lua API bindings
event_bus.rs # Priority-ordered event dispatch
lua/ # Lua 5.4 backend (mlua 0.12.2)
storage/ # SQLite logging + E2E keyring tables
db.rs # Database schema + migrations
writer.rs # Batched async writer
query.rs # Search + read queries
crypto.rs # AES-256-GCM encryption
types.rs # LogRow, StoredMessage
commands/ # Command system
parser.rs # /command arg parsing
registry.rs # Command registration (80+ built-in commands)
handlers_irc.rs # IRC & IRCv3 commands (/join, /chathistory, /bouncer, /redact, etc.)
handlers_ui.rs # UI commands (/clear, /close, /wizard, /bare, /shell, etc.)
handlers_admin.rs # Admin commands (/set, /reload, /e2e, /translate, /script, etc.)
handlers_dcc.rs # DCC commands (/dcc chat, /dcc close, etc.)
docs.rs # Bilingual command documentation loader (EN + PL)
Session architecture
On startup, repartee forks into two processes:
repartee
├── Backend (child) # headless daemon — IRC, state, socket listener
│ └── Unix socket # ~/.repartee/sessions/{pid}.sock
└── Shim (parent) # terminal bridge — renders UI, forwards input
The backend runs the tokio event loop, manages IRC connections, state, scripts, and logging. It listens on a Unix socket for shim connections.
The shim captures terminal events (keyboard, mouse, resize) and sends them to the backend as ShimMessage variants. The backend renders ratatui frames and sends raw terminal output back as MainMessage::Output. Communication uses length-prefixed bincode serialization.
On detach, the shim exits (shell gets its prompt back). The backend continues running. On reattach, a new shim connects to the socket. The shim sends a TerminalEnv snapshot (dimensions, font size, terminal type env vars) so the backend can adapt to the new terminal.
On SIGHUP (terminal closed unexpectedly), the backend auto-detaches instead of crashing.
Event flow
- Terminal events (keyboard, mouse) arrive via crossterm
event::pollin aspawn_blockingthread (or via socket from the shim) - Events are sent through a tokio mpsc channel to the main loop
- IRC events arrive via the
irccrate's async reader, converted toIrcEventenum variants - The main loop in
App::run()processes all events sequentially, updatingAppState - After each event batch, the UI is re-rendered from the current state
IRC connection layer
Each server connection spawns:
- An async reader task that receives IRC messages and sends
IrcEventto a shared mpsc channel - Messages are sent through the
irccrate'sSenderstored in the connection state
All connections share a single event channel, with events tagged by connection_id.
Scripting architecture
ScriptManager
└── Vec<Box<dyn ScriptEngine>>
└── LuaEngine (mlua)
├── Per-script Lua environments (sandboxed)
├── Event handlers (priority-sorted, per-event)
└── Command handlers
The ScriptEngine trait allows adding new languages (Rhai, etc.) by implementing the trait and registering with ScriptManager.
IRCv3 & Bouncer support
repartee implements 30+ IRCv3 and bouncer capabilities negotiated during connection via CAP LS 302 / REQ / ACK (plus dynamic CAP NEW / CAP DEL):
| Capability | Description |
|---|---|
multi-prefix | Multiple mode prefixes per nick (e.g. @+nick) |
extended-join | Account name and realname in JOIN messages |
server-time | Message timestamps from the server |
account-tag | Account name on every message |
cap-notify | Server-side capability change notifications |
away-notify | Real-time away status changes |
account-notify | Account login/logout notifications |
chghost | Real-time ident/hostname changes |
setname | Real-time realname/gecos changes (/setname) |
echo-message | Authoritative echo of sent messages |
invite-notify | Notifications for channel invites |
batch | Grouped message batches (netsplit, netjoin, chathistory, draft/multiline, soju.im/search) |
labeled-response | Request/response correlation via @label tags |
userhost-in-names | Full user@host in NAMES replies |
no-implicit-names | Suppresses automatic NAMES burst on JOIN |
message-tags | Arbitrary IRCv3 message metadata (+typing, +draft/reply, +draft/react, +draft/channel-context) |
monitor / extended-monitor | Server-side online presence watching (/monitor) |
draft/chathistory | Server-side message history retrieval (/chathistory) |
draft/event-playback | Includes non-message events in history batches |
draft/multiline | Multi-line message transmission and assembly |
draft/read-marker | Cross-device read position sync (MARKREAD) |
draft/message-redaction | Server-side message deletion (REDACT / /redact) |
draft/account-registration | In-band account registration (REGISTER / /register) |
draft/metadata-2 | User and channel key-value metadata (METADATA / /metadata) |
draft/extended-isupport | Extended RPL_ISUPPORT token discovery via ISUPPORT |
draft/webpush | Native IRCv3 WebPush notifications |
soju.im/bouncer-networks | Bouncer upstream network discovery and per-network sibling spawning (BOUNCER) |
soju.im/bouncer-networks-notify | Live notifications of upstream network changes |
soju.im/search | Server-side full-text log search (SEARCH / /bsearch) |
soju.im/client-cert | Client TLS certificate fingerprint management (CERTFP / /bcertfp) |
SASL mechanisms supported (strongest-first selection): ECDSA-NIST256P-CHALLENGE, SCRAM-SHA-512, SCRAM-SHA-256, SCRAM-SHA-1, EXTERNAL (client TLS certificate), OAUTHBEARER, and PLAIN.
WHOX (extended WHO) is auto-detected and used to populate account names and full user@host for nick entries.
Storage pipeline
AppState::add_message()
→ log_tx (tokio mpsc sender)
→ WriterTask (batches 50 rows / 1 second)
→ SQLite (WAL mode, FTS5 index)
Messages flow from the UI thread to the writer task asynchronously, ensuring zero UI blocking on disk I/O.