SWAGcommands
Commands

Subcommands

Build roots and leaves with their own callbacks and checks.

A subcommand tree starts with an immediate folder in subcommandsDir. Its index.ts defines the root, and each other file defines a leaf. /admin status and !admin status can share the same tree when the root uses CommandType.BOTH.

src/subcommands/
└── admin/
    ├── index.ts
    ├── status.ts
    └── ban.ts
src/subcommands/admin/index.ts
import { CommandType } from "swagcommands";
import type { SubcommandObject } from "swagcommands";

const admin = {
  type: CommandType.BOTH,
  description: "Server admin tools",
  aliases: ["mod"],
  guildOnly: true,
} satisfies SubcommandObject;

export default admin;

The root has no callback. Each leaf does:

src/subcommands/admin/status.ts
import type { SubcommandOptionObject } from "swagcommands";

const status = {
  description: "See the current status",
  callback: ({ commandName, subcommandName }) =>
    `${commandName} / ${subcommandName}: all good`,
} satisfies SubcommandOptionObject;

export default status;

Root preconditions run before leaf preconditions. A leaf can override response settings such as deferReply and reply; omitted settings inherit from the root. Each leaf may have its own init, aliases, argument metadata, options, autocomplete, and preconditions.

Message aliases and argument parsing

A message may use root and leaf aliases, for example !mod status. After the root and leaf tokens are consumed, the remaining tokens become args. The callback also gets commandName, subcommandName, and, for grouped options, subcommandGroup.

Subcommand groups

A leaf whose options are all Discord subcommand options represents a group. That can be invoked as /admin moderation ban or !admin moderation ban. Its callback receives subcommandGroup: "moderation" and subcommandName: "ban". Put the nested Discord option definitions in the group leaf's options array.

Slash-capable roots and leaves need descriptions. Every root folder needs exactly one index file. Deployment scope is controlled by the root's testOnly value, and deployment publishes the complete tree.

On this page