Recipes

Hot Reload

During development, Seyfert allows you to reload commands, events, components, and language files without restarting the bot.

Reloading Commands

// Reload all commands
await client.commands.reloadAll();

// Reload a specific command by name
await client.commands.reload('ping');

Reloading Events

await client.events.reloadAll();

Reloading Components

await client.components.reloadAll();

Reloading Language Files

// Reload all languages
await client.langs.reloadAll();

// Reload a specific locale
await client.langs.reload('es');

Reload Command

A practical pattern is to create a developer-only command for hot reloading:

import {
    Command,
    Declare,
    Options,
    createStringOption,
    type CommandContext,
} from 'seyfert';

const options = {
    target: createStringOption({
        description: 'What to reload',
        required: true,
        choices: [
            { name: 'Commands', value: 'commands' },
            { name: 'Events', value: 'events' },
            { name: 'Components', value: 'components' },
            { name: 'Languages', value: 'langs' },
            { name: 'All', value: 'all' },
        ] as const,
    }),
};

@Declare({
    name: 'reload',
    description: 'Reload bot modules',
})
@Options(options)
export default class ReloadCommand extends Command {
    async run(ctx: CommandContext<typeof options>) {
        const target = ctx.options.target;

        if (target === 'all' || target === 'commands') await ctx.client.commands.reloadAll();
        if (target === 'all' || target === 'events') await ctx.client.events?.reloadAll();
        if (target === 'all' || target === 'components') await ctx.client.components.reloadAll();
        if (target === 'all' || target === 'langs') await ctx.client.langs?.reloadAll();

        await ctx.editOrReply({ content: `Reloaded **${target}** successfully.` });
    }
}

Automatic Reload with @slipher/watcher

Manually restarting after every change gets old fast. @slipher/watcher keeps the gateway alive while it watches your source files, rebuilds on change, and restarts the worker.

pnpm add -D @slipher/watcher
src/watcher.ts
import { join } from 'node:path';
import { Watcher } from '@slipher/watcher';

const watcher = new Watcher({
    filePath: join(process.cwd(), 'dist', 'index.js'),
    srcPath: join(process.cwd(), 'src'),
    transpileCommand: 'tsc --project tsconfig.json',
});

(async () => {
    await watcher.spawnShards();
})();
package.json
{
    "scripts": {
        "watch": "pnpm build && node dist/watcher.js"
    }
}
pnpm watch