# Environment variables

> Look up the environment variables the collector, coding agent hooks and browser checks read, with their defaults.

Environment variables for the `blop` CLI, the [collector](/reference/glossary/#collector) and [browser checks](/reference/glossary/#browser-check). An unset variable means no override. Variables listed in the [Commands reference](/reference/cli/#environment) (port, host, URL, database path, output, colour, agent provider keys, OTLP flags) are not repeated here. Blop Cloud server variables are in [Blop Cloud environment variables](/reference/cloud-environment/).

## Collector variables

The collector resolves explicit start options first, then environment variables, then the project's `.blop/monitor.json` when the project is initialized, then built-in defaults. `blop.config.ts` configures browser checks, not the collector. `blop status --json` reports the store and retention of the selected collector; the Inspector's [Settings](/reference/settings/) shows effective values and their sources, never secret values.

| Variable | Default | Purpose |
|---|---|---|
| `BLOP_MONITOR_DB_PATH` | Project: `.blop/monitor/telemetry.sqlite`; else `telemetry.sqlite` in the state directory | Store path; an existing file is reused |
| `BLOP_MONITOR_RETENTION_HOURS`, `BLOP_MONITOR_MAX_DB_SIZE_MB` | `720` hours, `1024` MB | Store age limit and approximate size cap. Restart the collector to apply. Size eviction removes the oldest evidence first, even before its age limit. |
| `BLOP_MONITOR_STATE_DIR` | `$XDG_STATE_HOME/blop/monitor`, else `~/.local/state/blop/monitor` | Registry, PID and log files; a project collector keeps runtime files in `.blop/monitor/runtime` |
| `BLOP_MONITOR_RETENTION_TRACE_BATCH` | `100` | Traces evicted per retention pass |
| `BLOP_MONITOR_RETENTION_LOG_BATCH` | `5000` | Logs evicted per retention pass |
| `BLOP_MONITOR_RETENTION_INTERVAL_SECONDS` | `10` | Seconds between retention passes |
| `BLOP_MONITOR_TRACE_LOOKBACK_MINUTES` | `1440` | Store fallback lookback; HTTP list routes keep their own defaults |
| `BLOP_MONITOR_TRACE_LIMIT` | `100` | Store fallback trace limit |
| `BLOP_MONITOR_LOG_LIMIT` | `100` | Store fallback log limit |
| `BLOP_SOURCE_POLICY_FILE` | `source-policy.json` in the state directory | Capture consent for application and filelog sources and coding agent bindings. Setup, the collector and an enrolled receiver must use the same file. |
| `BLOP_LEDGER_POLICY_FILE` | Unset: no operator authority | Operator policy for worker ledgers; a private regular file owned by the collector user |
| `XDG_CACHE_HOME` | `~/.cache` | `blop/models` under it caches the local CPU embedding model for local memory index and search. First use downloads it from Hugging Face; telemetry and queries are never sent. |

The port defaults to the project's port, else `27811`; automatic startup picks a free port when none is explicit. Without an explicit URL, port or project, the CLI picks a registered local collector: the longest working-directory match wins, a sole running collector is accepted, and ambiguity is an error. An explicit target is never replaced after a connection failure.

## Coding agent variables

| Variable | Default | Purpose |
|---|---|---|
| `BLOP_CLAUDE_CODE_BIN`, `BLOP_CODEX_BIN`, `BLOP_CURSOR_AGENT_BIN`, `BLOP_GEMINI_BIN`, `BLOP_GOOSE_BIN`, `BLOP_OMP_BIN`, `BLOP_PI_BIN`, `BLOP_HERMES_BIN`, `BLOP_CRUSH_BIN`, `BLOP_AMP_BIN` | `PATH` and known install locations | Binary that `blop agents list` and the launchers use for that coding agent |
| `BLOP_AGENT_SETUP_DIR` | `blop/agents` (setup) and `blop/capture` (capture) under the XDG config directory | Agent setup records; global records are `<id>-global.json` |
| `BLOP_OPENCODE_SETUP_PATH` | `$XDG_CONFIG_HOME/blop/opencode.json`, else `~/.config/blop/opencode.json` | OpenCode setup record |
| `BLOP_AGENT_HOOK_DISABLED` | Off | Exactly `1` stops hook capture and delivery; `OTEL_SDK_DISABLED=true` does the same |
| `BLOP_AGENT_HOOK_STATE_DIR` | Collector state directory | Hook outbox and install state |
| `BLOP_AGENT_HOOK_COLLECTOR_URL` | `BLOP_MONITOR_URL`, else required | Collector for `blop agent hook` when no `--collector-url` is given |
| `BLOP_AGENT_HOOK_AGENT` | None | Default `--agent` for `blop agent hook` |
| `BLOP_AGENT_HOOK_TOOL_OWNER` | Detected | oh-my-pi hooks: `native` drops duplicate tool callbacks |
| `CLAUDE_CONFIG_DIR`, `CODEX_HOME`, `GEMINI_CLI_HOME`, `HERMES_HOME`, `HERMES_DATA_DIR_SUFFIX`, `GOOSE_PATH_ROOT`, `CRUSH_GLOBAL_CONFIG`, `XDG_CONFIG_HOME` | The host's own default | Where `blop agents install-hooks` writes that host's configuration. Without `HERMES_HOME`, Hermes uses `~/.hermes<suffix>` (`<LOCALAPPDATA>/hermes<suffix>` on Windows). Overrides of `PI_CODING_AGENT_DIR` and oh-my-pi profiles are refused. |

Hooks that Blop installs carry their own binding through `BLOP_AGENT_HOOK_POLICY_FILE`, `BLOP_AGENT_HOOK_SOURCE_ID`, `BLOP_AGENT_HOOK_PROJECT_ID` and `BLOP_AGENT_HOOK_TOKEN`. Do not set them yourself. `blop agents env <id>` prints the telemetry variables a host needs; a printed recipe does not prove the host sent telemetry.

## Browser check agent variables

The same variables have different defaults in browser checks and in the Inspector's chat. `blop test` uses flags, then `blop.config.ts`, then these variables. The chat reads the collector's environment and never loads `blop.config.ts`.

| Variable | Browser check default | Inspector chat default |
|---|---|---|
| `BLOP_AGENT_PROVIDER` | `openrouter` | `openai` |
| `BLOP_AGENT_MODEL` | None; required | `gpt-4o-mini` (`openai/gpt-4o-mini` with OpenRouter) |
| `BLOP_AGENT_API_KEY` | None; required | None; chat stays unconfigured |
| `BLOP_AGENT_BASE_URL` | The provider's OpenAI-compatible endpoint | Same |

Provider-native keys such as `OPENAI_API_KEY` are never read. Map one explicitly: `BLOP_AGENT_API_KEY="$OPENAI_API_KEY"`. `BLOP_AGENT_BASE_URL` is the model API, not your app or the collector. See [Agent providers](/checks/providers/).

## Browser check OpenTelemetry export

Browser checks export their own traces, metrics and logs to an OTLP backend only when an endpoint is set. Without one the OpenTelemetry SDK is not loaded.

| Variable | Default | Purpose |
|---|---|---|
| `OTEL_EXPORTER_OTLP_{TRACES,METRICS,LOGS}_ENDPOINT` | The generic endpoint plus the signal path | Full URL for one signal |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | `http/protobuf` | `http/json` also works; `grpc` is rejected |
| `OTEL_EXPORTER_OTLP_TIMEOUT` | Capped at `4500` ms | Per-export timeout; per-signal variants are capped the same way |
| `OTEL_EXPORTER_OTLP_{TRACES,METRICS,LOGS}_HEADERS` | None | Merged over `OTEL_EXPORTER_OTLP_HEADERS` |

Runs are not sampled and metrics use delta temporality. An export failure is logged and never fails the check run; shutdown waits at most 5 seconds in total.

## Browser check upload variables

A browser check run uploads its results only when `BLOP_INGEST_URL`, `BLOP_INGEST_SECRET` and `BLOP_PROJECT_ID` are all set; `platformUrl` and `platformApiKey` in `blop.config.ts` can supply the first two. Keep the secret private. An upload failure does not fail the run, and local capture needs none of these. `BLOP_RUN_ID` (default: generated) attaches results to a check run Blop Cloud already dispatched.

| Variable | Default | Purpose |
|---|---|---|
| `BLOP_ATTEMPT_NO` | None | Attempt number sent by the ingest client |
| `BLOP_BASE_URL` | None | GitHub Actions secret that Blop Cloud provisions; its generated workflow passes it as `--base-url` |
| `BLOP_MACHINE_TOKEN` | None | Private token read by the generated remote OpenTelemetry Collector configuration |

## Browser check container variables

Read only by `--containerized` runs; without that flag, nothing here enables a container.

| Variable | Default | Purpose |
|---|---|---|
| `BLOP_PLAYWRIGHT_IMAGE` | `mcr.microsoft.com/playwright:v<installed version>-noble` | Warm Playwright server image |
| `BLOP_PLAYWRIGHT_CONTAINER` | `blop-playwright` | Playwright container name |
| `BLOP_PLAYWRIGHT_NETWORK` | None | Shared Docker network |
| `BLOP_CAMOUFOX_IMAGE` | A local tag built from the installed versions | Warm Camoufox image; built locally when missing |
| `BLOP_CAMOUFOX_CONTAINER` | `blop-camoufox` | Camoufox container name |
| `BLOP_CAMOUFOX_NETWORK` | `BLOP_PLAYWRIGHT_NETWORK` | Camoufox Docker network |
| `BLOP_CONTAINER_DISABLE_CORS_BYPASS` | Unset: bypass on | Any non-empty value turns off the Playwright container's CORS bypass |

`BLOP_BROWSER_*` variables belong to the [Browser Harness CLI](/harness/cli/), not to browser checks.
