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

# CLI basics

> Understand the Clay CLI output contract, exit codes, environment variables, and authentication.

The Clay CLI (`clay`) is JSON-first: every command writes machine-readable JSON to stdout on success and a structured error envelope to stderr on failure. There are no spinners, colors, or progress bars, so agents and scripts can branch on the output and exit code directly.

## Output contract

| Result  | Behavior                                                                                   |
| ------- | ------------------------------------------------------------------------------------------ |
| Success | JSON is written to stdout, exit code `0`.                                                  |
| Failure | `{ "error": { "code", "message", "details"? } }` is written to stderr, non-zero exit code. |

Pipe stdout straight into `jq`, and read the exit code (`$?`) to decide what to do next.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay whoami | jq -r '.user.id'
```

## Exit codes

Branch on these from agents and scripts instead of parsing error text.

| Exit | Meaning                                                                                                                                         |
| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `0`  | Success.                                                                                                                                        |
| `1`  | Generic or unrecoverable (`server_error`, `contract_mismatch`, `conflict`, `internal_error`, `invalid_config_file`).                            |
| `2`  | `validation_error` — input was rejected as malformed.                                                                                           |
| `3`  | `auth_required` \| `auth_invalid` \| `auth_forbidden` — run [`clay login`](/cli/reference/login) to (re)authenticate.                           |
| `4`  | `rate_limited` (HTTP 429) — `details` has `retryAfter` (seconds), plus `limit`/`remaining`/`reset` when Clay sends the `X-RateLimit-*` headers. |
| `5`  | `network_error` \| `network_timeout` — could not reach Clay.                                                                                    |
| `6`  | `not_found` (HTTP 404).                                                                                                                         |

## Environment variables

| Variable                  | Purpose                                                                                                                 |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `CLAY_API_KEY`            | API key used when none is stored by `clay login`. A stored key wins over this variable.                                 |
| `CLAY_CONFIG_HOME`        | Highest-precedence config directory parent; `config.json` and `cache.json` live under `<CLAY_CONFIG_HOME>/clay`.        |
| `XDG_CONFIG_HOME`         | Used when `CLAY_CONFIG_HOME` is unset (`<XDG_CONFIG_HOME>/clay`), falling back to `~/.config/clay` when neither is set. |
| `CLAY_REQUEST_TIMEOUT_MS` | Per-request network timeout in milliseconds (default `60000`).                                                          |
| `CLAY_UPLOAD_TIMEOUT_MS`  | Bulk file-upload timeout in milliseconds (default `600000`).                                                            |

## Authentication

By default, [`clay login`](/cli/reference/login) opens a browser to authorize the CLI with OAuth — this works from a human terminal or an agent's shell tool. For headless contexts such as CI, pass an API key on stdin instead:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
echo "$CLAY_API_KEY" | clay login --stdin && clay whoami
```

`CLAY_API_KEY` also authenticates the CLI without logging in at all. Use [`clay whoami`](/cli/reference/whoami) as the canonical check that authentication is working, and [`clay logout`](/cli/reference/logout) to clear a stored credential.
