# CLI

The `recit` command is provided by `@recit/cli`:

```bash
pnpm add -D @recit/cli
npx recit --help
```

## Commands

| Command                       | Purpose                                                                                                      |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `recit init [file]`           | creates a starter deck and a `cover.svg` image; `--format motion` creates a starter film (`story.md`)        |
| `recit dev [file]`            | development server with hot reload; a motion story gets the video preview                                    |
| `recit build [file]`          | static site (`index.html` + `assets/`)                                                                       |
| `recit export [file]`         | PDF, one page per slide                                                                                      |
| `recit export [file] --html`  | single HTML file, no network dependency                                                                      |
| `recit render <file>`         | motion story or `film.json` to MP4, with Remotion (needs `@recit/motion-render`)                             |
| `recit convert <file>`        | Markdown story to its typed JSON (`kind: "story"`) and back; a motion story to and from its `film.json`      |
| `recit validate <files...>`   | checks stories of every format: JSON against its schema (JSON path), Markdown through its JSON (line)        |
| `recit dur <file>`            | duration of a motion story, per scene and in total                                                           |
| `recit extract [kind] <file>` | motion deck from data, deterministic: `rollup` (bundle stats, default) or `handover` (an agent's scene list) |
| `recit schema [name]`         | prints a JSON Schema, for editors (`story` by default)                                                       |
| `recit mcp serve`             | MCP server for agents, over stdio (needs `@recit/mcp`). `--root <dir>` bounds what it may read and write     |
| `recit i18n check [dir]`      | parity of every story's languages: same scenes, same structure, translated text                              |
| `recit i18n status [dir]`     | translated scenes per story and language                                                                     |
| `recit i18n extract <file>`   | writes `<story>.<locale>.json`, a companion with every text to translate                                     |

The file defaults to `slides.md` (`story.md` for `init --format motion`); `.mdx` and JSON stories
(`kind: "story"`) are accepted everywhere. The motion commands (`render`, `dur`, and `dev`,
`convert`, `validate` on a motion story) also accept a motion render model (`<name>.film.json`).

## Options

| Option                | Commands                                           | Default                                                    | Effect                                                                               |
| --------------------- | -------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `-c, --config <path>` | dev, build, export, render, convert, validate, dur | —                                                          | explicit configuration (otherwise `recit.config.*` is looked up in parent folders)   |
| `-p, --port <port>`   | dev                                                | `3000`                                                     | server port                                                                          |
| `--host <host>`       | dev                                                | `localhost`                                                | listening address                                                                    |
| `--open`              | dev                                                | —                                                          | opens the browser                                                                    |
| `--remote`            | dev                                                | —                                                          | [smartphone remote](/formats/deck/smartphone-remote) (local network, QR code, token) |
| `-o, --output <dir>`  | build                                              | `./dist`                                                   | output folder                                                                        |
| `--base <path>`       | build                                              | `./`                                                       | public URL prefix, to host the deck in a sub-folder                                  |
| `--no-strict`         | build                                              | —                                                          | does not fail on `enforceAntiOverload` errors                                        |
| `-o, --output <file>` | export                                             | `<deck>.pdf` or `<deck>.standalone.html`, next to the deck | output file                                                                          |
| `--html`              | export                                             | —                                                          | exports a self-contained HTML file instead of a PDF                                  |
| `--notes`             | export                                             | —                                                          | PDF: speaker notes page after each slide                                             |
| `--theme <mode>`      | export                                             | deck default                                               | PDF: `light` or `dark`                                                               |
| `--format <format>`   | init                                               | `deck`                                                     | `deck` (slides) or `motion` (a film; a `.json` file gives a `film.json`)             |
| `--config`            | init                                               | —                                                          | also creates `recit.config.ts`                                                       |
| `--force`             | init                                               | —                                                          | overwrites existing files                                                            |
| `--locale <locale>`   | dev, build, export                                 | file suffix, else `i18n.defaultLocale`                     | language to show, in a multilingual project (`slides.fr.md`, `slides.fr.json`)       |
| `--to <format>`       | convert                                            | the other one (`md` for a `film.json`)                     | `json` (typed story), `md` (Markdown story) or `film` (motion `film.json`)           |
| `-o, --output <file>` | convert                                            | standard output                                            | output file                                                                          |
| `--locale <locale>`   | convert                                            | `meta.lang`                                                | JSON → Markdown: language of the `{ "en": …, "fr": … }` values                       |
| `--json`              | validate, dur                                      | —                                                          | machine-readable output                                                              |
| `--aspect <aspect>`   | render, extract                                    | the story's                                                | `16:9`, `1:1` or `9:16`                                                              |
| `-o, --output <path>` | render                                             | `out/`                                                     | a `.mp4` file, or a folder that gets `<story>.mp4`                                   |
| `-o, --output <file>` | extract                                            | standard output                                            | a `film.json`, or a `.md` file for a Markdown story                                  |
| `--theme <theme>`     | extract                                            | `warm-editorial`                                           | theme of the deck                                                                    |
| `-o, --output <file>` | schema                                             | standard output                                            | output file                                                                          |
| `--strict`            | i18n check                                         | `i18n.strict`                                              | untranslated text is an error, not a warning                                         |
| `--locale <locale>`   | i18n extract                                       | —                                                          | target language (required)                                                           |
| `-c, --config <path>` | i18n                                               | —                                                          | explicit configuration                                                               |

## Examples

```bash
npx recit init talk.md --config
npx recit dev talk.md --port 4000 --open
npx recit build talk.md -o public/talk --base /talk/
npx recit export talk.md --notes --theme light -o talk.pdf
npx recit export talk.md --html -o talk.html
npx recit convert talk.md -o talk.json
npx recit validate talk.json talk.md
npx recit build talk.md --locale fr -o dist/fr
npx recit i18n extract talk.md --locale de
npx recit i18n check
```

Motion:

```bash
npx recit init --format motion
npx recit dev story.md
npx recit validate story.md
npx recit dur story.md
npx recit render story.md --aspect 1:1 --output out/
npx recit convert film.json -o story.md
npx recit convert story.md --to film -o film.json
npx recit extract handover scenes.json -o story.md
npx recit schema motion-film -o film.schema.json
claude mcp add recit -- npx recit mcp serve
```

## JSON and languages

Every Markdown story has a typed JSON equivalent. `recit convert` writes it in its canonical form,
with a `$schema` (`https://recit.dev/schema/v1/<format>.json`) for completion in editors. Both
compile to the same story, scene ids included.

Next to `talk.md`:

- `talk.json` with `"kind": "sidecar"` completes the story by scene id (fields, `data`, `strings`
  inserted with `:t[key]`);
- in a multilingual project (an `i18n` section in `recit.config`), `talk.fr.md` is the French
  variant and `talk.fr.json` a French companion. A missing language falls back to the default one.

`recit i18n check` fails when a variant has missing, extra or reordered scenes, or different
structural attributes (`layout`, `cols`…). Text identical to the default language is a warning, an
error with `--strict` or `i18n.strict`. Without an `i18n` section, there is nothing to check.

## Motion

A motion story (`format: motion`, see [Motion](/formats/motion)) is written in Markdown, in its
typed JSON, or as a motion render model (`<name>.film.json`). Every command reads them the same way,
through `parseDeck`, so an error names the line of the scene
(`story.md:14 (stat): label is required`) or its JSON pointer.

- `recit dev story.md` opens a browser preview that plays the film with the blocks engine of
  `@recit/motion-blocks` and the scene timing of `recit dur`. Space plays or pauses, ← and → change
  scene, R restarts, F goes full screen. Saving the story or `recit.config` reloads it in place.
  Relative media (`src: assets/logo.svg`) load from the story folder. `?scene=<n or id>` opens a
  scene, `?settled=1` shows its final state, paused.
- `recit render` loads `@recit/motion-render` on demand. It pulls in Remotion and a headless Chrome,
  so it is an optional package: install it next to the CLI (`pnpm add -D @recit/motion-render`).
  Without it, `recit render` says what to install.
- `recit mcp serve` starts the server of `@recit/mcp`, also optional, on stdio. Its tools read and
  write only inside one root — the current directory, or `--root <dir>`. A path that climbs out of
  it, points at a hidden file or has an unexpected extension is refused: an agent acts on content it
  did not write, so a path it passes is untrusted input.
- `recit convert` writes a `film.json` as its canonical Markdown story: the whole story is
  regenerated, so comments and layout are not kept.

## Exit codes

The exit code is `1` when the file is missing, compilation fails, the port is busy, Playwright is
missing (PDF), an optional package is missing (`render`, `mcp serve`), `build` hits a blocking
density error (see [Density rules](/formats/deck/density-rules)), or `validate` and `i18n check`
find an error.
