LLM and agent context

A compact, accurate summary of Athena to paste into an AI coding assistant (Claude Code, Copilot, Cursor) working in an Athena project. Keep it in your...

A compact, accurate summary of Athena to paste into an AI coding assistant (Claude Code, Copilot, Cursor) working in an Athena project. Keep it in your project's agent instructions.

What Athena is

A TypeScript Discord library for Node 18+, forked from Eris, targeting discord-api-types/v10 (re-exported as Constants). Package name: athena. Synchronous in-memory cache by default; optional pluggable and Redis-backed caches.

Top-level exports

import {
  Client, CommandClient, VERSION,
  // structures
  Base, BaseChannel, CategoryChannel, ForumChannel, MediaChannel, Guild, GuildChannel,
  GuildTextChannel, GuildVoiceChannel, GuildPreview, GuildAuditLogEntry, GuildIntegration,
  GuildTemplate, NewsChannel, NewsThreadChannel, PartialChannel, PrivateChannel, StageChannel,
  StageInstance, ThreadChannel, ThreadMember, UnavailableGuild, VoiceTextChannel, Member,
  Message, Role, User, VoiceState, Invite, PermissionOverwrite, Entitlement, SKU, Subscription,
  AutoModerationRule, GuildScheduledEvent,
  // interactions
  Interaction, CommandInteraction, ComponentInteraction, AutocompleteInteraction,
  ModalSubmitInteraction, PingInteraction, UnknownInteraction,
  // util
  Bitfield, Bucket, ChannelFlagBitfield, Collection, LRUCollection, NullCollection,
  RemoteBackedCollection, RedisCacheStore, GatewayIntentsBitfield, MessageFlagBitfield,
  MultipartData, PermissionBitfield, SequentialBucket, SKUFlagBitfield,
  // rest / gateway / errors
  Endpoints, RequestHandler, Shard, ShardManager, DiscordHTTPError, DiscordRESTError, CommandError,
  // builders / commands
  CommandBuilder, ComponentBuilder, NewComponentBuilder, ModalBuilder, Command, Event, CooldownHandler, SlashCommand
} from 'athena';

Construction

new Client(`Bot ${token}`, options?)        // token MUST start with "Bot "
new CommandClient({ token, options, commandContext?, commandMiddleware?, cooldownLogic?, deployGlobally? })

Default intents 3243773 (all non-privileged). Privileged: GuildPresences, GuildMembers, MessageContent.

Key conventions

  • Snowflake IDs are always string.
  • update(data) mutates a structure from a new dispatch payload (internal).
  • Base-derived objects have id, createdAt, toJSON().
  • Type guards narrow unions: interaction.isCommand(), channel.isTextBased(), etc.
  • Cache reads are synchronous: client.users.get(id), guild.members.get(id). For possibly-uncached, use async client.fetchUser(id) / guild.fetchMember(id).

Commands

@SlashCommand(new CommandBuilder('ping', 'Replies pong'))
class PingCommand extends Command {
  async handleCommand(context, interaction: CommandInteraction) {
    await interaction.createMessage({ content: 'Pong!' });
  }
}
client.registerCommand(new PingCommand());
client.on('ready', () => client.deployCommands());

Read options with getString / getRequiredInteger / getUser / getChannel / etc. Route modals and components by custom_id prefix matching the command name.

Components

ComponentBuilder = V1 (.toJSON(), max 5 rows). NewComponentBuilder = V2 (.toMessageData(), up to 40 components; cannot carry content/embeds/poll). Buttons: addNormalButton, addURLButton, addPremiumButton. Selects: addStringSelect, addChannelSelect, addRoleSelect, addUserSelect, addMentionableSelect.

Errors

DiscordRESTError (Discord JSON error, has numeric code), DiscordHTTPError (non-JSON/transport), CommandError enum emitted via the commandError event (NotDeveloperGuild, DeniedUser, DeniedGuild, MissingPermission, OnCooldown, MiddlewareError, UncaughtError).

Caching at scale

Per-cache overrides via options.cache (factories for users, members, messages, ...). LRUCollection(Class, max), NullCollection(Class). Cross-cluster dedup: RemoteBackedCollection + RedisCacheStore (over an injected Redis client) implementing RemoteCacheStore (getEntity/getEntities/getAllEntities/setEntity/removeEntity), resolved via client.fetchUser / guild.fetchMember.

When generating code, prefer

  • interaction.getRequiredString('name') over digging into interaction.data.options.
  • MessageFlags.Ephemeral over the literal 64.
  • PermissionFlagsBits.X over hex values.
  • CommandBuilder over hand-written command JSON.
  • await-ing all REST calls.
  • Imports from 'athena'; from 'discord-api-types/v10' only for types Athena does not re-export.

Common pitfalls

  • Missing the Bot token prefix.
  • getAllUsers: true without the GuildMembers intent (throws on construct).
  • Responding to an interaction after 3 seconds (code 10062) or twice (40060).
  • Not handling the error event.
  • Mixing V1 and V2 components on one message.