Skip to content

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.

Add the commands package to your project alongside the core library.

local commands = require("../luau_packages/commands")

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()
OptionTypeDefaultDescription
helpboolean?trueRegister the built-in /help command
watchboolean?trueAuto-watch loaded directories for changes
contextany?nilShared value passed to every command factory
onErrorErrorHandler?-Global fallback when a command throws
onGuardFailedGuardFailedHandler?-Global fallback when a guard rejects

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,
}

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)

Guild commands propagate instantly, making them ideal during development.

commandsManager:registerGuildAsync("YOUR_GUILD_ID"):await()

To clear all global commands from Discord:

commandsManager:unregisterAsync():await()

To clear a specific guild’s commands:

commandsManager:unregisterGuildAsync("YOUR_GUILD_ID"):await()

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()