Discord Slash Commands
When a bot module declares "discord" in its platforms array, its commands are automatically registered as Discord slash commands. This page explains the mapping, discord_options, and the registration lifecycle.
How it works
Extension developers declare commands once in lumio.config.json. Lumio handles the platform-specific dispatch:
| Platform | User types | Matching method |
|---|---|---|
| Twitch | !points 100 | IRC prefix match |
| YouTube | !points 100 | Chat prefix match |
| Kick | !points 100 | Chat prefix match |
| Trovo | !points 100 | Chat prefix match |
| Discord | /points amount:100 | Slash command interaction |
Your handler code is identical for all platforms. The args array is populated the same way regardless of where the command originated:
- Prefix command
!points 100producesargs: ["100"] - Discord slash command
/points amount:100producesargs: ["100"](positional from option order)
Registration flow
When an extension with Discord support is installed on an account that has a Discord connection:
- The API reads the extension manifest commands
- The API registers Discord slash commands via the Discord API (
POST /applications/\{app_id\}/guilds/\{guild_id\}/commands) - The Discord bot receives interactions via the Discord Gateway
- The bot dispatches to the Worker using the same sync HTTP path as prefix commands
Discord may take up to 1 hour to propagate guild-level command changes.
Adding discord_options
By default, commands are registered as simple slash commands with no options. To add typed parameters, use the discord_options field:
{
"triggers": {
"commands": [
{
"name": "points",
"description": "Show a user's points balance",
"cooldown_global": 5,
"min_role": "everyone",
"discord_options": [
{
"name": "user",
"type": "user",
"description": "User to check",
"required": false
}
]
},
{
"name": "give",
"description": "Give points to another user",
"cooldown_global": 10,
"min_role": "moderator",
"discord_options": [
{
"name": "user",
"type": "user",
"description": "Recipient",
"required": true
},
{
"name": "amount",
"type": "integer",
"description": "Points to give",
"required": true
}
]
}
]
}
}
Option types
| Type | Discord type | Description |
|---|---|---|
"string" | STRING | Text input |
"integer" | INTEGER | Whole number |
"boolean" | BOOLEAN | True/false toggle |
"user" | USER | Discord user mention picker |
"channel" | CHANNEL | Channel picker |
"role" | ROLE | Role picker |
Non-Discord platforms ignore the discord_options field entirely.
Args mapping
Discord options are mapped to the args array by position (order of declaration):
{
"discord_options": [
{ "name": "user", "type": "user", "required": true },
{ "name": "amount", "type": "integer", "required": true }
]
}
When a user runs /give user:@jane amount:50, the handler receives args: ["jane_user_id", "50"] — matching the declaration order.
For prefix platforms, !give @jane 50 produces the same args: ["@jane", "50"].
Handling Discord-specific behavior
Your handler can check ctx.user.platform to detect which platform triggered the command:
import { command } from "@zaflun/lumio-sdk/server";
export const points = command("points", async (ctx, args) => {
const targetUser = args[0] ?? ctx.user.id;
const points = await ctx.db.get("user_points", targetUser);
if (ctx.user.platform === "discord") {
// Discord supports richer formatting
return { reply: `**${ctx.user.displayName}** has **${points?.balance ?? 0}** points` };
}
return { reply: `${ctx.user.displayName} has ${points?.balance ?? 0} points` };
});
Sync on update
When you publish a new version that changes commands:
- Old Discord slash commands are removed
- New commands are registered with the Discord API
- Discord propagates changes (up to 1 hour for guild commands)
During the propagation window, users may see stale commands in the Discord autocomplete. This is a Discord API limitation.
Discord-only triggers
Keywords and patterns work in Discord the same as other platforms — they match against message content in text channels. Events use Discord-specific event types if available.
Timers fire to Discord channels the same way they fire to other platforms.