# CLI reference

Source: https://mostlyright.md/docs/reference/cli/

Use one `mr-data` command to work with the hosted backend and receive structured output under `--json`.

## Install

```bash
pip install mostlyright-data
mr-data --version
# mr-data 0.31.3
```

The wheel installs `mr-data` and nothing else. Every command runs on a bare CPython 3.11+ with no compiled extension, because the engine, the readers and the worker image live on the backend. The wheel also carries the `mr-data-build` agent skill, and the first invocation that finds it missing places it under `~/.claude/skills/mr-data-build` and `~/.codex/skills/mr-data-build`.

[`mr-data login`](/docs/reference/cli/auth/) signs this machine in once. It stores the credential at `~/.mostlyright/credentials`, mode 0600, and never prints it.

## Conventions every command shares

Every command accepts `--json`. It writes one JSON object to stdout and nothing else, no progress lines and no prose. Human mode prints the same payload as lines. Every hosted payload carries `schema_version` (prefix `mostlyright-thin-client-`), a `status` word and `"lane": "hosted"`. Three of the four portable commands carry their own `mr-data-*` schema versions: `auth`, `login` and `whoami`. `clarify`, the fourth, carries none.

Errors go to stderr. With `--json`, an error is one object:

```json title="a refusal, --json"
{
  "schema_version": "mr-data-error.v1",
  "code": "THIN_REQUEST_INVALID",
  "error": "mr-data query needs the question to ask: mr-data query RUN \"SELECT ...\"",
  "headline": "mr-data query needs the question to ask: mr-data query RUN \"SELECT ...\"",
  "remediation": ["…one line per step…"]
}
```

A refusal with a Studio retry window also includes `retry_after_seconds`.

From 0.27.1, `recipe` is the one command that tells the dataset page what it is doing, and `clarify --dataset` puts a pending question there. The recipe line is held back while the page shows a current line the agent set itself. The report never fails a command. `--no-activity` turns it off for one invocation. `MR_DATA_NO_ACTIVITY=1` turns it off for a whole schedule, which cannot pass a flag. `run`, `promote`, `checks`, `peek`, `query`, `receipt` and `download` report nothing. They still accept `--no-activity`, which has no effect there. Up to 0.27.0 they each reported a line too.

`mr-data download --output` takes a relative or absolute folder and expands `~`. `--output` defaults to `run-artifacts` in the current directory, and it never overwrites anything already there.

`--hosted` is accepted and stripped in silence. Every invocation already runs on the hosted backend. There is no `--local`.

### Exit codes

| Code | What it means |
| --- | --- |
| `0` | The command did what it says. |
| `1` | A no that is not a fault. `clarify` rejected the gate. `table archive` or `demote` did not move every table it was given. An `auth` payload includes a status that is none of the success words and none of `unsupported`, `not_implemented` or `refused`, which leaves `error` and `recovery_required`. |
| `2` | Every typed error, a `THIN_*` object on stderr, and the derived gates in the next table. |

Commands that derive a non-zero exit from a successful payload:

| Command | Exits `2` when |
| --- | --- |
| `run` | `status` is `run_awaiting_confirmation`. The run is held at the confirmation gate and has not started. |
| `status` | the run's own `status` is `failed`. |
| `watch` | the terminal event was `run_failed`. |
| `checks` | `checks_failed` is non-zero, or the run failed. |
| `verify` | `findings` is non-empty. |
| `query` | `status` is `query_still_running`. This command stopped waiting. The query did not stop. |
| `probe` | `status` is anything but `probe_answered`. |
| `auth tokens list` / `auth tokens revoke` | always. `status` is `unsupported`. |

`table archive` and `demote` take a list and never stop at the first error. They exit `1` when `counts.refused + counts.unreachable` is non-zero.

### Environment variables

| Variable | Effect |
| --- | --- |
| `MOSTLYRIGHT_CLOUD_URL` | The cloud origin to sign in against and resolve credentials for. `https://mostlyright.md` when unset. It must be an absolute HTTPS URL with no user information, no fragment and no trailing slash. A path or a query is accepted. A hosted command refuses `THIN_CONFIG_INVALID` for a URL that is not, and `mr-data login` refuses `LOGIN_CONFIG_INVALID`. |
| `MOSTLYRIGHT_API_KEY` | The legacy v1 shared key. Setting it makes it the effective authority. Receipts then carry `"environment_authority": "remains_effective"`, so a logout that cannot revoke it says so. |
| `MOSTLYRIGHT_ATTENDED` | Exactly `1` says a person is here to answer a clarifying question. Exactly `0` says nobody is, and that `0` vetoes any `--attended` flag. `mr-data` reads any other value as unattended and reports `unreadable_environment`. |
| `MR_DATA_NO_ACTIVITY` | `1` turns off the automatic dataset-page activity report for every command in that environment. |
| `MOSTLYRIGHT_SKILL_AUTOINSTALL` | `0` stops the wheel placing the `mr-data-build` agent skill. |
| `CLAUDE_CONFIG_DIR`, `CODEX_HOME` | Where the wheel places that skill. Default `~/.claude` and `~/.codex`. |
| `CLAUDECODE`, `CLAUDE_CODE_SESSION`, `CODEX_SESSION` | A non-empty value means a conversation with somebody in it. `mr-data` never reads the value. |
| `CI`, `GITHUB_ACTIONS` | Either one beside an agent-host variable makes the session headless. An agent host on a runner has nobody to ask. |

## Every command

| Command | What it does | Page |
| --- | --- | --- |
| `artifacts` | List the artifacts a run sealed, without downloading bytes | [Reading a table](/docs/reference/cli/read/) |
| `ask` | Ask the support agent and follow its answer | [Public datasets and support](/docs/reference/cli/public/) |
| `connected` | List or connect public datasets in the workspace | [Public datasets and support](/docs/reference/cli/public/) |
| `match` | Match records, manage profiles and follow jobs | [Record matching](/docs/reference/cli/match/) |
| `models` | List available models or suggest enrichment from a run's preview | [Enrich a table](/docs/build/enrich/) |
| `public` | Discover datasets and inspect schemas, samples and query results | [Public datasets and support](/docs/reference/cli/public/) |
| `reader` | Normalize pinned Reader options through Studio | [Readers](/docs/reference/readers/) |
| `search` | Search public rows and manage versioned table search | [Search](/docs/reference/cli/search/) |
| `source` | Queue and read a bounded source inspection | [Probe a source](/docs/build/probe-sources/) |
| `catalog` | ask the public-source catalogue what might answer a question | [Recipes and sources](/docs/reference/cli/recipe/) |
| `checks` | report how each check the recipe declared came out for one run | [Runs](/docs/reference/cli/run/) |
| `connections` | list saved connections available for recipes | [Recipes and sources](/docs/reference/cli/recipe/) |
| `cover` | generate and attach one branded cover image to a dataset | [Datasets](/docs/reference/cli/dataset/) |
| `dataset` | create the page, correct it, write its record, say who can read it, and retire it | [Datasets](/docs/reference/cli/dataset/) |
| `demote` | ask Studio to withdraw the live pointer from one table or many | [Tables](/docs/reference/cli/table/) |
| `diff` | compare two runs and say what changed | [Runs](/docs/reference/cli/run/) |
| `download` | bring one run's artifacts back here and check each one's digest | [Reading a table](/docs/reference/cli/read/) |
| `keys` | store a source credential by name, name the stored ones, and withdraw one | [Recipes and sources](/docs/reference/cli/recipe/) |
| `note` | write one cell of this run's decision record, or list what is written | [Runs](/docs/reference/cli/run/) |
| `open` | hand this terminal's session to the browser as a single-use address | [Signing in](/docs/reference/cli/auth/) |
| `parts` | list one table version's parts, so a training loader can shard them across workers | [Reading a table](/docs/reference/cli/read/) |
| `peek` | print the columns, types and first rows of the preview one run wrote | [Reading a table](/docs/reference/cli/read/) |
| `pin` | ask Studio to pin the live pointer and report the returned state | [Tables](/docs/reference/cli/table/) |
| `probe` | ask one source one question and print what it answered | [Recipes and sources](/docs/reference/cli/recipe/) |
| `promote` | record how often one table refreshes and why. A first succeeded run goes live without it | [Tables](/docs/reference/cli/table/) |
| `query` | ask one bounded read-only question of the table one run produced | [Reading a table](/docs/reference/cli/read/) |
| `receipt` | print the receipt, the record of how one run was built | [Runs](/docs/reference/cli/run/) |
| `recipe` | register or inspect recipe revisions, including incremental-refresh readiness | [Recipes and sources](/docs/reference/cli/recipe/) |
| `reschedule` | change how often one table refreshes, without starting a run | [Tables](/docs/reference/cli/table/) |
| `run` | start one run against a registered recipe, under stated ceilings | [Runs](/docs/reference/cli/run/) |
| `runs` | report this workspace's own runs, narrowed by status and by mode | [Runs](/docs/reference/cli/run/) |
| `status` | report what one run is doing, what it delivered, and why it failed | [Runs](/docs/reference/cli/run/) |
| `stream` | record a public wss venue and name the recording a build reads | [Streams](/docs/reference/cli/stream/) |
| `table` | report, resync, rename or retire a table | [Tables](/docs/reference/cli/table/) |
| `unpin` | ask Studio to remove a pin and report the returned pointer state | [Tables](/docs/reference/cli/table/) |
| `verify` | check one run's table against its manifest, part by part with `--deep` | [Runs](/docs/reference/cli/run/) |
| `watch` | stream one run's live progress, resuming across stream cuts | [Runs](/docs/reference/cli/run/) |
| `auth` | validate the effective device key with Cloud and explain the token boundary, on a bare interpreter with nothing installed beyond this wheel | [Signing in](/docs/reference/cli/auth/) |
| `clarify` | check whether a person is available to answer one question, then format the answer as a record. It contacts no external service unless you name a dataset | [Signing in](/docs/reference/cli/auth/) |
| `login` | sign in and store a device credential | [Signing in](/docs/reference/cli/auth/) |
| `whoami` | the compatibility alias for `auth status`, which validates against the remote | [Signing in](/docs/reference/cli/auth/) |

### Commands that should be hosted and are not yet

`mr-data <name>` refuses `THIN_COMMAND_HOSTED_PENDING` with the reason and exits `2`.

```
acquire-slices
```

`acquire-slices` does not run on the backend yet. The hosted request contract accepts one URL. A slice order needs two origin-bound locators, an ordered plan, and N+2 requests sharing one DNS epoch, which one hosted session each would break.

### Backend operator steps, which are never run from here

```
export-hosted-candidate
```

`export-hosted-candidate` refuses `THIN_COMMAND_IS_WORKER_INTERNAL`. It packages a finished Build for the backend to ingest, and the backend runs it on its own artifacts.

Any other word refuses `THIN_UNKNOWN_COMMAND`, a misspelling and a retired name alike. `mr-data --help` prints the whole list, and there is no second list of retired names.

## Refusal codes this client raises before the network

A `THIN_*` code is a stable token a script may branch on. None of them carries a credential.

| Code | What happened |
| --- | --- |
| `THIN_UNKNOWN_COMMAND` | The first non-flag token is not a command, or nothing named a command. |
| `THIN_COMMAND_HOSTED_PENDING` | The name exists and does not run on the backend yet. |
| `THIN_COMMAND_IS_WORKER_INTERNAL` | The name is a backend operator step. |
| `THIN_COMMAND_HAS_NO_HOSTED_LANE` | `--hosted` sits in front of one of those two names. |
| `THIN_COMMAND_FAILED` | An exception this client does not type. Report it. |
| `THIN_REQUEST_INVALID` | The contract does not accept the request this invocation assembled. A missing recipe, a sample with no ceiling, a backfill with no window. |
| `THIN_ARGUMENT_INVALID` | One stated value falls outside a closed vocabulary this client holds. A run identifier that is not one, or a `--mode` or `--status` naming a word the contract does not have. The message alone says how to correct it. |
| `THIN_CONFIG_INVALID` | `MOSTLYRIGHT_CLOUD_URL` is not a usable HTTPS origin. |
| `THIN_RESPONSE_INVALID` | Studio returned a body this client will not render. A required member missing, a URL that is not HTTPS, or a narrative cell that did not declare itself unsealed. |
| `THIN_RESPONSE_TOO_LARGE` | A JSON response exceeded the byte ceiling for its route (1 MiB). |
| `THIN_AUTHENTICATION_FAILED` | Cloud rejected the stored device credential. Run `mr-data login`. |
| `THIN_AUTHORIZATION_DENIED` | The Studio token does not carry the authority this call needs. The sentence quotes Studio's own code and the HTTP status. |
| `THIN_NOT_FOUND` | Studio has no such resource. A run in another workspace reads like one that does not exist. |
| `THIN_RATE_LIMITED` | Cloud asked this command to retry later. `retry_after_seconds` is on the refusal. |
| `THIN_STUDIO_UNREACHABLE` | Studio did not answer at all. |
| `THIN_STUDIO_UNAVAILABLE` | Cloud could not create a Studio token. |
| `THIN_STUDIO_REFUSED` | Studio returned an error status without its own code. |
| `THIN_STUDIO_<CODE>` | Studio returned its own code, carried through verbatim. `THIN_STUDIO_CONFIRM_REQUIRED`, `THIN_STUDIO_NOTHING_TO_PROMOTE`, `THIN_STUDIO_QUERY_TOO_MANY_PARTS` and the rest all follow this one rule. |

Per-command codes sit on the page for the command that raises them, among them `THIN_DOWNLOAD_DIGEST_MISMATCH`, `THIN_NO_CHECK_RESULTS`, `THIN_SECRET_MATERIAL_INVALID` and `THIN_NARRATIVE_CELL_TOO_LARGE`.

## Where to go next

- [Signing in](/docs/reference/cli/auth/): `login`, `auth`, `whoami`, `open`, `clarify`
- [Datasets](/docs/reference/cli/dataset/): `dataset`, `cover`
- [Recipes and sources](/docs/reference/cli/recipe/): `recipe`, `probe`, `catalog`, `connections`, `keys`
- [Runs](/docs/reference/cli/run/): `run`, `runs`, `status`, `watch`, `checks`, `receipt`, `note`, `diff`, `verify`
- [Reading a table](/docs/reference/cli/read/): `peek`, `query`, `download`, `parts`
- [Tables](/docs/reference/cli/table/): `table`, `promote`, `reschedule`, `pin`, `unpin`, `demote`
- [Streams](/docs/reference/cli/stream/): `stream`
