DJS Commandsv3 docs
Concepts

Commands

Define, register, and dispatch slash and prefix commands with @djs-commands/core.

A command in DJS Commands is a plain object. There are no decorators, no class hierarchies, and no on-disk conventions you have to follow. You build the object with defineCommand, you put the object somewhere your bot can find it, and you pass it to createCommandHandler.

defineCommand

defineCommand(command) returns its argument unchanged. It exists purely so the TypeScript compiler can give you autocomplete and structural validation as you type. At runtime it's identity.

import { defineCommand } from "@djs-commands/core";

const ping = defineCommand({
	name: "ping",
	description: "Replies with pong",
	run: async ({ reply }) => {
		await reply("pong");
	},
});

Required fields

FieldTypeDescription
namestringThe slash-command name. Must match Discord's naming rules: 1–32 characters, lowercase, [a-z0-9_-].
descriptionstringThe 1–100-character description shown in the Discord client.
run(ctx) => void | Promise<void>The handler. Receives a CommandRunContext.

Optional fields

FieldTypeNotes
optionsCommandOptionsTyped schema for slash-command options — see Options.
validatorsValidator[]Custom pre-handler checks. See Validators.
cooldownCooldownConfigRate limit. See Cooldowns.
ownerOnlybooleanWhen true, only IDs in botOwners (passed to the handler) can run it.
guildOnlybooleanWhen true, blocks DM invocations.
channelsstring[]Allow-list of channel IDs the command can run in.
permissionsPermissionsString[]Discord member permissions required (e.g. ["BanMembers"]).
rolesstring[]Role IDs the invoking member must have.
legacyCommandLegacyConfigOpt this command into legacy prefix invocation; supports aliases.

CommandRunContext

CommandRunContext is a discriminated union over the invocation source. Both branches share a unified surface so most handlers don't need to care whether they were invoked via slash or prefix:

type CommandRunContext = SlashRunContext | LegacyRunContext;

interface BaseRunContext {
	client: Client;
	author: User;
	guild: Guild | null;
	member: GuildMember | null;
	channel: TextBasedChannel | null;
	channelId: string | null;
	options: ResolveOptions<S>; // typed from your `options` schema
	reply: (content: CommandReplyInput) => Promise<unknown>; // use flags: MessageFlags.Ephemeral for ephemeral slash replies
}

type SlashRunContext = BaseRunContext & { type: "slash"; interaction: ChatInputCommandInteraction };
type LegacyRunContext = BaseRunContext & { type: "legacy"; message: Message };

When you need source-specific behavior, narrow on ctx.type:

import { MessageFlags } from "discord.js";

run: