Writing your own style

A style is a folder holding a style.yml and a prompts/ directory. There is no code to write and nothing to register — drop the folder in and it appears in the + New Spec menu beside the built-ins.

  1. Where a style can live
  2. Changing one prompt without forking a style
  3. style.yml, key by key
  4. The four rules that decide everything
    1. 1. A stage is satisfied when its artifacts exist
    2. 2. kind: is either ai or implement
    3. 3. There is no requires: key
    4. 4. gate: manual parks the walk for a human
  5. A prompt’s job
  6. Trying it

Where a style can live

Three places, and the folder name is the style’s id:

Scope Location
workspace <repo>/.local-workflows/styles/<id>/
profile ~/.local-workflows/styles/<id>/
builtin ships with the extension

Workspace wins over profile, which wins over builtin. Put a style in your profile to use it in every repository you open; put it in the workspace to commit it with the project, so the whole team runs the same process.

With a .code-workspace open, “workspace” means the workspace, not a repository. Styles are read from the workspace root’s .local-workflows/styles/, and a style committed inside one of the open repositories is not loaded. That is the same rule as spec placement: with several repositories open, the process is the workspace’s decision rather than each repository’s. See Workspaces.

Every style — built-in included — is parsed by the same code. That is what makes a shipped style and a hand-written one behave identically by construction, and what makes “eject a built-in and modify it” a file copy rather than a code generator.


Changing one prompt without forking a style

You usually do not need a whole style. The definition and the prompts resolve separately: the highest scope holding a style.yml supplies the definition, but every scope holding that id contributes prompts.

So to change how Kiro writes design documents, and nothing else:

.local-workflows/styles/kiro/prompts/design.md

No style.yml. Kiro’s own definition still drives the pipeline; your file replaces that one prompt. You inherit every later fix to the rest of the style instead of freezing a copy of it.


style.yml, key by key

schema: 1

# Names the process this implements. The folder name is the identity;
# this field asserts it.
id: my-process
name: My Process
desc: One line, shown in the style picker.

# NOT a stage. The first document is drafted in a native chat, because a
# conversation gets more out of a person than a form does. Declared here
# so the engine knows which stage a spec lands on when the file appears.
intake:
  prompt: prompts/intake.md
  produces: requirements.md

# What + New Spec offers. A single entry means nobody is asked.
specTypes:
  - id: feature
    label: Feature
    stages: [requirements, design, tasks, implement]
  - id: bug
    label: Bug fix
    stages: [requirements, tasks, implement]

# Read first by every phase: what this process is and that the document,
# not the reply, is the deliverable.
intro: prompts/intro.md

format:
  # Parser-critical rules. Given to every phase.
  grammar: prompts/grammar.md
  # House style, given only to the stage writing that document.
  house:
    requirements: prompts/format-requirements.md
    design: prompts/format-design.md
    tasks: prompts/format-tasks.md

stages:

  - id: requirements
    kind: ai
    produces: [requirements.md]
    gate: manual
    prompt: prompts/requirements.md

  - id: design
    kind: ai
    produces: [design.md]
    gate: manual
    prompt: prompts/design.md

  - id: tasks
    kind: ai
    produces: [tasks.md]
    mayProduce: [notes.md]      # written only when the work calls for it
    gate: manual
    prompt: prompts/tasks.md

  # The engine starts the session and does not wait. No artifacts, so
  # this stage is never satisfied - which makes it terminal.
  - id: implement
    kind: implement
    prompt: prompts/implement.md

For editor completion and hover docs on every key:

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

The four rules that decide everything

Get these and the format stops needing memorisation.

1. A stage is satisfied when its artifacts exist

This one rule does the most work in the whole design. It is why a spec folder someone else wrote resumes at the right phase, why intake can write requirements.md before the pipeline starts, and why re-running a finished phase does nothing.

Its consequence: every stage must leave an artifact. A stage that writes nothing can never be satisfied, so the walk would park on it forever — which is why “review the documents and report” is not a phase.

2. kind: is either ai or implement

ai runs the prompt and waits for the artifacts it declared. An ai stage with no produces is refused at load — it could never complete.

implement starts the session and does not wait. Declare no produces and it can never be satisfied, which makes it terminal — how you say the work for this phase happens somewhere the engine cannot reach. That is what both shipped styles do. Give an implement stage a produces and it becomes satisfiable, and no longer terminal.

A terminal stage must be the last one a spec type visits. Anything listed after it is unreachable, because the walk stops at the first unsatisfied stage — so that is refused at load too, rather than shipping a phase nobody can reach.

3. There is no requires: key

What a stage needs is whatever the prior stages of that spec type produced. Declaring it per stage would state the pipeline twice, and the two copies would eventually disagree.

This is also why a stage can appear in several spec types with different args and no conditionals: in a Bug fix that skips design, the tasks stage simply sees one document instead of two.

4. gate: manual parks the walk for a human

Put the gate on the phase that depends on a document, not on the one that wrote it. What a person approves is “this is good enough to build on” — a judgement made when you are about to rely on it.


A prompt’s job

Prompts are Markdown, and they are handed a specific, bounded context — never the whole folder, never a conversation.

Write a phase prompt about doing its job well. The pipeline, the deliverable-is-the-document rule, and the parser-critical grammar are already supplied by intro: and format.grammar:, to every phase. A prompt that re-explains them is duplicated text that will drift.

Keep an ## Open Questions section in your document format. It is the one hard block in the process: while it holds questions, the next phase will not start.


Trying it

  1. Run Local Workflows: Eject Style and pick a built-in. It copies the style’s files, byte for byte, into the scope you choose — your user profile (~/.local-workflows/styles/, the default, applies everywhere you work) or the workspace (committed with the repo). Existing files are listed and confirmed before anything is overwritten.
  2. To make it a new style rather than a replacement of the built-in, rename the folder and change id: and name: to match.
  3. Edit a prompt, or add a stage.
  4. Set style: my-process in .local-workflows/config.yml.
  5. + New Spec — your style is in the menu.

Starting from a copy rather than a blank file is the fastest path, because the shipped styles are heavily commented with the reasoning behind each key.

An ejected copy stops receiving improvements to the built-in. Kept under its original id it shadows the built-in outright. Reverting is deleting files — each file you remove falls back to the built-in.


Back to top

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