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

# Env and config

> Required env vars, .env precedence, the global config file, and the ralphy config verb.

`ralphy` reads two API keys, a handful of optional environment overrides, the project's `.env`, and a per-workspace JSON config. The precedence is fixed and documented here so a missing key in CI never silently picks up a different value than you expected.

## Required env vars

Two keys gate every meaningful operation:

<ParamField path="OPENROUTER_API_KEY" type="string" required>
  OpenRouter API key for every LLM + media model call. Get one at [openrouter.ai/keys](https://openrouter.ai/keys). `ralphy setup` pings the key against `GET /api/v1/auth/key` to verify.
</ParamField>

<ParamField path="ELEVENLABS_API_KEY" type="string" required>
  ElevenLabs API key for voiceover, music, and SFX generation, plus the Scribe transcription default. Get one at [elevenlabs.io/app/settings/api-keys](https://elevenlabs.io/app/settings/api-keys). `ralphy setup` pings against `GET /v1/user`.
</ParamField>

Both are required for a green `ralphy doctor`. The CLI raises `E_ENV_KEY_MISSING` (exit 4) the first time it needs a missing key.

## Optional env overrides

| Var                             | What it controls                                                       | Default               |
| ------------------------------- | ---------------------------------------------------------------------- | --------------------- |
| `RALPHY_PROJECT_DIR`            | Override project auto-detection — point at a specific checkout.        | (auto-detected)       |
| `RALPHY_HOME`                   | Root for `~/.ralphy/` — projects from `ralphy new`, global config.     | `$HOME/.ralphy`       |
| `RALPHY_REPO_ROOT`              | Repo root for `ralphy skill new` and other scaffold verbs.             | `process.cwd()`       |
| `RALPHY_BIN`                    | The path the installer recorded as the binary path.                    | (set by install.sh)   |
| `RALPHY_BIN_DIR`                | The directory containing the binary. Used to detect Homebrew installs. | (set by installer)    |
| `RALPHY_ASSETS_MANIFEST_URL`    | Override the companion-repo manifest URL.                              | (compiled-in default) |
| `RALPHY_DOCTOR_NO_UPDATE_CHECK` | Set to `1` to skip the 24h update check in `doctor`.                   | unset                 |
| `NO_COLOR`                      | Honored by `chalk` — disables ANSI colors when set to any value.       | unset                 |
| `HOME`                          | Resolves `~`. Used by Claude installer + skill detection.              | (system)              |

You'll rarely need any of these — defaults are right for both dev and binary installs.

## .env files

Every project carries a `<project>/.env`. When ralphy resolves a project root (see [CLI overview](/cli/overview)), it reads `.env` and merges keys into `process.env` — **but only for keys not already set**. Real shell-exported variables always win.

Order of precedence, lowest to highest:

1. Compiled-in default (e.g. `RALPHY_HOME = $HOME/.ralphy`).
2. `<project>/.env`.
3. Real environment variables (`export FOO=...` in your shell, `env FOO=...` prefix on the command).
4. CLI flag (`--cwd <path>` for the project root).

A typical `.env`:

```bash theme={"dark"}
OPENROUTER_API_KEY=sk-or-...
ELEVENLABS_API_KEY=xi-...
OPENROUTER_REFERER=https://yourdomain.example
OPENROUTER_TITLE=My UGC pipeline
```

`OPENROUTER_REFERER` and `OPENROUTER_TITLE` are optional headers OpenRouter uses for usage analytics. `ralphy setup` doesn't manage them — set them by hand if you want them tracked.

## .envrc + direnv

If you use [direnv](https://direnv.net), a `.envrc` at the project root will auto-load when you `cd` in. The CLI doesn't depend on direnv — `.env` is read directly — but the two coexist fine. `ralphy setup` writes to `.env`; if you keep `.envrc` in sync manually, your shell sees the keys without launching ralphy.

## Global config file

Two files matter:

* **`~/.config/ralphy/config.json`** — global. Holds `default_project_dir` (the link from `ralphy setup --link <path>`) and `imports[]` (profiles you've imported).
* **`<project>/.ralphy/config.json`** — per-workspace. Free-form key/value, managed by `ralphy config`.

The two are separate by design: global config is about *which* project ralphy points at; workspace config is about *how* that project behaves.

## ralphy config

```bash theme={"dark"}
ralphy config list                                         # everything
ralphy config get budgets.singleProject                    # dotted-path lookup
ralphy config set budgets.singleProject 5                  # auto-typed (number)
ralphy config set doctor.checkUpdates false                # auto-typed (boolean)
ralphy config set notes.lastBatch "spring-2026-001..010"   # string
```

`set` does best-effort type inference: `true`/`false` become booleans, parseable numbers become numbers, everything else stays a string. Dotted paths build the nested object on the fly.

Full surface: [`/reference/cli/config`](/reference/cli/config).

## Reading config from code

The CLI uses `cli/lib/config.ts` — `loadConfig()`, `saveConfig()`, `getNestedValue()`, `setNestedValue()`. The on-disk shape is unscoped JSON; the verb interprets dotted keys.

Common keys today:

| Key                   | Type   | Used by                                                           |
| --------------------- | ------ | ----------------------------------------------------------------- |
| `doctor.checkUpdates` | bool   | `ralphy doctor` — set to `false` to skip the 24h update check     |
| `budgets.<scope>`     | number | `E_BUDGET_EXCEEDED` gate (per-project / per-batch caps)           |
| `imports[]`           | array  | global config only — populated by `ralphy setup --import-profile` |

There's no enforced schema. The CLI reads what it expects and ignores the rest.

## Putting it together

When `ralphy generate image` runs, it sees:

1. `--cwd` (flag) — if set, this is the project root.
2. Walk up from cwd looking for `package.json#name = "ugc-cli"`.
3. `RALPHY_PROJECT_DIR` (env) — if set and valid.
4. `~/.config/ralphy/config.json#default_project_dir` — if set and valid.

Then it reads `<root>/.env` (without overwriting `process.env`), checks `OPENROUTER_API_KEY` is set (raises `E_ENV_KEY_MISSING` if not), and proceeds.

## Related

* [Setup and doctor](/cli/setup-doctor) — how keys land in `.env`
* [CLI overview](/cli/overview) — `--cwd` and project auto-detection
* [Error catalog](/cli/error-catalog) — `E_ENV_KEY_MISSING`, `E_PROJECT_NOT_LINKED`
* [cli/lib/project-root.ts](https://github.com/alecs5am/ralphy/blob/main/cli/lib/project-root.ts), [cli/commands/config.ts](https://github.com/alecs5am/ralphy/blob/main/cli/commands/config.ts)
