MeoCord: Decorator-based Discord bot framework for TypeScript
One call, through the pipeline
@Command('greet', CommandType.SLASH)
@Defer()
@UseGuard(MemberGuard)
@UseInterceptor(TraceInterceptor)
@UsePipe('name', TrimPipe)
async greet(interaction: ChatInputCommandInteraction, { name }: { name: string }) {
await respond(interaction).send({ content: `Hello, ${name}!` })
}/greet name: Ada Trace
Recorded from a real run of this code, at build time
- @Deferdeferreddeferred
- MemberGuardalloweddenied
- TraceInterceptorbeforenot reached
- TrimPipe" Ada " → "Ada"not reached
- greet()greets "Ada"not reached
- TraceInterceptorafternot reached
- respond()Hello, Ada!not reached
respond() edits the deferred reply: one call, whatever the state.
Why MeoCord
One pipeline, every call.
See howGuards, interceptors, validation, cooldowns and exception filters run in a fixed order around each handler they apply to.
One call answers Discord.
See howrespond()tracks each answer as unanswered, deferred or replied, and makes the call Discord expects: reply, update, edit or follow-up.Checked by the compiler.
See howA handler whose params don't fit its route or pattern fails to compile, and so does a catalog key the default catalog lacks.
Tested as it runs.
See howinvokeanddispatchrun a handler through the bot's own pipeline, with mocks of discord.js's own classes.
What you can build
Slash commands
A member types
/echoand picks its options.Subcommands
One command with groups and subcommands, such as
/settings notify email, each routed to a handler of its own.Buttons
A button's custom ID carries what the handler needs, read back as typed params.
Select menus
A member picks values from a menu, and the handler gets them.
Modals
A form a member fills in and submits, routed by its custom ID.
Context menus
A member right-clicks a user or a message and picks the bot's command.
Autocomplete
The bot suggests values for an option as the member types it.
Message commands
A member sends
!roll 20 for initiative, and the pattern and its schema hand the handler its values, typed.Reactions
A member reacts to a message with an emoji, and the bot acts on it.
Gateway events
Anything else Discord tells the bot, such as a member joining a server.
Where to go next
Learn
The Guide, in reading order: what a bot is made of, each kind of handler, the pipeline around it, testing and shipping.
Create a bot. The CLI asks which package manager to use.
npx meocord create my-botbunx meocord create my-botpnpm dlx meocord create my-botyarn dlx meocord create my-botGive it its token, in .env beside meocord.config.ts.
.env DISCORD_TOKEN=your-bot-tokenRun it, rebuilding as you save.
npx meocord start --devbunx meocord start --devpnpm exec meocord start --devyarn meocord start --dev
Look up
Every public symbol, by kind, with its types and examples, and every CLI command with its options.
Migrate or compare
Moving to 4.2 from an earlier MeoCord, or to MeoCord from another framework.