# bmad-plus intake

> Validate a pack questionnaire, plan the next questions, record answers with their status and render the brief a pack works from. Flags, exit codes, real output and errors.

Canonical: https://bmad-plus.rochetta.fr/docs/reference/cli-intake/
Language: en
BMAD+ version: 0.23.1
Documentation reviewed: 2026-10-19
Author: Laurent Rochetta
License: MIT

BMAD+ documentation › [Reference](https://bmad-plus.rochetta.fr/docs/reference/) › bmad-plus intake

An intake is the list of questions a pack needs answered before it acts. `bmad-plus intake` is the bookkeeper: it checks the questionnaire file, tells the assistant which questions to ask next, records what you said, and renders a brief that becomes the contract for the pack’s next steps. It never asks anything itself and never calls a model: your assistant (the host) asks you in your language, and the command keeps the record. Anyone who drives a pack that ships an intake needs it; in 0.23.0 that is the Design pack (`.agents/skills/pack-design/intake.yaml`, intake `design-read`).

<a id="synopsis"></a>
## Synopsis

**In your project terminal**

```sh
npx bmad-plus intake check FILE [--json]
npx bmad-plus intake plan   --intake FILE --answers FILE [--json]
npx bmad-plus intake record --intake FILE --answers FILE [--set id=VALUE]... [--default id]... [--reset] [--json]
npx bmad-plus intake render --intake FILE --answers FILE --out FILE [--json]
```

**Flags of bmad-plus intake**

| Flag | Argument | Default | What it does |
| --- | --- | --- | --- |
| `<action>` | `check`, `plan`, `record`, `render` | required | Which step to run. |
| `[file]` | path | none | Intake file to validate. Used by `check` only. |
| `-d, --directory <path>` | path | current directory | Project directory. Every other path is relative to it and must stay inside it. |
| `--intake <file>` | path | none | Intake file (the questionnaire). Required by `plan`, `record`, `render`. |
| `--answers <file>` | path | none | Answers file. Created by `record`; required by `plan`, `record`, `render`. |
| `--set <id=VALUE>` | id=VALUE | none | Record an answer. `id=UNKNOWN` marks the question unknown and copies its risk. Repeatable, one per question per call. |
| `--default <id>` | question id | none | Record the proposed default of a question as `defaulted`. Repeatable. |
| `--reset` | none | off | Start the answers file again, empty, for this intake, then apply the `--set` and `--default` of the same call. |
| `--out <file>` | path | none | Brief to write. Required by `render`. |
| `--json` | none | off | Machine-readable output with `schemaVersion: 1` and a `status` field. |

<a id="actions"></a>
## The four actions

**What each action does**

| Action | Purpose | Prints (plain output) |
| --- | --- | --- |
| `check FILE` | Validates an intake file against the contract. | `<file>: valid intake <id> (<pack>), N questions, M must-have.` or `<file>: not a valid intake` followed by one `  - problem` line each. |
| `plan` | Reads the intake and the answers; says whether the pack may start and which questions to ask next (must-haves first, never more than `max_per_message`). | `<id> (<pack>): ready\|not ready — A answered, D defaulted, U unknown, P not asked yet.`, `Must-haves still open: …`, `Ask next (at most N per message):` and one line per question. |
| `record` | Writes answers through the validator: kind, bounds and choices are checked, a value that does not fit is refused. | `Recorded a, b in <answers>.` (or `Reset <answers>…`), then the same lines as `plan`. |
| `render` | Writes the brief from the intake and the answers. | `Brief written to <out> (N bytes); the intake is ready.` or `…; a must-have is still open.` |

<a id="statuses"></a>
### Answer statuses

- `answered`: you gave the value (`--set id=VALUE`). A value you chose is `answered`, even when it equals the default.
- `defaulted`: you let the proposed default stand (`--default id`). The brief labels it a proposal not confirmed by the user.
- `unknown`: you do not know (`--set id=UNKNOWN`). The question’s `risk_if_unknown` is copied into the answers and listed under "Open questions" in the brief.
- A must-have question counts as handled once it is `answered` or `unknown` with its risk. A must-have cannot carry a default; the questionnaire validator refuses one.

<a id="intake-file"></a>
### The intake file

The questionnaire is a YAML file shipped with the pack. Top level fields: `schema_version` (must be 1), `id` and `pack` (lowercase slugs), `title`, optional `language` (`user` or a tag such as `fr`), optional `max_per_message` (integer 1 to 20, 6 when absent) and `sections`. Each section has an `id`, a `title` and `questions`. A question has a snake_case `id`, an `ask`, a `kind` (`text`, `choice` with at least two distinct `choices`, `number` with optional `min` and `max`, `boolean`, `list`), and optionally `must_have`, `default`, `feeds` (artifact anchors such as `brief.md#surface`) and `risk_if_unknown`. A must-have needs `risk_if_unknown` and refuses `default`. Unknown fields are refused.

<a id="reads-writes"></a>
## What it reads and writes

- Reads: the intake file and, for `plan`, `record` and `render`, the answers file. Each file is limited to 1 MiB (1,048,576 bytes) and must be a regular file.
- Writes: `record` writes the answers file (JSON, atomic write through a temporary file); `render` writes the brief. Nothing else.
- Keeps out of: `.git/`, `_bmad/`, `.bmad-plus/` and `node_modules/` at any depth; a path that leaves the project; any path through a symlink.
- `record` overwrites only an answers file that belongs to the same intake id. `render` overwrites only a brief it wrote before for the same intake (the second line of the file is the ownership marker).
- No network access, no process spawned, no model called.

<a id="exit-codes"></a>
## Exit codes

**Exit codes of bmad-plus intake**

| Code | Meaning |
| --- | --- |
| 0 | `check`: the file is valid. `plan`: ready, every must-have is answered or unknown with its risk. `record` and `render`: done. |
| 1 | Any error (printed as `Intake: <message>`), or `check` found the file invalid. |
| 2 | `plan` only: not ready, at least one must-have is still open. |

<a id="real-output"></a>
## Real output

These four transcripts come from the human acceptance run of 0.23.0 (Design pack installed in a demo app). The `npm notice` lines and the shell prompt are removed; the output is otherwise unchanged. The `plan` before any answer exits with 2.

**Validate the Design pack questionnaire**

```text
$ npx bmad-plus intake check .agents/skills/pack-design/intake.yaml --directory .\demo-app
.agents/skills/pack-design/intake.yaml: valid intake design-read (design), 13 questions, 3 must-have.
```

Output captured from a real run. Source: Captured during the 0.23.0 acceptance run, 2026-10-18 (step 4)

**Plan before any answer (exit code 2)**

```text
$ npx bmad-plus intake plan --intake .agents/skills/pack-design/intake.yaml --answers _bmad-output/design/intake.json --directory .\demo-app
design-read (design): not ready — 0 answered, 0 defaulted, 0 unknown, 13 not asked yet.
Must-haves still open: surface_kind, audience, job
Ask next (at most 6 per message):
  - surface_kind [choice] Which surface is this? A marketing landing page, a dashboard, a data table, a form, an auth or onboarding flow, a mobile screen, an email, a chat or AI surface, a checkout, a settings page, or something else? (must-have; choices: landing, dashboard, table, form, auth, onboarding, mobile, email, ai-chat, checkout, settings, other)
  - audience [text] Who uses it, and in what situation (device, time pressure, expertise, frequency)? (must-have)
  - job [text] What is the one job this page must get done, and how will you know it did? (must-have)
  - brand_assets [choice] Which brand assets exist already? None, a partial set (a logo and a colour or two), or a full kit (logo, palette, type, voice)? (choices: none, partial, full)
  - design_system [choice] Is a design system or component library already in use? (choices: none, shadcn, radix, mantine, material, fluent, carbon, polaris, other; default: "none")
  - aesthetic_family [choice] Does the brief imply an aesthetic family? Minimalist, brutalist, soft editorial, premium dense, or none in particular? (choices: minimalist, brutalist, soft-editorial, premium-dense, none; default: "none")
```

Output captured from a real run. Source: Captured during the 0.23.0 acceptance run, 2026-10-18 (step 5)

**Record three answers**

```text
$ npx bmad-plus intake record --intake .agents/skills/pack-design/intake.yaml --answers _bmad-output/design/intake.json --set surface_kind=dashboard --set "audience=Comptables en cabinet, sur ordinateur, en fin de mois" --set "job=Repérer les factures en retard et relancer en un clic" --directory .\demo-app
Recorded surface_kind, audience, job in _bmad-output/design/intake.json.
design-read (design): ready — 3 answered, 0 defaulted, 0 unknown, 10 not asked yet.
Ask next (at most 6 per message):
  - brand_assets [choice] Which brand assets exist already? None, a partial set (a logo and a colour or two), or a full kit (logo, palette, type, voice)? (choices: none, partial, full)
  - design_system [choice] Is a design system or component library already in use? (choices: none, shadcn, radix, mantine, material, fluent, carbon, polaris, other; default: "none")
  - aesthetic_family [choice] Does the brief imply an aesthetic family? Minimalist, brutalist, soft editorial, premium dense, or none in particular? (choices: minimalist, brutalist, soft-editorial, premium-dense, none; default: "none")
  - variance [number] Layout variance, from 1 (symmetric and safe) to 10 (asymmetric and bold)? Leave it open and Atelier sets it from the surface.
  - motion [number] Motion, from 1 (static) to 10 (choreographed)? Leave it open and Atelier sets it from the surface.
  - density [number] Density, from 1 (gallery-sparse) to 10 (cockpit-packed)? Leave it open and Atelier sets it from the surface.
```

Output captured from a real run. Source: Captured during the 0.23.0 acceptance run, 2026-10-18 (step 5)

**Render the brief and read its first lines**

```text
$ npx bmad-plus intake render --intake .agents/skills/pack-design/intake.yaml --answers _bmad-output/design/intake.json --out _bmad-output/design/brief.md --directory .\demo-app
Brief written to _bmad-output/design/brief.md (3022 bytes); the intake is ready.
$ Get-Content .\demo-app\_bmad-output\design\brief.md -TotalCount 3
# Design read
<!-- owned by bmad-plus intake design-read; written by bmad-plus intake render, do not edit -->
```

Output captured from a real run. Source: Captured during the 0.23.0 acceptance run, 2026-10-18 (step 5)

How to read it: after three answers, `plan` says `ready` because only the three must-haves (`surface_kind`, `audience`, `job`) block the pack; the other ten questions stay optional and `plan` keeps offering them, six at a time. The brief’s second line is the ownership marker: `render` will overwrite this file again, and refuse any other file at that path.

<a id="errors"></a>
## Errors and what to do

**Messages printed by bmad-plus intake**

| Message | Cause | What to do |
| --- | --- | --- |
| `Intake: --intake is required for intake plan` (same for `--answers`, `--out`) | A required flag is missing. | Add the flag named in the message. |
| `Intake: Use intake check FILE.` | `check` was run without a file. | Pass the intake file: `intake check .agents/skills/pack-design/intake.yaml`. |
| `Intake: Use intake check FILE, plan, record or render.` | Unknown action. | Use one of the four actions. |
| `<file>: not a valid intake` + `  - …` lines (exit 1) | The questionnaire breaks the contract, for example an unknown field or a must-have without `risk_if_unknown`. | Fix each listed problem in the intake file, then run `check` again. For a pack’s own file, reinstall or update the pack. |
| `Intake: nothing to record: pass --set id=VALUE, --default id or --reset` | `record` without anything to record. | Pass `--set`, `--default` or `--reset`. |
| `Intake: --set expects id=VALUE, got "…"` | The assignment has no `=`. | Write `--set id=VALUE`. |
| `Intake: question "x" is set twice in one call` | The same question appears twice in `--set`/`--default`. | Give each question once per call. |
| `Intake: no question "x" in intake "y"` | The id is not in the questionnaire. | Copy the id from `plan` output. |
| `Intake: question "x" has no default` | `--default` on a question without a default. | Use `--set x=VALUE` or `--set x=UNKNOWN`. |
| `Intake: x: value must be one of …` (or `needs a finite number`, `must be at least N`, `needs true or false`, …) | The value does not fit the question kind or bounds. | Ask the person again and record a value that fits. Nothing was written. |
| `Intake: <answers> does not answer this intake: …` + `Record again with --reset to start over.` | The answers file no longer fits the questionnaire (it changed after answers were recorded). | Run `record --reset`, then ask the questions again. |
| `Intake: <file>: exists and belongs to "other", not to intake "y"; move it away or pick another path` | The answers path holds another intake’s file. | Choose another `--answers` path. |
| `Intake: <file>: exists and is not a brief of intake "y" (its second line is not the ownership marker); move it away or pick another path` | `render` refuses to overwrite a file it did not write. | Choose another `--out` path or move the file. |
| `Intake: <file>: the intake never writes under _bmad/` (also `.git/`, `.bmad-plus/`, `node_modules/`) | The output path is in a reserved tree. | Write the answers and the brief elsewhere, for example under `_bmad-output/`. |
| `Intake: <file>: outside the project directory <root>` | The path leaves the project. | Use a path inside the project, or change `--directory`. |

<a id="examples"></a>
## Examples

<a id="example-cli-intake-design-read"></a>
### Ask first, then build: the design read

Design pack installed. The agent Atelier runs the intake through this command, so you answer in plain language and never type the commands yourself.

**In your AI assistant**

```text
Atelier, run the design read for the invoice list of my app, then build the screen.
```

**What you should get** The assistant runs `intake plan`, gets exit code 2 with the three open must-haves (`surface_kind`, `audience`, `job`) and asks you those first, at most six questions per message. It records your replies with `intake record`, checks that `plan` now says `ready`, and renders `_bmad-output/design/brief.md` with `intake render`. The brief lists each answer with its status; anything you left open appears under "Open questions" with its risk. The build then starts from that brief.

<a id="example-cli-intake-unknown-risk"></a>
### Saying "I do not know" on purpose

You can proceed without an answer to a must-have, but the risk stays attached to it.

**In your AI assistant**

```text
Atelier, I do not know who will use this screen yet. Record it as unknown and continue.
```

**What you should get** The assistant records the question with `--set audience=UNKNOWN`. The answers file stores status `unknown` and copies the question’s `risk_if_unknown`; `plan` counts that must-have as handled, but the pack starts only once the other two must-haves, `surface_kind` and `job`, are also answered or unknown with their risk. The brief shows “Answer: unknown” with the risk, and repeats it in “Open questions”. It does not invent an audience.

**See also**

- [bmad-plus swarm: run a swarm after the intake](https://bmad-plus.rochetta.fr/docs/reference/cli-swarm/)
- [bmad-plus nexus: durable runs](https://bmad-plus.rochetta.fr/docs/reference/cli-nexus/)
- [CLI overview and exit codes](https://bmad-plus.rochetta.fr/docs/reference/cli-overview/)
- [Project layout: where answers and briefs live](https://bmad-plus.rochetta.fr/docs/reference/project-layout/)

[BMAD+ documentation](https://bmad-plus.rochetta.fr/docs/) · [Reference](https://bmad-plus.rochetta.fr/docs/reference/)

[Source on GitHub](https://github.com/lrochetta/BMAD-PLUS)
