Creating a basic command
In order to start registering commands you need to create a subdirectory called commands (lowercase!) in your entry
point directory. If you were following Getting Started, it'll be src/commands.
Normally, you'd export one command per file to keep things organized. However, as we support various ways of exporting
commands from the file (export class ..., export default class, module.exports = class ... and
exports.MyCommand = class ...) you can export multiple commands from the same file.
Note that this doesn't create subcommands. We'll cover those in Plugin Subcommands
Note that by default Sapphire does not load the listeners required for processing message commands. You will need to
construct your SapphireClient with the loadMessageCommandListeners option set to true. For more information see
the SapphireClientOptions#loadMessageCommandListeners interface.
Create a ping.js file in your commands folder, which will send a message and then edit it with the elapsed time.
Arguments and other features are covered in other pages.
Creating a command class
Let's start by creating the file for the command class. In your commands folder, create a file named ping.js (or
ping.mjs / ping.ts if you're using ESM or TypeScript respectively). This command will send a message, and then edit
it with the bot's WebSocket latency.
Your project directory should now look something like this:
├── node_modules
├── package.json
└── src
    ├── commands
    │   └── ping.js
    └── index.js
With the file created, we can start writing our commands by extending the Command class, from which all
commands must be derived.
That said, here is an example of a ping command:
- CommonJS
- ESM
- TypeScript
const { Command } = require('@sapphire/framework');
class PingCommand extends Command {
  constructor(context, options) {
    super(context, {
      ...options,
      name: 'ping',
      aliases: ['pong'],
      description: 'ping pong'
    });
  }
}
module.exports = {
  PingCommand
};
import { Command } from '@sapphire/framework';
export class PingCommand extends Command {
  constructor(context, options) {
    super(context, {
      ...options,
      name: 'ping',
      aliases: ['pong'],
      description: 'ping pong'
    });
  }
}
import { Command } from '@sapphire/framework';
export class PingCommand extends Command {
  public constructor(context: Command.LoaderContext, options: Command.Options) {
    super(context, {
      ...options,
      name: 'ping',
      aliases: ['pong'],
      description: 'ping pong'
    });
  }
}
Let's go over what is defined in the constructor in this code:
- context: an object that contains file metadata required by the- Piececlass (which- Commandextends) in order to function.
- name: by default, the name of the file without the extension, i.e.- ping.jsbecomes- ping, so there's no need to define it.
- aliases: other ways users can call the command. You can have as many as you want!
- description: some text that you can use to display when a "help" command is used.
There are many other properties available, all of which can be seen in the CommandOptions interface,
but will also be explained in upcoming sections.
Creating the messageRun method
If you want to use message commands in your Sapphire bot, you have to make sure you meet the following prerequisites:
- Enable the Message Content IntentunderPrivileged Gateway Intentson the Discord Developer Portal for your application.
- In your Sapphire client options, set the intentsproperty to include the intentsGatewayIntentBits.GuildMessages,GatewayIntentBits.Guilds, andGatewayIntentBits.MessageContent.
- In your Sapphire client options set loadMessageCommandListenerstotrue.
All in all your code should look something like this:
- CommonJS
- ESM
- TypeScript
const { SapphireClient } = require('@sapphire/framework');
const { GatewayIntentBits } = require('discord.js');
const client = new SapphireClient({
  intents: [GatewayIntentBits.MessageContent, GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
  loadMessageCommandListeners: true
});
import { SapphireClient } from '@sapphire/framework';
import { GatewayIntentBits } from 'discord.js';
const client = new SapphireClient({
  intents: [GatewayIntentBits.MessageContent, GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
  loadMessageCommandListeners: true
});
import { SapphireClient } from '@sapphire/framework';
import { GatewayIntentBits } from 'discord.js';
const client = new SapphireClient({
  intents: [GatewayIntentBits.MessageContent, GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
  loadMessageCommandListeners: true
});
Commands have a messageRun method, which executes the command logic when it is invoked from a message. Define this
below the command's constructor:
- CommonJS
- ESM
- TypeScript
const { Command } = require('@sapphire/framework');
class PingCommand extends Command {
  constructor(context, options) {
    // ...
  }
  async messageRun(message) {
    const msg = await message.channel.send('Ping?');
    const content = `Pong from JavaScript! Bot Latency ${Math.round(this.container.client.ws.ping)}ms. API Latency ${msg.createdTimestamp - message.createdTimestamp}ms.`;
    return msg.edit(content);
  }
}
module.exports = {
  PingCommand
};
import { Command } from '@sapphire/framework';
export class PingCommand extends Command {
  constructor(context, options) {
    // ...
  }
  async messageRun(message) {
    const msg = await message.channel.send('Ping?');
    const content = `Pong from JavaScript! Bot Latency ${Math.round(this.container.client.ws.ping)}ms. API Latency ${msg.createdTimestamp - message.createdTimestamp}ms.`;
    return msg.edit(content);
  }
}
import { Command } from '@sapphire/framework';
import type { Message } from 'discord.js';
export class PingCommand extends Command {
  public constructor(context: Command.LoaderContext, options: Command.Options) {
    // ...
  }
  public async messageRun(message: Message) {
    const msg = await message.channel.send('Ping?');
    const content = `Pong from JavaScript! Bot Latency ${Math.round(this.container.client.ws.ping)}ms. API Latency ${
      msg.createdTimestamp - message.createdTimestamp
    }ms.`;
    return msg.edit(content);
  }
}
Any discord.js code can be executed here since the Sapphire Framework is an extension of it. The command can be
triggered with @bot ping or @bot pong (custom prefixes are mentioned in other documents).
Resulting code
Once you've set up the constructor and the messageRun method, your code should look like this:
- CommonJS
- ESM
- TypeScript
const { Command } = require('@sapphire/framework');
class PingCommand extends Command {
  constructor(context, options) {
    super(context, {
      ...options,
      name: 'ping',
      aliases: ['pong'],
      description: 'ping pong'
    });
  }
  async messageRun(message) {
    const msg = await message.channel.send('Ping?');
    const content = `Pong from JavaScript! Bot Latency ${Math.round(this.container.client.ws.ping)}ms. API Latency ${msg.createdTimestamp - message.createdTimestamp}ms.`;
    return msg.edit(content);
  }
}
module.exports = {
  PingCommand
};
import { Command } from '@sapphire/framework';
export class PingCommand extends Command {
  constructor(context, options) {
    super(context, {
      ...options,
      name: 'ping',
      aliases: ['pong'],
      description: 'ping pong'
    });
  }
  async messageRun(message) {
    const msg = await message.channel.send('Ping?');
    const content = `Pong from JavaScript! Bot Latency ${Math.round(this.container.client.ws.ping)}ms. API Latency ${msg.createdTimestamp - message.createdTimestamp}ms.`;
    return msg.edit(content);
  }
}
import { Command } from '@sapphire/framework';
import type { Message } from 'discord.js';
export class PingCommand extends Command {
  public constructor(context: Command.LoaderContext, options: Command.Options) {
    super(context, {
      ...options,
      name: 'ping',
      aliases: ['pong'],
      description: 'ping pong'
    });
  }
  public async messageRun(message: Message) {
    const msg = await message.channel.send('Ping?');
    const content = `Pong from JavaScript! Bot Latency ${Math.round(this.container.client.ws.ping)}ms. API Latency ${
      msg.createdTimestamp - message.createdTimestamp
    }ms.`;
    return msg.edit(content);
  }
}
Creating subcommands
For handling subcommands, please refer to the Sapphire Plugin Subcommands documentation.