# Auth, config, and output

> How purvey signs in, which commands need which access, where settings live, and how output, errors, and exit codes work.

HTML version: https://www.purveyors.io/docs/cli/auth-output

Use this page when you run purvey in scripts, CI, or agent tools. Output format, error envelopes, and exit codes are stable parts of the CLI contract.

purvey auth login stores a scoped key for your account on this machine. purvey auth logout removes it locally; revoke the key from your API keys in the Parchment Console if the machine is lost.

## purvey auth login

Log in to purveyors.io.

Usage: `purvey auth login [options]`

Access: None. Works without signing in.

| Argument or flag | Details |
| --- | --- |
| `--headless` | Print the approval URL instead of opening a browser; use it for agents, SSH sessions, and remote machines. The CLI finishes on its own once you approve. |

Examples:

```bash
purvey auth login
purvey auth login --headless
```

## purvey auth status

Show current login status and role.

Usage: `purvey auth status [options]`

Access: None. Works without signing in.

| Argument or flag | Details |
| --- | --- |
| `--pretty` | Print the status as indented, colorized JSON. |
| `--csv` | Print the status as a CSV row. |

Examples:

```bash
purvey auth status
purvey auth status --pretty
purvey auth status --json
```

## purvey auth whoami

Show the identity, plan, scopes, and capabilities of the active credential.

Usage: `purvey auth whoami`

Access: None. Works without signing in.

- Prints the account details unchanged: authenticated, userId, appRoles, primaryAppRole, apiPlan, ppiAccess, apiScopes, and capabilities (capabilities.profileStudio shows Studio access).
- Uses PARCHMENT_API_KEY or PURVEYORS_API_KEY when set, otherwise the stored login key.
- Without a credential it prints a signed-out result (authenticated: false).

Examples:

```bash
purvey auth whoami --pretty
purvey auth whoami | jq '.capabilities.profileStudio'
```

## purvey auth logout

Clear stored credentials.

Usage: `purvey auth logout`

Access: None. Works without signing in.

Examples:

```bash
purvey auth logout
```

## Access roles

Commands list the access they need. purvey auth login stores a scoped key for your account; PARCHMENT_API_KEY or PURVEYORS_API_KEY overrides it when set.

| Role | Meaning |
| --- | --- |
| viewer | any signed-in account, or any API key with catalog:read; enough for every catalog command. |
| member | a Purveyors membership; required for inventory, roast, roast-batch, sales, tasting, procurement, and reference-profile commands. |

## Global options

| Flag | Details |
| --- | --- |
| `--json` | Print results as compact JSON, the default for data commands; use it to be explicit. |
| `--pretty` | Print results as indented, colorized JSON for reading. |
| `--csv` | Print list results as CSV on commands that support it. |
| `--help` | Show help for purvey or any command. |
| `--version` | Print the installed CLI version. |

## Output and errors

Standard output: Structured JSON by default for most commands, CSV when explicitly requested on supporting commands, and human-readable reference text for `purvey context` unless JSON is requested.

Standard error: interactive progress and prompts, plus human-readable or structured fatal errors depending on mode.

- Most commands emit compact JSON to stdout by default.
- Use --json to request compact JSON explicitly.
- Use --pretty for indented JSON.
- Use --csv for array-shaped results that support CSV output.
- PURVEYORS_API_KEY or PARCHMENT_API_KEY, when set, is used instead of the key stored by `purvey auth login`.
- `purvey context` prints dense human-readable operator reference text unless --json or --pretty is passed.
- `purvey manifest` is the preferred machine-readable contract and always emits it on stdout.
- `purvey context --json` stays available for compatibility parity with existing context-based callers.
- `@purveyors/cli/manifest` exposes the same machine-readable contract for in-process consumers.
- `purvey config list/get/set/reset` stay human-readable in an interactive TTY, but emit JSON on stdout in machine mode and reject --csv.
- In interactive use, stderr may also carry prompts, spinners, and human-readable status lines.
- Parser mistakes like unknown options, unknown commands, and missing required arguments follow the same fatal-error contract as runtime command failures.
- Important exception: auth status prints human-readable output in an interactive TTY unless --json, --pretty, or --csv is passed; when piped or redirected it emits structured JSON automatically.

> **Structured errors**
>
> Emitted for parser and runtime command failures when the invocation is non-interactive or when --json, --pretty, or --csv selects a machine-readable output mode. Every error includes error, code, exitCode, message. `purvey auth status` keeps its status payload on stdout even when unauthenticated; this envelope documents command failures.

## Exit codes

| Exit code | Code | Meaning |
| --- | --- | --- |
| 0 | OK | success. |
| 1 | GENERAL_ERROR | unexpected error. |
| 2 | INVALID_ARGUMENT | invalid argument or input. |
| 3 | AUTH_ERROR | not signed in, the stored key was revoked, or your account or API key lacks access to this command. |
| 4 | NOT_FOUND | resource not found. |
| 5 | DEPENDENCY_CONFLICT | the change conflicts with related records, such as deleting a coffee that still has roasts or sales. |
| 6 | CONFIG_ERROR | configuration problem, such as a file path or API address the CLI cannot use. |

## ID reference

Each ID belongs to one kind of record. Passing the wrong kind is the most common reason a command returns NOT_FOUND.

| ID | Identifies | Used by |
| --- | --- | --- |
| `catalog_id` | a coffee listed in the Purveyors catalog | `catalog get`, `catalog similar`, `catalog compare`, `catalog price-history`, `inventory add --catalog-id`, `tasting get <bean-id>`, `roast list --catalog-id` |
| `inventory_id` | a coffee in your green inventory | `inventory get/update/delete`, `roast --coffee-id`, `roast list --coffee-id`, `tasting rate [bean-id]` |
| `roast_id` | one of your roast profiles | `roast get/chart/artisan-file/delete`, `roast list --roast-id`, `sales record --roast-id`, `sales list --roast-id`, `reference-profile compare roast:<roast-id>`, `reference-profile preview-from-roast/from-roast` |
| `batch_id` | one of your roast batches (a UUID); batch names can repeat, batch IDs cannot | `roast-batch get/update/delete`, `roast list --batch-id`, `roast create/import/update/from-reference --batch-id`, `sales record --batch-id`, `sales list --batch-id` |
| `sale_id` | one of your recorded sales | `sales update/delete` |
| `reference_profile_id` | one of your Studio reference profiles | `reference-profile get`, `reference-profile chart`, `reference-profile preview/save`, `reference-profile export`, `reference-profile artisan-file`, `reference-profile compare profile:<uuid>`, `roast from-reference` |
| `reference_revision_id` | immutable revision belonging to a reference profile | `reference-profile chart`, `reference-profile preview/save`, `reference-profile export`, `reference-profile compare revision:<uuid>`, `roast from-reference` |

## Common errors

| Problem | Exit codes | What to do |
| --- | --- | --- |
| Not logged in | 3 | Run `purvey auth login` or `purvey auth login --headless`. Run `purvey auth status` to confirm role after login. |
| Wrong ID type | 2, 4 | Verify whether the command wants catalog_id, inventory_id, roast_id, batch_id, sale_id, reference_profile_id, or reference_revision_id. See the ID map. |
| Missing required args in write commands | 2 | Pass the required positional arguments and flags shown by `--help`; `--form` is an interactive terminal alternative. |
| Parser mistakes like unknown options or commands | 2 | Unknown options, unknown commands, and missing required arguments use the same JSON error envelope contract in machine mode. In an interactive terminal with no explicit output flag, those parser failures stay human-readable. |
| Dependency conflict on delete | 5 | Delete dependent roast profiles and sales records explicitly, then retry. |
| Batch name matches more than one batch | 2 | `sales record --coffee-id --batch-name` lists each matching batch ID with its date; run it again with --batch-id. |
| Mutually exclusive watch flags | 2 | `roast watch` forbids using --auto-match together with --coffee-id. |
| Pagination only returning the first page | None | Only these commands page with --offset (default --limit): catalog search 10, inventory list 20, roast list 20, roast-batch list 20, sales list 20. For example `--limit 20 --offset 40` returns items 41-60. `roast list --include-totals` adds meta.totals.roasts; the last page is the one where --offset plus the rows returned reaches it. |

## Local files

| File | Path |
| --- | --- |
| Stored sign-in | ~/.config/purvey/credentials.json |
| Settings | ~/.config/purvey/config.json |

## purvey config list

Show all config values.

Usage: `purvey config list`

Access: None. Works without signing in.

- Interactive terminals print human-readable key = value lines.
- Machine mode emits the full config object as JSON.
- --csv is not supported on config commands.

Examples:

```bash
purvey config list
purvey config list --json
```

## purvey config get

Get a config value.

Usage: `purvey config get <key>`

Access: None. Works without signing in.

- Interactive terminals print the raw value with no decorators.
- Machine mode emits {"\<key>": value|null}.
- --csv is not supported on config commands.

| Argument or flag | Details |
| --- | --- |
| `<key>` | Required: Config key. |

Examples:

```bash
purvey config get form-mode
purvey config get form-mode --json
```

## purvey config set

Set a config value.

Usage: `purvey config set <key> <value>`

Access: None. Works without signing in.

- Interactive terminals print a human-readable success line.
- Machine mode emits the updated config value as JSON.
- --csv is not supported on config commands.

| Argument or flag | Details |
| --- | --- |
| `<key>` | Required: Config key. |
| `<value>` | Required: Config value. |

Examples:

```bash
purvey config set form-mode true
purvey config set form-mode true --json
```

## purvey config reset

Reset config to defaults.

Usage: `purvey config reset`

Access: None. Works without signing in.

- Interactive terminals print a human-readable success line.
- Machine mode emits {}.
- --csv is not supported on config commands.

Examples:

```bash
purvey config reset
purvey config reset --json
```

## Related

- [CLI overview](https://www.purveyors.io/docs/cli/overview): Install, sign in, and see every command group.
- [Context and manifest](https://www.purveyors.io/docs/cli/context-manifest): Readable and machine-readable references for your installed version.
- [API keys](https://www.purveyors.io/api-dashboard/keys): Review and revoke keys in the Parchment Console.
