Skip to main content
The interaction your function receives is how you answer. interaction.reply() takes what any message takes: a text, or an object with embeds, files, components…
src/commands/secret.ts
That is all: Discord shows the answer under the command, with the name of the person who used it.
Everything an interaction has is in the reference. What reply() accepts is listed in InteractionReplyOptions.

The five methods

Answers are sent one after the other, in the order they were asked: you can call reply() and followUp() without waiting for the first to finish, and they arrive in that order. A command answers once. A second reply() throws, and says what to do instead:
Likewise, edit() and followUp() need an answer first: “There is no answer to edit yet: call interaction.reply() first.” and “A follow-up comes after an answer: call interaction.reply() first.”

Answers only the person sees

Pass ephemeral: true to reply() or followUp() to show that message only to the person who used the command. Nobody else sees it, and they can dismiss it. To make every answer of a command ephemeral, put ephemeral: true on the command itself. Each reply() and followUp() can still say otherwise with its own ephemeral:
src/commands/roll.ts

When the answer takes time

Discord wants an answer within 3 seconds. You don’t have to care: after 2 seconds without an answer, ChapterJS tells Discord the answer is coming, the person sees “thinking…”, and your reply() completes it, up to 15 minutes later.
src/commands/report.ts
Call interaction.defer() yourself if you want “thinking…” to show up right away, or to choose what the answer looks like:
src/commands/lookup.ts
interaction.deferred tells whether the answer is still to come, and interaction.answered whether it was sent or promised.
Whether a deferred answer is ephemeral is decided when it is deferred. For a slow command whose answer must be private, put ephemeral: true on the command, or call interaction.defer({ ephemeral: true }) yourself: by the time ChapterJS defers for you, it only knows what the command says.

Changing or deleting the answer

edit() changes the answer that was sent. Only what you pass changes:
src/commands/countdown.ts
delete() removes it. Both work for 15 minutes after the command was used.

When your function fails

An error never stops the bot. The person gets a short, private answer, and you get the error in your terminal with the file and the line:
What the person reads depends on what happened: If the command had already answered, the bad news comes as another private message; if the answer was pending (“thinking…”), it becomes the answer. Both phrases can be translated: see What the bot answers by itself.
Keep the line of your code: chain with await, not .then(). An error in something awaited is reported with the line that awaited it.

A function that never answers

A command must answer. When run finishes without calling reply() (or defer()), the person sees “The application did not respond”, and your terminal says which command:

Translations

Show the command in the language of each person.

Sending messages

Embeds, files, polls: everything an answer can contain.