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

# Environment reference

> Every environment variable Avocado Studio reads, grouped by what it configures, with which process reads it and what happens when it is unset.

Avocado's configuration is spread over three places — the site, the
orchestrator, and the editor — and until now it was documented wherever it
happened to come up. This is the consolidated list.

<Note>
  **Which process reads what.** In **library mode** the site and the orchestrator
  are the same process, so both columns land in one `.env.local`. In a
  **standalone** deployment they are separate environments and the variables go
  where the table says.
</Note>

## Model providers

At least one key is required for chat. Everything else in the editor — the
preview, the property panel, click-to-select — works without one.

| Variable               | Default | What it does                                                                                                                           |
| ---------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `ANTHROPIC_API_KEY`    | —       | Anthropic planner. The best-tested path. Chat only; no image generation.                                                               |
| `OPENAI_API_KEY`       | —       | OpenAI planner, plus image generation and gpt-image editing.                                                                           |
| `GOOGLE_GENAI_API_KEY` | —       | Gemini planner and image generation. **Also needs `npm install @google/genai`**, an optional peer dependency nothing installs for you. |

Keys are read at startup. Adding one to a running server does nothing until you
restart it — which is the most common reason a key looks ignored.

### Model selection, per tier

Each provider resolves four tiers. Override any of them by name:

| Anthropic                   | OpenAI                   | Google                         |
| --------------------------- | ------------------------ | ------------------------------ |
| `ANTHROPIC_MODEL_FAST`      | `OPENAI_MODEL_FAST`      | `GOOGLE_GENAI_MODEL_FAST`      |
| `ANTHROPIC_MODEL_BALANCED`  | `OPENAI_MODEL_BALANCED`  | `GOOGLE_GENAI_MODEL_BALANCED`  |
| `ANTHROPIC_MODEL_REASONING` | `OPENAI_MODEL_REASONING` | `GOOGLE_GENAI_MODEL_REASONING` |
| `ANTHROPIC_MODEL_CODEX`     | `OPENAI_MODEL_CODEX`     | `GOOGLE_GENAI_MODEL_CODEX`     |

Also `ANTHROPIC_PROMPT_CACHE` and `ANTHROPIC_PROMPT_CACHE_TTL` for prompt
caching, and `OPENAI_VISION_MODEL` / `OPENAI_VISION_ALT_MODEL` /
`ANTHROPIC_VISION_ALT_MODEL` for the models that read attached images. See
[AI providers](/ai-providers).

### Images

| Variable                                                    | Default                       | What it does                                                                                                                                       |
| ----------------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `IMAGE_GEN_PROVIDER`                                        | `gemini`                      | Backend for image variations, the `image.generate` tool and `/image/generate`. `gemini` or `openai`; falls back if the chosen provider has no key. |
| `OPENAI_IMAGE_MODEL`                                        | `gpt-image-1-mini`            | OpenAI image model                                                                                                                                 |
| `GOOGLE_GENAI_IMAGE_MODEL`                                  | `gemini-3.1-flash-lite-image` | Gemini image model                                                                                                                                 |
| `VARIATION_DEFAULT_IMAGE_SOURCE`                            | `unsplash`                    | Default image branch for variations when the message gives no hint. `unsplash`, `ai`, `gemini` or `openai`. Message keywords always win.           |
| `UNSPLASH_ACCESS_KEY`                                       | —                             | Enables Unsplash search in the asset manager                                                                                                       |
| `GOOGLE_DRIVE_FOLDER_ID`, `GOOGLE_SERVICE_ACCOUNT_KEY_JSON` | —                             | A Google Drive folder as a media source                                                                                                            |
| `ORCHESTRATOR_GENERATED_IMAGE_DIR`                          | —                             | Where generated images are written                                                                                                                 |

### Voice input

`POST /audio/transcribe` tries OpenAI first, then falls back to Gemini when
OpenAI fails or is over quota.

| Variable                            | Default                  |
| ----------------------------------- | ------------------------ |
| `OPENAI_TRANSCRIBE_MODEL`           | `gpt-4o-mini-transcribe` |
| `OPENAI_TRANSCRIBE_FALLBACK_MODELS` | —                        |
| `GOOGLE_GENAI_TRANSCRIBE_MODEL`     | `gemini-2.5-flash`       |

With neither provider available, `/status/planner` reports
`features.audioTranscription: false` and the editor hides the microphone button.

## Access and security

The full picture, including what is open and what is closed by default, is on
[security and access](/reference/security). The variables:

| Variable                     | What it does                                                                                     |
| ---------------------------- | ------------------------------------------------------------------------------------------------ |
| `ACCESS_PASSWORD_HASH`       | sha256 of a password. `/auth/verify` exchanges it for a bearer token; the editor prompts for it. |
| `ORCHESTRATOR_ACCESS_TOKEN`  | A fixed bearer token, for scripts and CI.                                                        |
| `AGENT_SURFACE`              | `on` mounts the `/agent/*` routes in production. Off by default.                                 |
| `AGENT_CLI`                  | `1` opts into the path that spawns the Claude CLI on the host. Off everywhere by default.        |
| `AGENT_API_KEY`              | Enables agentic editing on `/agent/*`. Anthropic or OpenAI.                                      |
| `EDITOR_CORS_ORIGINS`        | Origins the site's editor routes accept                                                          |
| `ORCHESTRATOR_CORS_ORIGINS`  | Origins the orchestrator accepts                                                                 |
| `ORCHESTRATOR_PUBLIC_ORIGIN` | The orchestrator's own address, as the browser sees it                                           |

<Warning>
  **Library mode refuses every request under `NODE_ENV=production` when none of
  `ACCESS_PASSWORD_HASH`, `ORCHESTRATOR_ACCESS_TOKEN` or a code-level `auth` hook
  is configured.** That is deliberate. See [security and access](/reference/security).
</Warning>

## The site

Read by your Next.js app through the SDK.

| Variable                                               | What it does                                                                                                                                               |
| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DRAFT_MODE_SECRET`                                    | Validates `?secret=` on draft entry and on the preview render. Generated by `avocado-register` when missing.                                               |
| `ORCHESTRATOR_URL`                                     | Where the SDK fetches draft pages from. In library mode, your own mount — e.g. `http://localhost:3000/api/avocado`. Falls back to `http://127.0.0.1:4200`. |
| `NEXT_PUBLIC_SITE_URL`                                 | The site's own origin. Without it the pages carry no canonical link, no `og:url`, and a relative `og:image` no social crawler resolves.                    |
| `NEXT_PUBLIC_EDITOR_ORIGIN`                            | Where the editor lives, for the CORS answer                                                                                                                |
| `NEXT_PUBLIC_SITE_NAME`, `NEXT_PUBLIC_DEFAULT_SITE_ID` | Defaults used by the scaffolds                                                                                                                             |
| `DRAFT_DEFAULT_SITE_ID`, `DRAFT_DEFAULT_SESSION`       | Which site and session an unqualified draft request resolves to                                                                                            |
| `SITE_PUBLIC_ORIGIN`                                   | The site's public origin, as the orchestrator should address it                                                                                            |

A mismatch between the editor's draft secret and the site's `DRAFT_MODE_SECRET`
degrades to *"the preview shows published content"* rather than an error, which
is why it goes unnoticed. `avocado-register` warns about it.

## Publishing

| Variable                                                                                                               | What it does                                                                                                                                                   |
| ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PUBLISH_TOKEN`                                                                                                        | The publish secret. `POST /api/editor/publish` answers 401 without it under `NODE_ENV=production`; the orchestrator sends the same value as `x-publish-token`. |
| `PUBLISH_TARGET`                                                                                                       | Which publish target to use                                                                                                                                    |
| `PUBLISH_MODE`                                                                                                         | How publishing behaves                                                                                                                                         |
| `PUBLISH_GRACE_SECONDS`                                                                                                | Grace period before a publish is considered settled                                                                                                            |
| `PUBLISHED_CONTENT_PATH`                                                                                               | Where file-based publishing writes                                                                                                                             |
| `PUBLISH_GIT_BRANCH`, `PUBLISH_GIT_TOKEN`, `PUBLISH_GIT_AUTHOR_NAME`, `PUBLISH_GIT_AUTHOR_EMAIL`, `PUBLISH_GIT_STRICT` | Committing published content back to a repository                                                                                                              |
| `VERCEL_TOKEN`, `VERCEL_TEAM_ID`, `VERCEL_DEPLOY_HOOK_URL`                                                             | Triggering and reporting a Vercel deploy                                                                                                                       |

See [publishing](/integration/publishing).

## Persistence

Full detail on [state and backups](/operations/state-and-backups).

| Variable                                | Default                 | What it does                                                    |
| --------------------------------------- | ----------------------- | --------------------------------------------------------------- |
| `ORCHESTRATOR_DB_FILE`                  | `.data/orchestrator.db` | SQLite path. Auto-switches to `:memory:` under `NODE_ENV=test`. |
| `ORCHESTRATOR_STATE_FILE`               | —                       | Legacy JSON state, read once on first boot and then renamed     |
| `ORCHESTRATOR_JSON_MIGRATION_TTL_DAYS`  | `14`                    | Retention for that archived JSON                                |
| `ORCHESTRATOR_DB_BACKUP_INTERVAL_HOURS` | `24`                    | Snapshot interval                                               |
| `ORCHESTRATOR_DB_BACKUP_LIMIT`          | `14`                    | Rolling snapshots kept                                          |

## Operations

| Variable                               | What it does                                                                                                                                   |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `PORT`                                 | Port the orchestrator listens on                                                                                                               |
| `NODE_ENV`                             | `production` turns on the access gate and the publish guard                                                                                    |
| `LOG_LEVEL`                            | Log verbosity; `silent` for scripted runs                                                                                                      |
| `DEMO_MODE`                            | `1` runs the locked-down public demo — allow-listed ops, per-IP rate limiting, no AI image generation. See [demo mode](/operations/demo-mode). |
| `CHECKS_ON_APPLY`, `CHECKS_ON_PUBLISH` | Run [site health](/features/site-health) checks at those moments                                                                               |
| `AUTO_BOOTSTRAP_SITE_ORIGIN`           | Origin to bootstrap an unknown site from                                                                                                       |
| `ORCHESTRATOR_TOOL_MANIFEST_PATH`      | A [native tool](/integration/tools-mvp) manifest                                                                                               |

## Telemetry

| Variable                          | What it does                        |
| --------------------------------- | ----------------------------------- |
| `CHAT_TELEMETRY_PERSIST`          | Write chat telemetry to disk        |
| `CHAT_TELEMETRY_FILE`             | Where                               |
| `CHAT_TELEMETRY_LIMIT`            | How much to retain                  |
| `FEEDBACK_FILE`, `FEEDBACK_LIMIT` | Where thumbs-up/down feedback lands |

See [telemetry events](/observability/chat-telemetry-events) and
[token usage](/observability/token-usage-tracking).

## Chat pipeline flags

The chat pipeline reads about sixteen `CHAT_*` variables that tune the planner
rather than configure it — the parallel planner, the router head start, deferred
image resolution, streamed operation apply, auto-reasoning, adaptive schema
context. **Defaults are tuned for responsiveness; turn them off individually
when debugging, not as a matter of course.**

`CHAT_PARALLEL_PLANNER` · `CHAT_ROUTER_HEAD_START_MS` ·
`CHAT_LLM_INTENT_ROUTER` · `CHAT_INCREMENTAL_APPLY` ·
`CHAT_STREAM_APPLY_MIN_STEP_MS` · `CHAT_AUTO_REASONING` ·
`CHAT_AUTO_REASONING_BUDGET` · `CHAT_ADAPTIVE_SCHEMA_CONTEXT` ·
`CHAT_SCHEMA_BUDGET_BYTES` · `CHAT_STRICT_JSON_RESPONSE` ·
`CHAT_STRICT_PRIMARY_OP_MODE` · `CHAT_PLANNER_FORCE_SONNET` ·
`CHAT_COMPACT_CONTEXT_EXPERIMENT` · `CHAT_MINIMAL_CONTEXT_EXPERIMENT`

## Jira

Only read when the [Jira channel](/integration/jira) is configured.

`JIRA_BASE_URL` · `JIRA_USER_EMAIL` · `JIRA_API_TOKEN` · `JIRA_WEBHOOK_SECRET` ·
`JIRA_SITE_ID` · `JIRA_SESSION` · `JIRA_AGENT_ACCOUNT_ID` ·
`JIRA_TRIGGER_STATUS` · `JIRA_EXECUTE_STATUS` · `JIRA_PREVIEW_STATUS` ·
`JIRA_REVIEW_STATUS` · `JIRA_DONE_STATUS` · `JIRA_FAILED_STATUS` ·
`JIRA_AUTO_PUBLISH` · `JIRA_MAX_REVIEW_PASSES` · `JIRA_POLL_ENABLED` ·
`JIRA_POLL_INTERVAL_MS` · `JIRA_POLL_JQL`

## MCP server

| Variable                   | What it does                             |
| -------------------------- | ---------------------------------------- |
| `AVOCADO_MCP_PORT`         | Port for the streamable-HTTP transport   |
| `AVOCADO_MCP_BEARER_TOKEN` | Bearer token the HTTP transport requires |

See [MCP server](/integration/mcp-server).

## The editor CLI

The CLI reads these as an alternative to its flags — see
[CLI and packages](/reference/cli).

`AVOCADO_ORCHESTRATOR_URL` · `AVOCADO_SITE_ORIGIN` · `AVOCADO_PUBLISH_TOKEN` ·
`DRAFT_MODE_SECRET` · `PORT`
