Startup and shutdown
What create, login, feature startup, and deployment each do.
A bot has two independent milestones: SWAGcommands loads its local files, and the Discord client becomes ready. Treat them separately and startup becomes pleasantly predictable.
const swag = await SWAG.create({ client, commandsDir: "./dist/commands" });
await client.login(process.env.DISCORD_TOKEN);
if (!client.isReady()) await once(client, Events.ClientReady);
await swag.deployCommands();
await swag.startFeatures();SWAG.create() loads preconditions, features, commands, context menus, subcommands, and events. It runs BeforeCommands and AfterCommands features and registers event listeners. It does not publish application commands. swag.state is "ready" and swag.isReady() is true when local initialization succeeds.
startFeatures() waits for the Discord client to be ready and runs ClientReady features. Calling it again does not rerun them. If you have no client-ready features, it resolves without waiting. deployCommands() requires a ready Discord client and syncs slash and context-menu commands to Discord. Message commands don't need this step.
Shut down deliberately
async function shutdown() {
await swag.stopFeatures();
client.destroy();
}
process.once("SIGINT", () => void shutdown());
process.once("SIGTERM", () => void shutdown());stopFeatures() stops timers, aborts the feature signal, waits for in-flight jobs, and runs cleanup functions. It can be called more than once. A stopped instance cannot restart features. client.destroy() is still your job.
If startup fails
SWAG.create() rejects with InitializationError; it never hands back a half-loaded instance. Feature cleanup runs for completed features. startFeatures() also cleans up if a client-ready feature fails. A deployment failure rejects separately and leaves the local instance ready, so handle it in your startup script or CI. See Errors for the reporting hooks.