OpenSpec
ReferenceSchemas

schema.yaml

Every field of a schema definition, for reading or writing one.

schema.yaml lists the planning files a workflow creates. It also defines their order and the handoff to implementation.

Location

A project schema lives under openspec/schemas/<name>/:

openspec/schemas/review-first/
├── schema.yaml
└── templates/
    ├── proposal.md
    └── tasks.md

OpenSpec checks three places for that directory. The first match wins.

CopyDirectory
1. Project<project>/openspec/schemas/<name>/
2. User, macOS and Linux~/.local/share/openspec/schemas/<name>/
2. User, Windows%LOCALAPPDATA%\openspec\schemas\<name>\
3. PackageThe schemas installed with the CLI

If XDG_DATA_HOME is set, the user directory moves to $XDG_DATA_HOME/openspec/schemas/<name>/ on every platform.

The directory name is the lookup key used by --schema, config.yaml, and .openspec.yaml. If the name field differs from the directory name, OpenSpec still uses the directory name for lookup.

openspec schema which <name> prints the active directory and any lower-priority copies it hides.

Top-level fields

FieldContract
nameRequired. A non-empty string stored as the schema name. Lookup still uses the directory name.
versionRequired. A positive integer stored as the schema revision. The value doesn't change OpenSpec's behavior.
descriptionAn optional string printed by openspec schemas. With no value, the schema has no description.
artifactsRequired. A non-empty list of artifact entries.
applyOptional apply settings. With no block, OpenSpec uses the apply defaults.

Artifact fields

Each entry under artifacts defines one planning file or set of files.

FieldContract
idRequired. A unique, non-empty string used in dependencies, project rules, commands, and apply settings.
generatesRequired. A relative path or glob telling the agent where to write the artifact inside the change folder.
descriptionRequired. A string that labels the artifact in instructions sent to the agent.
templateRequired. A relative path to the artifact's format in the schema's templates/ folder.
instructionOptional guidance telling the agent what content to produce.
requiresA list of artifact IDs that must be complete first. Default: [].

generates

The path starts from the change folder. For a change named add-auth:

generates: proposal.md

The artifact goes here:

openspec/changes/add-auth/proposal.md

A glob can match several files:

generates: specs/**/*.md

This matches Markdown files below openspec/changes/add-auth/specs/. OpenSpec treats a value containing *, ?, or [ as a glob.

OpenSpec rejects absolute paths and paths containing a .. segment.

Completion

OpenSpec checks whether the output exists. It doesn't read the file to decide whether the artifact is complete.

generates valueComplete when
proposal.mdThat file exists.
specs/**/*.mdThe glob matches at least one file.

template

The path starts from the schema's templates/ folder. In the review-first schema:

template: proposal.md

OpenSpec reads this file:

openspec/schemas/review-first/templates/proposal.md

OpenSpec gives the template's contents to the agent as the output format. It doesn't copy the template into the change folder.

OpenSpec rejects absolute paths and paths containing a .. segment.

requires

  • Dependencies: every ID in requires must name another artifact in the same schema.
  • Ready state: an artifact becomes ready after all its dependencies are complete.
  • Invalid graphs: missing IDs, duplicate IDs, and dependency cycles fail validation.
  • Ties: when several artifacts are ready, their order in artifacts decides which one OpenSpec returns first.

Apply fields

apply defines what must exist before implementation starts.

FieldContract
requiresRequired. A non-empty list of artifacts that must exist before apply instructions become ready.
tracksAn optional relative path to a Markdown task file in the change folder. Default: null.
instructionOptional guidance sent to the agent when apply is ready. OpenSpec uses built-in guidance by default.

Artifact requires controls planning order. apply.requires controls when apply instructions become ready.

tracks

The path starts from the change folder. For a change named add-auth, tracks: tasks.md reads:

openspec/changes/add-auth/tasks.md

Apply stays blocked if that file is missing or contains no checkbox with task text. OpenSpec counts these checkbox forms:

- [ ] Pending task
- [x] Completed task
* [X] Completed task

Leading spaces are allowed. The tasks.md section of the spec-driven page defines the stricter format produced by the default schema.

The tracked file drives the apply state:

  • blocked: the file is missing, or no checkbox has task text.
  • ready: at least one tracked task is pending.
  • all_done: every tracked task is checked.

OpenSpec rejects absolute paths and paths containing a .. segment.

Apply defaults

BehaviorDefault
Required artifactsEvery artifact in the schema
Progress trackingNo tracked file
Agent guidanceBuilt-in apply guidance

Complete example

name: review-first
version: 1
description: Proposal and implementation checklist

artifacts:
  - id: proposal
    generates: proposal.md
    description: Why the change is needed and what it affects
    template: proposal.md
    instruction: |
      Explain the problem, the proposed change, and its impact.
    requires: []

  - id: tasks
    generates: tasks.md
    description: Trackable implementation checklist
    template: tasks.md
    instruction: |
      Break the approved proposal into ordered implementation tasks.
    requires:
      - proposal

apply:
  requires:
    - tasks
  tracks: tasks.md
  instruction: |
    Work through the pending tasks and mark each one complete.

Validation

openspec schema validate <name> checks:

  • Field types and required fields
  • Relative paths
  • Artifact IDs, dependencies, and cycles
  • Template files

Validation doesn't catch these mistakes:

MistakeWhat happens
A field is misspelled, such as instrutionOpenSpec ignores it. Validation doesn't report the typo.
apply.requires names an unknown artifact IDValidation doesn't report the unknown ID.
name differs from the schema directoryValidation passes. OpenSpec still uses the directory name for lookup.

On this page