News

v0.7.1

Security Audit Remediation

v0.7.1 closes every finding from the 2026-08-23 security audit — critical, warning, and info — headlined by hard identity gating on chanmod re-op paths, secret redaction across all log sinks, and botlink hub-side re-verification of relayed commands. It also adds .addhost / .delhost for hostmask management and turns input flood limiting on by default.

Added

  • `.addhost` / `.delhost`add or remove hostmasks on an existing user record, with mod_log attribution.
  • `mode()` / `api.mode()` accept a trailing `actor`so plugin-initiated mode changes attribute to the triggering user in mod_log.
  • Scoped `api.help.*` namespacethe help plugin no longer value-imports from src/ at runtime, backed by a new ESLint rule blocking value imports from src/ in all plugins.

Changed

  • Input flood limiting defaults onan omitted flood config block now applies FLOOD_DEFAULTS instead of disabling limiting; bot.example.json ships an explicit flood block.
  • SASL credential fatals exit on first hitwhile cert/DNS failures keep the retry budget. Startup warns when services_host_pattern is empty — it's now a valid bot.json key, and the example ships a concrete services host.

Fixed

  • Critical: chanmod identity gating on re-op pathsmass re-op and reactive -o/-h/-v re-enforcement route through the same hard identity gate as the auto-op join path, and channel-state account names thread into findByHostmask — a nick-squatter on a weak hostmask can no longer be re-opped on hostmask alone during recovery.
  • Critical: secret redaction across all sinks.chpass and other secret-bearing commands are redacted before the REPL log, botnet announce, and mod_log writes via a shared secret-commands module; botlink relay redaction sources the same set.
  • Critical: botlink hub re-checks relayed command flagsagainst its authoritative permission DB before forwarding a cross-leaf CMD, refusing unknown or under-privileged commands instead of blind-forwarding.
  • Permissions & identity fail closedflag verification rejects unknown flag chars, .flags owner-guard resolves the caller by account-aware handle, channel-scoped .flags no longer silently applies globally, DCC command auth keys on the scrypt-authenticated handle instead of hostmask, and services.verifyUser fails closed on type:'none'.
  • DCC hardeningauth lockout keys on handle / ident@host so nick rotation can't reset backoff, socket input is stripped of mIRC and control bytes before dispatch, the passive-offer listener is capped at one connection, and awaiting-password sessions count toward max_sessions.
  • Injection and output sanitizationa shared guard protects KICK/INVITE/JOIN/TOPIC/MODE positional params, account tags are sanitized at extraction, command words and logged user args are stripped of IRC formatting and control bytes on all transports, and command flood keys on ident@host.
  • Botlinkcross-leaf CMD replies are bound to the leaf the request was sent to, so a compromised leaf can't resolve another leaf's pending command; IPv6 literals are normalized, banned peers stay near-zero cost, and pass / link_salt are redacted in logs.
  • chanmod & flood enforcement precision$a: account pinning holds on reactive enforcement, enforcebans gains a mask-specificity floor and never kicks opped, voiced, or flagged members, and flood enforcement pins the offender's hostmask so a bystander who takes over a vacated nick is never punished.
  • Config & secrets hygieneenv-file permission checks sweep the whole config tree plus HEX_ENV_FILE, plugin load warns on inline secret-shaped config values lacking an _env sibling, and .say / .msg reject comma multi-target and leading-colon targets.

See CHANGELOG.md for the full list of changes.


v0.7.0

Services-Style Help, Delta Flags & the July Leak Sweep

v0.7.0 redesigns .help / !help in ChanServ services style with topic drill-down, makes .flags apply eggdrop-style deltas instead of replacing the whole flag string, closes every finding from the 2026-07-12 memleak audit — including a remotely-triggerable pre-auth botlink OOM — and lands a round of production fixes for reconnect, botlink sync, and auto-op races.

Breaking

  • `.flags` specs are now eggdrop-style deltas+ adds, - removes, sections apply left to right, and unknown letters are rejected. Previously the spec replaced the whole flag string (.flags self +d wiped +n) and -v actually granted v. The owner-escalation guard now compares current-vs-resulting n/m membership, and a last-owner guard refuses removing +n from the only owner.
  • `docker-compose.yml` renamed to `docker-compose.example.yml`copy it to docker-compose.yml and edit locally; all docker-compose.*.yml variants except the example are git-ignored, so personal overrides stay untracked.
  • ai-chat: `min_users` and `interests` removedboth ambient config knobs were parsed but never read by the AmbientEngine. Delete them from your ai-chat plugin config if present.

Changed

  • Help redesigned in ChanServ services stylethe index lists uppercased topics with aligned blurbs, commands live one level down in the topic view, and per-command detail uses the Syntax: / description / Requires: shape. New drill-downs: .help <topic> <command> and .help set <scope> <group>. A shared formatting service keeps .help and !help output identical.
  • Docker healthcheck simplified to a presence checkthe old 120s mtime-freshness window falsely reported a stably-connected container unhealthy.
  • Ollama fetch-failure errors name the target URLinstead of Node's bare fetch failed, while still classifying as retryable network errors.

Fixed

  • 2026-07-12 memleak audit — all findings closedhighlights: a remotely-triggerable pre-auth botlink OOM (un-terminated lines grew the buffer without bound — a socket-level byte-count guard now destroys them at the 4 KB pre-handshake cap and feeds the auto-ban tracker); outbound flow control disconnects peers whose write buffer exceeds 4 MB; bounded caps and sweeps across networkAccounts, DCC sessions, dispatcher binds, and the ai-chat / chanmod / flood / rss plugins.
  • Reconnect channel-tracking deadlockthe disconnecting window opened by clearAllChannels() never closed after a reconnect, so every new-session JOIN/NAMES was dropped and channel tracking stayed dead until restart. The flag now resets on registered.
  • Botlink hub sync wiped leaf password hashessyncUser() replaced records wholesale while sync frames never carry hashes, so every sync erased the leaf's local hash and DCC logins were rejected. The existing hash now carries across; hashes still never travel over the wire.
  • Auto-op double-grant raceservices emits user:identified before verifyUser() resolves, so every NickServ-verified auto-op landed twice. grantMode() now takes a per-channel|nick in-flight guard.
  • Stale pending DCC offers replaced on retryinstead of denied — the old offer's token could no longer complete anyway. attach() now warns when dcc.ip isn't a valid IPv4 address.
  • `plugins.json` overrides preserved on re-enable.set core plugins.<id>.enabled true reloaded with no config, silently falling back to on-disk defaults (wrong provider/model/channels). The loader now re-reads plugins.json and passes the merged config.

v0.6.0

Live Config, Audit Closures & Clean-Cut Plugin API

v0.6.0 retires the leak-prone .load / .unload / .reload plugin lifecycle in favour of a three-scope live settings registry (core, plugin:<id>, chanset), folds .helpset into a unified help corpus, lands the spotify-radio plugin, and closes a 2026-05-10 stability audit (3 CRITICAL + 89 WARNING + 55 INFO) and security audit (1 CRITICAL + 28 WARNING).

Breaking

  • `.load` / `.unload` / `.reload` removedplugin enable/disable now flows through .set core plugins.<id>.enabled true|false; .restart is the canonical path for picking up code edits. The cache-busting import path that powered .reload is deleted — Node ESM has no eviction API, and every cache-busted re-import minted a permanent module-graph entry.
  • `database`, `pluginDir`, `owner.handle`, `owner.hostmask` removed from `bot.json`they are bootstrap env vars now: HEX_DB_PATH, HEX_PLUGIN_DIR, HEX_OWNER_HANDLE, HEX_OWNER_HOSTMASK. The strict-object schema rejects legacy files with a hint pointing at the env var to set.
  • `api.config` removed from PluginAPIevery shipped plugin migrated to api.settings — typed defs via api.settings.register([...]) and reads via getString / getInt / getFlag. Deeply-nested config falls back to api.settings.bootConfig.
  • `.helpset` removedfolded into .help set <scope> [<key>] against a unified HelpRegistry corpus indexed across core commands, plugin commands, and all three settings scopes.
  • `plugin-load` / `plugin-unload` / `plugin-reload` mod_log action strings retiredhistorical rows remain queryable; new rows use coreset-set / pluginset-set / chanset-set / rehash / restart.

Added

spotify-radio pluginannounces the operator's currently-playing Spotify track to a channel and rebroadcasts a Jam share link. Strict URL allowlist, in-memory refresh-token rotation, NickServ ACC verification on every mutating command. pnpm run spotify:auth for the one-time OAuth flow.
Three-scope settings registrygeneralises the per-channel chanset pattern to core (bot-wide live config), plugin:<id>, and chanset. KV-canonical-after-first-boot: bot.json / plugins.json are first-run seeds, operator .set / .unset / .rehash writes win.
`.set` / `.unset` / `.info` / `.rehash` / `.restart`unified live-config commands. Audit attribution flows through auditActor(ctx) so REPL / IRC / DCC / botlink-relay all converge on the same mod_log shape.
Reload-class metadataevery schema field annotated with @reload:live|reload|restart; .set echoes the class as a hint — (applied live) / (applied; subsystem reloaded) / (stored; takes effect after .restart).
`PluginAPI.coreSettings` + `PluginAPI.settings`read-only view of bot-wide settings and read/write own plugin scope. api.settings.bootConfig exposes a frozen merged JSON snapshot for config that doesn't flatten to typed settings.
Unified `HelpRegistry` corpusstrict prefix-preserving identifiers with a fuzzy fallback for bare !help ban lookups. .help index is permission-filtered for unprivileged DCC/IRC users; REPL and botlink remain unfiltered.
Bounded channel-join retrychannels failing JOIN with permanent-error numerics (+b/+i/+k/+r) walk a configurable backoff schedule (default 5/15/45 min) instead of being stuck until reconnect.
Per-plugin bind cap (warn 500 / hard 1000)closes a memleak finding around plugins that bind without ever unbinding; bindsByPlugin tally in the dispatcher.
Healthcheck splitseparate liveness (/tmp/.hexbot-alive) and readiness (/tmp/.hexbot-connected) sentinels distinguish process-wedged from IRC-unreachable.

Changed

  • `src/bot.ts` split into focused modules-26% LOC with no behavior change; core settings defs co-locate their onChange handlers, kv-maintenance and audit-fallback become small classes, connect() / start() / shutdown() reshaped into named phases.
  • Public `types/` `.d.ts` synced with runtime APIplugin authors relying on public declarations for IDE autocomplete were missing audit, util, settings, coreSettings, banStore and half the recent additions to PluginAPI / HandlerContext / ChannelState.
  • Plugin example configs minimisedevery key whose value the plugin's own schema already supplies is removed; only operator-required and security-relevant keys remain. ai-chat and rss flip to enabled: false so the example doesn't auto-post on first boot.

Fixed

  • 2026-05-10 stability audit3 CRITICAL + 89 WARNING + 55 INFO closed. Every mutating IRC verb now flows through the message queue (chanmod recovery storms can't trip Excess Flood); fatal SQLite errors hand control to bot.shutdown() instead of bypassing teardown via process.exit(2); ensureChannel stops growing unboundedly under stray TOPIC / RPL_CHANNELMODEIS.
  • STS upgrade plaintext-leak windowmessageQueue.clear() now fires BEFORE client.quit() on STS upgrade so the close-time flushWithDeadline(100) can't drain queued PRIVMSGs (potentially containing .adduser password material or plugin tokens) over plaintext between upgrade decision and TLS reconnect.
  • 2026-05-10 security audit1 CRITICAL + 28 WARNING closed. Deep-freeze identity.require_acc_for and bootConfig so a plugin can't disable NickServ verification bot-wide; api.say / notice / action route through splitMessage + target sanitize; STS rejects duration-only directives over plaintext; .ban / .unban thread auditActor so exactly one mod_log row attributes to the caller.
  • `importWithCacheBust` ESM-cache leak resolved by deletionload() uses a plain await import(pathToFileURL(absPath).href); importedOnce, reload(name), and the plugin:reloaded / plugin:reload_failed events are gone.
  • `kv` VACUUM spam from 32-bit `setInterval` overflowthe 30-day delay (2.59 × 10⁹ ms) exceeded Node's TIMEOUT_MAX (~24.8 days), which clamps to 1 ms and fires continuously on startup. VACUUM folds into the daily maintenance handler with an elapsed-time check.
  • First-boot plugin double-load raceseeding core.plugins.<id>.enabled into KV pre-load fired the onChange listener, which fire-and-forgets applyPluginEnabled() and raced the awaited main load loop. Seed moves to after the loop where applyPluginEnabled is idempotent.
  • Memleak audit closurecaps on pendingHandshakes (4096), SharedBanList distinct channels (1024), RelayOrchestrator virtual sessions (64/leaf), and flood channelActionRate (1024 keys, oldest-by-insertion eviction); timers stored in fields and cleared on teardown; DCC / IRCBridge.attach() / Logger.addSinkByOwner listener lifecycles made symmetric.

Removed

  • Closed audit documentsdocs/audits/stability-all-2026-05-10.md and friends deleted after every finding was resolved; commit history retains the reasoning.

v0.5.0

AI Channel Regular, Ollama & BOTLINK v2

v0.5.0 reshapes ai-chat into a true channel regular — character engine, ambient participation, mood, on-demand games — adds an Ollama provider for self-hosted setups, hardens the BOTLINK handshake against replay, and closes 10 findings from a post-incident stability audit.

Added

Character engine9 personality presets (friendly, sarcastic, chaotic, deadpan, gossip, nightowl, oldhead…), per-channel assignment, runtime swap with !ai character <name>
Ambient participationbot speaks unprompted in quiet channels, answers unanswered questions, reacts to topic and join events; rate-limited per channel and globally
Thread-based engagementreplaces the old 60s timer with IRC-native floor-holding semantics; two users can be concurrently engaged in the same channel
Ollama providerself-hosted, private-by-default alternative to Gemini; flip provider between gemini and ollama with a plugin reload
On-demand game sessionsdrop a .txt into games/ and play it via !ai play <name>; ships with 20 Questions and Trivia
Founder-tier refusal gateai-chat refuses to respond when the bot's ChanServ tier is founder, with a per-line gated sender for mid-request tier changes
Bounded channel-join retrychannels stuck on +b/+i/+k/+r failures retry on a configurable backoff schedule (default 5/15/45 min) instead of waiting for reconnect
Nick collision detection + GHOST recoveryautomatic NickServ GHOST + reclaim when the configured nick is taken on connect
IDENTIFY-before-JOIN gatebot waits for confirmed identification before joining channels, eliminating the IDENTIFY/ChanServ probe race

Changed

  • BOTLINK v2 handshakeHMAC challenge-response replaces the replay-able scrypt wire token; every botnet must share a link_salt in bot.json
  • Hub-side BSAY re-checkfanout re-runs the originating user's +m permission so a compromised leaf can't bypass it
  • System-prompt assembly restructuredexplicit Persona / Right now / Rules sections with non-overridable safety clause; defense-in-depth dropper for fantasy-command prefixes

Breaking

  • `!ai` freeform removedtalk to the bot by nick (<botnick>: hello); !ai is now a subcommand console with !ai help
  • ai-chat private messaging removedthe plugin responds only in channels — PMs were a reconnaissance vector for prompt-injection probes
  • `triggers.engagement_seconds` removedreplaced by engagement.soft_timeout_minutes and engagement.hard_ceiling_minutes

Fixed

  • 2026-04-21 stability audit10 findings closed from the post-incident review of a 12+ hour outage where silent SASL failure left the bot unidentified and op-less
  • SASL silent failureNickServ "please identify" notice now triggers a one-shot password fallback and surfaces bot:identified on confirmation
  • Ambient tick-loop crash recoverywrapped in try/catch so a transient bug surfaces in the log instead of silently disabling ambient for the process lifetime
  • Engagement map leakeviction TTL with an unconditional 1000-entry cap so stale entries can't pin below the cap indefinitely

v0.4.1

Shell Injection & ReDoS Fixes

Two security fixes surfaced by audit follow-up: a command injection in the plugin build script and a polynomial ReDoS in the RSS HTML stripper.

Fixed

  • Shell command injection in plugin build scriptswitched from execSync with string interpolation to execFileSync with an argument array so paths with spaces or shell metacharacters cannot alter the command
  • Polynomial ReDoS in RSS HTML tag stripperreplaced the /<[^>]*>/g regex (O(n²) on pathological input) with a single-pass O(n) character scanner that buffers after < and flushes unclosed tags

v0.4.0

Plugin Bundling via tsup

Plugins are now compiled to self-contained bundles at build time. Polish around mode-grant safety, DCC error messages, and Docker image hygiene.

Changed

  • Plugins bundled via tsupplugins with a tsup.config.ts compile into self-contained dist/index.js bundles instead of being loaded as raw TypeScript via tsx; the loader resolves plugins/<name>/dist/index.js for bundled plugins
  • `.binds` output grouped by pluginsection headers for easier scanning
  • Topic plugin `protect_topic` renamed to `topic_lock`consistency with Eggdrop terminology
  • DCC CHAT rejection notices collapsedsingle generic "request denied" message — no longer leaks the specific denial reason to the connecting user

Fixed

  • Mode-grant commands targeting the bot itselfpreviously the bot could attempt to op/deop/voice itself, causing confusing no-ops and mode bounces
  • Docker build failure with plugin local node_modulesadded plugins/*/node_modules and plugins/*/dist to .dockerignore
  • ESLint errors on plugin `dist/` bundlesignore pattern updated to **/dist/ so plugin build output is excluded

Removed

  • `dcc.nickserv_verify` config fielddeprecated in 0.3.0; DCC now uses per-user passwords exclusively

v0.3.0

Audit Logging, AI Chat, RSS & Security Hardening

A foundation release: full mod_log audit pipeline, the ai-chat and rss plugins land, DCC gains password authentication, IRCv3 STS / account-tag / away-notify support, and four parallel audits (security, stability, memleak, quality) close ~50+ findings.

Added

  • `mod_log` audit pipelineschema rewrite with source/plugin/outcome/metadata; api.audit.log() for plugins; .modlog operator UI with filter grammar and DCC-only paging; .audit-tail REPL stream; retention knob
  • `ai-chat` pluginAI-powered chat via Gemini with provider adapter pattern, layered rate limiting, per-user token budgets, sliding-window context, multiple personality presets, on-demand game sessions, and ChanServ fantasy-command injection defense
  • RSS pluginpolls feeds and announces new items, SHA-1 dedup via KV store, first-run silent seeding, admin commands !rss list/add/remove/check, SSRF defense in depth (HTTPS-only, RFC1918 blocking, byte cap, DOCTYPE rejection)
  • DCC console log sinkper-session .console flags filter live log lines (m/o/j/k/p/b/s/d/w); .who is now the session-list command
  • ISUPPORT parsertyped ServerCapabilities snapshot covering PREFIX, CHANMODES, MODES, CHANTYPES, TARGMAX, CASEMAPPING; mode-batching and channel validation now follow what the connected IRCd advertises
  • IRCv3 caps expandedaway-notify (channel-aware), account-tag consumption, $a:account permission patterns, and Strict Transport Security (sts=) with auto-upgrade
  • Configurable command prefixcommand_prefix field in bot.json (default .)
  • Per-target message queueround-robin drain so a flooding target can't starve output to quieter channels
  • BotLink per-IP brute-force protectionescalating bans (5min → 24h cap), CIDR whitelist, per-IP pending-handshake limit, configurable handshake timeout
  • ChanServ-assisted join error recoveryasks ChanServ for help on 471/473/474/475/477 numerics with exponential backoff

Breaking

  • DCC CHAT requires per-user passwordsscrypt-hashed; existing users have no password_hash and are blocked from DCC until an admin runs .chpass <handle> <newpass>. Closes a Rizon-style vhost-persistence bypass.
  • Inline secrets removed from `bot.json`services.password, botlink.password, chanmod.nick_recovery_password, proxy.password, and +k keys must be referenced via <field>_env keys backed by .env
  • `chanmod` `channel_modes` legacy format removedvalues must start with + or - (e.g. "+nt"); unprefixed strings are rejected at parse time
  • `MessageQueue.enqueue(fn)` → `enqueue(target, fn)`core call sites updated; plugin code using api.say/api.notice/etc. is unaffected

Changed

  • Reconnect loop rewrittenHexBot owns the loop end-to-end; classifies disconnects into transient / rate-limited / fatal tiers with appropriate backoff. K/G-line and DNSBL blocks no longer cause exits — they expire on their own.
  • NickServ ACC/STATUS replies suppressed from DCC mirrorinternal verification chatter no longer narrates every !voice command twice in operator consoles

Fixed

  • 2026-04-14 security auditevery Phase 1 critical, Phase 2 warning, and Phase 3 info finding closed across the full codebase
  • 2026-04-14 stability audit10 subsystems hardened against months-of-uptime failure modes — DB error classification, plugin lifecycle fail-loud, services dedup, BotLink jitter, message-queue deadline, DCC eviction, plugin teardown
  • 2026-04-14 memleak auditevery scheduled finding closed across flood, chanmod, DCC, BotLink, RSS, services, memo, and connection-lifecycle; createPluginApi now returns a dispose that neutralises every method post-unload
  • 2026-04-14 quality auditgod-file splits across src/core/dcc/, src/core/botlink/, RSS, flood, plus cross-cutting dedup of permission and pending-request helpers
  • Stalled-reconnect zombie loop30s registration timeout fires on socket-connected so a TCP-but-no-IRC-greeting hang is classified transient and retried with backoff

v0.2.3

Startup Retry & Docker over WireGuard

Initial connection failures now back off and retry, ChanServ presence detection is automatic, and a Docker-over-WireGuard hang is fixed.

Added

  • Startup retry with exponential backofffirst-connection failures no longer exit the process
  • ChanServ auto-detectchanserv_op merged into chanserv_access

Changed

  • Refactored botlink, mode-enforce, and bot.tsreadability cleanup with no behaviour change
  • Detailed disconnect reason loggingconnection error handling enhanced

Fixed

  • IRC connection failure in Docker over WireGuarddisabled Node's Happy Eyeballs algorithm

v0.2.2

Single-Stage Dockerfile

Simpler Docker build using tsx at runtime; pnpm start is now the single entry point.

Changed

  • Dockerfile simplified to single-stage builduses tsx at runtime instead of compiling to JS
  • `tsx` moved from devDependencies to dependenciesrequired for runtime execution
  • `start:prod` script removedpnpm start is the single entry point

v0.2.1

Documentation Sync

Getting Started guide lands; README and core docs synced to current behaviour.

Added

  • Getting Started guidedocs/GETTING_STARTED.md

Changed

  • README overhauledhighlights section, full admin/bot-link/DCC command tables, documentation index
  • Comprehensive doc syncDESIGN.md, PLUGIN_API.md, DCC.md, plugins/README.md updated to match the current codebase
  • Healthcheck heartbeat uses `utimesSync`instead of writing unused file content

Fixed

  • Docker build failure on `husky` prepareran during --prod install and failed because husky is a devDependency

v0.2.0

Bot Linking & Channel Takeover Protection

Multi-bot networking inspired by Eggdrop botnet, persistent channel rejoin, ChanServ-backed takeover protection, and a round of security fixes.

Added

  • Bot linking protocolhub-and-leaf networking with state sync, command relay, party line chat, session relay, protection frames, and ban sharing — JSON-framed protocol over TCP with SHA-256 auth and rate limiting; admin commands .botlink status|disconnect|reconnect, .bots, .bottree, .relay, .whom
  • Persistent channel rejoinperiodic check every 30s; handles kick+ban, channel full, invite-only, bad key
  • ChanServ-based takeover protectiondetects unauthorized mass deop/mode changes and escalates: deop, kickban, akick
  • Enforce unauthorized `+k`/`+l` removalreactive (real-time) and proactive (on join via RPL_CHANNELMODEIS)
  • Channel mode trackingmode string, key, and limit tracked from MODE and channel info reply; new channel:modesReady event
  • Multi-stage Dockerfile + healthchecksmaller production images; healthcheck for orchestration tools

Changed

  • `channel_modes` Eggdrop-style format"+nt-s" means "ensure +n and +t, ensure -s, leave everything else alone"; modes not mentioned are no longer treated as unauthorized
  • `enforce_modes` gates both directionswhen off, neither additions nor removals run

Fixed

  • ChanServ OP on RizonOP request no longer gated on ChanServ being in the channel
  • DCC TOCTOU raceduplicate DCC CHAT requests now rejected when one is already pending
  • `!seen` cross-channel info disclosurequeries from a different channel omit channel name and message text
  • Bot-link security audit1 critical + 5 warning findings closed (permission bypass, frame validation, rate limiting)
  • Codebase security sweep8 additional warnings closed from full-codebase audit

v0.1.0

Initial Release

HexBot v0.1.0 is the first public release. The core bot framework is production-ready with a full plugin API, permission system, and Docker deployment.

Included

8 bundled pluginschanmod, flood, greeter, seen, topic, help, ctcp, 8ball
Bind system16 event types, pattern-matched handlers
Flag-based permissionsOwner, master, op, voice, deop; per-channel and global
Hot-reloadEdit and reload plugins without restarting
SASL authenticationPLAIN and EXTERNAL (CertFP)
IRCv3 capsextended-join, account-notify, chghost
SOCKS5 proxyTor and SSH tunnel support
DCC CHAT party lineRemote admin sessions
SQLite persistenceNamespaced per-plugin key/value store
Docker deploymentCompose file with host-mounted config and plugins

See the deploy guide to get started, or browse the plugin list to see what’s included.


Roadmap

upcomingRoadmap
  • XDCCFile serving over DCC
  • IdleRPGIdle-based RPG plugin