npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ikucord

v1.0.14

Published

A discord.js command/event handler and more!

Readme

IkuCord

IkuCord is a lightweight, structured discord.js command and event framework built for TypeScript. It simplifies registration, handles command execution pipelines, provides middleware, and includes a cache-backed rate-limiting system.

Table of Contents

Features

  • Automatic Registration: Auto-registers slash commands, autocomplete handlers, and User/Message Context Menus directly with Discord.
  • Command Aliases: Register multiple alternate names on Discord that map directly back to a single command handler.
  • Flexible Middleware Pipeline: Intercept commands with Global, Directory-wide, and Command-level middlewares executing sequentially.
  • Granular Rate-Limiting: Impose cache-backed cooldowns on commands and subcommands with developer bypasses.
  • Response Caching: Deterministically cache slash command responses per guild, channel, user, or globally to avoid repeated heavy queries or API requests.
  • Extensible Handlers: Override default error and cooldown responses globally using custom embeds, components, and logic.

Installation

Ensure you have discord.js installed, then add ikucord:

npm add ikucord
bun add ikucord
pnpm add ikucord
yarn add ikucord

Quick Start

1. Initialize the Client

Initialize IkuCord in your entry file (e.g. index.ts). You can pass a token parameter in the options, or by default, IkuCord will use the env variable DISCORD_TOKEN.

import { IkuCord } from "ikucord";
import { IntentsBitField } from "discord.js";
import path from "node:path";

new IkuCord({
  directories: {
    commands: path.join(__dirname, "commands"),
    events: path.join(__dirname, "events")
  },
  clientOptions: {
    intents: [
      IntentsBitField.Flags.Guilds,
      IntentsBitField.Flags.GuildMessages,
      IntentsBitField.Flags.MessageContent
    ]
  }
});

Awaiting Initialization

If you need to access the client outside of command handlers (such as at setup or module load time) and want to guarantee that IkuCord has fully loaded, you can safely await IkuCord.waitUntilReady(). This can be called from anywhere, even before new IkuCord() is constructed:

import { IkuCord } from "ikucord";

// Call this in an async context or function
async function run() {
  await IkuCord.waitUntilReady();
  const client = IkuCord.getClient();
  // client is now initialized and ready to use
}

2. Create a Command

Create command files within your commands directory (organized into subfolders representing command directories/categories). IkuCord also supports optional aliases, which register multiple slash commands under different names but execute the same handler.

import type { IkuCommand } from "ikucord";

const pingCommand: IkuCommand = {
  settings: {
    name: "ping",
    description: "Replies with pong!",
    aliases: ["p", "latency"], // Optional: registers /p and /latency mapping to this command
    cooldown: {
      time: "3s"
    }
  },
  handler: async ({ interaction }) => {
    await interaction.reply("Pong!");
  }
};

export default pingCommand;

Event Handling

Events are automatically registered from your events directory (configured via directories.events). The framework looks for an index.ts, index.mts, or index.cts file within that folder.

This index file must default export (or export a named events object) conforming to IkuCordEventsRegistry.

Multi-handler Execution Order

Each event option accepts an array of handler functions. The framework executes these event handlers sequentially, in the exact order they are declared in the array. If one handler fails, it logs the error but does not prevent subsequent handlers in the array from running.

Using Explicit EventHandler Types

Instead of defining functions inline, you can explicitly type your functions using the generic EventHandler<K> type (where K is the discord.js event name). This provides full type-safety for event parameters.

Here is an example structure defining multiple handlers for messageCreate and clientReady:

import { type IkuCordEventsRegistry, type EventHandler, Log } from "ikucord";

// Define individual event handlers using the EventHandler type
const logOnReady: EventHandler<"clientReady"> = async (client) => {
  Log.event("clientReady", `Logged in as ${client.user?.tag}!`);
};

const setBotActivity: EventHandler<"clientReady"> = async (client) => {
  client.user?.setActivity("Managing Discord servers");
};

const ignoreBots: EventHandler<"messageCreate"> = async (message, client) => {
  if (message.author.bot) return;
  Log.info(`User sent message: ${message.content}`);
};

const commandLogger: EventHandler<"messageCreate"> = async (message, client) => {
  if (message.content.startsWith("!")) {
    Log.info(`Command prefix matched in message: ${message.content}`);
  }
};

const localEventsRegistry: IkuCordEventsRegistry = {
  clientReady: {
    enabled: true,
    // Runs 'logOnReady' first, followed by 'setBotActivity'
    functions: [logOnReady, setBotActivity]
  },
  messageCreate: {
    enabled: true,
    // Runs 'ignoreBots' first, followed by 'commandLogger'
    functions: [ignoreBots, commandLogger]
  }
};

export default localEventsRegistry;

Middleware Configuration

IkuCord features a powerful middleware execution pipeline that runs before and after your command handlers. Middlewares are divided into three levels, executed in order: Global ➔ Directory ➔ Command.

Middleware Structure

A middleware implements the IkuCommandMiddleware interface:

import type { ChatInputCommandInteraction, Client } from "discord.js";

export type IkuMiddlewareType = 'global' | 'directory' | 'command';

export interface IkuCommandMiddleware {
  type: IkuMiddlewareType;
  beforeRun?: (interaction: ChatInputCommandInteraction, client: Client) => Promise<void>;
  afterRun?: (interaction: ChatInputCommandInteraction, client: Client) => Promise<void>;
}
  • beforeRun: Executes before permission checks, cooldown checks, and the command handler.
  • afterRun: Executes in a finally block after the command handler completes (regardless of whether it succeeded or threw an error).

1. Global Middleware

Global middlewares run on every single command.

  • Filename: $global.middleware.ts (or .mts / .cts).
  • Location: Must be placed in the parent directory of your commands folder (the parent of settings.directories.commands).
  • Type: Must be 'global'.
// $global.middleware.ts
import type { IkuCommandMiddleware } from "ikucord";

const globalMiddleware: IkuCommandMiddleware = {
  type: "global",
  beforeRun: async (interaction, client) => {
    console.log(`Global check: User ${interaction.user.tag} is running /${interaction.commandName}`);
  },
  afterRun: async (interaction, client) => {
    console.log(`Global check: /${interaction.commandName} execution finished`);
  }
};

export default globalMiddleware;

2. Directory Middleware

Directory middlewares run on all commands inside a specific subdirectory of your commands folder.

  • Filename: $dir.middleware.ts (or .mts / .cts).
  • Location: Must be placed inside the command subdirectory (e.g. commands/admin/$dir.middleware.ts).
  • Type: Must be 'directory'.
// commands/admin/$dir.middleware.ts
import type { IkuCommandMiddleware } from "ikucord";

const adminDirectoryMiddleware: IkuCommandMiddleware = {
  type: "directory",
  beforeRun: async (interaction, client) => {
    console.log(`Running admin command check for /${interaction.commandName}`);
  }
};

export default adminDirectoryMiddleware;

3. Command-level Middleware

Command-level middlewares run only on the specific command where they are defined.

  • Location: Defined directly within the command file as a property of the exported IkuCommand.
  • Type: Must be 'command'.
// commands/general/ping.ts
import type { IkuCommand } from "ikucord";

const pingCommand: IkuCommand = {
  settings: {
    name: "ping",
    description: "Ping pong!"
  },
  middleware: {
    type: "command",
    beforeRun: async (interaction, client) => {
      console.log("Specific ping middleware running");
    }
  },
  handler: async ({ interaction }) => {
    await interaction.reply("Pong!");
  }
};

export default pingCommand;

Halting Command Execution

You can halt command execution inside beforeRun by calling IkuCordMiddleware.before.stop(). This throws an IkuCordMiddlewareError and stops the pipeline. Make sure to reply to the interaction yourself before calling stop() if you want the user to receive a response.

import { IkuCordMiddleware } from "ikucord";
import type { IkuCommandMiddleware } from "ikucord";

const maintenanceMiddleware: IkuCommandMiddleware = {
  type: "global",
  beforeRun: async (interaction, client) => {
    const isMaintenance = true; // Replace with actual maintenance flag check
    
    if (isMaintenance) {
      // Reply to the interaction manually before halting
      await interaction.reply({
        content: "The bot is currently undergoing maintenance. Please try again later.",
        ephemeral: true
      });
 
      // Halts execution. Set the second argument to true to skip executing afterRun middlewares
      IkuCordMiddleware.before.stop("maintenance", true);
    }
  }
};

export default maintenanceMiddleware;

Command Options, Autocomplete & Subcommands

IkuCord fully supports standard Discord slash command options, dynamic autocompletes, subcommands, and subcommand groups using TypeScript-safe definitions.

1. Adding Options and Autocomplete

To use options, define the options array in settings. For dynamic user input suggestions, set autocomplete: true and provide an autocomplete function handler in your command object:

import { ApplicationCommandOptionType } from "discord.js";
import type { IkuCommand } from "ikucord";

const searchCommand: IkuCommand = {
  settings: {
    name: "search",
    description: "Search for items",
    options: [
      {
        name: "query",
        description: "The term to search for",
        type: ApplicationCommandOptionType.String,
        autocomplete: true,
        required: true
      },
      {
        name: "category",
        description: "Filter search by category",
        type: ApplicationCommandOptionType.String,
        choices: [
          { name: "Books", value: "books" },
          { name: "Movies", value: "movies" }
        ],
        required: false
      }
    ]
  },
  autocomplete: async ({ interaction, client, focusedOption }) => {
    // focusedOption contains the option currently typed by the user
    const choices = ["harry potter", "hobbit", "interstellar", "inception"];
    const filtered = choices.filter(choice => choice.startsWith(String(focusedOption.value).toLowerCase()));
    
    // Return up to 25 choice objects { name: string, value: string | number }
    return filtered.map(choice => ({ name: choice, value: choice }));
  },
  handler: async ({ interaction }) => {
    const query = interaction.options.getString("query");
    const category = interaction.options.getString("category") ?? "all";
    await interaction.reply(`Searching for "${query}" in category "${category}"...`);
  }
};

export default searchCommand;

2. Subcommands and Subcommand Groups

Organize your commands using nested subcommands or subcommand groups by setting the option's type to ApplicationCommandOptionType.Subcommand or SubcommandGroup:

import { ApplicationCommandOptionType } from "discord.js";
import type { IkuCommand } from "ikucord";

const configCommand: IkuCommand = {
  settings: {
    name: "config",
    description: "Configure bot settings",
    options: [
      {
        name: "set",
        description: "Set a configuration value",
        type: ApplicationCommandOptionType.Subcommand,
        options: [
          {
            name: "key",
            description: "The setting key to modify",
            type: ApplicationCommandOptionType.String,
            required: true
          },
          {
            name: "value",
            description: "The new value for the key",
            type: ApplicationCommandOptionType.String,
            required: true
          }
        ]
      },
      {
        name: "view",
        description: "View current configuration settings",
        type: ApplicationCommandOptionType.Subcommand
      }
    ]
  },
  handler: async ({ interaction }) => {
    const subcommand = interaction.options.getSubcommand();

    if (subcommand === "set") {
      const key = interaction.options.getString("key");
      const value = interaction.options.getString("value");
      await interaction.reply(`Setting \`${key}\` has been set to \`${value}\`.`);
    } else if (subcommand === "view") {
      await interaction.reply("Current configuration: Key=Value");
    }
  }
};

export default configCommand;

Context Menu Commands

IkuCord supports Discord's User and Message Context Menus. These commands appear when right-clicking a user or a message in the Discord UI.

Registration and Structure

Context menu files must be placed within your commands directory structure and end with the .contextMenu.ts (or .contextMenu.mts / .contextMenu.cts) extension.

To define a context menu command, export a default object of type IkuContextMenuCommand:

1. User Context Menus

import type { IkuContextMenuCommand } from "ikucord";

const userInfoContextMenu: IkuContextMenuCommand = {
  settings: {
    name: "User Info",
    type: "user", // Tells Discord to display this context menu on Users
    enabled: true, // Optional (defaults to true)
    devOnly: false, // Optional: restricts context menu to dev IDs
    testOnly: false // Optional: registers context menu to the devGuildID only
  },
  handler: async ({ interaction }) => {
    if (interaction.isUserContextMenuCommand()) {
      const targetUser = interaction.targetUser;
      await interaction.reply({
        content: `Username: ${targetUser.username}\nID: \`${targetUser.id}\``,
        ephemeral: true
      });
    }
  }
};

export default userInfoContextMenu;

2. Message Context Menus

import type { IkuContextMenuCommand } from "ikucord";

const logContentContextMenu: IkuContextMenuCommand = {
  settings: {
    name: "Log Content",
    type: "message", // Tells Discord to display this context menu on Messages
    enabled: true
  },
  handler: async ({ interaction }) => {
    if (interaction.isMessageContextMenuCommand()) {
      const targetMessage = interaction.targetMessage;
      console.log(`Logged message content: ${targetMessage.content}`);
      await interaction.reply({ content: "Logged message content!", ephemeral: true });
    }
  }
};

export default logContentContextMenu;

Cooldown Configuration

Cooldowns are backed by the internal caching layer. You configure the cooldown object directly inside the command's settings block. You can specify durations using human-readable strings (e.g. 10s, 15m, 1hr, 2d).

Supported Duration Formats

Both cooldowns and cache lifetimes accept case-insensitive duration strings. You can also combine multiple units (e.g., 1h 30m).

| Unit | Supported Abbreviations / Suffixes | Example | | :--- | :--- | :--- | | Milliseconds | ms | 500ms | | Seconds | s, sec, secs, second, seconds | 30s | | Minutes | m, min, mins, minute, minutes | 5m | | Hours | h, hr, hrs, hour, hours | 2h | | Days | d, day, days | 1d | | Weeks | w, wk, wks, week, weeks | 1w | | Months | mo, mon, mth, mths, month, months (30 days) | 1mo | | Years | y, yr, yrs, year, years (365 days) | 1y |

const exampleCommand: IkuCommand = {
  settings: {
    name: "example",
    description: "Example command with rate limiting",
    cooldown: {
      time: "5m",
      amount: 5, // Allow up to 5 execution casts before triggering cooldown (defaults to 1)
      devBypass: true, // Developers bypass cooldowns (defaults to true)
      bypassUsers: ["USER_ID_1", "USER_ID_2"] // Specific users who bypass this cooldown
    }
  },
  handler: async ({ interaction }) => {
    await interaction.reply("Command executed!");
  }
};

Subcommand Cooldowns

You can configure cooldowns on individual subcommands inside the command's options array. If a subcommand has a cooldown block, it tracks execution limits independently using an isolated cache key unique to that subcommand. If a subcommand does not have its own cooldown configuration, it automatically falls back to the parent command's top-level cooldown.

import { ApplicationCommandOptionType } from "discord.js";
import type { IkuCommand } from "ikucord";

const configCommand: IkuCommand = {
  settings: {
    name: "config",
    description: "Configure bot settings",
    cooldown: {
      time: "10s" // Fallback cooldown for subcommands without specific rate limits
    },
    options: [
      {
        name: "set",
        description: "Set a configuration value",
        type: ApplicationCommandOptionType.Subcommand,
        cooldown: {
          time: "3s" // Independent rate-limit specifically for this subcommand
        },
        options: [
          {
            name: "key",
            description: "The setting key to modify",
            type: ApplicationCommandOptionType.String,
            required: true
          }
        ]
      },
      {
        name: "view",
        description: "View settings",
        type: ApplicationCommandOptionType.Subcommand
        // Falls back to the parent command's 10s cooldown
      }
    ]
  },
  handler: async ({ interaction }) => {
    // Handler implementation
  }
};

Command Response Caching

You can optionally cache the responses of your slash commands using the internal/configured caching layer. This avoids running your command handler multiple times for identical inputs, saving API requests, server load, and database queries.

To enable caching, define the cache object within the command's settings:

import { ApplicationCommandOptionType } from "discord.js";
import type { IkuCommand } from "ikucord";

const weatherCommand: IkuCommand = {
  settings: {
    name: "weather",
    description: "Get the current weather",
    cache: {
      time: "5m", // Cache duration (supports human-readable strings like '10s', '15m', '1hr')
      scope: "guild" // Optional scope: 'global' | 'guild' | 'channel' | 'user' (defaults to 'global')
    },
    options: [
      {
        name: "location",
        description: "The city to search for",
        type: ApplicationCommandOptionType.String,
        required: true
      }
    ]
  },
  handler: async ({ interaction }) => {
    const location = interaction.options.getString("location");
    // This heavy database/API fetch will only run once per 5 minutes per guild!
    const weather = await fetchWeatherFromAPI(location);
    await interaction.reply(`The weather in ${location} is ${weather}.`);
  }
};

How it Works

  1. Option-Sensitive Keys: The framework automatically serializes all command arguments (options) passed by the user, sorting them alphabetically to produce a deterministic cache key unique to the inputs.
  2. Isolation Scopes:
    • global: Cache is shared bot-wide (all guilds, channels, and users see the cached result for identical options).
    • guild: Cache is isolated to the Discord server where the command was run.
    • channel: Cache is isolated to the specific text channel.
    • user: Cache is isolated to the individual executing user.
  3. Execution Interception: If a cached response exists, the framework intercepts the command and replays the cached message instantly, bypassing execution of your handler completely.

Preventing Caching on Handled Errors

By default, any interaction reply, editReply, or follow-up captured during a command handler execution will be cached for the configured duration. If your command catches an error internally and replies with a handled error embed/message, that response would normally be cached.

To prevent handled errors or specific executions from being cached, call IkuCordCache.cancelCommandCache() at any point inside your command handler:

import { IkuCordCache, type IkuCommand } from "ikucord";

const myCommand: IkuCommand = {
  // ... settings with cache config
  handler: async ({ interaction }) => {
    try {
      const result = await performHeavyAction();
      await interaction.reply(result);
    } catch (error) {
      // Prevent the error response from being cached
      IkuCordCache.cancelCommandCache();
      
      await interaction.reply({
        content: "Failed to perform action.",
        ephemeral: true
      });
    }
  }
};

Lifecyle Overrides

Configure custom responses for cooldowns or errors globally in settings. Since the returned object is spread into the interaction response, you can return standard Discord.js reply options including content, embeds, components, and files:

import { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js";

new IkuCord({
  // ...other options
  cooldownHandler: (interaction, timeLeft, command) => {
    const embed = new EmbedBuilder()
      .setTitle("Command Cooldown")
      .setDescription(`Please wait **${timeLeft.toFixed(1)}s** before running \`/${command.settings.name}\` again.`)
      .setColor("Orange");

    return {
      embeds: [embed]
    };
  },
  errorHandler: (interaction, error, command) => {
    const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
      new ButtonBuilder()
        .setLabel("Support Server")
        .setStyle(ButtonStyle.Link)
        .setURL("https://discord.gg/example")
    );

    return {
      content: `Something went wrong running \`/${command?.settings.name}\`: ${error.message}`,
      components: [row]
    };
  }
});

Custom Cache Backing (e.g. Redis)

By default, IkuCord uses an in-memory cache for tracking cooldowns. If you run multiple bot shards or need persistent cooldown states across restarts, you can override the backing cache store in settings using any custom provider like Redis:

import { IkuCord } from "ikucord";
import Redis from "ioredis";

const redis = new Redis("redis://localhost:6379");

new IkuCord({
  // ...other options
  cache: {
    get: async (key) => {
      return await redis.get(key);
    },
    set: async (key, value, ttl) => {
      if (ttl) {
        // ttl is provided in milliseconds by the framework
        await redis.set(key, value, "PX", ttl);
      } else {
        await redis.set(key, value);
      }
    },
    delete: async (key) => {
      await redis.del(key);
    }
  }
});

Configuration Reference

Framework Settings

Pass these options inside the new IkuCord(settings) constructor:

| Option | Type | Description | | :--- | :--- | :--- | | token | string | Optional. The Discord bot token. Defaults to process.env.DISCORD_TOKEN. | | clientOptions | ClientOptions | Required. Standard discord.js client constructor options (e.g. intents). | | directories | object | Required. Paths for loading resources:commands (string): Absolute path to the commands folder.events (string): Absolute path to the events folder (containing index.ts). | | devUserIDs | string[] | Optional. List of Discord user IDs treated as developers. Used for developer checks and cooldown bypasses. | | devGuildID | string | Optional. The guild ID used to register dev-only or test-only commands instantly. | | deleteUnregisteredCommands | boolean | Optional. Automatically delete application commands registered on Discord that are not found or enabled in the application. Defaults to true. | | cooldownHandler | function | Optional. Callback executed when a command is on cooldown. | | errorHandler | function | Optional. Callback executed when a command execution throws an error. | | cache | object | Optional. Custom cache backing implementation (implements get, set, delete). | | logger | object | Optional. Configuration settings for the framework log emitter. See Logger Settings below. |

Logger Settings

Configure log output options inside the logger object:

| Option | Type | Description | | :--- | :--- | :--- | | enabled | boolean | Toggle overall logger activity (defaults to true). | | level | string | Standard log level threshold (e.g. "info", "debug", "error"). | | timeFormat | "12HR" \| "24HR" | Timestamp representation format (defaults to "24HR"). | | middlewareLog | boolean | Enable/disable middleware execution events output. | | commandLog | boolean | Enable/disable command registration and execution events output. | | eventLog | boolean | Enable/disable listener lifecycle events output. | | fileLogging | object | Optional. Automatically write logs to local files:enabled (boolean): Toggle text file output.logFolder (string): Output directory for saved log files.logRetentionDays (number): Lifespan threshold for automated log cleanup. |

Command Settings

Define these settings inside each IkuCommand structure:

| Option | Type | Description | | :--- | :--- | :--- | | name | string | Required. Unique identifier and registration name for the slash command (lowercase). | | description | string | Required. Short explanation of what the command does. | | aliases | string[] | Optional. Additional command names registered on Discord that map to this command. | | enabled | boolean | Optional. Toggle whether the command should be loaded and registered (defaults to true). | | devOnly | boolean | Optional. Restrict execution to developer IDs declared in settings. | | testOnly | boolean | Optional. Restrict command registration to the designated devGuildID. | | permissionsRequired | PermissionResolvable[] | Optional. Array of discord.js permissions the executing user must possess. | | botPermissionsRequired | PermissionResolvable[] | Optional. Array of discord.js permissions the bot client must possess. | | cooldown | object | Optional. Cooldown/rate-limiting rules:time (string): Duration threshold (e.g. "10s", "15m", "1hr").amount (number): Allowable execution casts before triggering cooldown (defaults to 1).devBypass (boolean): Developers bypass cooldowns (defaults to true).bypassUsers (string[]): Specific Discord user IDs exempt from this cooldown. | | cache | object | Optional. Response caching rules:time (string): Cache duration threshold (e.g. "5m", "1hr").scope (string): Cache isolation scope ("global" \| "guild" \| "channel" \| "user", defaults to "global"). | | additionalFields | Record<string, any> | Optional. Custom metadata fields that you can query in custom middlewares or error handlers. |

Context Menu Settings

Define these settings inside each IkuContextMenuCommand structure:

| Option | Type | Description | | :--- | :--- | :--- | | name | string | Required. Name of the context menu option as it appears in the Discord UI. | | type | "user" \| "message" | Required. Target type of the context menu. | | enabled | boolean | Optional. Toggle whether the context menu command should be loaded and registered (defaults to true). | | devOnly | boolean | Optional. Restrict execution to developer IDs declared in settings. | | testOnly | boolean | Optional. Restrict context menu registration to the designated devGuildID. |