> ## 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.

# Using Git to Version and Share Doppels Capabilities

> Commit your Capability and Recipe YAML files to Git to version, review, and share automations across your team like any other source code.

Capabilities and Recipes are plain YAML files that live in your repository alongside your application code. There is no separate registry, no opaque binary format, and no external service required to store or share them. You commit them to Git, review them in pull requests, and share them with teammates the same way you share any other source file. When a teammate checks out your branch, they have everything they need to run the same Capability on their own machine.

## What to commit

**Commit these:**

| Path                | What it contains                              |
| ------------------- | --------------------------------------------- |
| `capabilities/`     | Capability YAML files — the public contracts  |
| `recipes/`          | Recipe YAML files — the local implementations |
| Space YAML (if any) | `space.yaml` in the project root              |

**Do not commit these:**

| Path        | What it contains                          |
| ----------- | ----------------------------------------- |
| `.doppels/` | Run history, logs, artifacts, local state |

Run history is machine-specific runtime data. It doesn't belong in version control and can grow large quickly. Add `.doppels/` to your `.gitignore`:

```gitignore theme={null}
.doppels/
```

## Versioning Capabilities

Every Capability has a `metadata.version` field. Use semantic versioning — `1.0.0`, `1.1.0`, `2.0.0` — and treat each published version as immutable.

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

metadata:
  name: hn-top-stories
  version: 1.0.0
  displayName: Fetch Top Hacker News Stories
```

Once a Capability version has been referenced in a Run, re-publishing a different manifest with the same version number is an error. The `capabilityRevision` digest would change, making the new manifest incompatible with any existing run records. Always increment `metadata.version` when you change a Capability's inputs, outputs, or display name.

<Note>
  The same immutability rule applies to Recipes that are referenced by a Share. If a Recipe version has been pinned in a `capabilityRevision`, changing it without bumping the version breaks the digest check. Increment `metadata.version` in the Recipe as well whenever you change its steps.
</Note>

## Recommended workflow

<Steps>
  <Step title="Freeze the session">
    After working through a problem in your agent, say the freeze phrase to trigger the `doppel-freeze` skill. The skill writes `capabilities/<name>.yaml` and `recipes/<name>.yaml` in your project.

    See [Freeze with Agent](/guides/freeze-with-agent) for the full walkthrough.
  </Step>

  <Step title="Review the YAML diff">
    Open the new files in your editor. Check that:

    * Inputs match what you actually need to provide
    * Steps reflect the commands and operations from the session
    * Outputs capture the values you care about
    * Approval settings are appropriate for the operation's risk level

    Treat this review the same way you'd review a new script or migration — the YAML is code.
  </Step>

  <Step title="Validate">
    Run `doppels validate` to confirm the manifests are clean before committing.

    ```shell theme={null}
    doppels validate
    ```

    Fix any errors reported. Common issues: a `returns` key that doesn't match a declared output, an expression referencing a step result that isn't yet produced, or a missing `approval` on a step.
  </Step>

  <Step title="Commit the YAML files">
    Stage and commit the Capability and Recipe files.

    ```shell theme={null}
    git add capabilities/hn-top-stories.yaml recipes/hn-top-stories.yaml
    git commit -m "freeze: hn-top-stories v1.0.0"
    ```

    The commit is the repeatable asset. The YAML is all a teammate needs to run the same Capability.
  </Step>

  <Step title="Share with teammates">
    Push the branch or merge to main. Teammates pull the changes and run the Capability locally with their own credentials:

    ```shell theme={null}
    doppels run capability/hn-top-stories --input limit=20 --yes
    ```

    No special setup required beyond having `doppels` on their `PATH`. The freeze skill is only needed if they want to freeze new sessions of their own — running an existing Capability needs only the CLI.
  </Step>
</Steps>

## Forking and modifying Recipes

Because Recipes are plain YAML in your repository, anyone on the team can fork them, adjust steps, and run a modified version. To create a variant:

1. Copy `recipes/<name>.yaml` to `recipes/<name>-variant.yaml`
2. Adjust the steps, add new `requires`, or change the shell commands
3. Keep `provides: [<name>]` pointing at the same Capability — the contract doesn't change, just the implementation
4. Run `doppels validate` to confirm the modified Recipe still satisfies the Capability's outputs
5. Run it: `doppels run capability/<name>`

The CLI will discover both Recipes providing the same Capability. If there are multiple, it will ask which one to use.

## Code review guidelines

Treat Capability and Recipe YAML changes like any other source change. When reviewing a pull request that modifies these files, check:

* **Inputs**: Are required inputs clearly named and typed? Are optional inputs given reasonable defaults?
* **Steps**: Do the shell commands do what the step name says? Is anything destructive or irreversible?
* **Approval settings**: Steps that write to databases, call external APIs, or modify infrastructure should have `approval: local` or `approval: always` unless the context clearly warrants `never`.
* **Returns**: Does `returns` cover all the outputs declared in the Capability? Are the expressions correct?
* **Version bump**: If an existing Capability is changing, did the author increment `metadata.version`?

<Tip>
  Adding a Capability is a low-risk change — it's purely additive. Changing an existing Capability's inputs or outputs is a breaking change for anyone who depends on that version. Always increment the version and consider whether existing callers need to be updated.
</Tip>
