SWAGcommands
Commands

Deploying application commands

Control when and where slash commands and context menus are published.

SWAGcommands loads files locally during SWAG.create(). To publish slash commands, slash subcommand roots, and context menus to Discord, call deployCommands() after the client is ready.

await client.login(process.env.DISCORD_TOKEN);
if (!client.isReady()) await once(client, Events.ClientReady);
await swag.deployCommands(); // scope: "all"

A message-only command is never deployed. Aliases are message-only too.

Pick a scope

ScopeWhat gets sentTarget
"global"Slash-capable and context-menu commands without testOnlyGlobal application commands
"test"Commands with testOnly: trueEach configured test guild
"all"Both manifests, global firstGlobal and test guilds

"all" is the default. Configure test guilds in SWAG.create({ testServers: [...] }), or override them for one call:

await swag.deployCommands({
  scope: "test",
  testGuildIds: ["YOUR_TEST_GUILD_ID"],
});

A root subcommand's testOnly controls its entire slash tree. If you move a command between global and test, deploy "all" so the old registration is removed as well as the new one being created.

The important bit: this is a full sync

Deployment uses Discord's bulk replacement endpoint. For each target, the local manifest becomes the complete command list: missing remote commands are removed. If another script manages commands in the same scope, those commands can disappear. Keep one owner per scope or include every command in this manifest.

To delete or rename a command, change the file and deploy its scope. To clear a target intentionally:

await swag.clearCommands({ scope: "global" });
await swag.clearCommands({ scope: "guild", guildId: "OLD_GUILD_ID" });

Clearing a guild is useful after removing it from testServers; SWAGcommands cannot know which guilds you targeted in an earlier run. Clearing one scope does not clear the other.

Results and failures

const result = await swag.deployCommands({ scope: "all" });
for (const target of result.targets) {
  console.log(target.scope, target.guildId, target.commands);
}

Targets sync independently. If a later target fails, earlier successful targets stay changed. A CommandDeploymentError exposes completedTargets and the failed target in its context. Deployment failures reject the method directly; they are not sent to runtime onError. Invalid local manifests can fail before any target changes.

On this page