Official Plugins

Yuna

Advanced prefix/text command parser for Seyfert — named options, dynamic prefixes, and watchers.

yunaforseyfert is an advanced parser for prefix/text commands in Seyfert. It adds custom syntax for named options, dynamic per-guild prefixes, and watchers for follow-up input. It installs as a Seyfert plugin and wires its parser and resolver for you.

Requires Seyfert v5. The plugin keeps seyfert as a peer dependency.

Installation

Installing...
pnpm add yunaforseyfert

Usage

Build the plugin list with definePlugins, register it on SeyfertRegistry, and pass it to the client. The plugin replaces the old setServices + HandleCommand subclass — no manual wiring:

import { Client, definePlugins } from 'seyfert';
import { Yuna } from 'yunaforseyfert';

const plugins = definePlugins(
    Yuna.plugin({
        parser: {
            syntax: { namedOptions: ['-', '--'] },
            logResult: true,
        },
        resolver: {
            logResult: true,
        },
    }),
);

declare module 'seyfert' {
    interface SeyfertRegistry { plugins: typeof plugins }

    interface InternalOptions {
        withPrefix: true;
    }
}

const client = new Client({
    plugins,
    commands: {
        prefix: () => ['!', '?'],
        reply: () => true,
    },
});

await client.start();

InternalOptions { withPrefix: true } is still required to enable prefix/text commands — the plugin does not set it for you. The prefix itself stays on the client (commands.prefix), not in the plugin options, and you pass only resolver options (the plugin injects the client).

Registering the plugin through SeyfertRegistry is what makes the plugin's client.yuna and ctx.yuna accessors typed everywhere.

Dynamic prefix per guild

Prefix configuration lives on the client. Return different prefixes per guild with an async function:

import { Client } from 'seyfert';

const client = new Client({
    commands: {
        prefix: async (message) => {
            const config = await db.getGuildConfig(message.guildId);
            return config?.prefixes ?? ['!'];
        },
        reply: () => true,
    },
});

Watchers

Watchers monitor text command interactions over time — useful for commands that need follow-up input. The plugin sets up the watcher controller automatically:

import { Command, Declare, type CommandContext } from 'seyfert';
import { Watch, Yuna } from 'yunaforseyfert';

@Declare({
    name: 'help',
    description: 'Interactive help',
})
@Watch({
    idle: 60_000,
    beforeCreate(ctx) {
        // Cancel any existing watcher for this user + command
        const existing = Yuna.watchers.find(ctx.client, {
            userId: ctx.author.id,
            command: this,
        });
        if (existing) existing.stop('replaced');
    },
})
export default class HelpCommand extends Command {
    async run(ctx: CommandContext) {
        await ctx.write({ content: 'What do you need help with? Reply with a topic.' });
    }
}