> ## Documentation Index
> Fetch the complete documentation index at: https://www.chapterjs.org/llms.txt
> Use this file to discover all available pages before exploring further.

# chapterjs start

> Run for everyone the bot you built, on one process or several

`chapterjs start` runs your bot in every server it is in, after [`chapterjs build`](https://www.chapterjs.org/run/build) prepared it. It is what the `start` script of your project runs, on the machine that hosts your bot:

```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
pnpm start
```

```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
npm run start
```

```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
yarn start
```

```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
bun start
```

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✓ Commands updated for everyone
✓ Online as my-bot in 128 servers
ℹ Intents computed from your files: GUILDS, GUILD_MESSAGES, MESSAGE_CONTENT
✓ 4 commands, 6 events loaded
```

That is all: the bot is online everywhere, with its commands shown in every server and in private messages. It runs what `chapterjs build` kept, not your files as they are now.

> [!NOTE]
>
> The `--processes` option, the environment variables and the exit codes are in the [CLI reference](https://www.chapterjs.org/reference/cli.md#chapterjs-start).

## What changes from dev

| | `chapterjs dev` | `chapterjs start` |
| - | - | - |
| Servers | Your test server only | Every server, except your test server when it knows it |
| Private messages | Never | Yes |
| Commands | Shown in your test server, at once | Shown everywhere, for everyone |
| A file that can't run | Keeps its last working version | Found by `chapterjs build`, before anything is online |
| Saving a file | Reloads it | Nothing: build and start again |
| Something to fix on Discord | Waits for you | Stops and says what to fix |
| Processes | One | As many as the size of your bot needs |

## What it needs

One value: the token of your bot.

```bash .env theme={"theme":{"light":"github-light","dark":"vesper"}}
BOT_TOKEN=
```

On a host, you usually upload no `.env` file: you give `BOT_TOKEN` in its settings (often called "environment variables" or "secrets"). Both work, and the real environment wins when both are there. Without it:

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ BOT_TOKEN is not set.
  Give it to the bot the way your host does it (its "environment variables" or "secrets"), or in a .env file in this folder.
  Copy the token of your bot from https://discord.com/developers/applications → your application → Bot → Reset Token.
```

> [!WARNING]
>
> Your token is a password. Never put it in your code, and never commit your `.env` file.

And a build. Without one, or with one made by another version of ChapterJS, the command stops and says what to run:

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ There is no build of your bot here.
  Run "chapterjs build" first (the build script of your project), then start again.
```

When your files changed since the build, the bot still starts, with the build:

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
⚠ Your files changed since the last build: the bot runs the build, not your changes. Run "chapterjs build" to put them online.
```

A build that can't run any more (a package or Node changed since it was made) stops the command: `✗ The build of your bot can't run any more: ...`, followed by `Run "chapterjs build" again: it says what to fix.`

## What it checks

The process you start checks everything once, for all the processes of the bot, before anything is online:

* **The token.** A refused token stops the command: `✗ Discord refused the bot token. ...`
* **The privileged intents** your files need. Nothing waits in production: the message is an error and the command stops.
  ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
  ✗ Your files need an option that is not enabled for your bot:
    - Message Content Intent, needed by src/events/ping.ts
    Enable it under "Privileged Gateway Intents", then save:
    https://discord.com/developers/applications/123456789012345678/bot
  ```
* **The commands**, registered for everyone, only when they changed since the last start from this folder: `✓ Commands updated for everyone`. Nothing is sent otherwise, and nothing is printed.
* **How many sessions the bot may still start today.** Discord limits that, and resets the token of a bot that goes over, so ChapterJS stops first:
  ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
  ✗ The bot needs to start 1 session(s) but Discord only allows 0 more until 10/7/2026, 9:00:00 AM. Going over that limit makes Discord reset the bot token, so the bot is not started. This usually means it was restarted too many times: wait, then start it again.
  ```

## A second bot for development

> [!NOTE]
>
> **We recommend two applications from the start: one bot for development on your computer, one bot for production.** Discord has no way to keep what one bot does on your computer apart from what it does for everyone: its commands, its presence, its settings and its limits are the bot's, in every server at once.

If you have one application only, make a second one for your computer: open the [Developer Portal](https://discord.com/developers/applications), click **New Application** again (name it after your bot, with "dev" in the name), and copy the token of its **Bot** page into the `.env` of your computer. Production keeps the token of the first application.

```bash .env on your computer theme={"theme":{"light":"github-light","dark":"vesper"}}
BOT_TOKEN=the token of the dev application
DEV_GUILD_ID=
```

Add the dev bot to your test server (`chapterjs dev` prints the link) and enable the same privileged intents on it when your files need some: `chapterjs dev` says which ones. From then on, the two bots have nothing in common:

* your test server only shows the commands of the dev bot, exactly as your files declare them, and never one twice;
* the presence, the privileged intents and the token of production stay as they are while you try things;
* Discord counts what each bot does on its own: the sessions it may start per day, the requests it may send.

The rest of this page about dev is for one bot doing both.

## One bot for dev and production

A bot in production and `chapterjs dev` can also share one token. Add `DEV_GUILD_ID` next to `BOT_TOKEN` in production too, with the same value as on your computer:

```bash .env theme={"theme":{"light":"github-light","dark":"vesper"}}
BOT_TOKEN=
DEV_GUILD_ID=
```

Production then leaves that server alone, and you can keep working with `chapterjs dev` on the **same bot** while it is online for everyone:

* what happens in your test server is only handled by `chapterjs dev`;
* what happens everywhere else, and in private messages, is only handled by `chapterjs start`.

They never answer the same thing. Without `DEV_GUILD_ID`, production runs every server, your test server included. With it, the server count leaves it out, and says so:

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✓ Online as my-bot in 128 servers
ℹ The dev server (DEV_GUILD_ID) is not counted: chapterjs start leaves it to chapterjs dev, and answers nothing there.
```

What one bot can't separate:

* **Commands.** Your test server shows the commands of everyone, like any server. `chapterjs dev` does not add them a second time: it only registers there the commands that are **new or different** in your project. Used in your test server, a command always runs the code on your computer. While you are changing a command that is already in production, your test server shows it twice (yours, and the one everyone has), and `chapterjs dev` tells you once:

  ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
  ℹ /poll is not the same here as in production, so My Server shows it twice: yours, and the one everyone has. It is shown once again when production runs your version.
  ```

  A command for everyone belongs to the bot, not to a server: Discord gives no way to hide it in one server, and removing it would remove it for everyone. That is why two bots is the way to never see that.

* **The presence.** `src/presence.ts` is sent by both, for one bot: Discord does not say which of the two it shows. The one you try on your computer may be seen by everyone.

* **The Developer Portal.** A privileged intent you enable to try an event is enabled for production too, and resetting the token stops production.

* **The limits.** The sessions a bot may start per day and the requests it may send are counted for the bot: what `chapterjs dev` uses is taken from production.

## Large bots

Discord splits large bots in several connections, called shards. ChapterJS asks Discord how many are needed and opens them by itself.

When there are many, it also spreads them over **several processes**, so your bot uses every CPU of the machine. You see it in the first line:

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✓ Online as my-bot in 18420 servers (20 shards, 5 processes)
```

Each process runs your project for its share of the servers, and what it prints starts with its number:

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
[3] ✗ src/commands/poll.ts:8 Discord refused POST /channels/{channel.id}/messages: Missing Permissions (50013). The bot is missing a permission for this, or acts on someone above it: the owner of the server, or a member or role higher than the bot's highest role.
```

* **Nothing to configure.** One process is used for every 4 shards, never more than your machine has CPUs. A bot under a few thousand servers runs in one process.
* **A process that stops by itself is started again**, and its servers are back in a moment. The others don't notice. One that ran for more than a minute starts again right away; one that keeps falling waits longer each time, up to a minute.
  ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
  ⚠ Process 3 of 5 stopped by itself (exit code 1): starting it again. Its servers are back in a moment.
  ```
* **Stopping the bot stops them all**, cleanly. When Discord refuses the bot for good in one process, every process stops and the command ends with exit code 1.

To choose the number yourself, pass it. It is never more than the number of shards:

```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
pnpm start --processes 8
```

```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
npm run start -- --processes 8
```

```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
yarn start --processes 8
```

```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
bun start --processes 8
```

Asking for more processes than the bot has shards runs one process per shard, and says so:

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
ℹ --processes 8 asks for more processes than your bot has shards (2): each process runs one at least, so it runs in 2 processes. Discord gives a bot more shards as it joins more servers.
```

Anything else after `start` is refused:

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ chapterjs start takes one option: --processes followed by a number, like "chapterjs start --processes 4". Got "--processes many".
```

### What it means for your code

Each process has its own memory. A variable of one process is not seen by the others:

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
// One counter per process: with 5 processes, 5 different numbers.
let commandsUsed = 0;
```

* The `ready` event runs once in each process, with the servers of that process.
* `guilds` and everything your bot [remembers](https://www.chapterjs.org/memory.md) are the ones of the process.
* Private messages are all handled by the first process.

To share something between processes, keep it outside of them, in a database.

> [!NOTE]
>
> Every process runs on the same machine. Spreading a bot over several machines is [not available yet](https://www.chapterjs.org/roadmap.md).

## Stopping

Press `Ctrl+C`, or let your host stop the process. The bot disconnects properly and goes offline at once:

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✓ Disconnected
```

> [card] [Deploy](https://www.chapterjs.org/run/deploy.md)
>
> Put your bot on a machine that stays on.

> [card] [Troubleshooting](https://www.chapterjs.org/run/troubleshooting.md)
>
> Every message, and what to do about it.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.