# Install and sign in

Source: https://mostlyright.md/docs/start/install/

Install `mr-data`, approve the device in your browser and connect the CLI to the hosted backend.

## Install

The package is `mostlyright-data`. The command it installs is `mr-data`.

```bash
python -m pip install mostlyright-data
```

Or as a standalone tool, with its own interpreter:

```bash
uv tool install mostlyright-data
```

The package needs CPython 3.11 or newer and has no third-party dependencies, compiled extensions or
Docker image. It runs on Linux, macOS and Windows because all builds execute on the hosted backend.

Check what you got:

```bash
mr-data --version
```

```text
mr-data 0.19.2
```

## Everything runs on the backend

`mr-data` sends requests to the hosted backend and prints the results. The hosted worker fetches and
parses sources, runs the SQL and checks, then writes the Parquet files. The run receipt records what
happened during the build.

- A command that reaches the backend needs a signed-in device credential. `mr-data --version`,
  `mr-data --help` and `mr-data dataset categories` do not.
- Building is free with a signed-in account. Reading data past the free sample counts against a
  monthly allowance. See [What counts against the allowance](#what-counts-against-the-allowance).

## Sign in

```bash
mr-data login
```

This is an RFC 8628 device flow against `https://mostlyright.md`:

1. The command prints a short user code on stderr and an address to approve it at, then tries to
   open that address in your browser. On a headless machine, open it yourself.
2. You approve the device in the browser as the signed-in user.
3. The command creates and stores a device key.

```text
    WDJB-MJHT

Open https://mostlyright.md/device?user_code=WDJB-MJHT to approve this device.
Waiting for approval...
```

The key is stored in `~/.mostlyright/credentials` with mode `0600`. The command prints its `mr_cli_`
prefix and last four characters, but never the raw key. If a credential already exists, `login`
returns `LOGIN_CREDENTIALS_EXIST`. Use `mr-data auth rotate` to replace it. Rotation revokes the old
key remotely before removing the local copy.

Two more flags: `--device-name NAME`, which defaults to the machine's hostname, and
`--credential-store secure-file`. Set `MOSTLYRIGHT_CLOUD_URL` to sign in against a different
deployment.

## Check the credential

```bash
mr-data auth status --json
```

`mr-data whoami` is the compatibility alias for the same thing. Both validate the effective
credential with Cloud and report stored metadata separately. Neither prints a credential.

```json
{
  "schema_version": "mr-data-auth-status.v1",
  "status": "authenticated",
  "effective_source": "stored_device",
  "remote_validation": "validated",
  "device": {
    "id": "zn0aFEzQjXzOH16F01VcWO4a5rg3NQTZ",
    "name": "my-laptop",
    "prefix": "mr_cli_",
    "last_four": "wunu",
    "created_at": "2026-08-19T20:25:49.647Z",
    "last_used_at": "2026-09-12T08:08:20.372Z"
  },
  "identity": {
    "cloud": { "organization_id": "WQUz...", "user_id": "VQGT...", "role": "owner" },
    "studio": {
      "principal_id": "8801ad48-56aa-564a-87e3-65ca7bd1fc3c",
      "workspace_id": "39ffafde-86ed-5d7b-b337-1c205ea79390"
    }
  },
  "stored_state": {
    "status": "available",
    "device": { "cloud_url": "https://mostlyright.md", "key_id": "zn0a...", "prefix": "mr_cli_" }
  }
}
```

`status` is `authenticated`, `refused` or `error`. A refusal includes `error_code` instead of
`identity`. A rate-limit refusal also includes `retry_after_seconds`.

The rest of `mr-data auth` is `devices`, `tokens`, `rotate`, `logout` and `recover`. `devices`
reports the device metadata Cloud holds. `tokens` says what the Studio transport token is and is
not. `logout` revokes remotely, then removes locally. `recover` resumes or clears an interrupted
credential write.

`MOSTLYRIGHT_API_KEY` in the environment takes precedence over the stored device key for that
process. `auth status` says so in `environment_notice`. `mr-data` cannot unset a credential a parent
process put in the environment.

## Where the agent skill goes

The package includes the `mr-data-build` agent skill. The first `mr-data` command copies it into your
agent's personal skill directory:

```text
~/.claude/skills/mr-data-build/
```

Codex gets the same tree at `~/.codex/skills/mr-data-build/`. `CLAUDE_CONFIG_DIR` and `CODEX_HOME`
move those roots. `mr-data` leaves a skill you have edited alone. A read-only home or a full disk
returns a reason and does not fail your command.

Turn the copy off with `MOSTLYRIGHT_SKILL_AUTOINSTALL=0`:

```bash
MOSTLYRIGHT_SKILL_AUTOINSTALL=0 mr-data status RUN_ID
```

## What counts against the allowance

Building is free with an account: datasets, recipes, runs and refreshes. Any signed-in workspace
can run every `mr-data` build command.

The first 500 rows of every table, in stored order, are free to everyone. Past them, a free
workspace may read 100,000 rows and run 1,000 queries a UTC month, shared by all of its members. A query costs one query plus the rows it
returns, and that includes `mr-data query` over your own runs. A download, including `mr-data
download`, counts the rows it contains, plus one query per table. A download whose size is known
in advance and would take you past your free rows is not started: the 402 below then also carries
`remaining` and `requested`.
A page of a table's parts is cut to the parts that fit instead, with `truncated: true`. A
subscribed workspace is never counted, for anyone working in it.

A spent allowance answers HTTP 402 with one body on every API, CLI and MCP path:

```json
{"schema_version":"mostlyright-usage-limit.v1","error":"usage_limit_exceeded","unit":"rows","limit":100000,"used":100250,"resets_at":"2026-11-01T00:00:00.000Z","upgrade_url":"https://mostlyright.md/dashboard/billing","detail":"You have used 100,250 of 100,000 free rows this month. Upgrade the workspace or wait for the reset. The first rows of every table stay free."}
```

`mr-data` prints this as `THIN_USAGE_LIMIT`. Subscribe at `upgrade_url` or wait for `resets_at`.
Two other errors have different causes. `THIN_AUTHENTICATION_FAILED` is HTTP 401 and means the
stored key was rejected, so sign in again. `THIN_STUDIO_UNAVAILABLE` is HTTP 503 and means you
should try later.

## The `--json` convention

Every command takes `--json` and prints exactly one machine-readable JSON object on stdout. It is a
per-command flag, written after the command name:

```bash
mr-data dataset categories --json
mr-data status RUN_ID --json
```

Every object includes a `schema_version` for its shape and a `status` for the outcome:
`dataset_created`, `recipe_registered`, `run_queued`, `run_status_reported`, `checks_reported`,
`query_answered`, `artifacts_downloaded`. The CLI keys and zero-pads repeated items rather than
listing them, so expect `{"row 01": …, "row 02": …}` where a list would be.

Exit codes: `0` on success, `2` where the answer is a gate a script must act on. A run held at the
run confirmation, a failed run read by `status` and a table that disagrees with its manifest all
exit `2`. An error prints a `code` and a `detail`. The CLI produces codes beginning `THIN_` before it
sends anything. Other codes come directly from the backend. [Run states and
errors](/docs/reference/run-states-and-errors/) lists them.

Two more environment variables matter. `MR_DATA_NO_ACTIVITY=1` stops commands reporting what they
are doing to the dataset page, and `--no-activity` does the same for one invocation.
`MOSTLYRIGHT_CLOUD_URL` points the whole client at another deployment.

## Next

- [Build your first dataset](/docs/start/first-dataset/): dataset, recipe, one full build and
  live table, in commands you can paste.
- [How a build works](/docs/start/how-it-works/): the objects, the run states and what is immutable.
- [CLI reference](/docs/reference/cli/): every command, one line each.
