# The manifest

A package is a directory under `.workbenches/` with a `workbench.yml` manifest, its instructions, and its skills. Every field is specified on [Spec 1 manifest](/docs/standard/manifest); this page is how to write one.

```text
.workbenches/
  core/
    workbench.yml
    instructions.md
    skills/
    runner/
      opencode.json
```

A package must sit at `.workbenches/<name>/workbench.yml`. The engine refuses one anywhere else, for every command: `Workbench must live beneath a .workbenches directory`.

## Create a package

### Scaffold

```sh
wb init core
wb init core --dir /path/to/repository
wb init migrations --runner opencode --model openai/gpt-5.6-terra
wb init migrations --runtimes local,docker --image ghcr.io/example/migrations:0.1.0
```

`wb init` writes a spec 1 package deterministically, with no model run.

| Option              | Effect                                                                                                  |
| ------------------- | ------------------------------------------------------------------------------------------------------- |
| `--dir <dir>`       | The repository. Defaults to the current directory.                                                      |
| `--runner <runner>` | The runner recorded in the manifest.                                                                    |
| `--model <id>`      | The model. Rejected when the model catalog does not know it.                                            |
| `--runtimes <list>` | Comma-separated runtimes, written in that order. Defaults to `local`.                                   |
| `--image <ref>`     | The image for `docker`, `e2b`, and `daytona`, which need one. `daytona` is written with `class: linux`. |

The scaffold is a placeholder. Replace every generated line.

### Let the creator write it

```sh
wb create core --task "Create a focused expert for this repository"
wb create .#core --task-file improvements.txt
```

`wb create` runs the official creator Workbench against your repository. It inspects the repository, writes `.workbenches/<name>/workbench.yml` and its supporting files, and finishes only when the package passes engine-owned verification: it validates the candidate, checks its version and package scope, and runs `wb smoke`. Invalid packages, out-of-scope edits, missing version increments, and failed smoke checks fail the result with a nonzero exit. A completed creator turn alone is not success.

- Naming an existing local package edits it. `create` never changes an immutable saved snapshot.
- Give exactly one brief: `--task`, `--task-file`, or `--stdin`. `--from <session>` can infer improvements from stored session evidence without one.
- `--detach --json` returns a receipt; `wb wait` waits for verification too, and its `authoring` result reports package selectors and paths, changed files, and the evidence path.
- Candidates that declare environment values, named workspaces, or host Docker access are verified with `--env-file`, `--env`, `--workspace`, and `--allow-host-docker`. Those values are used only for the final smoke and never written to the authoring record.
- `--runtime` picks which declared runtime the final smoke checks, and `--allow-unchecked-gpu` accepts a GPU discovery cannot see.

`wb create` spends a model run. The creator receives the exact `wb` build that started it.

## Write the manifest

```yaml
spec: 1
version: 0.1.0

name: migrations
description: Design, review, and safely apply project migrations.

runner: opencode
model:
    id: openai/gpt-5.6-terra
runner_config: ./runner/opencode.json

instructions: ./instructions.md
skills:
    - ./skills/migrations

tools:
    - cargo
    - dbctl

env:
    DATABASE_API_TOKEN:
        required: false

requirements:
    os: [linux, macos]
    memory_gb: 8

runtimes:
    docker:
        image: images.workbenches.dev/acme/migrations:0.1.0
    local: {}
```

### Rules

- **Spec.** Write the newest spec your installed `wb` supports: `wb init` scaffolds it and `wb validate` rejects anything else. Never guess a future version.
- **Version.** Semantic versioning. Increment it whenever package content changes, so each content identity has a distinct version. The registry refuses a push that is not higher than the last.
- **Runner and model.** Choose them from trial evidence on this Workbench's real tasks, and record the evidence. Without evidence, keep the existing valid choice and say it is unevaluated. They are locked: consumers connect credentials, they never override the runner, model, routes, or native configuration.
- **`runner_config`.** Put runner-native configuration inside the package. Use it to enforce what the instructions promise: deny sub-agent delegation, scope file permissions, deny secret files. Never package credential files or literal secrets.
- **Instructions and skills** stay inside the package, so it can be saved as a self-contained snapshot.
- **Tools** are exact executable names already on the runtime's `PATH`: installed on the host for `local`, or in the image otherwise. A gate script inside the package is not on `PATH`; invoke it by its skill path, and declare it in `tools` only when the image installs it. Presence is preflighted; version compatibility is not.
- **`env`** declares names, never values. Mark one optional only when the Workbench stays useful without it.
- **`mcps`** are remote HTTP MCP servers only. Reference declared variables in headers as `${NAME}`. An MCP server that depends on an unset optional variable is disabled for that run.
- **`runtimes`** lists the providers the Workbench supports, default first. Declare `local: {}` only when host execution is intentional. Never write `runtime`, a top-level `image`, or a top-level `docker`.
- **`requirements`** only for constraints the work truly depends on.

See [Runtimes, models, and permissions](/docs/authoring/configuration) for the runtime, image, model, and permission choices.

## Check it

From the repository root:

```sh
wb validate .#migrations
wb view .#migrations
wb smoke .#migrations
wb smoke .#migrations --runtime docker
wb add ./.workbenches/migrations --as migrations
wb run migrations --dry-run --task "Review the latest migration"
```

From elsewhere, use `/path/to/repository#migrations` or the path `/path/to/repository/.workbenches/migrations`. After `wb add`, the alias is live: new runs read the current files.

| Check           | Proves                                                                              |
| --------------- | ----------------------------------------------------------------------------------- |
| `validate`      | The package parses and its local files satisfy the schema.                          |
| `view`          | The resolved contract and authorization bindings, without values.                   |
| `smoke`         | The runner and every declared tool exist in the selected runtime. No model request. |
| `run --dry-run` | The request resolves, preflights, and translates without launching the runner.      |

None of these says whether the package produces good work. Only trials do. Smoke every declared runtime; on `e2b` and `daytona` it creates a billable sandbox. Then run one tiny real task without approving any permission prompt: a stall means the permission config is incomplete.

Keep four results distinct when you report: a file change, passing validation, passing smoke, and an end-to-end successful run.

## Boundaries the standard enforces

A Workbench prepares execution. Task graphs, schedules, approval stages, retries, and product interface behavior belong to whatever orchestrates it, not to the package.
