Configuration
The proxy reads one optional caveman.yaml file plus provider keys from environment variables. Secrets do not belong in YAML. The file controls mode, listen address, optimizer flags, and provider base URLs. The proxy is BSL 1.1.
A bare caveman start with no config is valid. Missing config means record mode on 127.0.0.1:8787. Add YAML only when you need a different upstream, listen address, label, or mode.
caveman.yaml
The loader (public/proxy/internal/config/config.go) reads ~/.caveman/caveman.yaml unless CAVEMAN_CONFIG points elsewhere.
# ~/.caveman/caveman.yaml
label: local # optional; tags local telemetry rows
mode: record # default; pass-through
listen: 127.0.0.1:8787 # where the proxy binds
optimizers: # provider-native optimizers, gated by id
anthropic-cache-breakpoints: true
providers: # per-provider base-URL overrides
azure_openai:
base_url: https://my-resource.openai.azure.com
openai_compatible:
base_url: http://127.0.0.1:11434/v1Anthropic, OpenAI, and Gemini have public defaults. azure_openai, bedrock, vertex, and openai_compatible need base_url because there is no universal upstream.
BYOK keys from the environment
Keys are read from the environment at request time, never from YAML.
| Provider | Environment variable |
|---|---|
anthropic | ANTHROPIC_API_KEY |
openai | OPENAI_API_KEY |
gemini | GEMINI_API_KEY |
azure_openai | AZURE_OPENAI_API_KEY |
openai_compatible | OPENAI_COMPAT_API_KEY |
go build -o ./bin/caveman-proxy ./public/proxy/cmd/caveman-proxy
ANTHROPIC_API_KEY=sk-ant-… ./bin/caveman-proxy # serve on 127.0.0.1:8787If no environment key is set, the proxy falls back to the inbound request's own auth header: x-api-key for Anthropic-style calls or bearer Authorization for OpenAI-style calls. Bedrock is absent because it signs each request with AWS SigV4.
Runtime modes
mode selects how the proxy may act on a request. Accepted values are record, recommend, shadow, canary, active, and compress. Default is record, which never transforms a body.
Unknown modes fail closed to record
Any unknown mode falls back to record. A typo cannot silently enable transforms. compress is the S4 lossy mode; it only does work when the engine-backed compressor is wired with CCR recovery. Otherwise it passes through. S4lossy · recoverable
The SSRF guard
standalone.StandaloneHTTPClient carries an SSRF dial guard that is always on in standalone mode. At dial time it blocks loopback, private RFC 1918 ranges, link-local addresses, and cloud metadata addresses.
Pointing at a local model server? Use the allowlist
Because the guard blocks loopback and private addresses, local model servers are blocked by default. Opt specific hosts back in with CAVE_SSRF_ALLOWLIST:
CAVE_SSRF_ALLOWLIST=127.0.0.1,localhost \
OPENAI_COMPAT_API_KEY=… ./bin/caveman-proxyAdd only hosts you run. The allowlist is the escape hatch; the guard stays on for everything else.
Driving it from the CLI
You usually don't run the binary by hand. caveman start launches caveman-proxy, and caveman wrap <agent> starts a child process with the relevant base URL environment set.