Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture

Overview

siggy is a terminal Signal client that wraps signal-cli via JSON-RPC over stdin/stdout. It is built on a Tokio async runtime with Ratatui for rendering.

+------------+   mpsc channels   +----------------+
|  TUI       | <---------------> |  Signal        |
|  (main     |   SignalEvent     |  Backend       |
|  thread)   |   UserCommand     |  (tokio task)  |
+------------+                   +--------+-------+
                                          |
                                   stdin/stdout
                                          |
                                 +--------v-------+
                                 |  signal-cli    |
                                 |  (child proc)  |
                                 +----------------+

Async runtime

The application uses a multi-threaded Tokio runtime (via #[tokio::main]). The main thread runs the TUI event loop. signal-cli communication happens in spawned Tokio tasks that communicate back to the main thread via tokio::sync::mpsc channels.

Event loop

The main loop in main.rs runs on a 50ms tick:

  1. Poll keyboard – check for key events via Crossterm (non-blocking, 50ms timeout)
  2. Drain signal events – process all pending SignalEvent messages from the mpsc channel
  3. Render – call ui::draw() with the current App state

This keeps the UI responsive while processing backend events as they arrive.

Startup sequence

  1. Load config from TOML (or defaults)
  2. Check if setup is needed (account field empty)
  3. If needed: run the setup wizard (signal-cli detection, phone input, QR linking)
  4. Open SQLite database (or in-memory for --incognito)
  5. Spawn signal-cli child process
  6. Load conversations and contacts from database + signal-cli
  7. Enter the main event loop

Key dependencies

CratePurpose
ratatui 0.29Terminal UI framework
crossterm 0.28Cross-platform terminal I/O
tokio 1.xAsync runtime
serde / serde_jsonJSON serialization for signal-cli RPC
rusqlite 0.32SQLite database (bundled)
chrono 0.4Timestamp handling
qrcode 0.14QR code generation for device linking
image 0.25Image decoding for inline previews
anyhow 1.xError handling
toml 0.8Config file parsing
dirs 6.xPlatform-specific directory paths
uuid 1.xRPC request ID generation