> ## 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.

# CLI

> Every command of chapterjs, what it reads from the environment, its exit codes and the symbols of its messages

The `chapterjs` command comes with the `chapterjs` package. Projects made with `create chapterjs` run it through their scripts (`dev`, `build`, `start`, `test`, `postinstall`).

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
Usage: chapterjs <command>

Commands:
  dev     Run your bot on your dev server and reload it when you save a file
  build   Check your bot and prepare it for production
  start   Run for everyone the bot that was built
  test    Check your bot without Discord: every file once, then your scenarios
  sync    Write the types of your project (dev does it too)

Options of start:
  --processes <n>   How many processes to use (by default: as many as the
                    size of your bot needs)
```

> [!NOTE]
>
> How to use each command is in the guide: [chapterjs dev](https://www.chapterjs.org/run/dev.md), [chapterjs build](https://www.chapterjs.org/run/build.md), [chapterjs start](https://www.chapterjs.org/run/start.md), [chapterjs test](https://www.chapterjs.org/testing.md), [Deploy](https://www.chapterjs.org/run/deploy.md). What every message means is in [Troubleshooting](https://www.chapterjs.org/run/troubleshooting.md).

## Commands

Every command runs in the folder of the project: the one with `package.json` and `src/`. Without `src/`, `dev`, `build` and `test` stop with `✗ There is no src folder here.`

### `chapterjs dev`

Runs the bot of the current folder on the test server of `DEV_GUILD_ID`, and reloads every file under `src/` when it is saved. Runs until stopped.

| Step | What happens |
| - | - |
| `.env` | `BOT_TOKEN` and `DEV_GUILD_ID` are read and checked, and `REDIS_URL` and `REDIS_PASSWORD` when they are there. Every problem is printed, then the command stops. |
| Types | `.chapterjs/` is written, like `chapterjs sync`. |
| Files | Every file of `src/` is loaded, and what they export with `command()`, `event()`, `button()`... is read. A broken file or declaration is reported and left out. |
| Redis | When a store says `storage: 'redis'`, Redis must answer: otherwise the reason is printed and the command stops. Every key written from `dev` starts with `dev:`. |
| Token | Checked with Discord. |
| Test server | The bot must be in it: otherwise an invite link is printed and, in a terminal, the command waits. |
| Privileged intents | Those the files need must be enabled: otherwise the files and the link are printed and, in a terminal, the command waits. |
| Connection | To the test server only. What happens in other servers and in private messages is dropped, and the intents that only serve private messages are not asked for. |
| Commands | Registered on the test server, only when they changed since the last time, without the ones production already shows as declared. Registered again after a reload that changed them. |
| New version | npm is asked, at most once a day, whether a newer `chapterjs` is published: if so, an `ℹ` gives the command to run, with the package manager of the project (its lockfile, else the one that started the command, else npm). Without an answer in 5 seconds, nothing is said. |
| Reload | On every save under `src/`: files are loaded again, a failing file keeps its last working version, the bot reconnects when the files need new intents. |
| Stop | `Ctrl+C` or `SIGTERM`: the session is closed and the bot goes offline at once. A second one exits without waiting. |

Takes no option.

### `chapterjs build`

Checks the project and compiles it into `.chapterjs/build/`. Needs no token and sends nothing to Discord.

| Step | What happens |
| - | - |
| Types | `.chapterjs/` is written, then `node_modules/.bin/tsc -b` runs when it exists and the project has a `tsconfig.json`. A type error stops the build. Without TypeScript, the build says so and goes on. |
| Files | The previous build is removed. Every file of `src/` is loaded, and what it declares is read. One broken file or declaration stops the build. |
| Compile | Every file of `src/`, with what it imports, is bundled into `.chapterjs/build/bot.js` (ESM, Node 24, packages left in `node_modules`, whitespace and syntax minified, names kept) with `bot.js.map` next to it (no sources inside). |
| Check | The compiled file is loaded once and every file is checked again. |
| Record | `.chapterjs/build/build.json`: the version of `chapterjs`, a fingerprint of `src/`, whether the files join voice channels. |

A build that fails leaves no `.chapterjs/build/` behind. Takes no option.

### `chapterjs start`

Runs the build for everyone. Runs until stopped.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
chapterjs start [--processes <n>]
```

| Step | What happens |
| - | - |
| `.env` | `BOT_TOKEN` is read and checked; `DEV_GUILD_ID`, `REDIS_URL` and `REDIS_PASSWORD` are read when they are there. |
| Build | `.chapterjs/build/` must exist and have been made by the same version of `chapterjs`. When `src/` is there and changed since the build, a `⚠` says so and the build runs anyway. |
| Files | Loaded from the build, never from `src/`. |
| Redis | When a store says `storage: 'redis'`, Redis must answer. Every process reaches it itself. |
| Token and privileged intents | Checked once. A problem is an error: nothing waits. |
| Commands | Registered for everyone, only when they changed since the last start from this folder. |
| Sessions | Discord is asked how many shards the bot needs and how many sessions it may still start today. Not enough sessions left stops the command. |
| Processes | One process for every 4 shards, never more than the machine has CPUs, never more than the shards, or what `--processes` asks. With several, the process you started forks the others, prefixes their lines with `[n] `, starts again one that stops by itself and stops them all together. |
| Connection | To every server, except the one of `DEV_GUILD_ID` when it is set. Private messages are handled. |
| Stop | `Ctrl+C` or `SIGTERM`: every process closes its session and the bot goes offline at once. |

**--processes** `integer`

How many processes run the bot: a whole number of 1 or more, written `--processes 4` or `--processes=4`. Capped at the number of shards, with an `ℹ` saying so. Anything else after `start` stops the command with `✗ chapterjs start takes one option: ...`.

### `chapterjs test`

Checks the bot against a Discord in memory. Needs no token and sends nothing to Discord.

| Step | What happens |
| - | - |
| Types | `.chapterjs/` is written, like `chapterjs sync`. The types are not checked: `chapterjs build` and the `typecheck` script do. |
| Files | Every file of `src/` is loaded, and what it declares is read. One broken file or declaration stops the command: `✗ This file can't run, so your bot was not tested.` A project that declares nothing stops with `ℹ Nothing to run yet`. |
| Checks | In a server in memory where the bot is an admin: every command is used with every option, with the required ones only, and once per hard value; every button, menu and form with its data and hard data; every event once; every task once. For each thing of a file that failed, `✗ Checked src/ping.ts: command /ping failed in 1 of 8 cases` followed by one line per failed case, with the file and the line of what threw, then what the files printed meanwhile. The files that passed are one line at the end: `✓ Checked every file once: 7 checks in 2 files` (or `✓ Checked the other 2 files once: 7 checks` when one failed); what was checked in them is not listed, nor what they printed. In a terminal, the file in progress is shown first (`↻ Checking src/ping.ts`, then one `→` line per thing and case tried), and erased once done. An event the server can not make happen is listed in an `ℹ`. |
| Scenarios | Every `*.test.ts` and `*.spec.ts` file of `src/` is loaded (never by the bot), and what it exports made with `scenario()` runs, each on a fresh server with empty stores. One line per test file: `✓ Tested src/file.test.ts`, or, for each scenario that failed, `✗ Tested src/file.test.ts: "label" failed` followed by the file, the line and the reason, then what the files printed meanwhile. A scenario that takes more than 10 seconds fails. A test file that declares no scenario is a `⚠`. |
| Bottom line | `✓ 7 checks and 2 scenarios passed`, or `✗ 1 of 7 checks and 1 of 2 scenarios failed`. |

Takes no option. Stores keep their data in memory: the `data/` folder of the project is never touched.

### `chapterjs sync`

Writes the `.chapterjs/` folder of the project: what the project adds to the types of `chapterjs` (the files of `public/`, its languages and its commands, found by reading the files without running them) and the `tsconfig.json` of the one TypeScript project that covers `src/`. Prints `✓ Types written to .chapterjs/`. Needs no token. `dev` and `build` do it too when they start; templates run it as `postinstall`.

Only files whose content changed are written; what an older version wrote is removed. `.chapterjs/cache/` and `.chapterjs/build/` are left alone.

### `chapterjs --version`

Prints the version of the package. `-v` works too.

### `chapterjs --help`

Prints the usage above. `-h` and no command at all do the same. Any other word is an error: `✗ "…" is not a command.`, followed by the usage.

## Environment

### `.env`

`dev` and `start` read the `.env` file of the project folder, when there is one, then the real environment: **a variable set in the environment wins** over the file. Values are trimmed.

**BOT\_TOKEN** `string` *required*

The token of the bot, from the **Bot** page of the application in the Developer Portal. A `Bot ` prefix is removed. Refused when empty, when it is a placeholder left from an example (`your-token-here`, `xxx`, `todo`, `changeme`, `<...>`…) or when it contains a space.

**DEV\_GUILD\_ID** `string`

The ID of the test server: 17 to 20 digits. Required by `dev`, which runs the bot in that server only. Optional for `start`, which then ignores that server, so that `dev` and `start` can share one token without answering the same thing twice. Refused when it is not an ID.

**REDIS\_URL** `string`

The address of the Redis that the stores declared with `storage: 'redis'` use: `redis://host:port`, `rediss://` for a TLS connection, `/1` at the end for a database other than the first, a user and a password before the host when there are some (`redis://user:password@host:6379`). Only needed when a store says `storage: 'redis'`; with it set and no such store, nothing is connected. Refused when it is not an address of that form. See [Storage](https://www.chapterjs.org/storage.md#in-redis).

**REDIS\_PASSWORD** `string`

The password of that Redis, when it is not in `REDIS_URL` (or to replace the one that is). Refused when `REDIS_URL` is not set.

Without a `.env` file, `dev` stops with `✗ There is no .env file in this folder.` when neither value is in the environment, and `start` with `✗ BOT_TOKEN is not set.` when the token is not.

### Other variables

**NO\_COLOR** `string`

Set to anything to print the symbols without color. Colors are only used when the output is a terminal anyway.

**NODE\_OPTIONS** `string`

Read by Node itself. `--max-old-space-size=<MB>` raises the memory the bot may use: see [Memory](https://www.chapterjs.org/memory.md).

Whether a person is watching (`dev` waits for a fix instead of stopping) is decided by the terminal: both the input and the output must be a terminal.

## Exit codes

| Code | Command | When |
| - | - | - |
| `0` | all | Stopped by `Ctrl+C` or `SIGTERM`, or finished: a build that succeeded, a test that passed, `sync`, `--version`, `--help`. |
| `1` | `dev`, `start` | A problem before connecting (a value of `.env`, the token, the test server or an intent when not waiting, no build, not enough sessions), or Discord refused the bot for good while it ran. Also a second `Ctrl+C`. |
| `1` | `build` | Type errors, a file that can't run, can't be compiled or can't run once compiled. |
| `1` | `test` | A file that can't run, a check or a scenario that failed. |
| `1` | any | An unknown command, or `start` with anything other than `--processes <n>`. |
| `78` | a process started by `start` | Discord refused the bot in that process: the one you started then stops every process and exits with `1`. |

## Symbols

Every line printed by the CLI starts with one of five symbols. Lines that follow the first one of a message are indented under it.

| Symbol | Meaning |
| - | - |
| `✓` | Something worked |
| `ℹ` | Something worth knowing |
| `↻` | A reload or a reconnection |
| `⚠` | Something to look at, that does not stop the bot |
| `✗` | Something failed: what happened, then what to do |

An error in a file of the project is prefixed with its path, and its line when known: `✗ src/commands/ping.ts:4 …`. With several processes, every line of a process starts with its number: `[2] ✓ …`.

## `.chapterjs/`

What the CLI keeps in the project, ignored by git:

| Path | Written by | What it is |
| - | - | - |
| `types/project.d.ts`, `tsconfig.json` | `sync`, `dev`, `build` | What the project adds to the types of `chapterjs`, and the one TypeScript project that covers `src/`. |
| `cache/commands.json`, `cache/commands.global.json` | `dev`, `start` | A fingerprint of the commands last registered on the test server and for everyone, so that nothing is sent when they did not change. |
| `cache/update.json` | `dev` | The latest version npm published, and when it was asked: it is asked again a day later. |
| `build/bot.js`, `build/bot.js.map`, `build/build.json` | `build` | The compiled bot, its map back to `src/`, and what the build was made of. |

The folder can be deleted at any time: `sync` writes the types again, the next `dev` or `start` registers the commands again, and `build` makes a new build.


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