Environment variables, complete
Every variable the runtime reads, grouped by subsystem. The dozen an operator actually sets are on Environment variables; this page is the exhaustive list, derived from current code paths in:
packages/coding-agent/src/**packages/ai/src/**(provider/auth resolution used by coding-agent)packages/utils/src/**andpackages/tui/src/**where those vars directly affect coding-agent runtime
It documents only active behavior.
Resolution model and precedence
Most runtime lookups use $env from @veyyon/utils (packages/utils/src/env.ts).
$env precedence, high to low:
- Existing process environment (
Bun.env) - Project
.env($PWD/.env) for keys not already set - Agent
.env(~/.veyyon/profiles/default/agent/.env, respectingVEYYON_CONFIG_DIR/VEYYON_CODING_AGENT_DIR) for keys not already set - Config-root
.env(~/.veyyon/profiles/default/.env, respectingVEYYON_CONFIG_DIRand the active profile) for keys not already set - Home
.env(~/.env) for keys not already set
Precedence is not the same as load order, and the difference matters if you are reading the source. Part of the home .env is applied FIRST, by packages/utils/src/dotenv-home.ts, because a VEYYON_CODING_AGENT_DIR or XDG_CONFIG_HOME set there sets where layers 3 and 4 are. packages/utils/src/dirs.ts imports that module before it resolves anything, so a directory is never computed from a pre-.env environment. env.ts then applies all four layers in full, overriding the values home contributed and nothing else, and refreshes the directory resolver. The result is the precedence listed above, whichever module a program imported.
That early phase applies only the variables that decide where a directory is: VEYYON_CODING_AGENT_DIR, VEYYON_CONFIG_DIR, and the four XDG_* bases. Everything else in your home .env, including every API key, waits for env.ts. The reason is that whatever is in the environment that early is inherited by every process veyyon spawns, and the sandboxed evaluator that runs your eval code is one of them: it should not receive your credentials.
Two variables are deliberately not read from a .env file at all. VEYYON_PROFILE selects the profile, and the profile sets where layers 3 and 4 are, so reading it out of one of them would be circular; set it in your shell or pass --profile. PATH is read only after env.ts has run, which is when binary lookup happens anyway, so extending PATH in a .env works as it always has.
1) Model/provider authentication
These are consumed via getEnvApiKey() (packages/ai/src/env-api-key.ts) unless noted otherwise.
Core provider credentials
The provider-first projection of this map lives in Providers; the two tables are two views of one source.
| Variable | Used for | Required when | Notes / precedence |
|---|---|---|---|
OPENAI_CODEX_OAUTH_TOKEN | OpenAI Codex OAuth auth | Using openai-codex provider | |
BASETEN_API_KEY | Baseten auth | Using baseten provider | |
CMD_API_KEY | Command Code auth | Using command-code provider | Preferred key alias; endpoint https://api.commandcode.ai/provider/v1, default moonshotai/Kimi-K2.7-Code |
COMMAND_CODE_API_KEY | Command Code auth | Using command-code provider without CMD_API_KEY | Fallback after CMD_API_KEY; keys are issued at https://commandcode.ai/studio/provider |
NOUS_API_KEY | Nous Research explicit/headless auth | Using nous-research without a /login | Either login is preferred: nous-research (device flow) or nous-research-api-key (pasted key); endpoint https://inference-api.nousresearch.com/v1, default anthropic/claude-sonnet-4.6 |
COREWEAVE_API_KEY | CoreWeave auth | Using coreweave provider | Takes precedence over WANDB_API_KEY |
WANDB_API_KEY | CoreWeave auth | Using coreweave provider | Fallback after COREWEAVE_API_KEY |
DEVIN_API_KEY | Devin auth | Using devin provider | |
SAKANA_API_KEY | Sakana auth | Using sakana provider | Takes precedence over FUGU_API_KEY |
FUGU_API_KEY | Sakana auth | Using sakana provider | Fallback after SAKANA_API_KEY |
ANTHROPIC_OAUTH_TOKEN | Anthropic API auth | Using Anthropic with OAuth token auth | Takes precedence over ANTHROPIC_API_KEY for provider auth resolution |
ANTHROPIC_API_KEY | Anthropic API auth | Using Anthropic without OAuth token | Fallback after ANTHROPIC_OAUTH_TOKEN |
ANTHROPIC_FOUNDRY_API_KEY | Anthropic via Azure Foundry / enterprise gateway | CLAUDE_CODE_USE_FOUNDRY enabled | Takes precedence over ANTHROPIC_OAUTH_TOKEN and ANTHROPIC_API_KEY when Foundry mode is enabled |
OPENAI_API_KEY | OpenAI auth | Using OpenAI-family providers without explicit apiKey argument | Used by OpenAI Completions/Responses providers |
GEMINI_API_KEY | Google Gemini auth | Using google provider models | Primary key for Gemini provider mapping |
GOOGLE_API_KEY | Gemini image tool auth fallback | Using gemini_image tool without GEMINI_API_KEY | Used by coding-agent image tool fallback path |
GROQ_API_KEY | Groq auth | Using Groq models | |
CEREBRAS_API_KEY | Cerebras auth | Using Cerebras models | |
FIREWORKS_API_KEY | Fireworks auth | Using Fireworks models | |
FIREPASS_API_KEY | Fire Pass auth | Using Fire Pass models | |
TOGETHER_API_KEY | Together auth | Using together provider | |
AIMLAPI_API_KEY | AIML API auth | Using aimlapi provider | OpenAI-compatible AIML API endpoint at https://api.aimlapi.com/v1 |
HUGGINGFACE_HUB_TOKEN | Hugging Face auth | Using huggingface provider | Primary Hugging Face token env var |
HF_TOKEN | Hugging Face auth | Using huggingface provider | Fallback when HUGGINGFACE_HUB_TOKEN is unset |
SYNTHETIC_API_KEY | Synthetic auth | Using Synthetic models | |
NVIDIA_API_KEY | NVIDIA auth | Using nvidia provider | |
NANO_GPT_API_KEY | NanoGPT auth | Using nanogpt provider | |
NOVITA_API_KEY | Novita auth | Using novita provider | |
VENICE_API_KEY | Venice auth | Using venice provider | |
LITELLM_API_KEY | LiteLLM auth | Using litellm provider | OpenAI-compatible LiteLLM proxy key |
LM_STUDIO_API_KEY | LM Studio auth (optional) | Using lm-studio provider with authenticated hosts | Local LM Studio usually runs without auth; any non-empty token works when a key is required |
OLLAMA_API_KEY | Ollama auth (optional) | Using ollama provider with authenticated hosts | Local Ollama usually runs without auth; any non-empty token works when a key is required |
LLAMA_CPP_API_KEY | llama.cpp auth (optional) | Using llama.cpp provider with authenticated hosts | Local llama.cpp usually runs without auth; any non-empty token works when a key is configured |
XIAOMI_API_KEY | Xiaomi MiMo auth | Using xiaomi provider | |
XIAOMI_TOKEN_PLAN_AMS_API_KEY | Xiaomi MiMo Token Plan auth (AMS) | Using xiaomi-token-plan-ams provider | |
XIAOMI_TOKEN_PLAN_CN_API_KEY | Xiaomi MiMo Token Plan auth (CN) | Using xiaomi-token-plan-cn provider | |
XIAOMI_TOKEN_PLAN_SGP_API_KEY | Xiaomi MiMo Token Plan auth (SGP) | Using xiaomi-token-plan-sgp provider | |
MOONSHOT_API_KEY | Moonshot auth | Using moonshot provider | |
XAI_API_KEY | xAI auth | Using xAI models or as fallback for xai-oauth | |
XAI_OAUTH_TOKEN | xAI OAuth/SuperGrok auth | Using xai-oauth provider | Takes precedence over XAI_API_KEY for xai-oauth |
OPENROUTER_API_KEY | OpenRouter auth | Using OpenRouter models | Also used by image tool when preferred/auto provider is OpenRouter |
MISTRAL_API_KEY | Mistral auth | Using Mistral models | |
ZAI_API_KEY | z.ai auth | Using z.ai models | Also used by z.ai web search provider |
ZHIPU_API_KEY | Zhipu Coding Plan auth | Using zhipu-coding-plan provider | |
UMANS_AI_CODING_PLAN_API_KEY | Umans AI Coding Plan auth | Using umans provider | |
MINIMAX_API_KEY | MiniMax auth | Using minimax provider | |
MINIMAX_CODE_API_KEY | MiniMax Code auth | Using minimax-code provider | |
MINIMAX_CODE_CN_API_KEY | MiniMax Code CN auth | Using minimax-code-cn provider | |
OPENCODE_API_KEY | OpenCode auth | Using opencode-go / opencode-zen models | |
QIANFAN_API_KEY | Qianfan auth | Using qianfan provider | |
QWEN_OAUTH_TOKEN | Qwen Portal auth | Using qwen-portal with OAuth token | Takes precedence over QWEN_PORTAL_API_KEY |
QWEN_PORTAL_API_KEY | Qwen Portal auth | Using qwen-portal with API key | Fallback after QWEN_OAUTH_TOKEN |
ZENMUX_API_KEY | ZenMux auth | Using zenmux provider | Used for ZenMux OpenAI and Anthropic-compatible routes |
VLLM_API_KEY | vLLM auth/discovery opt-in | Using vllm provider (local OpenAI-compatible servers) | Any non-empty value works for no-auth local servers |
CURSOR_ACCESS_TOKEN | Cursor provider auth | Using Cursor provider | |
AI_GATEWAY_API_KEY | Vercel AI Gateway auth | Using vercel-ai-gateway provider | |
CLOUDFLARE_AI_GATEWAY_API_KEY | Cloudflare AI Gateway auth | Using cloudflare-ai-gateway provider | Base URL must be configured as https://gateway.ai.cloudflare.com/v1/<account>/<gateway>/anthropic |
ALIBABA_CODING_PLAN_API_KEY | Alibaba Coding Plan auth | Using alibaba-coding-plan provider | |
DEEPSEEK_API_KEY | DeepSeek auth | Using DeepSeek models | |
KILO_API_KEY | Kilo auth | Using Kilo models | |
OLLAMA_CLOUD_API_KEY | Ollama Cloud auth | Using ollama-cloud provider | |
WAFER_SERVERLESS_API_KEY | Wafer Serverless auth | Using wafer-serverless provider | Pay-as-you-go Wafer SKU; validated against https://pass.wafer.ai/v1/models |
GITLAB_TOKEN | GitLab Duo auth | Using gitlab-duo provider |
/login nous-research stores the Portal refresh token and supplies refreshed short-lived inference access tokens to requests and model discovery. When no stored OAuth credential is selected, NOUS_API_KEY supplies the headless fallback.
GitHub/Copilot tokens
| Variable | Used for | Notes |
|---|---|---|
COPILOT_GITHUB_TOKEN | GitHub Copilot provider auth | Generic GitHub tokens are not used here |
GH_TOKEN | GitHub API auth in web scraper | Web scraper fallback after GITHUB_TOKEN |
GITHUB_TOKEN | GitHub API auth in web scraper | Web scraper checks this before GH_TOKEN |
Auth broker / auth gateway (remote credential vault)
When the broker is enabled, the local SQLite credential store is bypassed and all OAuth refresh / access tokens live on the broker host. See auth-broker-gateway.md for the full protocol, CLI surface, and 5-min/15-s usage cache layering.
| Variable | Used for | Required when | Notes / precedence |
|---|---|---|---|
VEYYON_AUTH_BROKER_URL | Base URL of the remote auth-broker (e.g. https://broker.tailnet:8765); selects broker mode | Resolving credentials through a broker; also required by veyyon auth-gateway serve (the gateway is itself a broker client) | Wins over auth.broker.url in config.yml. When set with no resolvable token, resolveAuthBrokerConfig() hard-errors instead of falling back to local SQLite. |
VEYYON_AUTH_BROKER_TOKEN | Bearer token sent on every broker endpoint except /v1/healthz | VEYYON_AUTH_BROKER_URL is set and no token is available from auth.broker.token or <config-dir>/auth-broker.token | Resolution: this env → auth.broker.token ($ENV_NAME indirection supported) → <config-dir>/auth-broker.token (mode 0600). <config-dir> is ~/.veyyon/ (respecting VEYYON_CONFIG_DIR). |
VEYYON_AUTH_BROKER_SNAPSHOT_TTL_MS | Freshness window for the encrypted local broker snapshot cache | Optional in broker mode | Default 3600000 (1 h). Freshness is based on broker snapshot.generatedAt; 0 disables cache reads/writes and forces the old blocking fetch every startup. |
VEYYON_AUTH_BROKER_SNAPSHOT_CACHE | Path to the encrypted local broker snapshot cache | Optional in broker mode | Defaults to ~/.veyyon/profiles/<profile>/cache/auth-broker-snapshot.enc (or XDG cache equivalent). Useful for tests, ephemeral hosts, or relocating the 0600 cache file. |
The gateway has no dedicated env vars, it inherits VEYYON_AUTH_BROKER_*. Its own inbound bearer token lives at <config-dir>/auth-gateway.token and is managed via veyyon auth-gateway token.
2) Provider-specific runtime configuration
Anthropic Foundry Gateway (Azure / enterprise proxy)
When CLAUDE_CODE_USE_FOUNDRY is enabled, Anthropic requests switch to Foundry mode:
-
Base URL resolves from
FOUNDRY_BASE_URL(fallback remains model/default base URL if unset). -
API key resolution for provider
anthropicbecomes:ANTHROPIC_FOUNDRY_API_KEY→ANTHROPIC_OAUTH_TOKEN→ANTHROPIC_API_KEY. -
ANTHROPIC_CUSTOM_HEADERSis parsed as comma/newline-separatedkey: valuepairs and merged into request headers. They are also forwarded whenANTHROPIC_BASE_URLpoints to a non-Anthropic host (e.g. a corporate API gateway), so enterprise gateways requiring proprietary auth headers work without enabling Foundry mode. -
TLS client/server material can be injected from env values:
NODE_EXTRA_CA_CERTS,CLAUDE_CODE_CLIENT_CERT,CLAUDE_CODE_CLIENT_KEY. Each accepts either:- a filesystem path to PEM content, or
- inline PEM (including escaped
\nsequences).
NODE_EXTRA_CA_CERTSis honoured for every provider fetch (OpenAI-compatible, Codex, Ollama, Azure Responses, Google, Anthropic), not just Foundry, Bun’sfetchdoes not consume the env var natively, so the bundle is merged intoRequestInit.tls.caalongside the system root store. TheCLAUDE_CODE_*mTLS material remains Anthropic-Foundry-specific.
| Variable | Value type | Behavior |
|---|---|---|
CLAUDE_CODE_USE_FOUNDRY | Boolean-like string (1, true, yes, on) | Enables Foundry mode for Anthropic provider |
FOUNDRY_BASE_URL | URL string | Anthropic endpoint base URL in Foundry mode |
ANTHROPIC_FOUNDRY_API_KEY | Token string | Used for Authorization: Bearer <token> |
ANTHROPIC_CUSTOM_HEADERS | Header list string | Extra headers; format header-a: value, header-b: value or newline-separated. Also forwarded outside Foundry whenever ANTHROPIC_BASE_URL is non-Anthropic. |
NODE_EXTRA_CA_CERTS | PEM path or inline PEM | Extra CA chain for server certificate validation |
CLAUDE_CODE_CLIENT_CERT | PEM path or inline PEM | mTLS client certificate |
CLAUDE_CODE_CLIENT_KEY | PEM path or inline PEM | mTLS client private key (must be paired with cert) |
Amazon Bedrock
| Variable | Default / behavior |
|---|---|
AWS_REGION | Primary region source |
AWS_DEFAULT_REGION | Fallback if AWS_REGION unset |
AWS_PROFILE | Enables named profile auth path |
AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY | Enables IAM key auth path |
AWS_BEARER_TOKEN_BEDROCK | Highest-precedence bearer token auth path; skips AWS profile/credential-chain lookup when set |
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI / AWS_CONTAINER_CREDENTIALS_FULL_URI | Marks Bedrock as available in provider detection (credential resolution itself covers env keys, profiles/SSO/credential_process, then IMDSv2) |
AWS_WEB_IDENTITY_TOKEN_FILE + AWS_ROLE_ARN | Marks Bedrock as available in provider detection (same caveat as the ECS variables above) |
AWS_BEDROCK_SKIP_AUTH | If 1, injects dummy credentials (proxy/non-auth scenarios) |
HTTPS_PROXY / HTTP_PROXY | Honored via Bun’s native fetch proxy support (the provider no longer ships an AWS SDK / proxy-agent transport) |
NO_PROXY | Excludes matching hosts from Bun’s native proxy routing |
Region fallback in provider code: options.region → AWS_REGION → AWS_DEFAULT_REGION → us-east-1.
Azure OpenAI Responses
| Variable | Default / behavior |
|---|---|
AZURE_OPENAI_API_KEY | Required unless API key passed as option |
AZURE_OPENAI_API_VERSION | Default v1 |
AZURE_OPENAI_BASE_URL | Direct base URL override |
AZURE_OPENAI_RESOURCE_NAME | Used to construct base URL: https://<resource>.openai.azure.com/openai/v1 |
AZURE_OPENAI_DEPLOYMENT_NAME_MAP | Optional mapping string: modelId=deploymentName,model2=deployment2 |
Base URL resolution: option azureBaseUrl → env AZURE_OPENAI_BASE_URL → option/env resource name → the model row’s baseUrl in models.yml.
Google Vertex AI
| Variable | Required? | Notes |
|---|---|---|
GOOGLE_CLOUD_PROJECT | Yes (unless passed in options) | Primary project ID source |
GCP_PROJECT | Fallback | Alternate project ID source |
GCLOUD_PROJECT | Fallback | Alternate project ID source |
GOOGLE_CLOUD_PROJECT_ID | OAuth login helper only | Used by Gemini CLI OAuth project discovery |
GOOGLE_VERTEX_LOCATION | Yes (unless passed in options) | Primary Vertex location source |
GOOGLE_CLOUD_LOCATION | Fallback | Alternate Vertex location source |
VERTEX_LOCATION | Fallback | Alternate Vertex location source |
GOOGLE_CLOUD_API_KEY | Conditional | Direct Vertex API-key auth; otherwise ADC fallback can authenticate when project and location are set |
GOOGLE_APPLICATION_CREDENTIALS | Conditional | If set, file must exist; otherwise ADC fallback path is checked (~/.config/gcloud/application_default_credentials.json) |
Kimi
| Variable | Default / behavior |
|---|---|
KIMI_CODE_OAUTH_HOST | Primary OAuth host override |
KIMI_OAUTH_HOST | Fallback OAuth host override |
KIMI_CODE_BASE_URL | Overrides Kimi usage endpoint base URL (usage/kimi.ts) |
OAuth host chain: KIMI_CODE_OAUTH_HOST → KIMI_OAUTH_HOST → https://auth.kimi.com.
Gemini CLI compatibility
| Variable | Default / behavior |
|---|---|
VEYYON_AI_GEMINI_CLI_VERSION | Overrides the Gemini CLI user-agent version tag (0.46.0 if unset) |
VEYYON_AI_ANTIGRAVITY_VERSION | Overrides the Antigravity / Cloud Code Assist user-agent version tag (2.1.4 if unset) |
OpenAI Codex responses (feature/debug controls)
| Variable | Behavior |
|---|---|
VEYYON_CODEX_DEBUG | 1/true enables Codex provider debug logging |
VEYYON_CODEX_WEBSOCKET | 1/true enables websocket transport preference |
VEYYON_OPENAI_STATEFUL | Overrides the stateful-chaining default for the platform OpenAI Responses API (previous_response_id, forces store: true): on by default against api.openai.com, off elsewhere |
VEYYON_CODEX_WEBSOCKET_IDLE_TIMEOUT_MS | Positive integer override (default 300000) |
VEYYON_CODEX_WEBSOCKET_RETRY_BUDGET | Non-negative integer override (default 5) |
VEYYON_CODEX_WEBSOCKET_RETRY_DELAY_MS | Positive integer base backoff override (default 500) |
VEYYON_CODEX_WEBSOCKET_FIRST_EVENT_TIMEOUT_MS | Positive integer wait for the first websocket event before falling back to SSE (default 60000). Switches transport rather than failing the request |
VEYYON_CODEX_WEBSOCKET_MAX_IDLE_REUSE_MS | Longest quiet period a reused socket is trusted for before a fresh handshake (default 30000); 0 disables the ceiling |
VEYYON_CODEX_WEBSOCKET_PING_INTERVAL_MS | Positive integer keepalive ping interval (default 10000) |
VEYYON_CODEX_WEBSOCKET_PONG_TIMEOUT_MS | Positive integer wait for a pong before the socket is treated as dead (default 60000) |
VEYYON_CODEX_WEBSOCKET_MESSAGE_QUEUE_CAPACITY | Positive integer inbound frame queue capacity (default 4096) |
VEYYON_OPENAI_STREAM_FIRST_EVENT_TIMEOUT_MS | Positive integer OpenAI first-event timeout override; 0 disables. veyyon config set providers.streamFirstEventTimeoutSeconds <seconds> provides the persisted config equivalent |
VEYYON_OPENAI_STREAM_IDLE_TIMEOUT_MS | Positive integer OpenAI stream idle timeout override; 0 disables. veyyon config set providers.streamIdleTimeoutSeconds <seconds> provides the persisted config equivalent |
Cursor provider debug
| Variable | Behavior |
|---|---|
DEBUG_CURSOR | Enables provider debug logs; 2/verbose for detailed payload snippets |
DEBUG_CURSOR_LOG | Optional file path for JSONL debug log output |
Transport selection (OpenRouter, Perplexity)
Both providers can be reached over two different HTTP APIs, and these pick which one.
| Variable | Behavior |
|---|---|
VEYYON_OPENROUTER_RESPONSES | OpenRouter uses the Responses API unless this is exactly 0, which selects chat completions. Any other value leaves the default in place |
VEYYON_PERPLEXITY_RESPONSES | Perplexity web search uses the Responses API only when this is exactly 1 |
Prompt cache controls
| Variable | Behavior |
|---|---|
VEYYON_CACHE_RETENTION | If long, enables long retention where supported (anthropic, openai-responses, Bedrock retention resolution) |
VEYYON_CACHE_ENFORCEMENT | What happens when a request’s cache markers demonstrably did not take effect: off, warn (default), or error. error aborts the turn. Anthropic only. Overridden by an explicit per-request level, and the cache.blockOnRejection setting selects error through the same resolver. See prompt caching. |
3) Web search subsystem
Search provider credentials
| Variable | Used by |
|---|---|
EXA_API_KEY | Exa search provider and Exa MCP tools |
BRAVE_API_KEY | Brave search provider |
PERPLEXITY_API_KEY | Perplexity search provider API-key mode |
PERPLEXITY_COOKIES | Perplexity cookie-auth search mode |
TAVILY_API_KEY | Tavily search provider |
ZAI_API_KEY | z.ai search provider (also checks stored OAuth in agent.db) |
OPENAI_API_KEY / Codex OAuth in DB | Codex search provider availability/auth |
VEYYON_CODEX_WEB_SEARCH_MODEL | Codex search provider model override |
MOONSHOT_SEARCH_API_KEY / KIMI_SEARCH_API_KEY | Kimi/Moonshot search provider env auth |
MOONSHOT_SEARCH_BASE_URL / KIMI_SEARCH_BASE_URL | Kimi/Moonshot search endpoint override |
KAGI_API_KEY | Kagi search provider |
JINA_API_KEY | Jina search provider |
PARALLEL_API_KEY | Parallel search provider |
SEARXNG_ENDPOINT, SEARXNG_TOKEN | SearXNG endpoint and optional bearer token |
SEARXNG_BASIC_USERNAME, SEARXNG_BASIC_PASSWORD | SearXNG HTTP Basic Auth credentials |
SearXNG also reads the equivalent searxng.endpoint, searxng.token, searxng.basicUsername, and searxng.basicPassword settings from ~/.veyyon/profiles/default/agent/config.yml; environment variables are fallbacks.
Anthropic web search auth chain
searchAnthropic() resolves credentials in this order:
ANTHROPIC_SEARCH_API_KEYauthStorage.getApiKey("anthropic")fallback credentials (runtime/config overrides, stored API-key credentials, stored OAuth credentials, then generic Anthropic env fallback:ANTHROPIC_FOUNDRY_API_KEYin Foundry mode, otherwiseANTHROPIC_OAUTH_TOKEN/ANTHROPIC_API_KEY)
For either credential path, base URL resolution is:
ANTHROPIC_SEARCH_BASE_URLFOUNDRY_BASE_URLwhenCLAUDE_CODE_USE_FOUNDRYis enabledANTHROPIC_BASE_URLhttps://api.anthropic.com
Related vars:
| Variable | Default / behavior |
|---|---|
ANTHROPIC_SEARCH_API_KEY | API key used exclusively for the Anthropic web search provider. Highest-priority search auth; overrides ANTHROPIC_API_KEY / OAuth / Foundry for search calls without affecting chat completions. |
ANTHROPIC_SEARCH_BASE_URL | Base URL used exclusively for the Anthropic web search provider. Applied to either ANTHROPIC_SEARCH_API_KEY or fallback Anthropic credentials; overrides ANTHROPIC_BASE_URL (and FOUNDRY_BASE_URL in Foundry mode) for search calls. |
ANTHROPIC_SEARCH_MODEL | Search model override. Defaults to claude-haiku-4-5. |
ANTHROPIC_BASE_URL | Generic fallback base URL for Anthropic requests when no search-specific base URL is set. |
Use ANTHROPIC_SEARCH_BASE_URL (optionally with ANTHROPIC_SEARCH_API_KEY) to keep chat routed through an enterprise gateway (ANTHROPIC_BASE_URL or CLAUDE_CODE_USE_FOUNDRY=true) while pointing web search at a direct Anthropic endpoint, or vice versa.
Perplexity OAuth flow behavior flag
| Variable | Behavior |
|---|---|
VEYYON_AUTH_NO_BORROW | If set, disables macOS native-app token borrowing path in Perplexity login flow |
4) Python tooling and kernel runtime
| Variable | Default / behavior |
|---|---|
VEYYON_PY | Boolean-like override for the Python eval backend: truthy (1/true/yes/on) enables, any other value disables; unset defers to the eval.py setting (default enabled) |
VEYYON_JS | Same boolean-like override for the JavaScript eval backend; unset defers to the eval.js setting (default enabled) |
VEYYON_PYTHON_SKIP_CHECK | If 1, skips Python interpreter availability checks (subprocess runner still starts on demand) |
VEYYON_PYTHON_INTEGRATION | If 1, opts gated integration tests in (e.g. python-runner-integration.test.ts) into running against real Python |
VEYYON_PYTHON_IPC_TRACE | If 1, logs NDJSON frames exchanged with the Python runner subprocess |
VEYYON_RUBY_IPC_TRACE | Same, for the Ruby runner subprocess |
VEYYON_JULIA_IPC_TRACE | Same, for the Julia runner subprocess |
VIRTUAL_ENV | Highest-priority venv path for Python runtime resolution |
Extra conditional behavior:
- If
BUN_ENV=testorNODE_ENV=test, Python availability checks are treated as OK and warming is skipped. - Python env filtering denies common API keys and allows safe base vars +
LC_,XDG_,VEYYON_prefixes. - Every eval kernel spells its IPC trace variable
VEYYON_<LANGUAGE>_IPC_TRACE, with the language spelled out in full (PYTHON,RUBY,JULIA), not abbreviated the way the source directories are. A language added later follows the same convention: it comes from one helper inpackages/coding-agent/src/eval/kernel-base.tsrather than from each kernel formatting its own name.
5) Agent/runtime behavior toggles
| Variable | Default / behavior |
|---|---|
VEYYON_SMOL_MODEL | Ephemeral model-role override for smol (CLI --smol takes precedence) |
VEYYON_STREAM_FRAME_MAX_BYTES | Bytes one frame of a streamed protocol may occupy before the reader rejects it and cancels the source: a line, a JSONL record, or an SSE event ending at a blank line. Default 67108864 (64 MiB). Covers provider response streams, MCP server stdout and session files. A value that is not a positive integer keeps the default, so a typo cannot remove the bound. The refusal is terminal and never retried. |
VEYYON_SLOW_MODEL | Ephemeral model-role override for slow (CLI --slow takes precedence) |
VEYYON_PLAN_MODEL | Ephemeral model-role override for plan (CLI --plan takes precedence) |
VEYYON_NO_TITLE | If set (any non-empty value), disables auto session title generation on first user message |
VEYYON_SKIP_SETUP | If set to any value other than empty/0/false/no (case-insensitive), skips the first-run setup wizard (no setup scenes are shown). |
VEYYON_TINY_DEVICE | ONNX execution provider for local tiny models; overrides the providers.tinyModelDevice setting (setting default: default, which selects CPU-only inference; also supports cpu, gpu, metal/webgpu, auto, cuda, dml, coreml, wasm, webnn, webnn-gpu, webnn-cpu, webnn-npu) |
VEYYON_TINY_DTYPE | ONNX quantization/precision for local tiny models; overrides the providers.tinyModelDtype setting (setting default: default, which selects each model’s shipped dtype, currently q4; also supports auto, fp32, fp16, q8, int8, uint8, q4, bnb4, q4f16, q2, q2f16, q1, q1f16) |
VEYYON_NO_INTERLEAVED_THINKING | If 1, disables Anthropic interleaved thinking budget behavior and uses output-token inflation for older thinking mode |
VEYYON_NO_INTENT | If 1, tool schemas ship without the injected i intent parameter, so the model stops stating what each call is for. Tools that already opt out are unaffected |
NULL_PROMPT | If true, system prompt builder returns empty string |
VEYYON_BLOCKED_AGENT | Self-recursion prevention: read once from the process env when the task tool is constructed, and any spawn whose agent type equals it is rejected with Cannot spawn <name> agent from within itself (recursion prevention). The comparison is against the name the caller wrote, before retired-name resolution, so it must be spelled the way the spawn spells it (deep, not the retired task, unless the caller itself writes task). Nothing in the product sets it; it is a harness/debug knob. |
VEYYON_SUBPROCESS_CMD | Overrides subagent spawn command (veyyon / veyyon.cmd resolution bypass) |
VEYYON_TASK_MAX_OUTPUT_BYTES | Max captured output bytes per subagent (default 500000) |
VEYYON_TASK_MAX_OUTPUT_LINES | Max captured output lines per subagent (default 5000) |
VEYYON_TIMING | If set (any non-empty value), prints a hierarchical timing-span tree to stderr via logger.printTimings(). In interactive mode the tree prints once the agent is ready (before the TUI starts); in print mode it prints after the whole prompt batch completes. Print-mode prompts are wrapped in print:prompt:initial / print:prompt:next spans so each user message shows up as its own row. VEYYON_TIMING=x exits the process with code 0 right after printing in interactive mode (use to measure cold startup only). VEYYON_TIMING=full lists every module-load entry instead of just the top N. |
VEYYON_DEBUG_STARTUP | If set (any non-empty value), streams one synchronous [startup] <phase>:start / :done marker line to stderr as each startup phase begins/ends, including command-module imports (cli:load:<name>) and the native addon extraction/dlopen (native:*). Unlike VEYYON_TIMING (which prints only once startup completes), the markers survive a hard hang: the last line on stderr states the phase the process is stuck in. Combine with VEYYON_TIMING freely; markers and the span tree share the same phase names. |
VEYYON_PACKAGE_DIR | Overrides package asset base dir resolution (docs, examples, and CHANGELOG assets) |
VEYYON_REPAIR_DISABLE | If 1/true/yes, disables malformed-tool-call schema repair (calls fail instead of being repaired) |
VEYYON_DISABLE_LSPMUX | If 1, disables lspmux detection/integration and forces direct LSP server spawning |
VEYYON_RPC_EMIT_TITLE | Boolean-like flag enabling title events in RPC mode |
SMITHERY_URL | Smithery web URL override (default https://smithery.ai) |
SMITHERY_API_URL | Smithery API base URL override (default https://api.smithery.ai) |
SMITHERY_API_KEY | Smithery API key for managed MCP auth lookup |
PUPPETEER_EXECUTABLE_PATH | Browser tool Chromium executable override |
LITELLM_BASE_URL | LiteLLM proxy base URL fallback (http://localhost:4000/v1 if unset); an explicit baseUrl on the litellm provider in models.yml wins |
LM_STUDIO_BASE_URL | Default implicit LM Studio discovery base URL override (http://127.0.0.1:1234/v1 if unset) |
OLLAMA_BASE_URL | Default implicit Ollama discovery base URL override (OLLAMA_HOST if unset, then http://127.0.0.1:11434) |
OLLAMA_HOST | Ollama host used for implicit Ollama discovery when OLLAMA_BASE_URL is unset; accepts Ollama-style values such as 127.0.0.1:11434 or http://host:11434 |
OLLAMA_CONTEXT_LENGTH | Positive integer context-window override for implicit Ollama discovery; affects Veyyon context budgeting only and does not change Ollama’s runtime num_ctx |
LLAMA_CPP_BASE_URL | Default implicit Llama.cpp discovery base URL override (http://127.0.0.1:8080 if unset) |
VEYYON_EDIT_VARIANT | Forces edit tool variant when valid (patch, replace, hashline, apply_patch) |
VEYYON_STRICT_EDIT_MODE | If 1, suppresses the built-in per-model fallback that turns a hashline default into another mode for models known to do badly with it (today: any model id containing kimi falls back to replace). It does not affect the two overrides that outrank edit.mode anyway: an edit.modelVariants pattern that matches the active model wins first, then VEYYON_EDIT_VARIANT, then edit.mode |
VEYYON_FORCE_IMAGE_PROTOCOL | Forces supported image protocol (kitty, iterm2/iterm, sixel, none) where used |
VEYYON_ALLOW_SIXEL_PASSTHROUGH | Allows SIXEL passthrough when VEYYON_FORCE_IMAGE_PROTOCOL=sixel |
VEYYON_NO_WEBP | If 1 or true (case-insensitive), excludes WebP from image encoding so images are sent as PNG/JPEG only (llama.cpp/Ollama STB decoders cannot read WebP). Read per call, so it takes effect at runtime. |
VEYYON_NO_PTY | If 1, disables interactive PTY path for bash tool |
VEYYON_DIALECT | Force-enables owned (in-band) tool calling with the named dialect when no configured dialect wins: glm, hermes, kimi, xml, anthropic, deepseek, harmony, qwen3, gemini, gemma, minimax, pi-native; 1/true mean glm. Unrecognized values are ignored. Same set as the tools.format setting. |
VEYYON_HARMONY_DEBUG | Debug. If 1, includes the full removed text as removedBlob in each harmony-leak audit event (the onHarmonyLeak hook); otherwise only a redacted length/hash/preview is emitted. Use to inspect what harmony-leak scrubbing removed. |
VEYYON_MCP_TIMEOUT_MS | Overrides MCP client request timeout (ms) for every MCP server. 0 disables client-side timeouts (AbortSignal never fires). Invalid (negative or non-numeric) values are ignored with a warning and the per-server config or default (30000) is used |
VEYYON_PIPED_STDIN_WAIT_MS | How long veyyon -p "prompt" waits for the FIRST byte of piped stdin when the prompt is already on the command line (default 10000). It bounds only the wait before anything arrives, so a slow or large piped document is still read in full; 0 waits indefinitely, which is what happens when the pipe is your only input. It exists because a parent process that spawns Veyyon with an inherited pipe it never writes to and never closes sends no EOF, and the run would otherwise block forever. |
VEYYON_STACK | If 1, fatal CLI errors print the full inspected error (stack + source context) instead of the default concise message + cause chain report |
VEYYON_EDIT_FUZZY | true/1 or false/0 forces fuzzy matching in the edit tool on or off; auto (the default) reads the edit.fuzzyMatch setting. Any other value fails the call |
VEYYON_EDIT_FUZZY_THRESHOLD | Similarity floor for fuzzy matching, 0-1. auto (the default) reads the edit.fuzzyThreshold setting. A value outside the range, or not a number, fails the call |
VEYYON_STREAM_FIRST_EVENT_TIMEOUT_MS | Cross-provider first-event watchdog in ms; 0 disables it. A per-request streamFirstEventTimeoutMs wins, and OpenAI-family transports prefer VEYYON_OPENAI_STREAM_FIRST_EVENT_TIMEOUT_MS. Default 100000 |
VEYYON_STREAM_IDLE_TIMEOUT_MS | Cross-provider maximum idle gap between streamed events in ms, applied once the first event has arrived; 0 disables it. A per-request streamIdleTimeoutMs wins, and VEYYON_OPENAI_STREAM_IDLE_TIMEOUT_MS is the OpenAI-family alias. Default 120000 |
VEYYON_NO_THINKING_LOOP_GUARD | If 1, disables the repeated-thinking-block loop detector for the models it normally guards |
VEYYON_MAX_AST_FILES | Positive integer cap on how many files one ast_edit call may rewrite (default 1000) |
VEYYON_TOKENIZER_ACCURATE | If 1, uses the accurate tokenizer instead of the fast estimate. Ignored under NODE_ENV=test |
VEYYON_REQ_DEBUG | If 1, dumps every provider HTTP request and its response stream to rr-session-<n>.json and rr-session-<n>.res.log in the process working directory, mode 0600. The dumps include request headers, so they contain credentials. A dump that cannot be written is logged and the request proceeds |
VEYYON_PROXY | Egress proxy URL for every provider request. VEYYON_PROXY_<PROVIDER> (the provider id uppercased with non-alphanumerics as _, e.g. VEYYON_PROXY_GITHUB_COPILOT) overrides it for one provider. Localhost, RFC1918, link-local and cloud metadata hosts always bypass the proxy, as do NO_PROXY/no_proxy matches |
VEYYON_EVAL_SYSTEM_PROMPT_SECTIONS | Benchmark instrumentation, not an operator knob. A JSON object of section name to replacement text. When set, the benchmark payload becomes the only source of prompt sections and the run logs that the override is active. Invalid JSON fails the build |
VEYYON_EVAL_SYSTEM_PROMPT_STATEMENTS | The statement-level counterpart to the section override, same benchmark-only status. See system prompt architecture |
VEYYON_NO_PTY is also set internally when CLI --no-pty is used.
6) Storage and config root paths
These are consumed via @veyyon/utils/dirs and affect where coding-agent stores data.
| Variable | Default / behavior |
|---|---|
VEYYON_CONFIG_DIR | Config root dirname under home (default .veyyon). A name, not a path: an absolute value is rejected at startup. |
VEYYON_PROFILE | Activate a named profile (relocates the user base to ~/.veyyon/profiles/<name>) |
VEYYON_WORKTREE_DIR | Base directory for task-isolation worktrees (default ~/.veyyon/profiles/<name>/wt) |
VEYYON_GITHUB_CACHE_DB | Path override for the GitHub tool cache database |
VEYYON_AUTORESEARCH_DB_DIR | Directory override for the autoresearch database |
VEYYON_CODING_AGENT_DIR | Full override for the agent directory (default ~/<config dir>/profiles/<active-or-default>/agent) |
PWD | Used when matching canonical current working directory in path helpers |
7) Shell/tool execution environment
(From packages/utils/src/procmgr.ts and coding-agent bash tool integration.)
| Variable | Behavior |
|---|---|
VEYYON_BASH_NO_CI | Suppresses automatic CI=true injection into spawned shell env |
CLAUDE_BASH_NO_CI | Legacy alias fallback for VEYYON_BASH_NO_CI |
VEYYON_BASH_NO_LOGIN | Disables login-shell mode; shell args become ['-c'] instead of ['-l','-c'] |
CLAUDE_BASH_NO_LOGIN | Legacy alias fallback for VEYYON_BASH_NO_LOGIN |
VEYYON_SHELL_PREFIX | Optional command prefix wrapper |
CLAUDE_CODE_SHELL_PREFIX | Legacy alias fallback for VEYYON_SHELL_PREFIX |
VISUAL | Preferred external editor command |
EDITOR | Fallback external editor command |
Current implementation: VEYYON_BASH_NO_LOGIN/CLAUDE_BASH_NO_LOGIN are active; when either is set, getShellArgs() returns ['-c'].
8) UI/theme/session detection (auto-detected env)
These are read as runtime signals; they are usually set by the terminal/OS rather than manually configured.
| Variable | Used for |
|---|---|
COLORTERM, TERM, WT_SESSION | Color capability detection (theme color mode) |
COLORFGBG | Terminal background light/dark auto-detection |
TERM_PROGRAM, TERM_PROGRAM_VERSION, TERMINAL_EMULATOR | Terminal identity in system prompt/context |
TMUX_PANE, CMUX_SURFACE_ID, KITTY_WINDOW_ID, TERM_SESSION_ID, WT_SESSION | Stable per-terminal session breadcrumb IDs |
SHELL, ComSpec, TERM_PROGRAM, TERM | System info diagnostics |
APPDATA, XDG_CONFIG_HOME | lspmux config path resolution |
HOME | Path shortening in MCP command UI |
9) TUI runtime flags (shared package, affects coding-agent UX)
| Variable | Behavior |
|---|---|
VEYYON_NOTIFICATIONS | off / 0 / false suppress desktop notifications |
VEYYON_TUI_WRITE_LOG | If set, logs TUI writes to file |
VEYYON_HARDWARE_CURSOR | If 1, enables hardware cursor mode |
VEYYON_NO_SYNC_OUTPUT | If set (any non-empty value), disables DEC 2026 synchronized-output wrappers while keeping TUI autowrap guards |
VEYYON_TUI_SYNC_OUTPUT | 0 disables synchronized output, 1 forces it on. It shares one override tier with VEYYON_NO_SYNC_OUTPUT and VEYYON_FORCE_SYNC_OUTPUT, and an opt-out always beats a force-on. With no override the default comes from TERM_FEATURES, WT_SESSION, a terminal allowlist, and then a runtime DECRQM probe |
VEYYON_FORCE_SYNC_OUTPUT | 1 forces synchronized output on, unless an opt-out is also set |
VEYYON_TUI_SCROLL_TRANSPORT | alt-arrows releases the mouse grab and moves the transcript to the alternate screen with Alternate Scroll Mode, so the terminal keeps native selection and sends wheel ticks as cursor keys. Any other value keeps the default mouse transport |
VEYYON_NO_DECCARA | If set (truthy), disables Kitty DECCARA rectangular-SGR background fills (forces padded-string rendering) |
VEYYON_DEBUG_REDRAW | If 1, enables redraw debug logging |
VEYYON_FORCE_IMAGE_PROTOCOL | Forces terminal image protocol detection (kitty, iterm2/iterm, sixel, none) |
VEYYON_TUI_RESIZE_IN_PLACE | 1/true force in-place resize (no alt-screen borrow, no ED3 rewrap); 0/false force the alt-screen fast path. Default-on for Warp, which re-reports its size on alt-screen toggles |
10) Commit generation controls
| Variable | Behavior |
|---|---|
VEYYON_COMMIT_TEST_FALLBACK | If true (case-insensitive), force commit fallback generation path |
VEYYON_COMMIT_NO_FALLBACK | If true, disables fallback when agent returns no proposal |
VEYYON_COMMIT_MAP_REDUCE | If false, disables map-reduce commit analysis path |
DEBUG | If set, commit agent error stack traces are printed |
Security-sensitive variables
Treat these as secrets; do not log or commit them:
- Provider/API keys and OAuth/bearer credentials (all
*_API_KEY,*_TOKEN, OAuth access/refresh tokens) - Cloud credentials (
AWS_*,GOOGLE_APPLICATION_CREDENTIALSpath may expose service-account material) - Search/provider auth vars (
EXA_API_KEY,BRAVE_API_KEY,PERPLEXITY_API_KEY, Anthropic search keys) - Foundry mTLS material (
CLAUDE_CODE_CLIENT_CERT,CLAUDE_CODE_CLIENT_KEY,NODE_EXTRA_CA_CERTSwhen it points to private CA bundles) VEYYON_REQ_DEBUGis not a secret itself, but therr-session-*.jsondumps it writes into the working directory record request headers verbatim, so a dump carries whatever credential authenticated the request. Delete the files or keep them out of the repository
Python runtime also explicitly strips many common key vars before spawning kernel subprocesses (packages/coding-agent/src/eval/py/runtime.ts).