The spec-enabled Chorus plugins resolve a **spec mode** — the shape proposal authoring takes.
OpenSpec mode is one of three, and it is the default whenever OpenSpec is usable in the
repository you are working in. When it is active, the
[AI-DLC workflow](/guides/ai-dlc-workflow/) still runs exactly as usual, but instead of
free-form Markdown typed straight into Chorus, the agent writes structured files on disk with
the [`openspec`](https://github.com/Fission-AI/OpenSpec) CLI and mirrors them into your
proposal's document drafts. The local files are the working copy; the Chorus drafts are a
faithful mirror your reviewers read on the proposal page.

## The three spec modes

| Mode | What the agent writes | When you get it |
| --- | --- | --- |
| `openspec` | Structured files under `openspec/changes/<slug>/`, mirrored into drafts | Default when OpenSpec is usable |
| `lite` | [Chorus-native local specs](/guides/spec-lite-mode/) under `.chorus/specs/<slug>/` | Default when OpenSpec is not usable |
| `off` | Free-form drafts, no local spec files at all | Only when you ask for it |

All six spec-enabled plugins use the same resolution rules, but resolve and show the mode
at different points:

| Runtime | When it resolves and where to check |
| --- | --- |
| Claude Code, Codex, Kiro, Pi | At session start (Kiro: agent spawn); the injected `## Spec Mode` context states the result. |
| dsh | At plugin load; the first agent step receives the `## Spec Mode` context. |
| OpenClaw | When a stage skill reaches its spec-mode step, using the shipped resolver. It does not add spec-mode context at session start. Run `/chorus spec` or `/chorus status` to inspect the mode. |

For example, a resolved OpenSpec mode is reported as `CHORUS_SPEC_MODE=openspec`.
Do not infer a mode from whether a connection notice appeared.

## How the mode is chosen

In precedence order:

1. **An explicit `CHORUS_SPEC_MODE` wins.** Set it to `openspec`, `lite`, or `off` to pin the
   mode for a shell, a repository, or a CI job.
2. **Otherwise OpenSpec is the default whenever it is usable.** Usable means all three of: an
   `openspec/` directory at the repository root (created by `openspec init`), the `openspec`
   CLI on your `PATH`, and OpenSpec not switched off (see
   [Choose a different mode](#choose-a-different-mode)).
3. **Otherwise you get `lite`** — the Chorus-native fallback, which needs nothing installed.

If you pin `CHORUS_SPEC_MODE=openspec` in a place where OpenSpec is not usable, the session
reports that the requested mode cannot be honored, and the workflow **stops** rather than
quietly authoring something else.

Fix the cause (install the CLI, run `openspec init`, or re-enable OpenSpec) or pick a mode
that works. A mode you asked for is never silently downgraded.

Unrecognized `CHORUS_SPEC_MODE` values are treated as if unset, with an explanation; use one
of the three exact values above. The standalone skill distribution does not include spec-mode
routing and keeps writing free-form documents.

## Install and initialize

OpenSpec is a Node CLI from Fission AI. Install it globally, then initialize the repository
where the agent authors proposals:

```bash
npm install -g @fission-ai/openspec
openspec init
```

`openspec init` creates the `openspec/` working directory (`changes/`, `specs/`, config, and
instruction files). Restart sessions that resolve at startup; reload the dsh plugin for
load-time settings. OpenClaw resolves again at the next spec-mode step. The process doing
the resolution must see both the `openspec/` directory and the CLI.

For plugin installation, see the [agent platforms reference](/reference/agents/).

## What changes in proposal, develop, and yolo

With the mode active, the proposal, develop, and yolo skills author a change on disk under a
kebab-case slug and mirror three file types into your Chorus proposal's document drafts:

- **PRD:** `openspec/changes/<slug>/proposal.md`
- **Tech design:** `openspec/changes/<slug>/design.md`
- **Spec (one per capability):** `openspec/changes/<slug>/specs/<capability>/spec.md`

`openspec/changes/<slug>/tasks.md` is **not** mirrored: Chorus task drafts are the source of
truth for tasks, so the OpenSpec task list is left on disk.

So that a later run can recover the change, the proposal description carries one exact line:

```text
OpenSpec change slug: <slug>
```

The mirror is byte-faithful — the plugin streams each file's bytes into the draft rather than
re-typing the content through the model, which keeps the local file and the Chorus draft
identical. You do not run this yourself; the plugin's skill handles it with the native MCP
client, `chorus mcp call <tool> --arg-file content=<file>`, and falls back to the legacy
`chorus-api.sh` / `chorus-mcp-call.sh` wrappers only when the `chorus` CLI is not on `PATH`.
The plugin's OpenSpec skill defines the exact contract, including its halt-on-error rules and
post-approval re-sync.

## When `openspec archive` runs

`openspec archive` is deferred to the very end of the change. After the **last** task of the
change is verified, the agent follows its runtime's hook reminder or skill instructions to run:

```bash
openspec archive <slug>
```

Archiving moves the change out of `openspec/changes/` and merges its spec deltas into the
long-term specs under `openspec/specs/`. The plugin then mirrors the updated
`openspec/specs/<capability>/spec.md` files back into the matching Chorus documents. Until
that point the change stays in flight and Chorus only ever sees the delta spec, so there is
no half-merged state to reason about.

## Choose a different mode

Three switches, in precedence order:

1. **`CHORUS_SPEC_MODE`** (all runtimes). The direct control — it names the mode you want
   instead of describing what to avoid:

   ```bash
   export CHORUS_SPEC_MODE=lite   # Chorus-native local specs
   export CHORUS_SPEC_MODE=off    # free-form, no local spec files
   ```

2. **`enableOpenSpec` userConfig toggle** (Claude Code plugin only, default on). Set it to
   off in the plugin's install configuration to make OpenSpec unusable plugin-wide, including
   the archive reminder.
3. **`CHORUS_OPENSPEC_MODE=off` environment variable** (all runtimes). The older, per-shell
   OpenSpec opt-out, still honored:

   ```bash
   export CHORUS_OPENSPEC_MODE=off
   ```

Note that the last two make OpenSpec *unusable*, which lands the session on
`lite` rather than on free-form. If you want no local spec files at all, ask for `off`
explicitly. Either way, an existing `openspec/` directory is left on disk untouched and new
proposals get no OpenSpec slug line.

## For agents

- **Triggers.** The proposal, develop, and yolo skills consume the runtime's resolved
  `CHORUS_SPEC_MODE`. Use injected `## Spec Mode` context where provided. OpenClaw instead
  runs the shipped resolver at each spec-mode step; without injected context on other
  runtimes, follow that runtime's skill fallback. Never reimplement the resolution rule
  from prose. `CHORUS_OPENSPEC_ACTIVE=1` indicates a usable `openspec`; on `lite` follow
  spec-lite, on `off` author inline. If explicit `openspec` cannot be honored, **halt** —
  do not fall back. After the last task is verified, follow the runtime's hook or skill
  instructions for `openspec archive <slug>`; do not assume every runtime has PostToolUse.
- **Constraints.** Every document-draft mirror call must go through
  `chorus mcp call <tool> '<json>' --arg-file content=<file>` (the native MCP client) with the
  file's bytes streamed verbatim — falling back to the legacy `chorus-api.sh mcp-tool` /
  `chorus-mcp-call.sh` wrappers only when `chorus` is not on `PATH`. Never re-type document
  content inline, and halt on any error. Do not mirror `tasks.md`. The proposal description
  must carry the exact line `OpenSpec change slug: <slug>`. When the mode is not `openspec`,
  do not scaffold `openspec/changes/` and do not add the slug line. The standalone
  skill distribution does not support spec modes.
