About HexBot
Internet Relay Chat was one of the earliest widely adopted real-time systems on the internet. Networks like EFnet, Undernet, DALnet, and QuakeNet connected large numbers of users through a distributed set of servers, all speaking a simple, open protocol. There was no central authority and very little built-in persistence—channels, users, and permissions existed as long as the network could maintain a consistent view of them.
That model worked, but it came with trade-offs. Networks were prone to instability, and channels required constant oversight. Operators couldn’t realistically provide that 24/7, which is where bots came in. A bot could remain connected indefinitely, maintain operator status, enforce basic rules, and respond immediately to events. Over time, bots expanded beyond moderation into general-purpose utilities—tracking users, serving information, automating repetitive tasks, and integrating external data.
Despite being built in different languages and environments, most IRC bots converged on similar design patterns. They reacted to events, exposed commands, and used some form of permission system to control behavior. Many supported dynamically extending functionality through scripts or modules. These approaches weren’t formalized, but they proved practical and have remained consistent across implementations.
HexBot follows the same general model. It’s a modular IRC bot for Node.js, written in TypeScript, with a focus on predictable behavior and maintainability. It uses an event-driven core, supports runtime plugin loading, and provides a structured API for building extensions. The aim is to keep the flexibility that made IRC bots useful, while making them easier to develop, reason about, and operate with modern tooling.
Key Features
Architecture
HexBot uses a two-tier module system. Core modules are always loaded and provide the bot’s foundational services — the IRC bridge, dispatcher, permission engine, channel state, and database. Plugins are isolated, hot-reloadable units that register event binds against the dispatcher and never depend on each other.
Plugins call bind(type, flags, mask, handler) to subscribe to IRC events. The dispatcher matches incoming events against all registered binds, checks permissions, and calls handlers in registration order.