Navigation

Slash Commands

Triggered by / in the message input. The TipTap suggestion API powers the picker; definitions live in SlashCommandDefinitionMap.

Command reference

CommandKindParametersResult
/flipImmediate client—Posts 🌝 **Heads** or 🌚 **Tails**
/meImmediate clientmessage (required)Posts *message* (italic emphasis)
/rollImmediate client—Posts 🎲 Rolled a **N** (1–100)
/shrugImmediate clienttext (optional)Posts text¯\_(ツ)_/¯
/tableflipImmediate client—Posts (╯°□°)╯︵ ┻━┻
/unflipImmediate client—Posts ┬─┬ノ( º _ ºノ)
/topicImmediate tRPCtext (optional)Calls room.updateRoom to set/clear the topic
/pollDialog → tRPC—Opens the poll dialog; on submit posts a MessageType.Poll message
/remindDialog → tRPC—Opens the scheduled-job dialog → scheduled messages
/scheduleDialog → tRPC—Opens the scheduled-job dialog → scheduled messages

How it works

Adding a command touches three places (per the registry pattern): the SlashCommandType enum, its SlashCommandDefinitionMap entry (icon, title, description, parameters[], type), and an arm in useExecuteSlashCommand.

All execution happens in useExecuteSlashCommand via a switch on SlashCommandType — the definition is static metadata only, with no execute() method. Three execution paths:

  • Client-only (Flip, Me, Roll, Shrug, TableFlip, Unflip) — build the sendMessage input inline and fall through to the normal sendMessage.
  • Server call (Topic) — call a tRPC mutation directly (room.updateRoom), no message posted by the command itself.
  • Dialog (Poll, Remind, Schedule) — open a dialog that owns its own submit, so richer inputs use normal form controls instead of inline parameter chips.

Typing a command

flowchart TD
    A([User types /]) --> B[TipTap suggestion activates]
    B --> C{User picks command}
    C -->|no parameters| D[useExecuteSlashCommand immediately]
    C -->|has parameters| E[SlashCommandSuggestion.command fires]
    E --> F[Read remaining editor text after range]
    F --> G[Delete from range.from to doc end]
    G --> H{remainingText?}
    H -->|yes| I[parseTextAndParameters → restore parameterValues + trailingMessage]
    H -->|no| J[empty parameterValues]
    I --> K[setPendingSlashCommand + parsed values]
    J --> K
    K --> L[SlashCommandParameters UI shows with chips pre-filled]
    L --> M([User fills in + submits])
    M --> D

Parameter mode ↔ text serialisation

Collapsing parameter mode back to text (Escape, or Backspace in an empty command/trailing input) rebuilds the input as:

/CommandType parameterName1|value1 parameterName2|value2 trailingMessage

ID_SEPARATOR (|) separates a parameter name from its value; parameters are space-separated; the last parameter's value is greedy; re-parsing uses prefix matching per parameter in definition order. The RichTextEditor remounts with the formatted text and focuses at the end.

Key files

FileRole
apps/web/app/models/message/slashCommands/SlashCommandType.tscommand enum
apps/web/app/services/message/slashCommands/SlashCommandDefinitionMap.tsRecord<SlashCommandType, SlashCommand> — static definitions
apps/web/app/composables/message/slashCommand/useExecuteSlashCommand.tsexecution switch
apps/web/app/composables/message/slashCommand/useSlashCommandExtension.tsTipTap extension (mirrors MentionExtension)
apps/web/app/services/message/slashCommands/SlashCommandSuggestion.tspicker suggestion config
apps/web/app/services/message/slashCommands/parseTextAndParameters.tstext → parameterValues re-parsing
apps/web/app/store/message/input/slashCommand.tspendingCommand + parameterValues + trailingMessage store
apps/web/app/components/Message/Model/Message/Input/ActionsMenuButton.vuethe composer's + menu over the dialog commands

Notes

The three commands that open a dialog rather than send something — /poll, /schedule and /remind — are also the composer's + menu, which is Discord's home for creating a poll. The menu runs the same useExecuteSlashCommand with the same type and takes each entry's icon from SlashCommandDefinitionMap, so a command and its menu entry cannot drift; only the entry's wording differs, because a command's title names the command (/poll) where a menu of actions wants a verb.

The send pipeline is untouched by commands: sendComposerMessage, RichTextEditor, and the mention suggestion know nothing about slash commands. Client-only commands go through the same sendMessage as a hand-typed message.

Details

Command palette

Keyboard shortcuts