Skip to main content
A Recipe is the execution plan behind a Capability. Where a Capability answers what an automation produces, a Recipe answers how. It declares the runtime, the tools that must be present, the steps to execute, how outputs are captured, and whether any step requires human approval before it runs. Recipes live in your repository alongside Capabilities and run entirely on your local machine — no cloud execution, no token cost.

Linking a Recipe to a Capability

A Recipe connects to one or more Capabilities through the provides field:
When you run doppels run capability/release-build, the CLI finds the Recipe that provides it, validates the manifest, checks prerequisites, and executes the steps. A single Capability can have multiple Recipes (different implementations for different environments), and a single Recipe can provide multiple Capabilities.

Two runtimes

Recipes support two runtimes: shell for automated execution and manual for human-driven runbooks.

Shell runtime

The shell runtime runs each step as an isolated shell process. Use it for any automation that can execute non-interactively with predictable inputs and outputs.

Manual runtime

The manual runtime documents a human procedure through a runbook file. Use it when work must be performed by a person — reviewing an approval, executing a GUI-only operation, or gathering evidence from an external system.
The procedure.readme path points to a Markdown file (relative to your workspace) that describes what the human must do. The evidence block declares the typed values the operator must supply to confirm the procedure was completed. These become part of the run record.

Key field reference

array
required
A list of Capability names this Recipe implements. Each name must match the metadata.name of a Capability manifest discoverable in your project.
string
required
The execution model. Must be either shell (automated steps) or manual (human runbook).
array
A list of shell commands that must be present on PATH before the Recipe can run. The CLI checks these before executing any steps and reports a clear error if any are missing.
string
The default approval policy applied to every step that does not set its own approval. Accepted values:
  • never — step executes without prompting.
  • always — step always pauses for human confirmation.
  • local — step pauses only when running outside a CI environment.
Approval is never inferred. Every step must resolve its approval policy from either defaults.approval or its own approval field.
string
required
A unique identifier for this step within the Recipe. Referenced in expressions as steps.<id>.<result> to pass results forward to later steps or to returns.
string
A human-readable label shown in CLI output and run logs.
string
The approval policy for this specific step. Overrides defaults.approval when set. Accepted values are the same as defaults.approval: never, always, or local.
object
A map of environment variable names to values. Use expressions here to inject input values or results from prior steps:
The script then reads these as normal shell variables ($VERSION, $PREV_CHECKSUM).
string
The shell interpreter to use. Typically sh or bash.
string
The shell script to execute. Write the script using environment variables — never use {{ }} expressions directly inside a script. This prevents shell injection.
string
Declares that this step produces a file artifact at the given POSIX-relative path. The path may contain expressions:
string
Declares that this step produces a scalar result from an exported environment variable. The script must export the variable before the step exits:
object
Maps step results back to the output names declared in the Capability. Every output declared by all provided Capabilities must appear here.
string
(manual runtime only.) A POSIX-relative path to a Markdown file that describes the procedure a human operator must follow. The file is displayed to the operator at run time and becomes part of the run record.
object
(manual runtime only.) A map of named values the operator must supply when confirming the procedure was completed. Each entry declares a type using the same type vocabulary as Capability inputs and outputs (string, integer, number, boolean, artifact). Evidence values are recorded in the run and can be referenced by downstream automations.

Using expressions safely

Expressions use the {{ ... }} syntax inside quoted YAML strings. Two forms are supported:
  • {{ inputs.<name> }} — the value of a declared Capability input.
  • {{ steps.<step-id>.<result> }} — a named result produced by a prior step.
Use expressions in env values, declarative path fields (like produces.file), and returns values. Never use expressions inside run.script. Instead, assign expression values to environment variables in the env block and read those variables in the script. This design prevents shell injection and keeps the script portable.

Path rules

All paths in a Recipe — in produces.file, procedure.readme, or any other declarative field — must use POSIX syntax relative to your workspace root. Absolute paths (starting with /), Windows-style paths (containing \ or drive letters like C:), and paths containing .. segments are all prohibited. This rule keeps the same Recipe portable across macOS, Linux, and Windows.

Where to store Recipe manifests

Place Recipe manifests in the recipes/ directory at the root of your project:
File names do not need to match metadata.name, but keeping them aligned makes navigation straightforward. Commit both capabilities/ and recipes/ to your repository — they are the repeatable assets that grow your automation library.

Capabilities

Understand the Capability contract that Recipes implement.

Spaces

See how Spaces scope discovery of your Capabilities and Recipes.

Validate and Run

Step-by-step guide to validating manifests and executing your first run.

YAML Schema Reference

Complete schema reference for all Recipe fields.