Skip to main content

Client

ArcClient extends discord.js Client. All discord.js options, properties, events, and REST methods are available on it.

Constructor

import { ArcClient } from "arcscord";

const client = new ArcClient(token, options);
ParameterTypeDescription
tokenstringBot token from the Discord Developer Portal.
optionsArcClientOptionsClient configuration. Extends discord.js ClientOptions.

Options

intents (required)

Gateway intents to enable. Inherited from discord.js. At minimum "Guilds" is needed for slash commands.

const client = new ArcClient(process.env.DISCORD_TOKEN!, {
intents: ["Guilds"],
});

All discord.js ClientOptions (partials, rest, presence, etc.) are also accepted.


applicationId

Discord application ID. When provided, loadCommands (and loadHandlers) can register commands via the REST API before the clientReady event fires, without waiting for discord.js to hydrate client.application.

const client = new ArcClient(process.env.DISCORD_TOKEN!, {
intents: ["Guilds"],
applicationId: process.env.APPLICATION_ID!,
});

logger

Controls the built-in logger. All fields are optional.

OptionTypeDefaultDescription
level"trace" | "debug" | "info" | "warn" | "error" | "fatal""info"Minimum level to log. Use "debug" to see command/component execution logs during development.
format"pretty" | "json""pretty"Output format. Use "json" in production or containers.
loggerFunc(...data: unknown[]) => voidconsole.logCustom function to receive each log line.
customLoggerLoggerConstructorArcLoggerReplace the built-in logger class entirely. Must satisfy LoggerInterface.
diagnosticsobjectSecondary output channel for detailed error diagnostics (separate format/function).
const client = new ArcClient(process.env.DISCORD_TOKEN!, {
intents: ["Guilds"],
logger: {
level: process.env.NODE_ENV === "production" ? "info" : "debug",
format: process.env.NODE_ENV === "production" ? "json" : "pretty",
},
});

Defaults can also be set via environment variables: ARCSCORD_LOG_LEVEL, LOG_LEVEL, ARCSCORD_LOG_FORMAT, LOG_FORMAT.


enableInternalTrace

Enables verbose trace logs from framework internals — command dispatch, middleware steps, locale detection, etc. Useful for debugging framework behavior.

const client = new ArcClient(process.env.DISCORD_TOKEN!, {
intents: ["Guilds"],
enableInternalTrace: true,
});

Default: false.


baseMessages

Overrides framework-generated messages sent to users. Currently supports one key:

baseMessages.error — the message sent when an unhandled error occurs during a command or component handler.

const client = new ArcClient(process.env.DISCORD_TOKEN!, {
intents: ["Guilds"],
baseMessages: {
error: (id, context) => ({
content: `An error occurred (id: \`${id}\`). Please contact support.`,
}),
},
});

The context argument contains:

  • context.locale — the detected i18next language for the interaction (when locale manager is enabled).
  • context.t — a fixed translation function for that locale.

managers

Per-manager configuration. All fields are optional.

FieldManagesDocumentation
managers.commandSlash, user, and message commands — result handler, dispatch diagnosticsResult handler
managers.componentButtons, select menus, modals — result handler, dispatch diagnosticsResult handler
managers.eventDiscord.js event listeners — intent checks, result handlerEvents
managers.localei18next integration — language map, detection, resourcesLocalization

Example with event intent check configuration:

const client = new ArcClient(process.env.DISCORD_TOKEN!, {
intents: ["Guilds"],
managers: {
event: {
intentCheck: {
missing: "warn", // warn when an event has no matching intent
partialCoverage: "off",
},
},
},
});

Manager properties

ArcClient exposes four manager instances:

PropertyDescription
client.commandManagerRegisters commands with Discord and dispatches interactions.
client.componentManagerRoutes component custom IDs and dispatches interactions.
client.eventManagerWraps discord.js event listeners with result handling.
client.localeManageri18next wrapper used at registration time and per interaction.

Methods

loadHandlers(handlers)

Convenience method. Loads commands, components, and events in a single call.

await client.loadHandlers({
commands: [avatarCommand, pingCommand],
components: [simpleButton, profileModal],
events: [messageEvent],
});

If applicationId is set, commands are registered immediately over REST without waiting for clientReady. Otherwise, loadHandlers waits for the client to be ready before pushing commands.


loadCommands(commands, group?, guild?)

Registers commands with Discord and loads them into the command manager. Returns Result<true, InternalError>.

const [err] = await client.loadCommands([pingCommand, avatarCommand]);
if (err) {
client.logger.fatalError(err);
}

// Guild-scoped registration
await client.loadCommands([adminCommand], "admin", process.env.GUILD_ID!);

The optional group parameter is an internal label for the command set (used by deleteUnloadedCommands). The optional guild parameter restricts registration to a specific guild.


loadComponents(components)

Loads component handlers into the component manager. Returns the number of loaded handlers.

client.loadComponents([simpleButton, profileModal, roleMenu]);

loadEvents(events)

Registers event handlers and attaches discord.js listeners. Returns the number of loaded handlers.

await client.loadEvents([messageEvent, inviteEvent]);

createLogger(name)

Returns a new logger instance scoped to the given name, using the same output function and configuration as the client logger.

const log = client.createLogger("my-module");
log.info("started");

Full setup example

src/index.ts
import { ArcClient } from "arcscord";
import { avatarCommand, pingCommand } from "./commands";
import { simpleButton, profileModal } from "./components";
import { messageEvent } from "./events";

const client = new ArcClient(process.env.DISCORD_TOKEN!, {
intents: ["Guilds"],
applicationId: process.env.APPLICATION_ID,
logger: {
level: process.env.NODE_ENV === "production" ? "info" : "debug",
format: process.env.NODE_ENV === "production" ? "json" : "pretty",
},
managers: {
event: {
intentCheck: { missing: "warn" },
},
},
});

await client.loadHandlers({
commands: [avatarCommand, pingCommand],
components: [simpleButton, profileModal],
events: [messageEvent],
});

void client.login();