Skip to content

Repository files navigation

Custom Command Bot

A Discord bot that lets your community create its own slash commands, no code required. Staff design commands in a built-in editor right inside Discord, and the bot renders them with Discord's Components V2 for a clean, modern look. It works for any community: everything is configured per guild, and commands are only ever registered in the servers you choose.

Features

  • Rich, block-based commands rendered with Discord Components V2
  • Multi-page replies and private (hidden) responses
  • Staff-only command editor, no file editing needed
  • Local SQLite storage out of the box, nothing else to run
  • Optional GitHub-backed storage with change polling
  • Safe concurrent editing through optimistic revision checks
  • A proposals API so external tools can suggest commands, with staff approval cards in Discord
  • Read and search API for proposal clients
  • Guild-scoped registration only, so global commands are never created

Quick start

You'll need Node.js 22 or newer and a Discord bot application with the applications.commands scope.

npm install
cp .env.example .env
cp config.example.json config.json
npm run dev

Then:

  1. Put your bot token in .env as DISCORD_TOKEN.
  2. In config.json, set guild_ids to your server's ID and staff_role_ids to the roles allowed to manage commands.

That's it. The bot stores everything in a local SQLite database at ./data/commands.db, so you don't need a GitHub account or anything beyond Discord itself.

This setup runs through ts-node, which is great for tinkering. When you're ready to run it for real, see Running in production.

Running in production

For a deployment, compile the TypeScript once and run the build output:

npm ci
npm run build
npm start

Put it under a process supervisor (or Docker) so it comes back after a reboot, and use the /health endpoint for monitoring. docs/DEPLOYMENT.md walks through all of it: systemd, Docker and docker compose, health checks, and encrypting the data volume.

Where your data lives

Everything the bot remembers sits in ./data by default:

  • commands.db: command bodies, including edits made through Discord
  • proposals.db: staged proposals and the Discord identities attached to them (only when proposals are enabled)
  • commands-cache.json: a JSON mirror of command bodies (only in GitHub mode)

One thing worth knowing up front: proposals.db contains Discord user IDs and reviewer names, and Discord's Developer Terms ask that this data be encrypted at rest. The bot doesn't encrypt files itself, so run the data directory on encrypted storage such as BitLocker, LUKS, or an encrypted cloud volume. docs/DATA_STORAGE.md explains what's stored and why, and docs/BACKUPS.md shows how to back it up safely.

Importing commands

If you already have command files (one <name>.json per command), import a whole directory at once:

npm run import:commands -- ./commands

Existing commands are skipped. Add --replace to overwrite them.

GitHub repository mode

If you'd rather keep command content in Git, replace commands.repository in config.json with:

{
  "type": "github",
  "owner": "your-org",
  "repo": "your-command-repo",
  "directory": "commands",
  "branch": "main",
  "token_env": "GITHUB_TOKEN"
}

Set the environment variable named by token_env to your GitHub token. Each command lives as its own <command-name>.json file in that repository (a separate one from this bot's source), and blob revisions are used to detect conflicting edits. commands.poll_minutes controls how often the bot checks for external changes; set it to 0 to turn polling off.

GitHub mode is designed to fail safe: a file that can't be read is never treated as a deletion, and if the repository is unreachable your live commands keep working. docs/GITHUB_REPOSITORY.md covers the repository layout, token permissions, commit behavior, and how degraded states are handled.

Discord commands

  • /create_command name:<name> opens a new-command editor.
  • /edit_command name:<name> opens an existing command.
  • /reload_commands reloads the configured repository.

All three are limited to roles listed in staff_role_ids.

Proposals API

External tools can suggest new or updated commands over HTTP. Enable proposals.enabled, pick a review channel, and set COMMAND_API_KEY. Suggestions are staged for staff to approve or reject from a Discord card; set proposals.require_approval to false if you'd rather apply valid proposals immediately.

Endpoints:

  • GET /health
  • GET /api/v1/commands
  • GET /api/v1/commands/{name}
  • GET /api/v1/commands/search?q=...
  • POST /api/v1/commands/proposals

docs/PROPOSALS_API.md has the full reference, including how to put a TLS reverse proxy in front of it.

Command format

Commands are defined in a structured JSON format. See docs/AUTHORING.md.

Documentation

Development

npm run build
npm test
npm run lint
npm run format:check

About

A Discord bot that lets your community create its own slash commands, no code required.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages