A terminal-based Signal messenger client with an IRC aesthetic. Wraps signal-cli via JSON-RPC for the messaging backend.
brew tap johnsideserf/siggy
brew install siggyDownload the latest release for your platform from Releases.
Linux / macOS (one-liner):
curl -fsSL https://raw.githubusercontent.com/johnsideserf/siggy/master/install.sh | bashWindows (PowerShell):
irm https://raw.githubusercontent.com/johnsideserf/siggy/master/install.ps1 | iexBoth scripts download the latest release binary and check for signal-cli.
Requires Rust 1.70+.
cargo install siggyOr clone and build locally:
git clone https://github.com/johnsideserf/siggy.git
cd siggy
cargo build --release
# Binary is at target/release/siggy- signal-cli installed and accessible on PATH (or configured via
signal_cli_path) - A Signal account linked as a secondary device (the setup wizard handles this)
siggy # Launch (uses config file)
siggy -a +15551234567 # Specify account
siggy -c /path/to/config.toml # Custom config path
siggy --setup # Re-run first-time setup wizard
siggy --demo # Launch with dummy data (no signal-cli needed)
siggy --incognito # No local message storage (in-memory only)On first launch, the setup wizard guides you through locating signal-cli, entering your phone number, and linking your device via QR code.
Config is loaded from:
- Linux/macOS:
~/.config/siggy/config.toml - Windows:
%APPDATA%\siggy\config.toml
account = "+15551234567"
signal_cli_path = "signal-cli"
download_dir = "/home/user/signal-downloads"
notify_direct = true
notify_group = true
desktop_notifications = false
inline_images = true
mouse_enabled = true
send_read_receipts = true
theme = "Default"
proxy = ""All fields are optional. signal_cli_path defaults to "signal-cli" (found via PATH), and download_dir defaults to ~/signal-downloads/. On Windows, use the full path to signal-cli.bat if it isn't in your PATH.
- Messaging -- Send and receive 1:1 and group messages
- Attachments -- Image previews rendered inline as halfblock art; non-image attachments shown as
[attachment: filename] - Clickable links -- URLs and file paths are OSC 8 hyperlinks (clickable in terminals like Windows Terminal, iTerm2, etc.)
- Typing indicators -- Shows who is typing with contact name resolution
- Message sync -- Messages sent from your phone appear in the TUI
- Persistence -- SQLite message storage with WAL mode; conversations and read markers survive restarts
- Unread tracking -- Unread counts in sidebar with "new messages" separator in chat
- Notifications -- Terminal bell on new messages (configurable per direct/group, per-chat mute) and OS-level desktop notifications
- Contact resolution -- Names from your Signal address book; groups auto-populated on startup
- Message reactions -- React with
rin Normal mode; emoji picker with badge display (π 2 β€οΈ 1) - Reply / quote -- Press
qon a focused message to reply with quoted context - Edit messages -- Press
eto edit your own sent messages - Delete messages -- Press
dto delete locally or remotely (for your own messages) - Message search --
/search <query>withn/Nto jump between results - @mentions -- Type
@in group chats to mention members with autocomplete - Message selection -- Focused message highlight when scrolling;
J/Kto jump between messages - Read receipts -- Status symbols on outgoing messages (Sending β Sent β Delivered β Read β Viewed)
- Disappearing messages -- Honors Signal's disappearing message timers; set per-conversation with
/disappearing - Group management -- Create groups, add/remove members, rename, leave via
/group - Message requests -- Accept or delete messages from unknown senders
- Block / unblock -- Block contacts or groups with
/blockand/unblock - Mouse support -- Click sidebar conversations, scroll messages, click to position cursor
- Color themes -- Selectable themes via
/themeor/settings - Setup wizard -- First-run onboarding with QR code device linking
- Vim keybindings -- Modal editing (Normal/Insert) with full cursor movement
- Command autocomplete -- Tab-completion popup for slash commands
- Settings overlay -- Toggle notifications, sidebar, inline images from within the app
- Responsive layout -- Resizable sidebar that auto-hides on narrow terminals (<60 columns)
- Incognito mode --
--incognitouses in-memory storage; nothing persists after exit - Proxy support -- Configure a Signal TLS proxy via the
proxyconfig field for use in restricted networks - Demo mode -- Try the UI without signal-cli (
--demo)
| Command | Alias | Description |
|---|---|---|
/join <name> |
/j |
Switch to a conversation by contact name, number, or group |
/part |
/p |
Leave current conversation |
/attach |
/a |
Open file browser to attach a file |
/search <query> |
/s |
Search messages in current (or all) conversations |
/sidebar |
/sb |
Toggle sidebar visibility |
/bell [type] |
/notify |
Toggle notifications (direct, group, or both) |
/mute |
Mute/unmute current conversation | |
/block |
Block current contact or group | |
/unblock |
Unblock current contact or group | |
/disappearing <dur> |
/dm |
Set disappearing message timer (off, 30s, 5m, 1h, 1d, 1w) |
/group |
/g |
Open group management menu |
/theme |
/t |
Open theme picker |
/contacts |
/c |
Browse synced contacts |
/settings |
Open settings overlay | |
/help |
/h |
Show help overlay |
/quit |
/q |
Exit siggy |
Type / to open the autocomplete popup. Use Tab to complete, arrow keys to navigate.
To message a new contact: /join +15551234567 (E.164 format).
The app uses vim-style modal editing with two modes: Insert (default) and Normal.
| Key | Action |
|---|---|
Ctrl+C |
Quit |
Tab / Shift+Tab |
Next / previous conversation |
PgUp / PgDn |
Scroll messages (5 lines) |
Ctrl+Left / Ctrl+Right |
Resize sidebar |
Press Esc to enter Normal mode.
| Key | Action |
|---|---|
j / k |
Scroll down / up 1 line |
J / K |
Jump to previous / next message |
Ctrl+D / Ctrl+U |
Scroll down / up half page |
g / G |
Scroll to top / bottom |
h / l |
Move cursor left / right |
w / b |
Word forward / back |
0 / $ |
Start / end of line |
x |
Delete character at cursor |
D |
Delete from cursor to end |
y / Y |
Copy message body / full line |
r |
React to focused message |
q |
Reply / quote focused message |
e |
Edit own sent message |
d |
Delete message (local or remote) |
n / N |
Jump to next / previous search match |
i |
Enter Insert mode |
a |
Enter Insert mode (cursor right 1) |
I / A |
Enter Insert mode at start / end of line |
o |
Enter Insert mode (clear buffer) |
/ |
Enter Insert mode with / pre-typed |
| Key | Action |
|---|---|
Esc |
Switch to Normal mode |
Enter |
Send message / execute command |
Backspace / Delete |
Delete characters |
Up / Down |
Recall input history |
Left / Right |
Move cursor |
Home / End |
Jump to start / end of line |
Keyboard --> InputAction --> App state --> SignalClient (mpsc) --> signal-cli (JSON-RPC stdin/stdout)
signal-cli --> JsonRpcResponse --> SignalEvent (mpsc) --> App state --> SQLite + Ratatui render
+------------+ mpsc channels +----------------+
| TUI | <---------------> | Signal |
| (main | SignalEvent | Backend |
| thread) | UserCommand | (tokio task) |
+------------+ +--------+-------+
|
stdin/stdout
|
+--------v-------+
| signal-cli |
| (child proc) |
+----------------+

