sigil-irc
The canonical IRC protocol library for the Sigil ecosystem. Covers both client and server flows for modern IRCv3 (Tier 1 ratified caps + Tier 2 high-value drafts), plus a convenience client API with TLS and cooperative I/O.
Features
Wire layer
- IRC line parser — handles RFC 1459/2812 prefix/command/params/trailing
- IRCv3 message tags — full
@key=value;…parsing/serialization with escape handling (\:\s\\\r\n) - Identity type — fully-qualified
<nick>@<server-domain>with display + canonical accessors (federation-ready from day one) - Numeric reply constants — named bindings for the 50+ relevant IRC numerics (welcome, MOTD, errors, SASL, MONITOR)
Capability negotiation (both directions)
- CAP state machines —
cap-client-stateandcap-server-stateadvance values with no I/O - Tier 1 caps —
sasl,message-tags,server-time,account-tag,account-notify,extended-join,userhost-in-names,multi-prefix,away-notify,chghost,invite-notify,setname,batch,labeled-response,echo-message,cap-notify - Tier 2 caps —
draft/chathistory,draft/read-marker,MONITOR
SASL (both directions)
- PLAIN —
authzid \0 authcid \0 password - EXTERNAL — TLS client cert
- SCRAM-SHA-256 — RFC 5802 / RFC 7677 challenge-response (requires sigil-crypto v0.15.0+ for
pbkdf2-sha256+hmac-sha256-bytes) - Chunked AUTHENTICATE — full base64 chunking per the IRCv3 spec
Read the rest
IRCv3 features
- BATCH — start/end line builders, reftag generator, batch-tag tracking
- CHATHISTORY — query parsing (BEFORE/AFTER/LATEST/AROUND/BETWEEN/TARGETS) + serialization
- MARKREAD (
draft/read-marker) — query/set parsing + line builders - MONITOR — subcommand parsing + numeric reply builders (730–734)
- Server-time, msgid, account, batch, label, +draft/reply, +typing — typed tag accessors
Convenience client (legacy)
The (sigil irc connection) module retains a high-level client convenience API with TLS, SASL, channel tracking, NickServ identify, and an event loop — backwards compatible with prior sigil-irc releases.
IRC over WebSocket
The sibling sigil-irc-websocket package provides (sigil irc websocket), composing the public sigil-websocket client API with the IRC message parser for browser/WASM use. It avoids adding a WebSocket dependency to the core sigil-irc package used by native/desktop IRC clients.
Usage
Client (high-level convenience)
(import (sigil irc)
(sigil irc websocket))
(define conn (make-irc-connection
server: "irc.libera.chat"
port: 6697
nick: "mybot"
tls: #t))
(irc-on conn 'PRIVMSG
(lambda (msg)
(irc-privmsg conn (irc-message-target msg) "Hello!")))
(irc-connect conn)
(irc-join conn "#mychannel")
(irc-run conn)Browser/WASM IRC over WebSocket
(import (sigil irc))
(define session
(irc-ws-connect
url: "wss://enclave.example/irc"
nick: "web-client"))
(irc-ws-register session)
(irc-ws-privmsg session "#sigil" "hello")
(let ((msg (irc-ws-receive session)))
(when (irc-message? msg)
(display (irc-message-command msg))
(newline)))Server (consumer drives I/O)
(import (sigil irc message)
(sigil irc cap-negotiation)
(sigil irc capability)
(sigil irc sasl)
(sigil irc numerics))
;; Build per-connection state
(define cap (make-cap-server-state
server-name: "enclave.example"
supported: (list (make-cap CAP-SASL value: "PLAIN,EXTERNAL")
(make-cap CAP-MESSAGE-TAGS)
(make-cap CAP-SERVER-TIME)
(make-cap CAP-BATCH)
(make-cap CAP-LABELED-RESPONSE))))
(define sasl-state
(make-sasl-server-state
supported-mechanisms: (list SASL-PLAIN SASL-EXTERNAL)
server-name: "enclave.example"
verify: my-password-checker))
;; Inside your accept fiber, on each line:
(let* ((msg (parse-irc-message line))
(cap-out (cap-server-advance cap msg client-nick: nick))
(sasl-out (sasl-server-advance sasl-state msg client-prefix: nick)))
(for-each write-line cap-out)
(for-each write-line sasl-out))Identity is per-server from day one
(import (sigil irc identity))
(define alice (make-irc-identity "alice" "enclave.example"))
(irc-identity->canonical alice) ; => "[email protected]"
(irc-identity->display alice) ; => "alice" (default: nick only)
(irc-identity->display alice show-server?: #t)
; => "[email protected]"This is a federation-readiness constraint: future CrafterNet sovereign-per-server federation hinges on identities being qualified from day one. Local-display helpers strip the suffix for UX; storage and protocol always use the canonical form.
Modules
| Module | Purpose |
|---|---|
(sigil irc) | Top-level re-exports |
(sigil irc message) | Line parsing/serialization, IRCv3 tags |
(sigil irc tags) | Typed tag accessors (server-time, account, batch, label, …) |
(sigil irc identity) | Qualified nick@server identity |
(sigil irc numerics) | Numeric reply constants |
(sigil irc capability) | Capability descriptors, Tier 1+2 names |
(sigil irc cap-negotiation) | CAP state machines (client + server) |
(sigil irc sasl) | SASL state machines (PLAIN, EXTERNAL, mechanism dispatch) |
(sigil irc sasl-scram) | SCRAM-SHA-256 driver (RFC 5802/7677) |
(sigil irc batch) | BATCH command + tag helpers |
(sigil irc chathistory) | CHATHISTORY query parser/serializer |
(sigil irc read-marker) | draft/read-marker (MARKREAD) helpers |
(sigil irc monitor) | MONITOR command + numeric reply builders |
(sigil irc connection) | High-level client convenience API (TLS, event loop) |
Dependencies
- sigil-socket (TCP)
- sigil-tls (TLS for the convenience client)
- sigil-crypto v0.15.0+ (base64, HMAC, PBKDF2 — SCRAM needs the v0.15 SHA-256 byte primitives) The optional
sigil-irc-websocketpackage also depends on: - sigil-irc
- sigil-websocket
Building / testing
sigil deps install
sigil testFor development against unreleased sibling packages, use a dev-redirects.sgl and run sigil test --redirects ./dev-redirects.sgl.
License
BSD-3-Clause
$ git clone https://codeberg.org/sigil/sigil-irc
v0.16.2 — latest by version, released 14 Jul 2026
All releases — 7 tags in this repository.
One page per file, and every line has a permalink.
543888f8
75e3f45f
24715ae3
The last 20 commits keep a page here. Everything older lives in the clone.