djs-commandsv2 docs
Getting Started

Your first command

Define, register, and run a slash command end-to-end.

The fastest path to a running bot is npx create-djs-commands — it scaffolds the directory layout, tsconfig.json, and .env.example for you. This page walks through the same setup by hand so you understand each piece.

Define a command

A command is just a plain object you build with defineCommand. The function is identity at runtime — it exists for IDE autocomplete and type inference.

src/commands/ping.ts
import { defineCommand } from "@djs-commands/core";

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

The handler receives a CommandRunContext with a unified reply() (works for both slash and legacy invocations), the invoking author, the guild, member, and typed options.

Wire up a Client

Pass your commands to createCommandHandler along with a discord.js Client. The handler subscribes to interactionCreate and dispatches matching slash commands. On clientReady, it registers the command list with Discord.

src/index.ts
import { createCommandHandler } from "@djs-commands/core";
import { Client, GatewayIntentBits } from "discord.js";
import ping from "./commands/ping";

const token = process.env.DISCORD_TOKEN;
if (!token) {
	console.error("DISCORD_TOKEN environment variable is required");
	process.exit(1);
}

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

const handler = createCommandHandler({
	client,
	commands: [ping],
});

await handler.ready;

client.once("clientReady", (c) => {
	console.log(`Logged in as ${c.user.tag}`);
});

await client.login(token);

Or skip the manual import and let the framework load the directory for you:

createCommandHandler({
	client,
	commandDir: "./src/commands",
});

In dev (NODE_ENV !== "production") the directory is watched and edited files hot-reload without a restart.

Run the bot

DISCORD_TOKEN=... bun run src/index.ts

Once the bot is online, run /ping in any guild it's invited to. You should see pong come back.

The first time you run a freshly registered command, Discord may take a minute to propagate it. Subsequent code edits with the same command name update instantly.

Next steps

  • Add typed options — see Commands → Options.
  • Gate execution with role/permission/channel checks — see Validators.
  • Rate-limit with built-in cooldowns — see Cooldowns.
  • Persist state (prefixes, disabled commands, your own data) — see Storage.
  • Build rich replies with Components V2 — see Components V2.
  • Extend the handler with a plugin — see Plugins.

Coming from v1?

If you're upgrading from @d3oxy/djs-commands, the Migration from v1 guide walks through every API that moved or was dropped, with side-by-side examples.

On this page