config.yml

Every setting spec-driven development reads, in one file: .local-workflows/config.yml.

  1. The file is optional
  2. The keys
  3. style
  4. specRoot
  5. source
  6. checkpoints
  7. ai: — what runs the AI phases
  8. ai.stages: — one phase, different settings
  9. Every error the file can raise

The file is optional

Every key has a default. A fresh install writes nothing and works — a missing file, an empty file, and a file of comments all mean “the defaults”. You only create it to change something.

The file is committed, so the whole team runs the same process on the same settings.

It never reaches an AI. The extension reads it and hands each phase only the values that phase needs. Model choice, style id, and source settings stay in the engine.

For editor completion and hover docs on every key, put this on the first line:

# yaml-language-server: $schema=https://local-workflows/schemas/sdd-config.schema.json

The keys

style: kiro             # which process runs
specRoot: .local-workflows/specs
source: ado             # manual | ado | gh
checkpoints: required   # required | optional | none

ai:
  uses: ai@1            # what runs the AI phases
  provider: ghcp        # passed to the plugin, like every key below
  model: auto
  stages:               # per-phase overrides, keyed by phase id
    design:
      model: claude-opus-5
      thinking: high
Key Values Default
style kiro, spec-kit, or a style you wrote kiro
specRoot a path inside the repository .local-workflows/specs
source manual | ado | gh unset — + New Spec asks each time
checkpoints required | optional | none required
ai.uses a plugin reference ai@1
ai.<anything else> passed to the plugin as an arg model: auto is the only default
ai.stages.<id> the same keys, for one phase

style

The process: its phases, its gates, its prompts, and the spec types in the + New Spec menu. kiro and spec-kit ship; your own works the same way.


specRoot

Where spec folders live, relative to the repository.

Two spellings are refused when the file is read:

  • An absolute path — D:\specs or /specs. Specs live in the repository because the whole point is that process state travels with git; a root outside it would put half the state somewhere no teammate clones.
  • A path with .. that climbs out of the repository — refused for the same reason.

Backslashes are accepted and read as /, so a Windows-style relative path works.

In a .code-workspace, specRoot: is ignored. One feature spanning five repositories is one spec, not five, so placement becomes the workspace’s decision — localWorkflows.specRoot in the workspace file, which unlike this key may point anywhere, including outside the workspace. Every other key on this page still applies. See Workspaces.


source

Where the work item behind a spec comes from: written by hand (manual), Azure DevOps (ado), or GitHub (gh).

This is the one key with no default on purpose. Unset means the file does not say, and + New Spec asks each time — which is the difference between a team that has standardised and one that has not. A default would answer a question nobody was asked, and make the setting impossible to leave open.


checkpoints

Whether the plan gets “run the tests and stop” barriers between groups of tasks. Read by the tasks prompt when the plan is written; nothing else branches on it.


ai: — what runs the AI phases

uses: names the plugin, ai@1 by default. Every other key in the block is passed straight to that plugin as an argprovider, model, thinking, and whatever the provider adds next quarter. The config file does not keep a list of allowed keys, so a switch the plugin grows never waits for an extension release; the plugin validates its own args.

Two defaults are worth knowing:

  • model: auto — the provider picks. A pinned model name goes stale, and a team that has not formed an opinion should not be made to hold one.
  • provider has no default here — ai@1’s own manifest defaults it to ghcp. Writing it here again would leak it: a phase that overrides uses: to a different plugin inherits the file-level args, and would receive a provider that plugin never declared.

ai.stages: — one phase, different settings

Overrides keyed by phase id — the same ids format.house uses in a style.

ai:
  model: auto
  stages:
    design:
      thinking: high

The merge is per key, not per block: design above gets thinking: high and keeps model: auto. Naming one setting never silently drops the others. A stage may also override uses: to run a different plugin entirely.


Every error the file can raise

All of these are raised when the file is read, not in the middle of a run:

The file says The error
anything that is not valid YAML config.yml is not valid YAML: ...
a list, or a bare value, at the top config.yml must be a mapping of settings, e.g. 'style: kiro'.
style: or ai.uses: that is not text '...' must be text.
a source: or checkpoints: value not in its list expected one of ...
an absolute specRoot: spec folders live in the repository.
a specRoot: with .. climbing out climbs out of the repository.
an ai: or ai.stages: entry that is not a mapping '...' must be a mapping.

A key the file does not know is not an error here — unknown keys under ai: are plugin args by design. The schema line at the top of this page is what flags a genuinely misplaced key while you type.


Back to top

Local Workflows is a VS Code extension. Everything it does is declared in a YAML file you own.