Installation
Three ways to run Citadel Bot. All of them start from the same code; they differ only in how configuration is supplied. Make sure you've covered the Prerequisites first.
Option A — Self-host (npm)
# 1. Clone and install
git clone https://github.com/Sk3tch-Dev-Ux/citadel-cftools-bot.git
cd citadel-cftools-bot
npm install
# 2. Create config from the examples
cp config/.env.example config/.env
cp config/config.example.js config/config.js
cp config/servers.example.js config/servers.js
# 3. Edit the three config files (see Client/Server Configuration), then start
npm start
On first boot with REFRESH_SLASH_COMMAND_API_DATA=true, the bot registers its
slash commands. Global commands can take up to an hour to appear; set
TEST_SERVER_GUILD_ID to register them instantly in one server while you
test.
To keep it running in the background, use PM2:
npm run pm2:start # start under PM2
npm run pm2:logs # tail logs
npm run pm2:stop
Option B — Docker
The repo ships a Dockerfile (node:24-alpine).
npm run docker:build
npm run docker:start # runs with --env-file ./.env
npm run docker:logs
Mount or bake in your config/ files, or supply everything via environment
variables (see Option C).
Option C — Coolify (environment-only)
For managed deploys, the bot can run with environment variables only — no
committed secrets, no mounted config files. A prestart step
(scripts/coolify-config.js) generates config/config.js and
config/servers.js from the environment at container start. If you provide
those files yourself, they take precedence — the generator never overwrites.
- New resource → Application → source the GitHub repo, branch
main. - Build pack: Dockerfile.
- Set the environment variables.
- Deploy. On boot the bot generates config, registers slash commands, connects to Discord, and starts the storefront relay.
- Invite the bot to your guild with the
botandapplications.commandsscopes.
No public domain or port is required — it's a Discord gateway client, not a web
app. (USE_API=false; set true + a port only for the optional health route.)
[!TIP] channel-dependent features (chat feed, killfeed, auto-LB) off. To enable those, provide a full
config/servers.js— see Server Configuration.
Inviting the bot
Generate an invite under OAuth2 → URL Generator with scopes bot and
applications.commands, and these permissions:
- View Channels, Send Messages, Embed Links, Attach Files (for heatmaps), Read Message History, Use External Emojis, Send Messages in Threads, Use Application Commands
Or build the URL directly (replace CLIENT_ID):
https://discord.com/api/oauth2/authorize?client_id=CLIENT_ID&permissions=277025770496&scope=bot+applications.commands
Next: Client Configuration.