Section titled Registering slash commandsRegistering slash commands

For fully functional slash commands, you need three important pieces of code:

  1. The individual command files, containing their definitions and functionality.
  2. The command handler, which dynamically reads the files and executes the commands.
  3. The command deployment script, to register your slash commands with Discord so they appear in the interface.

These steps can be done in any order, but all are required before the commands are fully functional.

This page details how to complete Step 3. Make sure to also complete the other pages linked above!

Read first!

Section titled Command registrationCommand registration

Slash commands can be registered in two ways; in one specific guild, or for every guild the bot is in. We're going to look at single-guild registration first, as this is a good way to develop and test your commands before a global deployment.

Your application will need the applications.commands scope authorized in a guild for any of its slash commands to appear, and to be able to register them in a specific guild without error.

Slash commands only need to be registered once, and updated when the definition (description, options etc) is changed. As there is a daily limit on command creations, it's not necessary nor desirable to connect a whole client to the gateway or do this on every ClientReady event. As such, a standalone script using the lighter REST manager is preferred.

This script is intended to be run separately, only when you need to make changes to your slash command definitions - you're free to modify parts such as the execute function as much as you like without redeployment.

Section titled Guild commandsGuild commands

Create a deploy-commands.js file in your project directory. This file will be used to register and update the slash commands for your bot application.

Add two more properties to your config.json file, which we'll need in the deployment script:


{
"token": "your-token-goes-here",
"clientId": "your-application-id-goes-here",
"guildId": "your-server-id-goes-here"
}

With these defined, you can use the deployment script below:

deploy-commands.js

_44
import { REST, Routes } from 'discord.js';
_44
import { readdir } from 'node:fs/promises';
_44
import { join } from 'node:path';
_44
import { fileURLToPath } from 'node:url';
_44
import config from './config.json' assert { type: 'json' };
_44
_44
const { clientId, guildId, token } = config;
_44
_44
const commands = [];
_44
_44
// Grab all the command files from the commands directory you created earlier
_44
const foldersPath = fileURLToPath(new URL('commands', import.meta.url));
_44
const commandFolders = await readdir(foldersPath);
_44
_44
for (const folder of commandFolders) {
_44
// Grab all the command files from the commands directory you created earlier
_44
const commandsPath = join(foldersPath, folder);
_44
const commandFiles = await readdir(commandsPath).then((files) => files.filter((file) => file.endsWith('.js')));
_44
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
_44
for (const file of commandFiles) {
_44
const filePath = join(commandsPath, file);
_44
const command = await import(filePath);
_44
if ('data' in command && 'execute' in command) {
_44
commands.push(command.data.toJSON());
_44
} else {
_44
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
_44
}
_44
}
_44
}
_44
_44
// Construct and prepare an instance of the REST module
_44
const rest = new REST().setToken(token);
_44
_44
try {
_44
console.log(`Started refreshing ${commands.length} application (/) commands.`);
_44
_44
// The put method is used to fully refresh all commands in the guild with the current set
_44
const data = await rest.put(Routes.applicationGuildCommands(clientId, guildId), { body: commands });
_44
_44
console.log(`Successfully reloaded ${data.length} application (/) commands.`);
_44
} catch (error) {
_44
// And of course, make sure you catch and log any errors!
_44
console.error(error);
_44
}

Once you fill in these values, run node deploy-commands.js in your project directory to register your commands to the guild specified. If you see the success message, check for the commands in the server by typing /! If all goes well, you should be able to run them and see your bot's response in Discord!

Section titled Global commandsGlobal commands

Global application commands will be available in all the guilds your application has the applications.commands scope authorized in, and in direct messages by default.

To deploy global commands, you can use the same script from the guild commands section and simply adjust the route in the script to .applicationCommands(clientId)

Test


_11
const data = await rest.put(Routes.applicationCommands(clientId), { body: commands });

Section titled Where to deployWhere to deploy

Guild-based deployment of commands is best suited for development and testing in your own personal server. Once you're satisfied that it's ready, deploy the command globally to publish it to all guilds that your bot is in.

You may wish to have a separate application and token in the Discord Dev Portal for your dev application, to avoid duplication between your guild-based commands and the global deployment.

Tip

Section titled Further readingFurther reading

You've successfully sent a response to a slash command! However, this is only the most basic of command event and response functionality. Much more is available to enhance the user experience including:

  • applying this same dynamic, modular handling approach to events with an Event handler.
  • utilising the different Response methods that can be used for slash commands.
  • expanding on these examples with additional validated option types in Advanced command creation.
  • adding formatted Embeds to your responses.
  • enhancing the command functionality with Buttons and Select Menus.
  • prompting the user for more information with Modals.

Section titled Resulting codeResulting code