DJS Commands
Modern Discord.js command handler — TypeScript-first, Components V2 native, with pluggable persistence.
v2.0 · live on NPM
Build Discord bots
you'll actually ship.
A modern command handler for Discord.js — strongly typed, Components V2 native, with pluggable persistence. No magic decorators, no runtime reflection.
— Framework
Everything you need.
Nothing you don't.
TypeScript-first
Plain objects, full inference. defineCommand returns its argument unchanged — autocomplete is real, decorators are extinct.
Components V2 native
JSX runtime + plain-function fallback. Containers, sections, modals, action rows — both APIs return identical builders.
Validators that compose
Built-in role / permission / channel gates plus your own async predicates. First failure wins, with a typed reason.
Distributed cooldowns
Per-user, per-guild, per-user-per-guild, global. Pluggable CacheAdapter — Redis for sharded bots, in-memory for dev.
Bring your own DB
Drizzle, Prisma, Mongoose — first-party adapters for the Storage contract. Or write six methods and ship your own.
Plugins, not magic
setup / teardown lifecycle, command bundles, no global state. Plugins add what you need — nothing you don't.
— defineCommand
Plain objects.
Strongly typed.
Define a slash command as a plain object. Options are inferred. The handler context unifies slash and legacy invocations behind a single reply().
Read the deep dive
import { defineCommand } from "@djs-commands/core";
export default defineCommand({
name: "ban",
description: "Ban a user from this server",
guildOnly: true,
permissions: ["BanMembers"],
cooldown: { type: "perGuild", duration: 10_000 },
options: {
target: { type: "user", description: "Who to ban", required: true },
reason: { type: "string", description: "Why" },
days: {
type: "integer",
description: "Days of messages to delete",
choices: [0, 1, 7] as const,
},
},
run: async ({ options, reply }) => {
// options.target → User
// options.reason → string | undefined
// options.days → 0 | 1 | 7 | undefined
await reply(`Banning ${options.target.tag}…`);
},
});— Adapters
Pluggable persistence.
Six CRUD methods. The framework reads / writes guild prefixes, disabled commands, and channel locks through the Storage contract — pick a first-party adapter or write your own.
Or write your own — six methods
— v1 → v2
Coming from @d3oxy/djs-commands?
Every v1 API has a v2 equivalent. The migration guide walks through every option that moved or was dropped — with side-by-side examples.
Migration guide
Ready to ship?
One command, one minute. The CLI scaffolds the directory layout, tsconfig, env file, and a working /ping.
Last updated on
