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

# CLI: Instructions

> The opentrain instructions command group — author, review, publish, and sync rich instruction manuals from the terminal.

`opentrain instructions` is the agent-first authoring surface for [instruction manuals](/docs/developers/concepts/instruction-manuals). Every command wraps the corresponding [Instructions API endpoint](/docs/developers/api-reference/instructions/capabilities), supports `--json` for the raw response, and accepts `-` for stdin on file inputs. `--key <idempotency-key>` is available on workspace/manual creation, direct and stored changeset apply, changeset submit, revision restore, publish, and docs-as-code sync—not on update, archive, permission, reviewer-decision, or asset commands. Requires CLI **0.3.0 or later** (`npm install -g @opentrain-ai/cli@latest`).

Changeset-backed page authoring helpers and `sync` accept `--dry-run` to validate without writing and `--submit` to store the changeset for human review. Those flags do not apply to metadata, permission, reviewer-decision, asset, or publication commands. Whole-document replacement always demands the explicit `--confirm-replace` flag.

## Discovery and search

```bash theme={null}
opentrain instructions capabilities --json
opentrain instructions search --query "bounding boxes" [--workspace <id>] [--manual <id>] [--audience WORKER]
```

## Workspaces and permissions

```bash theme={null}
opentrain instructions workspaces list|get|create|update|archive
opentrain instructions workspaces create --name "Operations" [--key <k>]
opentrain instructions permissions list --workspace <id>
opentrain instructions permissions grant --workspace <id> --principal <userId> --role EDITOR|REVIEWER|VIEWER
opentrain instructions permissions revoke --workspace <id> --principal <userId>
```

Workspace creation also requires a verified user with employer organization membership and persists the creator's `OWNER` permission record. Permission listing needs both `instructions:read` and `instructions:publish`; list/grant/revoke require workspace `OWNER`. Granting an existing principal updates their role.

## Manuals and trees

```bash theme={null}
opentrain instructions manuals list --workspace <id>
opentrain instructions manuals create --workspace <id> --title "Reviewer handbook" \
  [--audience REVIEWER] [--binding JOB:<jobId>[:precedence]]... [--key <k>]
opentrain instructions manuals get|update|archive --manual <id>
opentrain instructions tree --manual <id> [--audience WORKER] [--include-archived]
```

Archive commands require workspace `OWNER`. They retain rows but make the archived workspace/manual inaccessible through the current public API. `tree --audience` is an exact-match draft filter.

## Pages

```bash theme={null}
opentrain instructions page get --page <id> [--revision N] [--format json|html|markdown]
opentrain instructions page create --workspace <id> --manual <id> --title "Edge cases" \
  [--parent <pageId>] [--content-file doc.json|-] [--page-key <clientPageKey>]
opentrain instructions page patch --workspace <id> --page <id> --base-revision N \
  [--base-checksum <sha256>] --ops-file patch.json|-
opentrain instructions page replace --workspace <id> --page <id> --base-revision N \
  --content-file doc.json --confirm-replace
opentrain instructions page move --workspace <id> --page <id> (--parent <id> | --root) [--position N]
opentrain instructions page rename|archive|restore --workspace <id> --page <id> [...]
```

`--format markdown` always prints the machine-readable loss report alongside the render — nothing is silently down-converted. Content files accept a full canonical envelope or a bare `doc` node (the CLI wraps and checksums it locally).

## Changesets

```bash theme={null}
opentrain instructions changeset validate|diff|apply|submit --file changeset.json|- [--workspace <id>]
opentrain instructions changeset list --workspace <id> [--status SUBMITTED]
opentrain instructions changeset get --changeset <id>
# Reviewer lifecycle
opentrain instructions changeset approve --changeset <id> [--note "…"]
opentrain instructions changeset reject  --changeset <id> [--note "…"]
opentrain instructions changeset apply   --changeset <id> [--key <k>]   # apply a stored APPROVED proposal
```

A `CREATE_PAGE` operation with `clientPageKey: "x"` can be referenced by other operations in the same file as `parentPageId: "new:x"`, in any order. Conflicted applies print structured conflicts and exit non-zero.

## Versions and publications

```bash theme={null}
opentrain instructions versions list --manual <id>
opentrain instructions versions diff --manual <id> --a N --b N
opentrain instructions versions restore --manual <id> --revision N [--key <k>]
opentrain instructions publications list --manual <id>
opentrain instructions publish --manual <id> --base-revision N [--audience WORKER]... [--note "…"] [--key <k>]
opentrain instructions manifest --manual <id> --publication N [--audience WORKER]
```

Restore never rewrites history — it lands as a new revision. Publishing needs `instructions:publish` plus workspace `OWNER`. Omitting every `--audience` publishes to all four audiences; pass one or more flags for a narrower release.

## Private media

```bash theme={null}
opentrain instructions assets upload --workspace <id> --file ./walkthrough.mp4   # prepare + PUT + finalize
opentrain instructions assets prepare|finalize|list|get [...]
opentrain instructions assets attach --workspace <id> --page <id> --asset <id> [--node <nodeId>]
```

The CLI hashes the file locally (SHA-256), infers the kind from the MIME type, and attaches by asset ID — documents never carry raw storage URLs. Finalization confirms trusted upload metadata but does not independently re-hash the stored bytes server-side.

## Docs-as-code: checkout, status, diff, sync

```bash theme={null}
opentrain instructions checkout --workspace <id> --manual <id> --dir ./handbook
opentrain instructions status --dir ./handbook [--remote]
opentrain instructions diff --dir ./handbook
opentrain instructions sync --dir ./handbook --confirm-replace [--dry-run] [--submit] [--key <k>]
```

`checkout` writes each page as canonical JSON plus a manifest of page IDs, revisions, and checksums. Edit the files, inspect drift with `status`/`diff`, then `sync` pushes every modified page back as one revision-guarded changeset and advances the manifest. `--dry-run` validates first; `--submit` routes the sync through human review.

## Render previews

```bash theme={null}
opentrain instructions preview --page <id> [--revision N] --format html|markdown
opentrain instructions preview --content-file doc.json --format markdown
```
