Seyfert
npm i seyfertEverything you need to ship
Each line ships with a receipt. No refunds — you won't be needing one.
Typed end to end
Inference everywhere: command options, event payloads, interaction responses. Quitting `as any` is hard. We made it mandatory.
Ready for the big leagues
Proven from tiny side projects to multi-million-guild bots. Sharding, presence chunking and raw gateway access come in the box.
Let the decorators work
@Declare, @Options, @AutoLoad. No boilerplate, no manual REST calls, no bookkeeping. The decorators clock in so you don't have to.
Yours to rebuild
Custom cache, custom REST, custom client. Swap any piece the day you need it to behave differently. We won't take it personally.
Updates on day one
Threads, components v2, polls, interactions — there to use the same day Discord ships them, not a release later.
And a whole ecosystem
Official plugins: Redis cache, uWS gateway, cooldowns — drop in what fits, swap what doesn't. And honestly, we ran out of room here.
Your whole bot, in four files
A command. A guard in front of it. Buttons that talk back. Replies in any language. The everyday machinery of a real bot, already wired in. Pick a tab, steal the code.
import {
Declare, Options, Command, createStringOption,
type CommandContext,
} from 'seyfert';
const options = {
message: createStringOption({
description: 'What should I echo back?',
required: true,
}),
};
@Declare({ name: 'echo', description: 'Repeat after me' })
@Options(options)
export default class EchoCommand extends Command {
async run(ctx: CommandContext<typeof options>) {
await ctx.write({ content: ctx.options.message });
}
}
// that's the whole file.declare it and run it — registration and uploads happen on their own
Same boot, two worlds
import {
Client, Collection, GatewayIntentBits, Events,
} from 'discord.js';
import { readdirSync } from 'node:fs';
// 1 · the ceremony
const client = new Client({
intents: [GatewayIntentBits.Guilds],
});
client.commands = new Collection();
// 2 · hand-roll a command loader
for (const file of readdirSync('./commands')) {
const command = require(`./commands/${file}`);
client.commands.set(command.data.name, command);
}
// 3 · hand-roll a dispatcher
client.on(Events.InteractionCreate, async (i) => {
if (!i.isChatInputCommand()) return;
await client.commands.get(i.commandName)?.execute(i);
});
client.login(process.env.TOKEN);
// 4 · still owed: node deploy-commands.js, by hand
// seyfert.config.mjs
import { config } from 'seyfert';
export default config.bot({
token: process.env.BOT_TOKEN ?? '',
locations: { base: 'dist', commands: 'commands' },
intents: ['Guilds'],
});
// src/index.ts
import { Client } from 'seyfert';
const client = new Client();
// connects, loads everything, uploads your commands
client.start().then(() =>
client.uploadCommands({ cachePath: './commands.json' }));
// that's the boot. all of it.
// one hour here is seven years in discord.js
Shine brighter, burn less
84 MB where discord.js needs 206 — 2.45× lighter under the same load.
FULL MEASUREMENTS ↗Production bots, in orbit
Real bots, really shipped, all circling one core. Hover one to hear it from the team.
After years of experience with Discord.js, Discordeno and Eris, Seyfert proved to be unmatched for large-scale music bots - dropping our RAM usage to under 1 GB (from almost 4 GB) while handling 200% more servers.
Listen— running seyfertAdd yours — open a PR ↗
Ready to build your bot?
You made it through the arms. The center is where you start building.