Getting Started
The commands framework is a separate package that sits on top of the core discord-luau bot, handling routing, guards, cooldowns, and more. This page gets you from setup to a working slash command.
Installation
Section titled “Installation”Add the commands package to your project alongside the core library.
local commands = require("../luau_packages/commands")Creating a Commands instance
Section titled “Creating a Commands instance”Pass your bot to Commands.new. It wires up all interaction listeners automatically.
local bot = discord.bot.new({ token = env.DISCORD_BOT_TOKEN, intents = builders.intents.new({ "Guilds" }):build(), reconnect = true,})
local commandsManager = commands.new(bot)
bot:connectAsync():await()| Option | Type | Default | Description |
|---|---|---|---|
help | boolean? | true | Register the built-in /help command |
watch | boolean? | true | Auto-watch loaded directories for changes |
context | any? | nil | Shared value passed to every command factory |
onError | ErrorHandler? | - | Global fallback when a command throws |
onGuardFailed | GuardFailedHandler? | - | Global fallback when a guard rejects |
Writing a command
Section titled “Writing a command”Each command is a table matching CommandDefinition. Create a file under your commands directory, e.g. src/commands/ping.luau.
local builders = require("../../luau_packages/builders")local classes = require("../../luau_packages/classes")
return { command = builders.interaction.interaction.new() :setName("ping") :setDescription("Replies with Pong!") :addIntegrationType("GuildInstall") :addContext("Guild") :build(),
execute = function(interaction: classes.TypesCommand) interaction:messageAsync({ content = "Pong!" }):await() end,}Loading commands from disk
Section titled “Loading commands from disk”commands:load() recursively finds every .luau file under the given directory and registers it. If watch is enabled (the default), it also starts watching for file changes so commands hot-reload on save.
bot.onAllShardsReady:listenOnce(function() commandsManager:load("src/commands") commandsManager:registerAsync():await()end)Registering to a guild
Section titled “Registering to a guild”Guild commands propagate instantly, making them ideal during development.
commandsManager:registerGuildAsync("YOUR_GUILD_ID"):await()Unregistering commands
Section titled “Unregistering commands”To clear all global commands from Discord:
commandsManager:unregisterAsync():await()To clear a specific guild’s commands:
commandsManager:unregisterGuildAsync("YOUR_GUILD_ID"):await()The built-in /help command
Section titled “The built-in /help command”Commands.new registers a /help command automatically. It paginates all registered commands by category using Discord’s Components V2, with Previous / Next navigation. Disable it by passing help = false.
local commandsManager = commands.new(bot, { help = false })Full script
local discord = require("../luau_packages/discord")local builders = require("../luau_packages/builders")local commands = require("../luau_packages/commands")local env = require("../.env")
local bot = discord.bot.new({ token = env.DISCORD_BOT_TOKEN, intents = builders.intents.new({ "Guilds" }):build(), reconnect = true,})
local commandsManager = commands.new(bot)
bot.onAllShardsReady:listenOnce(function() commandsManager:load("src/commands") commandsManager:registerAsync():await()end)
bot:connectAsync():await()References
Section titled “References”- Command Options & Transforms - typed options and value pre-processing
- Guards & Permissions - restricting who can run a command
- Hot Reload & Plugins - file watching and the plugin system