docs: add workflows reference, reorganize into docs/reference/, and add --version flag (#2244)

* docs: add workflows reference, reorganize into docs/reference/, and add --version flag

- Move integrations.md, extensions.md, presets.md into docs/reference/
- New docs/reference/workflows.md: command reference for all workflow
  commands, built-in SDD Cycle workflow with Mermaid diagram, step types,
  expressions, input types, state/resume, and FAQ
- Rename workflow input feature_name to spec with prompt 'Describe what
  you want to build' to match speckit.specify command terminology
- Add --version / -V flag to root specify command with tests
- Update docs/toc.yml, README.md links, and docs/upgrade.md cross-reference
  to use reference/ paths
- Add workflow command to README CLI reference table

* docs: update speckit_version requirement to >=0.7.2 in workflow example
This commit is contained in:
Manfred Riem
2026-04-16 13:34:08 -05:00
committed by GitHub
parent 8d2797dc03
commit 02a1d610df
14 changed files with 369 additions and 34 deletions

View File

@@ -316,7 +316,7 @@ Community projects that extend, visualize, or build on Spec Kit:
## 🤖 Supported AI Coding Agent Integrations
Spec Kit works with 30+ AI coding agents — both CLI tools and IDE-based assistants. See the full list with notes and usage details in the [Supported AI Coding Agent Integrations](https://github.github.io/spec-kit/integrations.html) guide.
Spec Kit works with 30+ AI coding agents — both CLI tools and IDE-based assistants. See the full list with notes and usage details in the [Supported AI Coding Agent Integrations](https://github.github.io/spec-kit/reference/integrations.html) guide.
Run `specify integration list` to see all available integrations in your installed version.
@@ -367,6 +367,7 @@ and supports the following commands:
| `extension` | Manage extensions |
| `preset` | Manage presets |
| `integration` | Manage integrations |
| `workflow` | Run, manage, and search workflows. See the [Workflows reference](https://github.github.io/spec-kit/reference/workflows.html) |
### `specify init` Arguments & Options
@@ -510,7 +511,7 @@ specify extension add <extension-name>
For example, extensions could add Jira integration, post-implementation code review, V-Model test traceability, or project health diagnostics.
See the [Extensions reference](https://github.github.io/spec-kit/extensions.html) for the full command guide. Browse the [community extensions](#-community-extensions) above for what's available.
See the [Extensions reference](https://github.github.io/spec-kit/reference/extensions.html) for the full command guide. Browse the [community extensions](#-community-extensions) above for what's available.
### Presets — Customize Existing Workflows
@@ -526,7 +527,7 @@ specify preset add <preset-name>
For example, presets could restructure spec templates to require regulatory traceability, adapt the workflow to fit the methodology you use (e.g., Agile, Kanban, Waterfall, jobs-to-be-done, or domain-driven design), add mandatory security review gates to plans, enforce test-first task ordering, or localize the entire workflow to a different language. The [pirate-speak demo](https://github.com/mnriem/spec-kit-pirate-speak-preset-demo) shows just how deep the customization can go. Multiple presets can be stacked with priority ordering.
See the [Presets reference](https://github.github.io/spec-kit/presets.html) for the full command guide, including resolution order and priority stacking.
See the [Presets reference](https://github.github.io/spec-kit/reference/presets.html) for the full command guide, including resolution order and priority stacking.
### When to Use Which

289
docs/reference/workflows.md Normal file
View File

@@ -0,0 +1,289 @@
# Workflows
Workflows automate multi-step Spec-Driven Development processes — chaining commands, prompts, shell steps, and human checkpoints into repeatable sequences. They support conditional logic, loops, fan-out/fan-in, and can be paused and resumed from the exact point of interruption.
## Run a Workflow
```bash
specify workflow run <source>
```
| Option | Description |
| ------------------- | -------------------------------------------------------- |
| `-i` / `--input` | Pass input values as `key=value` (repeatable) |
Runs a workflow from a catalog ID, URL, or local file path. Inputs declared by the workflow can be provided via `--input` or will be prompted interactively.
Example:
```bash
specify workflow run speckit -i spec="Build a kanban board with drag-and-drop task management" -i scope=full
```
> **Note:** All workflow commands require a project already initialized with `specify init`.
## Resume a Workflow
```bash
specify workflow resume <run_id>
```
Resumes a paused or failed workflow run from the exact step where it stopped. Useful after responding to a gate step or fixing an issue that caused a failure.
## Workflow Status
```bash
specify workflow status [<run_id>]
```
Shows the status of a specific run, or lists all runs if no ID is given. Run states: `created`, `running`, `completed`, `paused`, `failed`, `aborted`.
## List Installed Workflows
```bash
specify workflow list
```
Lists workflows installed in the current project.
## Install a Workflow
```bash
specify workflow add <source>
```
Installs a workflow from the catalog, a URL (HTTPS required), or a local file path.
## Remove a Workflow
```bash
specify workflow remove <workflow_id>
```
Removes an installed workflow from the project.
## Search Available Workflows
```bash
specify workflow search [query]
```
| Option | Description |
| ------- | --------------- |
| `--tag` | Filter by tag |
Searches all active catalogs for workflows matching the query.
## Workflow Info
```bash
specify workflow info <workflow_id>
```
Shows detailed information about a workflow, including its steps, inputs, and requirements.
## Catalog Management
Workflow catalogs control where `search` and `add` look for workflows. Catalogs are checked in priority order.
### List Catalogs
```bash
specify workflow catalog list
```
Shows all active catalog sources.
### Add a Catalog
```bash
specify workflow catalog add <url>
```
| Option | Description |
| --------------- | -------------------------------- |
| `--name <name>` | Optional name for the catalog |
Adds a custom catalog URL to the project's `.specify/workflow-catalogs.yml`.
### Remove a Catalog
```bash
specify workflow catalog remove <index>
```
Removes a catalog by its index in the catalog list.
### Catalog Resolution Order
Catalogs are resolved in this order (first match wins):
1. **Environment variable**`SPECKIT_WORKFLOW_CATALOG_URL` overrides all catalogs
2. **Project config**`.specify/workflow-catalogs.yml`
3. **User config**`~/.specify/workflow-catalogs.yml`
4. **Built-in defaults** — official catalog + community catalog
## Workflow Definition
Workflows are defined in YAML files. Here is the built-in **Full SDD Cycle** workflow that ships with Spec Kit:
```yaml
schema_version: "1.0"
workflow:
id: "speckit"
name: "Full SDD Cycle"
version: "1.0.0"
author: "GitHub"
description: "Runs specify → plan → tasks → implement with review gates"
requires:
speckit_version: ">=0.7.2"
integrations:
any: ["copilot", "claude", "gemini"]
inputs:
spec:
type: string
required: true
prompt: "Describe what you want to build"
integration:
type: string
default: "copilot"
prompt: "Integration to use (e.g. claude, copilot, gemini)"
scope:
type: string
default: "full"
enum: ["full", "backend-only", "frontend-only"]
steps:
- id: specify
command: speckit.specify
integration: "{{ inputs.integration }}"
input:
args: "{{ inputs.spec }}"
- id: review-spec
type: gate
message: "Review the generated spec before planning."
options: [approve, reject]
on_reject: abort
- id: plan
command: speckit.plan
integration: "{{ inputs.integration }}"
input:
args: "{{ inputs.spec }}"
- id: review-plan
type: gate
message: "Review the plan before generating tasks."
options: [approve, reject]
on_reject: abort
- id: tasks
command: speckit.tasks
integration: "{{ inputs.integration }}"
input:
args: "{{ inputs.spec }}"
- id: implement
command: speckit.implement
integration: "{{ inputs.integration }}"
input:
args: "{{ inputs.spec }}"
```
This produces the following execution flow:
```mermaid
flowchart TB
A["specify<br/>(command)"] --> B{"review-spec<br/>(gate)"}
B -- approve --> C["plan<br/>(command)"]
B -- reject --> X1["⏹ Abort"]
C --> D{"review-plan<br/>(gate)"}
D -- approve --> E["tasks<br/>(command)"]
D -- reject --> X2["⏹ Abort"]
E --> F["implement<br/>(command)"]
style A fill:#49a,color:#fff
style B fill:#a94,color:#fff
style C fill:#49a,color:#fff
style D fill:#a94,color:#fff
style E fill:#49a,color:#fff
style F fill:#49a,color:#fff
style X1 fill:#999,color:#fff
style X2 fill:#999,color:#fff
```
Run it with:
```bash
specify workflow run speckit -i spec="Build a kanban board with drag-and-drop task management"
```
## Step Types
| Type | Purpose |
| ------------ | ------------------------------------------------ |
| `command` | Invoke a Spec Kit command (e.g., `speckit.plan`) |
| `prompt` | Send an arbitrary prompt to the AI coding agent |
| `shell` | Execute a shell command and capture output |
| `gate` | Pause for human approval before continuing |
| `if` | Conditional branching (then/else) |
| `switch` | Multi-branch dispatch on an expression |
| `while` | Loop while a condition is true |
| `do-while` | Execute at least once, then loop on condition |
| `fan-out` | Dispatch a step for each item in a list |
| `fan-in` | Aggregate results from a fan-out step |
## Expressions
Steps can reference inputs and previous step outputs using `{{ expression }}` syntax:
| Namespace | Description |
| ------------------------------ | ------------------------------------ |
| `inputs.spec` | Workflow input values |
| `steps.specify.output.file` | Output from a previous step |
| `item` | Current item in a fan-out iteration |
Available filters: `default`, `join`, `contains`, `map`.
Example:
```yaml
condition: "{{ steps.test.output.exit_code == 0 }}"
args: "{{ inputs.spec }}"
message: "{{ status | default('pending') }}"
```
## Input Types
| Type | Coercion |
| --------- | ------------------------------------------------- |
| `string` | Pass-through |
| `number` | `"42"``42`, `"3.14"``3.14` |
| `boolean` | `"true"` / `"1"` / `"yes"``True` |
## State and Resume
Each workflow run persists its state at `.specify/workflows/runs/<run_id>/`:
- `state.json` — current run state and step progress
- `inputs.json` — resolved input values
- `log.jsonl` — step-by-step execution log
This enables `specify workflow resume` to continue from the exact step where a run was paused (e.g., at a gate) or failed.
## FAQ
### What happens when a workflow hits a gate step?
The workflow pauses and waits for human input. Run `specify workflow resume <run_id>` after reviewing to continue.
### Can I run the same workflow multiple times?
Yes. Each run gets a unique ID and its own state directory. Use `specify workflow status` to see all runs.
### Who maintains workflows?
Most workflows are independently created and maintained by their respective authors. The Spec Kit maintainers do not review, audit, endorse, or support workflow code. Review a workflow's source before installing and use at your own discretion.

View File

@@ -16,11 +16,13 @@
- name: Reference
items:
- name: Integrations
href: integrations.md
href: reference/integrations.md
- name: Extensions
href: extensions.md
href: reference/extensions.md
- name: Presets
href: presets.md
href: reference/presets.md
- name: Workflows
href: reference/workflows.md
# Development workflows
- name: Development

View File

@@ -76,7 +76,7 @@ Run this inside your project directory:
specify init --here --force --ai <your-agent>
```
Replace `<your-agent>` with your AI coding agent. Refer to this list of [Supported AI Coding Agent Integrations](integrations.md)
Replace `<your-agent>` with your AI coding agent. Refer to this list of [Supported AI Coding Agent Integrations](reference/integrations.md)
**Example:**

View File

@@ -351,8 +351,16 @@ def show_banner():
console.print(Align.center(Text(TAGLINE, style="italic bright_yellow")))
console.print()
def _version_callback(value: bool):
if value:
console.print(f"specify {get_speckit_version()}")
raise typer.Exit()
@app.callback()
def callback(ctx: typer.Context):
def callback(
ctx: typer.Context,
version: bool = typer.Option(False, "--version", "-V", callback=_version_callback, is_eager=True, help="Show version and exit."),
):
"""Show banner when no subcommand is provided."""
if ctx.invoked_subcommand is None and "--help" not in sys.argv and "-h" not in sys.argv:
show_banner()

View File

@@ -255,7 +255,7 @@ def evaluate_expression(template: str, context: Any) -> Any:
----------
template:
The template string (e.g., ``"{{ steps.plan.output.task_count }}"``
or ``"Processed {{ inputs.feature_name }}"``.
or ``"Processed {{ inputs.spec }}"``.
context:
A ``StepContext`` or compatible object.

35
tests/test_cli_version.py Normal file
View File

@@ -0,0 +1,35 @@
"""Tests for the --version CLI flag."""
from unittest.mock import patch
from typer.testing import CliRunner
from specify_cli import app
runner = CliRunner()
class TestVersionFlag:
"""Test --version / -V flag on the root command."""
def test_version_long_flag(self):
"""specify --version prints version and exits 0."""
with patch("specify_cli.get_speckit_version", return_value="1.2.3"):
result = runner.invoke(app, ["--version"])
assert result.exit_code == 0
assert "specify 1.2.3" in result.output
def test_version_short_flag(self):
"""specify -V prints version and exits 0."""
with patch("specify_cli.get_speckit_version", return_value="1.2.3"):
result = runner.invoke(app, ["-V"])
assert result.exit_code == 0
assert "specify 1.2.3" in result.output
def test_version_flag_takes_precedence_over_subcommand(self):
"""--version should work even when a subcommand follows."""
with patch("specify_cli.get_speckit_version", return_value="0.7.2"):
result = runner.invoke(app, ["--version", "init"])
assert result.exit_code == 0
assert "specify 0.7.2" in result.output

View File

@@ -54,7 +54,7 @@ workflow:
description: "A test workflow"
inputs:
feature_name:
spec:
type: string
required: true
scope:
@@ -65,7 +65,7 @@ steps:
- id: step-one
command: speckit.specify
input:
args: "{{ inputs.feature_name }}"
args: "{{ inputs.spec }}"
- id: step-two
command: speckit.plan
@@ -1152,8 +1152,8 @@ class TestWorkflowDefinition:
from specify_cli.workflows.engine import WorkflowDefinition
definition = WorkflowDefinition.from_string(sample_workflow_yaml)
assert "feature_name" in definition.inputs
assert definition.inputs["feature_name"]["required"] is True
assert "spec" in definition.inputs
assert definition.inputs["spec"]["required"] is True
assert definition.inputs["scope"]["default"] == "full"

View File

@@ -62,10 +62,10 @@ requires:
any: ["claude", "gemini"] # At least one required
inputs:
feature_name:
spec:
type: string
required: true
prompt: "Feature name"
prompt: "Describe what you want to build"
scope:
type: string
default: "full"
@@ -75,7 +75,7 @@ steps:
- id: specify
command: speckit.specify
input:
args: "{{ inputs.feature_name }}"
args: "{{ inputs.spec }}"
- id: review
type: gate
@@ -99,7 +99,7 @@ steps:
```bash
# Run with required inputs
specify workflow run ./workflow.yml --input feature_name="user-auth"
specify workflow run ./workflow.yml --input spec="Build a user authentication system with OAuth support"
# Check validation
specify workflow info ./workflow.yml

View File

@@ -11,7 +11,7 @@ steps:
- id: specify
command: speckit.specify
input:
args: "{{ inputs.feature_name }}"
args: "{{ inputs.spec }}"
- id: review
type: gate
@@ -35,10 +35,10 @@ specify workflow search
specify workflow add speckit
# Or run directly from a local YAML file
specify workflow run ./workflow.yml --input feature_name="user-auth"
specify workflow run ./workflow.yml --input spec="Build a user authentication system with OAuth support"
# Run an installed workflow with inputs
specify workflow run speckit --input feature_name="user-auth"
specify workflow run speckit --input spec="Build a user authentication system with OAuth support"
# Check run status
specify workflow status
@@ -59,20 +59,20 @@ specify workflow remove speckit
```bash
specify workflow add speckit
specify workflow run speckit --input feature_name="user-auth"
specify workflow run speckit --input spec="Build a user authentication system with OAuth support"
```
### From a Local YAML File
```bash
specify workflow run ./my-workflow.yml --input feature_name="user-auth"
specify workflow run ./my-workflow.yml --input spec="Build a user authentication system with OAuth support"
```
### Multiple Inputs
```bash
specify workflow run speckit \
--input feature_name="user-auth" \
--input spec="Build a user authentication system with OAuth support" \
--input scope="backend-only"
```
@@ -88,7 +88,7 @@ Invoke an installed Spec Kit command by name via the integration CLI:
- id: specify
command: speckit.specify
input:
args: "{{ inputs.feature_name }}"
args: "{{ inputs.spec }}"
integration: claude # Optional: override workflow default
model: "claude-sonnet-4-20250514" # Optional: override model
```
@@ -225,7 +225,7 @@ Workflow definitions use `{{ expression }}` syntax for dynamic values:
```yaml
# Access inputs
args: "{{ inputs.feature_name }}"
args: "{{ inputs.spec }}"
# Access previous step outputs
args: "{{ steps.specify.output.file }}"
@@ -245,10 +245,10 @@ Workflow inputs are type-checked and coerced from CLI string values:
```yaml
inputs:
feature_name:
spec:
type: string
required: true
prompt: "Feature name"
prompt: "Describe what you want to build"
task_count:
type: number
default: 5

View File

@@ -7,15 +7,15 @@ workflow:
description: "Runs specify → plan → tasks → implement with review gates"
requires:
speckit_version: ">=0.6.1"
speckit_version: ">=0.7.2"
integrations:
any: ["copilot", "claude", "gemini"]
inputs:
feature_name:
spec:
type: string
required: true
prompt: "Feature name"
prompt: "Describe what you want to build"
integration:
type: string
default: "copilot"
@@ -30,7 +30,7 @@ steps:
command: speckit.specify
integration: "{{ inputs.integration }}"
input:
args: "{{ inputs.feature_name }}"
args: "{{ inputs.spec }}"
- id: review-spec
type: gate
@@ -42,7 +42,7 @@ steps:
command: speckit.plan
integration: "{{ inputs.integration }}"
input:
args: "{{ inputs.feature_name }}"
args: "{{ inputs.spec }}"
- id: review-plan
type: gate
@@ -54,10 +54,10 @@ steps:
command: speckit.tasks
integration: "{{ inputs.integration }}"
input:
args: "{{ inputs.feature_name }}"
args: "{{ inputs.spec }}"
- id: implement
command: speckit.implement
integration: "{{ inputs.integration }}"
input:
args: "{{ inputs.feature_name }}"
args: "{{ inputs.spec }}"