Slash Commands
Learn how to create slash commands that users can discover and use! Build interactive commands like /help, /ping, and more.
Learning Objectives
By the end of this module, you will be able to:
Command Definitions
Create a file that defines all your bot's slash commands.
Creating src/commands.ts
This file tells Towns Protocol what commands your bot has. Each command needs a name and description.
import type { PlainMessage, SlashCommand } from '@towns-protocol/proto'
const commands = [
{
name: 'help',
description: 'Show bot help and available commands',
},
{
name: 'ping',
description: 'Check if the bot is responsive',
},
{
name: 'stats',
description: 'Show community or user stats',
},
] as const satisfies PlainMessage<SlashCommand>[]
export default commandsCommand Naming Tips
- • Use lowercase, single words (help, ping, stats)
- • Keep descriptions short and clear
- • Commands appear in autocomplete when users type "/"
Challenge: Define 3 Commands
Add help, ping, and info commands
Basic Command Handlers
Implement handlers that respond when users type your commands.
1. Help Command
The /help command shows users what your bot can do.
bot.onSlashCommand('help', async (handler, { channelId }) => {
try {
await handler.sendMessage(channelId, `
🤖 **Bot Help**
**Available Commands:**
• \`/help\` - Show this help message
• \`/ping\` - Check bot status
• \`/stats\` - View community stats
Type \`/\` to see all commands!
`)
} catch (error) {
console.error('Error in /help:', error)
}
})2. Ping Command
The /ping command lets users check if your bot is working.
bot.onSlashCommand('ping', async (handler, { channelId }) => {
try {
await handler.sendMessage(channelId, '🏓 Pong! Bot is online.')
} catch (error) {
console.error('Error in /ping:', error)
}
})Error Handling
Always wrap commands in try/catch. This prevents one failing command from crashing your entire bot!
Challenge: Create a Help Command
Make it list /help, /ping, and /stats commands
Command Parameters
Handle arguments and user mentions in your commands.
User Mentions
Commands can accept user mentions like /stats @user
bot.onSlashCommand('stats', async (handler, { channelId, userId, mentions }) => {
try {
if (mentions && mentions.length > 0) {
// User mentioned someone: /stats @user
const targetUser = mentions[0]
await handler.sendMessage(channelId, `
📊 **Stats for ${targetUser.displayName}**
💬 Messages: 150
👍 Reactions: 45
📅 Joined: 2 weeks ago
`)
} else {
// No mention: show community stats
await handler.sendMessage(channelId, `
📊 **Community Stats**
👥 Members: 1,234
💬 Messages Today: 567
🔥 Most Active: Alice
`)
}
} catch (error) {
console.error('Error in /stats:', error)
}
})Parameter Structure
- •
mentions- Array of mentioned users - •
userId- Who ran the command - •
channelId- Where it was run
Challenge: Stats with Mentions
Show user stats if mentioned, otherwise show community stats
Command Registration
Register your commands so users can discover them in Towns.
Step 1: Get Your Bot Token
To register commands, you need your bot's token from Towns:
- 1. Open Towns app
- 2. Type
/bearer-tokenin any channel - 3. Copy the long token that appears in the side panel
- 4. This is your APP_PRIVATE_DATA token
Step 2: Automatic Registration
Your commands are automatically registered when your bot starts! When you initialize your bot with commands, they're synced to Towns:
// Commands are automatically synced on bot initialization
const bot = await makeTownsBot(privateData, jwtSecret, {
commands: myCommands // ✨ Automatically registered!
})
// Your bot is now ready with slash commands!
bot.onSlashCommand('help', async (handler, event) => {
// Handle the command
})Auto-Discovery
Users can type "/" in Towns and see your commands in autocomplete! They can discover what your bot does without asking.
Updating Commands
If you add, remove, or change commands, simply restart your bot. Commands are automatically synced on every restart!
Module 2 Complete!
Awesome! You've learned how to create slash commands. Users can now type "/" and discover your bot's features through an intuitive command interface!