Skip to content

OpenSpec mode

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

ModeWhat the agent writesWhen you get it
openspecStructured files under openspec/changes/<slug>/, mirrored into draftsDefault when OpenSpec is usable
liteChorus-native local specs under .chorus/specs/<slug>/Default when OpenSpec is not usable
offFree-form drafts, no local spec files at allOnly when you ask for it

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

RuntimeWhen it resolves and where to check
Claude Code, Codex, Kiro, PiAt session start (Kiro: agent spawn); the injected ## Spec Mode context states the result.
dshAt plugin load; the first agent step receives the ## Spec Mode context.
OpenClawWhen a stage skill reaches its spec-mode step, using the shipped resolver. There is no SessionStart injection. 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 the absence of a connection toast.

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).
  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 like unset, with an explanation; use one of the three exact values above. The standalone skill distribution does not include spec-mode routing and continues to author free-form.

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

Terminal window
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.

What changes in proposal, develop, and yolo

Section titled “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 a later run can recover the change, the proposal description carries one exact line:

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 exact contract (its halt-on-error rules and post-approval re-sync) lives in the authoritative sources rather than being reproduced here — see docs/OPENSPEC_MODE.md and the plugin skill public/chorus-plugin/skills/openspec-aware/SKILL.md.

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:

Terminal window
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.

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:

    Terminal window
    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:

    Terminal window
    export CHORUS_OPENSPEC_MODE=off

Note what the last two now mean: they 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.

  • 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 public/skill/ distribution does not support spec modes.
  • Cite. public/chorus-plugin/bin/resolve-spec-mode.sh (the single-source resolution contract), docs/OPENSPEC_MODE.md (user-facing summary), and the authoritative skills public/chorus-plugin/skills/openspec-aware/SKILL.md (Claude Code) and plugins/chorus/skills/openspec-aware/SKILL.md (Codex).