# Run

`wb run` starts a Workbench on a task. It accepts a saved alias only; `--dir` and `--repo` select what the agent works on, never the package source.

```sh
wb run <alias> [task] [options]
```

## Give it a task

A run needs exactly one task:

```sh
wb run project-core "Explain the storage architecture"
wb run project-core --task "Review this migration"
wb run project-core --task-file ./brief.md
cat brief.md | wb run project-core --stdin
```

| Option               | Effect                                                   |
| -------------------- | -------------------------------------------------------- |
| `[task]`             | The task as a positional argument.                       |
| `--task <text>`      | The same, as an option.                                  |
| `--task-file <file>` | Read the task from a UTF-8 file. Use it for long briefs. |
| `--stdin`            | Read the task from standard input.                       |

Without one, the run fails with `wb run requires a task`. Unknown options are rejected.

## Choose the output

| Option     | Output                                                                                   |
| ---------- | ---------------------------------------------------------------------------------------- |
| none       | A colorized, terminal-safe Markdown stream of the run, the same for every runner.        |
| `--final`  | Only the final assistant response.                                                       |
| `--json`   | Normalized events as NDJSON, one per line. See [Event protocol](/docs/standard/events).  |
| `--detach` | Start in the background and print the session ID. With `--json`, print a launch receipt. |
| `--color`  | Force color in human output. `NO_COLOR` or `--no-color` turns it off.                    |

`--final` and `--json` cannot be combined. Stdout carries only the selected output. Errors go to stderr as `error: <message>`, or a red `✗ <message>` in a terminal.

```sh
wb run project-core --task "Review this migration" --final
wb run project-core --task "Review this migration" --json
wb run project-core --task-file ./brief.md --detach --json
```

Once a run has started, `--json` reports a failure as `run.failed` on stdout with a non-zero exit. A failure before it starts (arguments, preflight, authentication, worker startup) prints `error: <message>` on stderr, emits no events, and exits 1 or 3.

### Detach

`--detach` creates a durable session and run, launches a background worker, and returns. Supervise it with `wait`, `send`, and `answer`; see [Sessions](/docs/cli/sessions). A detached run cannot start a first-time runner sign-in, which needs a person at a terminal: run one foreground task first.

## Choose the workspace

### `--dir`

```sh
wb run project-core --dir ./app --task "Add pagination"
```

The primary workspace defaults to the current directory. `--dir` selects another. It is the runner's working directory and is read-write.

### `--workspace`

```sh
wb run project-core --dir ./app --workspace api=../api \
  --workspace schemas=../schemas --task "Review the cross-repository change"
```

`--workspace NAME=PATH` binds a named workspace the manifest declares. It is repeatable. Missing required bindings, undeclared names, unavailable directories, and duplicate paths fail before the runner launches.

Inside a run each location is `WORKBENCH_WORKSPACE_<NAME>`, with hyphens as underscores, such as `WORKBENCH_WORKSPACE_API`. Local runs use the host path. Docker, E2B, and Daytona use `/workspaces/<name>`. Docker enforces read-only declarations at the mount. E2B and Daytona copy the directories and return read-write changes as pending outcomes. On the local runtime access is a preflight check, not a sandbox.

### `--repo`

```sh
wb run project-core --repo owner/project --task "Audit authentication"
wb run project-core --repo owner/project --ref main \
  --task "Add pagination and tests and open a draft PR"
```

`--repo owner/name` runs against an isolated GitHub checkout instead of your directory. `--ref` picks a branch, tag, or commit and defaults to the repository's default branch.

- The engine resolves the ref to an exact commit and checks it out in the session's managed storage. It never uploads or synchronizes your current directory.
- Access uses `GH_TOKEN`, then `GITHUB_TOKEN`, then an existing `gh auth login`. This is separate from `wb connect`.
- The runner gets `GH_TOKEN` and Git configured to use `gh` for HTTPS. Commits use the authenticated account's GitHub no-reply identity.
- The agent uses ordinary `git` and `gh` to commit, push, open or update a pull request, and inspect CI. Nothing is published automatically when a run ends.
- The token keeps its real permissions. Repository mode is not a restriction to pull request operations, so use a suitably scoped token.
- Private repositories need read access. Opening a pull request needs Contents and Pull requests write. CI inspection needs Actions and Checks read.
- The checkout is shallow. Submodules are kept but not initialized, and Git LFS files are not downloaded.
- `--repo` cannot be combined with `--dir`, `--workspace`, host Docker access, or `--dry-run`.

Workbench authors do not need to declare `git` or `gh`. For Docker and E2B the engine adds a cached tooling layer on top of the image. On Daytona it installs them in the sandbox, which needs a root user or passwordless `sudo` when the image lacks them.

Resume keeps the managed checkout and the runner's Git state. A confirmed pull request URL the agent records as a `pull_request` outcome link is returned with the outcome.

## Bind environment values

```sh
wb run project-core --task "Review this migration" --env-file .env.workbench
wb run project-core --task "Review this migration" \
  --env API_URL=https://api.example.com
```

| Option              | Effect                                                                                                                                                              |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--env-file <file>` | Read values from a dotenv file. Entries the Workbench does not declare are ignored.                                                                                 |
| `--env NAME=value`  | Set one value. Repeatable. An undeclared name is rejected as a likely typo, unless it is a provider key for an allowed route or the selected sandbox runtime's key. |

Precedence is `--env`, then `--env-file`, then the inherited environment. Values are used only for that invocation and never written to run metadata or events. Prefer `--env-file` or the environment for secrets, because command-line values stay in shell history. A required variable that is missing fails with `Missing required environment variable: NAME`.

Only declared values, the selected provider's credential variables, and the selected runner's private credential store reach the run. After a model route is chosen, other providers' keys are stripped.

## Pick the connection

```sh
wb run project-core --connection openrouter --task "Review this migration"
```

`--connection <provider>` uses one authenticated provider for this run without changing your saved default. It must match a route the Workbench allows. Resolution order is `--connection`, then the `wb connect` default for the runner and runtime, then the first allowed authenticated route in manifest order. See [Models and connections](/docs/cli/models).

## Pick the runtime

```sh
wb run project-core --runtime docker --task "Review this migration"
```

`--runtime <name>` selects a runtime the Workbench declares. Without it the first declared runtime is used. Naming one it does not declare fails and lists the declared ones. See [Runtimes](/docs/cli/runtimes).

## Track it in a project

```sh
wb project create "Demo"
wb run project-core --project demo --task "Review this migration" --detach
```

`--project <name-or-slug>` groups the session under a local project. It must already exist; `--project` never creates one, and an unknown name fails before anything is dispatched with a suggestion such as `No project "X". Did you mean "Y"?`. See [Projects, status, studio, and MCP](/docs/cli/projects).

## Other options

| Option                  | Effect                                                                                                                      |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `--allow-host-docker`   | Grant a declared host Docker engine binding for this run. Gives the run effective administrative access to the Docker host. |
| `--allow-unchecked-gpu` | Accept a local GPU requirement when discovery finds no GPU.                                                                 |
| `--dry-run`             | Resolve, preflight, and translate without launching.                                                                        |

## What happens

1. The package is resolved and validated, and its bytes are captured for the session.
2. The selected runtime is checked against the Workbench's requirements.
3. The runtime is prepared: an image pulled or built, a container or sandbox created, the workspace mounted or copied.
4. Every declared tool, the runner, and authentication are verified inside it.
5. The runner launches. Only now can a model request happen.

Preflight failure stops the run before spending model tokens. A run spends your provider credentials and billing, and sandbox time on E2B and Daytona.

## The agent's context

The engine gives the runner a short `<workbench_context>` block before the package instructions, explaining the outbox and result delivery, and a `<workbench_runtime>` block with the actual workspace paths, access, and outbox path. It never includes environment values or credentials. The agent writes requested files to `WORKBENCH_OUTPUT_DIR`; see [Outcomes](/docs/cli/outcomes).
