> ## Documentation Index
> Fetch the complete documentation index at: https://docs.doppels.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Doppels YAML Schema Reference: Capability, Recipe, Space

> Complete YAML schema reference for Capability, Recipe, and Space manifests — the three document types that define automations in Doppels.

All Doppels manifests share a single `apiVersion: doppels.so/v1alpha1` and are validated against JSON Schema Draft 2020-12. The YAML you write is a deterministic subset of the full YAML specification: no tags, timestamps, anchors, aliases, or merge keys are permitted. Numbers follow JSON numeric grammar. This constraint ensures that manifests parse identically across every runtime and toolchain that implements the schema, and that diffs stay readable in code review.

***

## Capability schema

A Capability defines the **public contract** of an automation — what inputs it accepts and what outputs it guarantees. It says nothing about how the work gets done; that responsibility belongs to a Recipe. A Capability can exist without a Recipe, in which case a person fulfills the contract manually.

```yaml theme={null}
apiVersion: doppels.so/v1alpha1
kind: Capability

metadata:
  name: greet            # machine-readable name — used in CLI commands
  version: 1.0.0         # semantic version — immutable once published
  displayName: Greet     # human-readable label shown in the UI and CLI output

inputs:
  name:
    type: string
    required: true        # omit or set false for optional inputs

outputs:
  message:
    type: string
  report:
    type: artifact
    mediaType: text/plain  # MIME type — required when type is artifact
```

### Input and output types

| Type       | Description                                                                          |
| ---------- | ------------------------------------------------------------------------------------ |
| `string`   | Text value.                                                                          |
| `integer`  | Whole number within the JSON portable range `[-9007199254740991, 9007199254740991]`. |
| `number`   | Any finite JSON number. Integral values must fall within the same portable range.    |
| `boolean`  | Exactly `true` or `false`. No tolerant conversion.                                   |
| `artifact` | A file. Set `mediaType` to the appropriate MIME type.                                |

All declared outputs are part of the required result. A run that does not produce every declared output is an error.

***

## Recipe schema — `shell` runtime

A Recipe defines **how** a Capability runs. It declares `provides` to bind itself to one or more Capabilities, and it lists the ordered steps that produce the required outputs. The `shell` runtime runs each step's script in an isolated `sh` or `bash` process.

```yaml theme={null}
apiVersion: doppels.so/v1alpha1
kind: Recipe

metadata:
  name: greet-shell
  version: 1.0.0

provides: [greet]           # names of the Capabilities this Recipe implements

runtime: shell

requires:
  commands: [echo]          # tools that must be present on PATH before the run starts

defaults:
  approval: never           # never | always | local — applies to all steps unless overridden

steps:
  - id: say-hello
    name: Print greeting
    env:
      NAME: "{{ inputs.name }}"   # inject input into the step environment
    run:
      shell: sh                   # sh or bash
      script: |
        # Use the env var here — never a {{ }} expression inside script
        export MSG="Hello, $NAME!"
    produces:
      message:
        env: MSG                  # captures the value of the exported MSG variable

returns:
  message: "{{ steps.say-hello.message }}"   # maps step result to Capability output
```

Steps execute in the order they are declared. `stdout` and `stderr` are logged but are not results — only values captured via `produces` become outputs. `returns` must cover every output declared in every Capability named in `provides`.

### `produces` capture methods

| Field                  | Description                                                                                    |
| ---------------------- | ---------------------------------------------------------------------------------------------- |
| `produces.<name>.file` | Captures a file artifact. The path is relative to the workspace. Supports `{{ }}` expressions. |
| `produces.<name>.env`  | Captures the final value of a named exported environment variable.                             |

### `defaults.approval` values

| Value    | Meaning                                                                  |
| -------- | ------------------------------------------------------------------------ |
| `never`  | Steps run without asking for approval.                                   |
| `always` | Every step requires explicit approval before running.                    |
| `local`  | Approval required only when running locally (not in automated contexts). |

Approval is never inferred. Every step resolves its approval policy from `defaults.approval` or its own `approval` field.

***

## Recipe schema — `manual` runtime

The `manual` runtime records a human fulfillment of a Capability. Instead of steps and scripts, it points to a runbook document and collects evidence from the person completing the work.

```yaml theme={null}
apiVersion: doppels.so/v1alpha1
kind: Recipe

metadata:
  name: service-check-manual
  version: 1.0.0

provides: [service-status]
runtime: manual

procedure:
  readme: ./service-check-runbook.md    # path to the runbook, relative to workspace

evidence:
  notes:
    type: string                        # additional evidence collected during the manual run
```

The procedure explains the expected work. Outputs are collected directly according to the Capability contract, and `evidence` captures any proof-of-completion that the procedure requires beyond the standard outputs.

***

## Space schema

A Space is the configuration boundary for a project. It groups the Capabilities and Recipes discovered by convention within its directory and associates them with an Organization context. Capabilities and Recipes are discovered from the filesystem — they are not enumerated inside the Space manifest itself.

```yaml theme={null}
apiVersion: doppels.so/v1alpha1
kind: Space

metadata:
  name: my-project
  displayName: My Project
  labels:
    environment: production
```

Note that Space has **no `metadata.version`** field. Unlike Capabilities and Recipes, a Space represents mutable desired state rather than a published, immutable definition.

***

## YAML rules

These rules apply to all Doppels manifests. The `doppels validate` command enforces them.

* **Paths must be POSIX-style and relative to the workspace.** No absolute paths (starting with `/`), no drive prefixes (`C:`), no backslash separators (`\`), and no parent-directory segments (`..`). This keeps manifests portable across macOS, Linux, and Windows.
* **Never use `{{ }}` expressions inside `run.script`.** Inject values through the `env:` block and reference them as normal shell variables (`$NAME`). This prevents shell injection vulnerabilities.
* **Quote ambiguous tokens.** YAML plain scalars like `yes`, `no`, `on`, `off`, `~`, and date-like strings are interpreted differently by YAML 1.1 and 1.2 parsers. When you intend them as strings, always quote them: `"yes"`, `"on"`, `"~"`.
* **Comments and block scalars are allowed.** Use `#` for comments and `|` or `>` for multiline strings (scripts, runbook paths, etc.).
* **Prohibited YAML features:** tags (e.g. `!!str`), timestamps, anchors (`&anchor`), aliases (`*alias`), and merge keys (`<<:`). None of these are permitted in any Doppels manifest.
