Deploy HexBot
Requirements
Node.js and pnpm for manual install. Docker + Compose for containerized deployment.
Quick Start — Docker
The recommended deployment method. Plugins, config, and data are mounted from the host so you can edit and reload without rebuilding the image.
git clone https://github.com/jstnmthw/hexbot
cd hexbot
cp config/bot.example.json config/bot.json
cp config/plugins.example.json config/plugins.json
# edit config/bot.json with your IRC server and credentials
docker compose up -d
docker compose logs -fDCC CHAT ports 49152-49171 are exposed by default.
Manual Install
git clone https://github.com/jstnmthw/hexbot
cd hexbot
pnpm install
cp config/bot.example.json config/bot.json
cp config/plugins.example.json config/plugins.json
# edit config files
pnpm start # production, no REPL
pnpm dev # development, with interactive REPLConfiguration
Two JSON files control the bot. Both are ignored by git — only the example files are committed.
config/bot.json
IRC server, services (NickServ/SASL), queue rate, DCC settings, SOCKS5 proxy, and logging level. Owner, DB path, and plugin directory are bootstrap env vars now: HEX_OWNER_HANDLE, HEX_OWNER_HOSTMASK, HEX_DB_PATH, HEX_PLUGIN_DIR.
{
"irc": {
"host": "irc.rizon.net",
"port": 6697,
"tls": true,
"nick": "HexBot",
"channels": ["#hexbot"]
},
"services": { "type": "anope", "sasl": true, "sasl_mechanism": "PLAIN" },
"dcc": { "enabled": false, "port_range": [49152, 49171] },
"proxy": { "enabled": false, "host": "127.0.0.1", "port": 9050 }
}config/plugins.json
Plugins are auto-discovered from plugins/ — this file is only needed to override config, restrict channels, or disable specific plugins.
{
"chanmod": {
"channels": ["#hexbot"],
"config": { "auto_op": true, "enforce_modes": false }
},
"greeter": {
"channels": ["#hexbot"],
"config": { "message": "Welcome to {channel}, {nick}!" }
},
"flood": { "enabled": false }
}REPL Commands
Run with pnpm dev to get an interactive REPL with owner-level access — no IRC auth required.
| .help [cmd] | List commands or show detail for one |
| .status | Connection info, uptime, bind and user counts |
| .uptime | One-line uptime report |
| .say <target> <msg> | Send a message to a channel or user |
| .msg <target> <msg> | Send a PRIVMSG to any target |
| .join / .part | Join or part a channel |
| .flags [handle] [+flags [#chan]] | View or set user flags |
| .adduser / .deluser / .users | User management |
| .chpass <handle> <newpass> | Set or rotate a user's DCC password (REPL/DCC only) |
| .chanset / .chaninfo | Per-channel plugin settings |
| .binds [plugin] | List active event binds |
| .plugins | List loaded plugins and their status |
| .set <scope> <key> <value> | Live config write — core, plugin:<id>, or chanset scope |
| .unset <scope> <key> | Revert a setting to its default |
| .info <scope> | Show all settings for a scope |
| .rehash [scope] | Reload config from disk into the live registry |
| .reset <plugin> | Restore a plugin's settings to defaults |
| .restart | Restart the bot process (picks up code edits) |
| .modlog [filter...] | Query the moderation audit log (DCC/REPL only) |
| .audit-tail [filter...] | Stream audit:log events live (REPL only) |
Applying Plugin Changes
v0.6.0 retired .load / .unload / .reload — the ESM cache-busting they relied on leaked module-graph entries. Plugin lifecycle is now driven through the live settings registry, with .restartas the canonical “pick up code edits” path.
# Enable or disable a plugin live (no restart):
.set core plugins.chanmod.enabled true
.set core plugins.chanmod.enabled false
# Tweak a plugin setting at runtime:
.set plugin:chanmod auto_op true
.unset plugin:chanmod auto_op # revert to default
.info plugin:chanmod # show all settings
# Pull edits from disk back into the live registry:
.rehash
# Pick up code edits to a plugin file:
.restart