nirc-rs/README.md

12 KiB
Executable File

nirc-rs

a multi-protocol terminal chat client written in Rust.

nirc-rs is a TUI (terminal user interface) chat client that places you in control of your data and communications. Inspired by naim, it consolidates eight chat protocols into a single terminal interface — no web browsers, no Electron, no JavaScript.

Version: 0.9.0 License: GPL-3.0-or-later Author: Jeremy Anderson - dcos.net Repository: https://git.dcos.net/dcosnet/nirc-rs


Features

Protocols

Protocol Status Transport Notes
IRC Tested & Working TLS (6697) / plaintext SASL PLAIN, CTCP, ISUPPORT, operator commands
ADC/DC++ Tested & Working TLS / plaintext Hub search, file transfers, varnish guard pipeline
Matrix 🔧 Implemented, Untested HTTPS (matrix-sdk 0.18) Megolm E2EE, SQLite crypto store, room sync
Discord 🔧 Implemented, Untested WebSocket (wss) Gateway events, REST API
Stout 🔧 Implemented, Untested WebSocket (wss) Revolt-compatible fork
Spacebar 🔧 Implemented, Untested WebSocket (wss) Revolt fork
Nerimity 🔧 Implemented, Untested WebSocket (wss) Custom platform
BitChat 🔧 Implemented, Untested libp2p (TCP) P2P, mDNS discovery, gossipsub

UI

  • Tab-based interface — channels, queries, and server statuses each get their own tab
  • Window list (F4 toggle) — side panel showing all open windows with protocol badges and unread indicators
  • F1 dropdown menu — QBasic 4.5 / aptitude-style menu bar for discoverable access to all commands
  • Transfer ticker — footer bar showing active transfer progress (speed, ETA, percentage)
  • HTML markup rendering — messages containing HTML are rendered appropriately
  • Theming — four built-in themes (default, solarized, gruvbox, dracula) with per-color overrides
  • Timestamps — color-coded by protocol (IRC=yellow, Matrix=magenta, ADC=blue, BitChat=green)
  • Status bar — connection info, local IP, window count, unread count
  • Bracket paste support — pasted text is inserted at cursor position
  • Scrollback — per-tab message history (configurable, default 5000 lines)

Security

  • TLS everywhere — rustls with webpki-roots (no system OpenSSL dependency)
  • SASL authentication — PLAIN mechanism for IRC (EXTERNAL with client certs on roadmap)
  • Encrypted identity vault — AES-256-GCM with Argon2id key derivation (64 MiB memory, 3 iterations), keys zeroed from RAM on lock
  • ADC guard pipeline — varnish-style security: rate limits, IP validation, SSRF prevention, path traversal blocking
  • Zeroize — sensitive key material uses the zeroize crate to securely clear memory

File Transfers

  • yamux-multiplexed streams — multiple transfers over a single TCP connection
  • SHA-256 verification — computed in-flight during transfer, not post-hoc
  • Resume support — offset-based, writes to .partial then atomically renames on completion
  • 256 KiB I/O buffers — minimizes syscalls, maximizes throughput
  • 2 GiB size cap — prevents resource exhaustion
  • Cancellation — via tokio::CancellationToken
  • Transfer ticker — real-time speed and ETA in the footer

Extensibility

  • Plugin system — dynamically loaded .so shared libraries via libloading
  • Variables & aliases — user-defined variables (/set), command aliases (/alias)
  • Custom keybindings — map any key to a slash-command in config.toml
  • Per-channel logging — naim-compatible format, 10 MiB rotation with 3 copies

Installation

# Prerequisites: Rust 1.75+ (via rustup), a C compiler
git clone https://git.dcos.net/dcosnet/nirc-rs.git
cd nirc-rs
cargo build --release
cp target/release/nirc-rs ~/.local/bin/

Via cargo install

cargo install nirc-rs

System packages

Arch Linux (AUR), Debian/Ubuntu .deb, RPM .spec, and Nix flake are available in the packaging/ directory. See packaging/ for details.


Quick Start

Run nirc-rs with no arguments. It creates ~/.nirc/config.toml with sensible defaults and opens the TUI:

nirc-rs

Connect to an IRC server:

/connect irc irc.libera.chat:6697
/join #rust

That's it — you're chatting. See QUICKSTART.md for a more detailed walkthrough.


Key Bindings

Key Action
Enter Send message or command
Backspace Delete character before cursor (UTF-8 safe)
Delete Delete character after cursor
Left / Right Move cursor in input line
Home / End Previous / next window
Insert Scroll chat to bottom (unlock auto-scroll)
Ctrl-N Jump to next window with unread messages
Ctrl-B Jump back to previously active window
Ctrl-P Previous buffer
Ctrl-A Next active buffer
Ctrl-Z Cycle highlight (rotate through highlight words)
Ctrl-W Delete word before cursor
Ctrl-K Delete from cursor to end of line
Ctrl-A / Ctrl-E Cursor to start / end of line
Ctrl-U Clear entire input line
Ctrl-L Force terminal redraw
Ctrl-C Quit nirc-rs
Tab Tab-complete (nick/command), or cycle to next window if input is empty
F1 Toggle dropdown menu bar
F4 Cycle window list visibility (Auto → Visible → Hidden)
PgUp / PgDn Scroll chat history (PgUp locks view; new messages won't auto-scroll until you PgDn back)
Up / Down Navigate command history

Configuration Reference

Configuration lives at ~/.nirc/config.toml (auto-created on first run). A full example:

[global]
nickname = "yournick"
realname = "Your Name"
log_level = "info"              # error | warn | info | debug | trace
auto_connect = ["libera"]       # server names to connect on startup

# ─── Servers ────────────────────────────────────────────────────────────
[[servers]]
name = "libera"
protocol = "irc"                # irc | matrix | adc | discord | stout | spacebar | nerimity | bitchat
address = "irc.libera.chat:6697"
tls = true
auto_join = ["#rust", "#nirc"]
auto_reconnect = true

[servers.extra]
sasl_mechanism = "plain"        # plain | external (external not yet implemented)
sasl_username = "your-account"
sasl_password = "your-password"

[[servers]]
name = "adc-hub"
protocol = "adc"
address = "hub.example.com:2780"
tls = false
auto_join = []

# ─── Appearance ─────────────────────────────────────────────────────────
[appearance]
theme = "default"               # default | solarized | gruvbox | dracula
show_timestamps = true
clock_24h = true
max_scrollback = 5000

[appearance.custom_colors]
# Override individual theme colors:
# accent = "#FF79C6"
# error_fg = "#FF5555"
# bg = "#1E1E2E"

# ─── Notifications ──────────────────────────────────────────────────────
[notifications]
desktop_enabled = true
bell_enabled = true
debounce_ms = 2000
extra_highlight_words = ["urgent", "ops"]

# ─── File Transfers ─────────────────────────────────────────────────────
[transfers]
download_dir = "~/downloads"    # defaults to system downloads dir
buffer_size = 262144            # 256 KiB in bytes
max_concurrent = 3
auto_accept_from = []           # nicks that auto-accept files from

# ─── Custom Keybindings ─────────────────────────────────────────────────
[keybindings]
# "F5" = "/connect irc libera"
# "Ctrl-G" = "/jump"

Matrix Server Configuration

[[servers]]
name = "matrix"
protocol = "matrix"
address = "https://matrix.org"
auto_join = ["#nirc:matrix.org"]

[servers.extra]
user_id = "@alice:matrix.org"
password = "hunter2"
device_id = "NIRC-DEVICE-1"
device_name = "nirc-rs"
# access_token = "syt_abc..."   # for session resume without password

BitChat P2P Configuration

[[servers]]
name = "bitchat"
protocol = "bitchat"
address = "/ip4/0.0.0.0/tcp/9394"

[servers.extra]
bootstrap = "/ip4/1.2.3.4/tcp/9394/p2p/QmSomePeerId"

Protocol Details

IRC (Tested & Working)

Full IRCv3 support with:

  • TLS via rustls (port 6697, auto-detected)
  • SASL PLAIN authentication
  • CTCP — auto-responds to VERSION requests
  • ISUPPORT — server capability negotiation
  • Operator commands/oper, /kill, /kline, /unkline, /wallops
  • Channel ops/op, /deop, /kick, /invite, /mode
  • User commands/whois, /who, /names, /topic, /away, /me, /notice
  • Raw IRC/raw or /quote to send arbitrary IRC lines
  • UTF-8 safe backspace and cursor movement

ADC/DC++ (Tested & Working)

  • Hub connection — HSUP, HSID, INF handshake sequence
  • Hub search — SCH command for searching hub file listings
  • File transfers — yamux-multiplexed, SHA-256 verified, resumable
  • Security pipeline — rate limiting, IP validation (reject private/link-local IPs), SSRF prevention, path traversal blocking
  • BINF — user info broadcast with I4/U4 support for incoming C-C connections

Other Protocols

The following protocols are fully implemented in the codebase but have not been tested against live servers yet. They are on the TODO list for upcoming releases:

  • Matrix — E2EE via megolm, SQLite-backed crypto store, dedicated OS thread for non-Send crypto types, full room/member/event handling
  • Discord — Gateway WebSocket, REST API integration
  • Stout — Revolt-compatible fork via REST + WebSocket
  • Spacebar — Revolt fork via REST + WebSocket
  • Nerimity — Custom platform via REST + WebSocket
  • BitChat — P2P via libp2p (TCP, mDNS discovery, gossipsub, noise protocol, request-response)

Plugin System

nirc-rs supports dynamically loaded plugins via .so shared libraries (Linux/macOS). Plugins implement the Plugin trait and are loaded at runtime via libloading.

// src/plugins/mod.rs defines the trait:
pub trait Plugin {
    fn name(&self) -> &str;
    fn on_message(&self, msg: &ChatMessage) -> Option<ChatMessage>;
    fn on_command(&self, cmd: &str, args: &[&str]) -> Option<String>;
}

Place compiled .so files in ~/.nirc/plugins/ and they will be loaded automatically.


File Transfers

File transfers are yamux-multiplexed over existing connections:

  • Send: /sendfile nick /path/to/file or /xfer <protocol> <nick> [filepath]
  • Receive: /acceptfile <transfer-id> ~/downloads/
  • Monitor: /transfers to list active transfers; footer ticker shows real-time progress
  • Resume: interrupted transfers resume from the last byte written (offset-based, .partial files)
  • Verify: SHA-256 hash verified in-flight during transfer
  • Size limit: 2 GiB maximum per file

Wire protocol: 4-byte magic (NAIM), 2-byte version, flags, 8-byte file size, 8-byte resume offset, filename, optional 64-byte SHA-256 — all little-endian.


Contributing

Contributions are welcome. The project uses Rust edition 2021 and requires Rust 1.75+.

git clone https://git.dcos.net/dcosnet/nirc-rs.git
cd nirc-rs
cargo test          # run all tests
cargo build --release  # production build

For bug reports, feature requests, or protocol testing, visit https://git.dcos.net/dcosnet/nirc-rs.


License

nirc-rs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

See LICENSE for the full text.

Copyright (C) 2026 dcos.net