IRCv3 Support

Comprehensive implementation status of IRC protocol features in repartee, covering RFC 2812 core protocol and IRCv3 capability extensions.

Capability Negotiation

repartee implements the full IRCv3 capability negotiation framework including CAP LS 302 with multiline parsing, CAP REQ/ACK/NAK, and CAP NEW/DEL for runtime capability changes.

FeatureStatusNotes
CAP LS 302DoneMultiline parsing, field3/field4 handling
CAP REQ/ACK/NAKDoneRequest + detect acceptance
CAP ENDDoneProperly closes negotiation
CAP NEW/DELDoneRuntime capability changes via cap-notify

Tier 1 -- Must Have

CapabilityStatusSpecNotes
multi-prefixDone3.1All mode prefixes per user in NAMES
extended-joinDone3.1JOIN includes account + realname
ircnet.com/extended-joinDone--IRCnet ircd 2.12 vendor extension: JOIN also carries <uid> <ip> <netjoin>. Takes precedence when both variants are acked
server-timeDone3.2@time tag used as message timestamp
account-tagDone3.2User account in message tags
cap-notifyDone3.2Server-side capability change notifications
away-notifyDone3.1Real-time away status changes
account-notifyDone3.1Account login/logout notifications
chghostDone3.2Real-time ident/hostname changes
SASL EXTERNALDone3.1CertFP-based authentication via client TLS certificate
SASL SCRAM-SHA-256Done3.1RFC 5802/7677 challenge-response with server signature verification
SASL mechanism selectionDone--Auto-detect best: EXTERNAL > SCRAM-SHA-256 > PLAIN

Tier 2 -- High Value

CapabilityStatusSpecNotes
echo-messageDone3.2Server echoes own messages back; local echo suppressed
invite-notifyDone3.2Channel members see invites
batchDone3.2NETSPLIT/NETJOIN produce summary messages; carries multiline + chathistory batches
userhost-in-namesDone3.2nick!user@host parsing in NAMES
message-tagsDone3.2Tags extracted, stored in buffer and DB; also carries client tags on TAGMSG
draft/chathistoryDone--Server/bouncer history: scroll-back paging + reconnect gap-fill (see below)
draft/event-playbackDone--Requests JOIN/PART/mode replay inside CHATHISTORY batches
draft/multilineDone--Long/paste messages framed as one BATCH; inbound reassembly (see below)
+typing client tagDone--Ratified typing indicator on TAGMSG. Send + receive, status-line item in TUI and web UI (see below)

Tier 3 -- Nice to Have

CapabilityStatusNotes
msgidDoneRead from message-tags; drives CHATHISTORY deduplication and reconnect anchors
monitorNot StartedNick online/offline tracking
labeled-responseNot StartedMatch responses to requests
replyNot StartedMessage threading via +draft/reply
setnameNot StartedReal-time realname changes

Server-side history (draft/chathistory)

When the server or bouncer (soju, ergo, …) advertises draft/chathistory, repartee requests history over the wire and folds it into the same SQLite-backed backlog it keeps locally — so you no longer have to drop into the read-only log browser to read older messages.

  • Scroll-back paging -- scrolling a channel or query toward the top pages older messages with CHATHISTORY BEFORE and prepends them to the live view (irssi/WeeChat/The Lounge style). In the web UI the scroll position is anchored so loading older pages never makes the view jump, and the viewport auto-fills on a fresh connect so scroll-back is reachable even before the window overflows.
  • Reconnect gap-fill -- after a reconnect, CHATHISTORY AFTER/LATEST fills the gap since the last message you saw, so nothing is missed across a blip. Multi-page gaps keep paginating until caught up.
  • Quiet ingest -- history batches are stored and rendered in place without re-triggering notifications or activity counters.
  • Deduplication -- rows are de-duplicated by msgid (with a millisecond-timestamp fallback for msgid-less servers), so overlapping pages and live/history races don't double up. draft/event-playback is requested alongside so JOIN/PART/mode changes replay inside the batch, and encrypted logs are decrypted on these reads.

Multiline messages (draft/multiline)

draft/multiline lets a genuinely multi-line message travel as a single logical message instead of N separate lines.

  • Outbound -- a pasted or composed multi-line message is framed as one BATCH of type draft/multiline, honouring the server's advertised max-bytes/max-lines limits, and paste-coalesced so a paste is one message rather than a flood. This is E2E-safe: an encrypted multi-line message stays a single RPE2E unit.
  • Inbound -- incoming multiline batches are reassembled into one message for display and storage; oversized or inconsistent batches are rejected and FAIL BATCH MULTILINE_* errors are surfaced rather than swallowed.
  • TUI compose -- press Alt+Enter to add a line break in the composer and send the whole block as one multiline message.
  • Web -- the web composer sends multi-line input as one \n-preserving message when the cap is active (and still falls back to line-by-line sending when it isn't).

Typing indicators (+typing)

repartee implements the ratified +typing client tag. It rides on TAGMSG and needs only message-tags, so there is no separate capability to negotiate and nothing to configure to get it working.

  • States -- active (you are composing), paused (text is still in the input but you have stopped for a moment), and done (the input is empty again). active and paused render identically; the distinction is not surfaced.
  • Timing -- notifications are throttled to one every 3 s per target. A received active expires after 6 s and a paused after 30 s, so a peer that crashes mid-sentence never leaves a stuck indicator. Sending a real message retracts the indicator implicitly -- no done is sent after it.
  • What counts as typing -- non-empty text that isn't a /command. A /me (or /action ) draft is a message, so it does announce typing.
  • Send/receive are separate -- [typing] show controls whether you see other people; send_channels and send_queries independently control whether you announce your own, in channels and in private queries respectively. All three default to on.
  • Compatibility -- repartee only ever sends the ratified +typing, but still accepts the pre-ratification +draft/typing on receive. The tag is suppressed on servers that block it via ISUPPORT CLIENTTAGDENY, and is never sent on an unregistered connection.
  • Never noisy -- a TAGMSG never opens a buffer, never lands in your log or scrollback, and never bumps an activity or unread counter. Replayed history batches and your own echo-message reflections are ignored, and ignore-list rules apply. Typing state is dropped on PART, QUIT, KICK, nick change, netsplit and disconnect.
  • Flood-safe -- typing frames are charged against the same flood budget as everything else and are skipped when headroom runs low, so an indicator can never get you flooded off.
  • Scripting -- hook api.on("irc.typing", ...) to observe or suppress typing notifications. See the Lua API reference.

The indicator is rendered by the typing status-line item (in the default [statusbar] items list), in both the TUI and the web UI: alice is typing…, alice and bob are typing…, alice, bob and 2 others are typing….

RFC 2812 -- Core Protocol

Connection Registration

FeatureStatusNotes
PASSDoneServer password sent before registration
NICKDoneNickname setting + ERR_NICKNAMEINUSE retry
USERDoneUsername/realname registration
OPERDoneIRC operator login
QUITDoneDisconnect with message
USER MODEDone+i, +w, etc.

Channel Operations

FeatureStatusNotes
JOINDoneMultiple channels, keys
PARTDoneLeave with reason
CHANNEL MODEDone+beiklmnostRIv and prefix modes
TOPICDoneGet/set, RPL_TOPIC/RPL_TOPICWHOTIME
NAMESDoneRPL_NAMREPLY with prefix parsing, multi-prefix, userhost-in-names
LISTDoneChannel listing
INVITEDoneInvite user + notification
KICKDoneKick with reason

Messaging & Queries

FeatureStatusNotes
PRIVMSGDoneChannel + private, CTCP ACTION
NOTICEDoneServer + user notices
TAGMSGDoneTag-only message; carries the +typing client tag. Never stored or displayed
WHO / WHOXDoneBasic WHO (352) + WHOX (354) with account tracking; SID/UID-aware on ircu-family and IRCnet (see below)
WHOISDoneFull multi-line WHOIS display
WHOWASDoneOffline user lookup
AWAYDoneSet/unset + RPL_AWAY display
WALLOPSDoneWall message display

CTCP

FeatureStatusNotes
ACTIONDoneSend + receive
VERSIONDoneAuto-response
PINGDoneAuto-response
TIMEDoneAuto-response
FINGERDoneAuto-response
SOURCEDoneAuto-response

ISUPPORT (005)

FeatureStatusNotes
Token collectionDoneRaw tokens stored on Connection
Structured parsingDonePREFIX, CHANMODES, NETWORK, STATUSMSG, WHOX, EXTBAN, CASEMAPPING
Behavior adaptationDoneUpdated on each RPL_ISUPPORT, NETWORK drives label

Custom Extensions

FeatureStatusNotes
WHOXDoneExtended WHO with field selectors, token matching, account field. Auto-detect via ISUPPORT WHOX token. Auto-WHO on channel join populates NickEntry. Full parity on ircu-family and IRCnet ircd (see below).
ExtbanDone$a:account -- account-based bans/exempts/invites. /ban -a account shorthand. ISUPPORT EXTBAN awareness.

WHOX on ircu-family and IRCnet

/who -- and the nick-list metadata the automatic join-time WHO feeds -- understands the SID/UID-aware replies these ircds send, so away state, account names, ident and real hostnames populate correctly instead of coming back blank.

  • Field selector per lineage -- the portable selector %tcuihnfar is used everywhere; IRCnet ircd 2.12 (detected by the ISUPPORT IDCHAN token) gets %tcuihnfaUr, adding the U (user UID) field. The extra field is never sent to other ircds, which would silently shift the reply layout.
  • Reply layout disambiguated by arity -- a 10-argument 354 is the portable layout, an 11-argument one is IRCnet's (with the UID). An account of "0" means "not logged in".
  • Plain WHO (352) now updates state too -- previously it only printed a line, so on servers without WHOX the join-time WHO was wasted and away/host/ident never landed in the nick list.
  • Trailing-parameter fix -- IRCnet sends :<hop> <sid> <realname> where the RFC says :<hop> <realname>, so a stray 4-character SID used to render glued to the realname. The hopcount is now stripped everywhere and the SID only on IRCnet-lineage servers, both defensively.

Skipped

CapabilityReason
metadata / metadata-notifyRarely deployed
stsStrict Transport Security -- out of scope for now
zcryptNiche, rarely used
Note: All new protocol handling includes tests. Message tags propagate to the scripting API and storage layer. The capability negotiation framework is extensible for future additions.