Skip to content

IRCv3 Capabilities

ferrixd advertises 29 capabilities in CAP LS 302 (plus sts when a policy is configured), implemented against the IRCv3 specifications. Negotiation notes:

  • CAP REQ is all-or-nothing: if any requested token is unknown, the entire request is NAK'd.
  • cap-notify clients are informed via CAP NEW/CAP DEL if the advertised set ever changes.
  • sasl carries a value (sasl=PLAIN,EXTERNAL,SCRAM-SHA-256), and so does sts when [server].sts is configured: plaintext connections see sts=port=<tls-port>, TLS connections see sts=duration=<secs>[,preload]. sts cannot be REQed — it is advisory only.

The full set

CapabilitySpec statusWhat it gives the client
saslratifiedauthentication during registration; mechanisms PLAIN, EXTERNAL, SCRAM-SHA-256guide
message-tagsratifiedsend/receive message tags, incl. client-only +tags and TAGMSG
server-timeratifiedtime= tag (millisecond UTC) on all relayed messages — essential for history
echo-messageratifiedyour own messages echoed back with their final tags (msgid, time)
account-tagratifiedaccount= tag on messages from logged-in users
away-notifyratifiedAWAY changes broadcast to common channels
extended-joinratifiedJOIN carries account name and realname
chghostratifiedin-place user@host changes instead of quit/rejoin fakery
setnameratifiedlive realname changes via SETNAME
multi-prefixratifiedall prefixes in NAMES/WHO (@+nick)
userhost-in-namesratifiedNAMES entries as full nick!user@host
cap-notifyratifiedCAP NEW/DEL on capability changes
invite-notifyratifiedchannel ops see INVITEs issued by others
batchratifiedgrouped message delivery (chathistory replay, netsplits)
labeled-responseratifiedlabel= tag echoed on all responses to a labeled command — including the echo-message echo itself, and on the BATCH reference when the handler frames its own batch (CHATHISTORY). A command with no response gets a labeled ACK
standard-repliesratifiedmachine-readable FAIL/WARN/NOTEcodes ferrixd emits
account-notifyratifiedlogin/logout of channel members broadcast as ACCOUNT
extended-monitorratifiedMONITOR watchers also receive AWAY/ACCOUNT/SETNAME/CHGHOST for monitored nicks (each gated on the matching cap)
no-implicit-namesratifiedsuppress the automatic NAMES reply on JOIN (explicit NAMES still answers) — faster joins for clients that don't need member lists
stsratifiedstrict transport security policy ([server].sts config); advertised per connection, never REQable
draft/chathistorydraftserver-side history replay — reference
draft/metadata-2draftkey-value metadata on users and channels via METADATA, incl. SUB/UNSUB/SUBS subscriptions and push notifications when a subscribed key changes
draft/multilinedraftmulti-line messages in a batch; the cap's value carries the limits (max-bytes=4096,max-lines=100), which are enforced (FAIL BATCH MULTILINE_MAX_LINES/MULTILINE_MAX_BYTES). Capable recipients receive a real batch; everyone else gets the lines as individual messages (the spec's fallback)
draft/account-registrationdraftaccount self-registration via REGISTER
draft/read-markerdraftper-account read markers via MARKREAD, synced across a user's connections
draft/event-playbackdraftCHATHISTORY also replays JOIN/PART/QUIT/NICK/KICK/TOPIC/MODE events
draft/message-redactiondraftdelete sent messages from history via REDACT (author or channel op), federated over S2S
draft/channel-renamedraftrename channels in place via RENAME; non-supporting members get a PART/JOIN resync
draft/pre-awaydraftset AWAY before registration completes (bouncers, multi-connection clients)
draft/extended-isupportdraftreceive RPL_ISUPPORT during CAP negotiation, before RPL_WELCOME

Server features that are not capabilities

Some IRCv3 server features are advertised through ISUPPORT or user modes rather than CAP, so clients never REQ them:

FeatureAdvertised asNotes
Bot modeISUPPORT BOT=B, umode +Ba user sets MODE <nick> +B to declare itself a bot; shown in WHOIS (RPL_WHOISBOT, 335), the WHO flags, and a bare @bot message tag on its messages (for message-tags clients). Synced across S2S links
UTF8ONLYISUPPORT UTF8ONLYthe wire protocol is UTF-8-validated at parse time, so non-UTF-8 content is never relayed
Network iconISUPPORT draft/ICON=<url>set via [server].icon; a URL (ideally HTTPS, square) to the network's icon, with an optional {size} template
WEBIRCWEBIRC commandtrusted gateways ([[webirc]]) rewrite a client's apparent host/IP after a constant-time password check and a source-address allow-list
WebSocketsws:// / wss:// listenersws_bind/wss_bind; negotiates the text.ircv3.net and binary.ircv3.net subprotocols, one IRC line per WebSocket message

A note on tagged delivery

Tags are attached per recipient: each client receives exactly the tags its negotiated capability set entitles it to. A server-time-only client sees time=; a client with message-tags + account-tag also sees account= and msgid=; a tagless legacy client sees a bare classic line. No client ever pays (in bytes or parsing) for a capability it didn't ask for.

Example negotiation

» CAP LS 302
« :irc.example.org CAP * LS * :sasl=PLAIN,EXTERNAL,SCRAM-SHA-256 message-tags server-time echo-message account-tag away-notify extended-join chghost setname multi-prefix …
« :irc.example.org CAP * LS :… batch draft/chathistory standard-replies draft/metadata-2 labeled-response draft/multiline draft/account-registration account-notify
» CAP REQ :sasl server-time message-tags batch labeled-response
« :irc.example.org CAP * ACK :sasl server-time message-tags batch labeled-response
» AUTHENTICATE SCRAM-SHA-256

» CAP END

Compatibility

Draft capabilities (draft/ prefix) track their specifications; when a draft is ratified, ferrixd will advertise the ratified name (and, per cap-notify, connected clients learn about it live). Clients that negotiate nothing get a well-behaved RFC 1459 server — every modern capability-negotiated behavior is opt-in via CAP.

Dual-licensed under MIT or Apache-2.0.