# Configuration
Precedence, highest first: CLI flags → environment (`OPENLATCH_*`) → `~/.openlatch/config.toml` → defaults.
The egress route is the one exception. It resolves **per key** rather than per block, and its ladder is longer: CLI flag → `OPENLATCH_*` → `[proxy]` in `config.toml` → the standard `https_proxy` family → OS discovery → direct. See [egress.md](egress.md).
`openlatch init` writes `config.toml` for you. Edit it by hand only for what the CLI has no command for.
## Environment variables
| `OPENLATCH_DIR` | State directory: config, token, logs, outbox | `~/.openlatch` |
| `OPENLATCH_PORT` | Daemon port. `init` binds this exact port; unset, it probes 7443–7543. | `7443` |
| `OPENLATCH_API_URL` | Cloud API base URL | `https://app.openlatch.ai` |
| `OPENLATCH_API_KEY` | API key (credential chain: environment → keychain → encrypted file) | — |
| `OPENLATCH_SKIP_KEYRING` | Treat the OS keychain as unavailable, so the env var wins | unset |
| `OPENLATCH_LOG` | `error` / `warn` / `info` / `debug` / `trace` | `info` |
| `OPENLATCH_PROXY` | Proxy URL for every outbound request. **The one channel that may carry a credential** (`http://user:pass@host:port`) — it is a per-process channel, unlike argv, and `init` strips the password into the OS credential store rather than persisting it. | unset |
| `OPENLATCH_NO_PROXY` | Additive bypass list. Loopback (`127.0.0.0/8`, `::1`, `localhost`) always bypasses and needs no entry. | unset |
| `OPENLATCH_PROXY_MODE` | `auto` / `manual` / `direct` | `auto` |
| `OPENLATCH_PROXY_AUTH` | `auto` / `none` / `basic` / `negotiate`. NTLM is deliberately absent. | `auto` |
| `OPENLATCH_PROXY_PAC_URL` | Explicit PAC URL. Refused on Linux with `OL-1225` — this client ships no JavaScript engine. | unset |
| `OPENLATCH_PROXY_SPN` | Kerberos SPN override | `HTTP/<proxy-host>` |
| `OPENLATCH_CA_BUNDLE` | PEM bundle merged on top of the OS trust store — the intercepting proxy's root | unset |
| `https_proxy` / `HTTPS_PROXY` / `http_proxy` / `HTTP_PROXY` / `ALL_PROXY` / `no_proxy` / `NO_PROXY` | Honoured below `[proxy]` in `config.toml`. **Lowercase wins** within a pair; on Unix, a pair that disagrees is a `doctor` warning. | unset |
| `OPENLATCH_BOUNDARY_ENABLED` | Model-boundary listener. While on, the daemon points the agent at it — but only once a synthetic request proves the listener can reach the provider. Being wired disables Claude Code Remote Control. | `true` |
| `OPENLATCH_BOUNDARY_PORT` | Boundary port. A non-default port makes the instance isolated. | `7600` |
| `OPENLATCH_BOUNDARY_OWN_WIRING` | Let an isolated instance write its own agent config | derived from the port |
| `OPENLATCH_BOUNDARY_UPSTREAM` | Where the boundary forwards. Every model call and provider credential goes here — change it only for a local harness. | `https://api.anthropic.com` |
| `OPENLATCH_BOUNDARY_TRANSFORMS_ACT` | Whether an acting `prefix_reorder` rule may rewrite the forwarded request body. Off, the boundary measures and forwards the original bytes. | `false` |
| `OPENLATCH_POLICY_ENABLED` | Local policy evaluation. `false` is a complete off switch, not observe mode. | `true` |
| `OPENLATCH_INVENTORY_ENABLED` | Configuration-plane monitoring | `true` |
| `OPENLATCH_CLOUD_BATCH_MAX_EVENTS` | Events per ingest batch, clamped to `1..=100` | `50` |
| `OPENLATCH_CLOUD_BATCH_MAX_WAIT_MS` | Flush deadline, anchored to the first buffered event | `5000` |
| `OPENLATCH_CLOUD_OUTBOX_MAX_BYTES` | Outbox cap before drop-oldest (0 disables) | `104857600` |
| `OPENLATCH_CLOUD_FALLBACK_MAX_BYTES` | Fallback-log cap before drop-oldest (0 disables) | `52428800` |
| `OPENLATCH_CLOUD_ENABLED` | Parsed so existing configs keep loading, then ignored — cloud forwarding is not optional. Point `OPENLATCH_API_URL` elsewhere to change *where* events go. | ignored |
| `OPENLATCH_AUTO_UPDATE` | Background auto-update worker. `openlatch update --check --json` is the manual probe. | `true` |
| `OPENLATCH_UPDATE_CHECK` | Startup version check | `true` |
| `OPENLATCH_NPM_REGISTRY` | Registry origin for `openlatch update` | `https://registry.npmjs.org` |
| `OPENLATCH_TELEMETRY_DISABLED` | `1` opts out of anonymous usage telemetry | unset |
## What the daemon writes into the agent's config
While the model boundary is enabled, the daemon writes three keys into Claude Code's settings — after its bind succeeds and a synthetic round trip proves the listener can reach the provider — and removes them on teardown. Nothing else writes them, so the agent config can never name a listener that does not exist.
| `ANTHROPIC_BASE_URL` | `http://127.0.0.1:<boundary port>` | Routes the agent's provider traffic through the boundary |
| `ANTHROPIC_CUSTOM_HEADERS` | An install identifier, merged with whatever is already there | Attributes model calls to this install |
| `NO_PROXY` / `no_proxy` | `127.0.0.1,localhost`, merged into the existing list | Claude Code has no implicit loopback bypass; without it the agent would tunnel to its own laptop through the corporate proxy and get a `502` |
The `NO_PROXY` entries are deliberately **left behind** on teardown: they carry no ownership marker, and a host's own loopback belongs in its own bypass list either way.