# Factory CLI reference

Source: https://opvs.ai/docs/factory/cli

> The opvs ship, builds, machines, engines, env routines, projects and scheduled-runs commands.

The CLI commands that run the factory, read from `@opvs-ai/cli` 0.27.11. Every command takes `--help`. For boards, tasks, comments and the rest, see the [CLI reference](/developers/tools/cli).

Install: `npm install -g @opvs-ai/cli`, then sign in with `opvs auth request`. The ids below are examples; use your own.

## `opvs ship`: the ship line

All `ship` commands take `--project <id|slug>` and `--format text|json`. A slug that matches two projects is refused; pass the id from `opvs projects list`.

Command

Does

`opvs ship status`

Shows on or off, Practice or Live, the repository, the Ship app connection, what happens after a merge, and the owners

`opvs ship set --enabled <on|off> --mode <practice|live> --after-merge <merge-only|workflow|runner>`

Changes the ship line. Practice observes without shipping; Live can ship

`opvs ship connect [--open]`

Prints both ways to connect GitHub: install the Ship app, or link one already installed

`opvs ship prs [--pr <n,…>] [--card <ref,…>] [--state <s,…>] [--all]`

Lists the pull requests the ship line knows

`opvs ship hold <pr> --reason <text>`

Stops one pull request from shipping

`opvs ship release <pr>`

Lifts a hold

`opvs ship approve <pr> --head <sha>`

Approves an owner-class release at its exact 40-character head commit

`opvs ship owners add <user>` / `remove <user>`

Changes who may approve owner-class releases

```bash
opvs ship status --project 9d7642c4-8151-4c3e-977e-9f30d5a52844
# → on a project with no ship line yet:
# → This project has no ship line yet. Start one with: opvs ship set --project 9d7642c4-8151-4c3e-977e-9f30d5a52844 --enabled off --mode practice --after-merge merge-only
```

**Errors**

Message

When

What to do

`This project has no ship line yet. Start one with: …`

The project has no ship line

Run the `opvs ship set` command it prints

A slug refused as ambiguous

Two projects share the slug

Pass the project's UUID

## `opvs builds`: running builds

Command

Does

Needs

`opvs builds read <ref> [--last <1-5>]`

The build's current command, recent steps and messages

`board:read` and workspace membership

`opvs builds tell <ref> <message>`

Sends the build a message, or saves it on the card

`builds:tell`, or workspace admin

```bash
opvs builds read WEB-12 --last 3
opvs builds tell WEB-12 "The API client lives in src/clients/v2"
# → on a card that does not exist:
# → Error: could not resolve card 'WEB-99999' (the board could not be reached).
```

**Errors**

Message

When

What to do

`Error: could not resolve card '…'`

The ref is wrong, or its board is not in your workspace

Pass a card ref such as `WEB-12`, or the card's task UUID

## `opvs machines`: machines

Command

Does

`opvs machines list [--project <id>] [--json]`

This workspace's machines: name, short id, status, sidecar version, last health check, whether the build loop runs, project

`opvs machines get <id> [--json]`

One machine, by id, short code or prefix

```bash
opvs machines list
# → name  short_id  status  sidecar_version  last_health_check  worker_loop_running  worker_loop_changed_at  project_id
opvs machines get env_3k9x2ab
```

**Errors**

Message

When

What to do

`Error: '…' is not a valid environment reference.`

The id is not a short code, an 8+ character UUID prefix or a UUID

Use a short code like `env_3k9x2ab`, or the full UUID

## `opvs engines`: engines for the workspace

Command

Does

`opvs engines list [--json]`

Which engines are on, off, expired or timed

`opvs engines off <harness> --reason <text> [--until <when>]`

Switches an engine off. `--until` takes ISO 8601, `+2h` / `+30m`, or a local `HH:MM`. Without it, off until switched on

`opvs engines on <harness>`

Switches it back on

Harness names: `claude_code`, `codex`, `openhands`, `opencode`, `cursor`, `grok`, `pi`, `agy`.

```bash
opvs engines list
# → harness      state  reason  set by
# → claude_code  ON
opvs engines off codex --reason "Provider outage, retrying at 18:00Z" --until +2h
```

**Errors**

Message

When

What to do

`error: required option '--reason <text>' not specified`

`engines off` without a reason

Add `--reason`; the next person who looks sees it

## `opvs env routines`: scheduled prompts on a desk

Command

Does

Needs

`opvs env routines list <env-id>`

The desk's routines and their last runs

`opvs env routines set <env-id>`

Replaces every routine from a JSON array

Workspace admin

`opvs env routines run <env-id> <routine-id>`

Runs one now; skipped if that session is busy

Workspace admin

```bash
opvs env routines list 3f2b9c1e-7a4d-4e8b-9c2f-1d5e6a7b8c9d
# → on an id that is not one of your desks:
# → Error: environment '3f2b9c1e-7a4d-4e8b-9c2f-1d5e6a7b8c9d' not found
```

**Errors**

Message

When

What to do

`Error: environment '…' not found`

No desk with that id in your workspace

Find the id with `opvs machines list`

`403`

`set` or `run` by someone who is not a workspace admin

Ask a workspace admin

## `opvs projects`: projects for the factory

Command

Does

`opvs projects create -n <name> [-b <board-id>]`

Creates a project

`opvs projects add-board <id> <board_id>`

Adds a board

`opvs projects set-routing <id> [--model] [--provider] [--harness] [--claimable-by]`

Defaults every card inherits. `none` clears one

`opvs projects health <id> --profile factory`

Project and member-board health. Exit `0` healthy or incomplete, `2` not healthy, `1` when no verdict could be read

`opvs projects bundle get <id>` / `set <id>`

The rules and commands every build in the project receives. `set` replaces each list you pass

`opvs projects set-status <id> <active|on_hold|completed> [--handoff <text>]`

Lifecycle status

`opvs projects archive <id> [--undo]`

Hides the project; its boards leave it

```bash
opvs projects create -n "Checkout rebuild"
opvs projects health 812228dc-9e9f-4d12-8acb-91054d41ee79 --profile factory
# → Project health — Checkout rebuild
# → Verdict: NOT HEALTHY — at least one check failed
```

**Errors**

Message

When

What to do

`Error: Project not found`

The id is wrong or belongs to another workspace

Find it with `opvs projects list`

## Board and card commands the factory uses

Command

Does

`opvs boards projects <board>`

`resolved`, `none` or `ambiguous`: a factory board needs `resolved`

`opvs boards move-to-project <board> <projectId> --yes`

Moves a board to one project, leaving the others in one step

`opvs boards health <board> --profile factory`

Claim wiring, roles, dead dependencies. Exit `2` when a check fails

`opvs tasks runnable <boardId>`

The cards a builder could claim right now

The errors for these are in the [CLI reference](/developers/tools/cli#board-and-project-health).

## `opvs scheduled-runs`: start the factory later

Command

Does

`opvs scheduled-runs create --project <uuid> --run-at <time> [--board <uuid>]`

Queues a run

`opvs scheduled-runs list` / `get <id>` / `cancel <id>`

Manage queued runs

At `--run-at` (checked about once a minute) the project, or one board, is armed as if you pressed Play: builders start claiming and those builds spend. It stays armed until someone pauses it. Scheduling itself costs nothing.

```bash
opvs scheduled-runs create --project 812228dc-9e9f-4d12-8acb-91054d41ee79 --run-at 2026-11-07T08:00:00Z
opvs scheduled-runs list
# → [] when nothing is queued
```

**Errors**

Status

When

What to do

`403`

You are not a workspace admin

Ask a workspace admin

`404`

The project does not exist

Check the full project UUID
