Usage
Environment variables
Environment variables: a Cyberine usage recipe.
| Var | Default | Used by |
|---|---|---|
OPENCODE_MODEL | deepseek/deepseek-v4-pro | OpenCode adapter |
OPENCODE_VARIANT | high | OpenCode adapter (minimal/high/max) |
OPENCODE_AGENT | plan (config) / build (interactive) | OpenCode agent (--agent); plan is read-only (safe Q&A worker), build can edit. Config/--sample/demo default plan; the interactive launcher (cyberine chat /run, cyberine run --bg, TUI n) defaults build so a chat session plans AND builds with no manual env. An explicit value always wins |
OPENCODE_SKIP_PERMISSIONS | true | pass --dangerously-skip-permissions (required for headless OpenCode, else it stalls on a permission prompt) |
CYBERINE_OPENCODE_MAX_RETRIES | 2 | extra spawn retries when OpenCode crashes at startup on a transient local-DB lock (PRAGMA wal_checkpoint), so the only file-capable worker is not lost to a fluke. Only transient errors are retried (never a real task failure or timeout) |
CYBERINE_OPENCODE_DEEPSEEK_MODEL | deepseek/deepseek-v4-pro | model for the opencode-deepseek build fleet. Pinned to DeepSeek independently of the generic OPENCODE_MODEL so a project/global .env that points OPENCODE_MODEL at another provider can never silently make the "deepseek" fleet run the wrong model |
CYBERINE_OPENCODE_KIMI_MODEL | moonshotai/kimi-k2.7-code | model for the opencode-kimi build fleet. The default provider is dead as of 2026-08-25 (opencode holds no moonshotai credential AND that account is suspended), so the worker self-skips until opencode auth login adds one or a funded MOONSHOT_API_KEY is exported. Repointing this at a credentialled provider (e.g. minimax/MiniMax-M3) also revives it — mind that opencode model ids are CASE-SENSITIVE |
CYBERINE_RULES | true | inject a RULES preamble from <CYBERINE_HOME>/rules/*.md (global) + <cwd>/.cyberine/rules/*.md (project) ahead of the task; set 0/false to disable |
CYBERINE_RULES_MAX_TOKENS | 4000 | token budget (approx chars/4) for the injected RULES preamble before it is truncated |
CYBERINE_SKELETON_TOKENS | 150 | token budget (approx chars/4) for the thin HEAD-keyed repo skeleton injected by LocalBrain.boot() via buildCachedRepoSkeleton. The skeleton is a dense per-directory pointer (~10 lines); workers pull the full map for the module they touch. Cache stored under .local/repo-skeleton-cache/<headSha>.txt; invalidated automatically on every new commit |
CYBERINE_LSP_CMD | (unset) | language server command for the lsp_query worker tool (T312). Format: command and space-separated args, e.g. typescript-language-server --stdio. Unset = auto-detect (typescript-language-server then deno lsp). Set to force a specific binary or disable by not installing any server |
CYBERINE_INSTRUCTION_FILES | true | discover and inject ecosystem instruction files (AGENTS.md / CLAUDE.md) from the target repo into loop worker system messages; set 0/false to disable |
CYBERINE_INSTRUCTION_FILENAMES | AGENTS.md,CLAUDE.md | comma-separated ordered list of filenames to search at each directory level; the first existing file in this list wins per directory |
CYBERINE_INSTRUCTION_FILES_MAX_BYTES | 32768 | max combined byte size of all discovered instruction files; when exceeded, files are dropped from the root end so the nearest-to-cwd file always survives |
CYBERINE_INSTRUCTION_FILES_GLOBAL | false | when true, also read global standard files outside the project git repo (for ~/.config/AGENTS.md-style overrides); default off |
OPENROUTER_API_KEY | (empty) | OpenRouter loop adapter (enables it) |
OPENROUTER_MODEL | deepseek/deepseek-v4-pro-0813 | OpenRouter loop adapter. When unset, the router auto-selects deepseek/deepseek-v4-pro-0813 for complex tasks and deepseek/deepseek-v4-flash-0731 for trivial/standard tasks. The date suffix is mandatory on this route — OpenRouter's undated deepseek/deepseek-v4-pro is a frozen 2026-04-23 legacy alias, not a moving "latest" (the inverse of DEEPSEEK_MODEL below). Re-point in src/core/openrouterModelIds.ts; see Switch the OpenRouter loop model |
OPENROUTER_BASE_URL | https://openrouter.ai/api/v1 | OpenRouter loop adapter |
CYBERINE_ORACLE_MODEL | (empty) | Enables the consult_oracle tool for loop workers and selects its single high-reasoning model |
CYBERINE_ORACLE_BASE_URL | OPENROUTER_BASE_URL | OpenAI-compatible endpoint used only by consult_oracle |
CYBERINE_ORACLE_API_KEY | OPENROUTER_API_KEY | API key used only by consult_oracle; its token usage and estimated cost are added to the worker run |
GATEWAY_BASE_URL | http://localhost:41400/v1 | gateway adapters. If your .env predates the uncommon-port migration it may still read http://localhost:4000/v1 (LiteLLM's raw container-internal default) — Cyberine warns at startup (T551) when it detects this and every gateway-routed call ECONNREFUSEs until it's updated |
CYBERINE_GATEWAY_PORT | 41400 | docker host port for the gateway (uncommon, on-demand); keep GATEWAY_BASE_URL in sync |
GATEWAY_API_KEY | sk-litellm-master-key (in-code fallback only) | gateway adapters. Must match the running gateway's LITELLM_MASTER_KEY exactly. Since T581, docker-compose.yml no longer accepts a hardcoded default for LITELLM_MASTER_KEY (every clone used to ship the identical literal as a working shared secret) — run .claude/skills/cyberine-project-devstack/scripts/devstack.sh up, which generates a random key on first use and writes both LITELLM_MASTER_KEY and GATEWAY_API_KEY to .env for you |
LOOP_MODEL_A / LOOP_MODEL_B | anthropic/claude / openai/gpt | gateway adapters (must match litellm.config.yaml) |
CLI_AGENT_CMD | claude | reserved for the generic CLI adapter path |
JUDGE_MODEL | deepseek/deepseek-v4-pro-0813 | legacy judge model for OpenRouter path (superseded by CYBERINE_JUDGE_MODEL_STRONG; still read when the new vars are unset) |
CYBERINE_JUDGE_MODEL | (empty) | pin a single judge model for all tiers — overrides auto-selection; unset = auto by task tier |
CYBERINE_JUDGE_MODEL_STRONG | deepseek/deepseek-v4-pro-0813 | judge model for complex tasks (large refactors, repo-wide scope); used on the OpenRouter path when CYBERINE_JUDGE_MODEL is unset |
CYBERINE_JUDGE_MODEL_WEAK | deepseek/deepseek-v4-flash-0731 | judge model for trivial/standard tasks (QA and simple code edits); cheaper and faster than the strong model; used on the OpenRouter path when CYBERINE_JUDGE_MODEL is unset. Also the sentinel the DeepSeek-direct judge path reads to detect an operator override (src/judges/selectJudgeModel.ts) — change the default and that constant together |
CYBERINE_JUDGE_TIMEOUT_MS | 60000 | hard wall-clock budget (ms) for a single judge's decide() call. WorkflowEngine races every judge against this timeout (T551) so an unreachable/misconfigured judge-model endpoint (e.g. a stale GATEWAY_BASE_URL) cannot hold a run's state at running forever with no recorded verdict — a judge that times out is treated as failed (recorded on the step's verdict rationale) and the run still reaches a terminal state |
CYBERINE_OTEL_ENDPOINT | (empty) | OTLP/HTTP collector base URL (e.g. http://localhost:4318) for the OpenTelemetry GenAI span exporter (kyv0t) — see OpenTelemetry GenAI export. Empty (default) fully disables the exporter: no @opentelemetry/* package is ever imported, no network call, no new startup cost |
DEEPSEEK_API_KEY | (empty) | DeepSeek-direct worker + judges (enables them; preferred over OpenRouter) |
DEEPSEEK_BASE_URL | https://api.deepseek.com | DeepSeek-direct endpoint |
DEEPSEEK_MODEL | deepseek-v4-pro | DeepSeek-direct model (worker + judges). deepseek-v4-pro (Think, default — carries design/reasoning tasks) or deepseek-v4-flash (cheaper, no deep reasoning). When unset, the router's variant selection automatically uses deepseek-v4-pro for complex tasks and deepseek-v4-flash for trivial/standard tasks. Setting this env var pins the model and skips variant selection entirely |
MOONSHOT_API_KEY | (empty) | Moonshot Kimi-direct key; enables the loop-kimi-build key-only worker (add it to CYBERINE_BUILD_FLEET) |
MOONSHOT_BASE_URL | https://api.moonshot.ai/v1 | Moonshot Kimi endpoint (mainland: https://api.moonshot.cn/v1) |
MOONSHOT_MODEL | kimi-k2.7-code | Moonshot Kimi model id for loop-kimi-build. When unset, the router auto-selects kimi-k2-thinking for complex tasks and kimi-k2-turbo-preview for trivial/standard tasks. Setting this env var pins the model and skips variant selection |
XIAOMI_API_KEY | (empty) | Xiaomi MiMo-direct key (platform.xiaomimimo.com); enables loop-mimo-direct (compare fleet) + the loop-mimo-build key-only worker (add it to CYBERINE_BUILD_FLEET) |
XIAOMI_BASE_URL | https://api.xiaomimimo.com/v1 | Xiaomi MiMo endpoint (regional: token-plan-cn/token-plan-ams/token-plan-sgp.xiaomimimo.com/v1) |
XIAOMI_MODEL | mimo-v2.5-pro | Xiaomi MiMo model id (mimo-v2.5-pro, mimo-v2.5, mimo-v2-pro, mimo-v2-flash, mimo-v2-omni) |
MINIMAX_API_KEY | (empty) | MiniMax-direct key (platform.minimax.io); enables loop-minimax-direct (compare fleet) + the loop-minimax-build key-only worker (add it to CYBERINE_BUILD_FLEET) |
MINIMAX_BASE_URL | https://api.minimax.io/v1 | MiniMax OpenAI-compatible endpoint (international platform) |
MINIMAX_MODEL | MiniMax-M3 | MiniMax model id (MiniMax-M3, MiniMax-M2.7, MiniMax-M2.7-highspeed, MiniMax-M2.5, MiniMax-M2) |
MMX_TOKEN_KEY | (empty) | MiniMax mmx CLI Token Plan key. OPTIONAL: if empty but the mmx CLI is installed and logged in (mmx login session), the mmx-text-build worker and the mmx_image_generate/mmx_speech_synthesize implementer tools still work — the CLI uses its own login. Set this only to override the CLI session with an explicit key |
CYBERINE_MMX_MODEL | MiniMax-Text-01 | model id the mmx-text-build worker passes to mmx text chat --model |
COPILOT_MODEL | gpt-4o | GitHub Copilot model id; OAuth token stored in ~/.cyberine/copilot.json (run cyberine auth login copilot); enables loop-copilot-build key-only worker |
OPENAI_API_KEY | (empty) | consumed by the LiteLLM gateway (litellm.config.yaml) to route openai/* model aliases; ALSO enables the native key-only worker loop-openai-build (no gateway/CLI) |
OPENAI_BASE_URL | https://api.openai.com/v1 | OpenAI direct adapter base URL |
OPENAI_MODEL | gpt-4o | OpenAI direct model id for loop-openai-build |
GEMINI_API_KEY | (empty) | Google Gemini direct key; enables loop-gemini-build key-only worker |
GEMINI_BASE_URL | https://generativelanguage.googleapis.com/v1beta/openai | Gemini OpenAI-compatible endpoint |
GEMINI_MODEL | gemini-2.5-pro | Gemini model id for loop-gemini-build |
PERPLEXITY_API_KEY | (empty) | Perplexity direct key (api.perplexity.ai, OpenAI-compatible). Enables the loop-perplexity-build worker and the perplexity backend of the web_search tool (the default backend is a Claude seat, see CYBERINE_WEB_SEARCH_BACKEND) |
PERPLEXITY_BASE_URL | https://api.perplexity.ai | Perplexity chat completions endpoint base. Rarely overridden |
PERPLEXITY_MODEL | sonar-pro | Perplexity model id sent on every web_search call on the perplexity backend (also the default for loop-perplexity-build). sonar-pro has native web search; override only to A/B another sonar variant |
CYBERINE_WEB_SEARCH_BACKEND | auto | web_search backend: auto (a Claude seat when one is usable, else Perplexity when keyed), seat or perplexity. Config key research.searchBackend. See "Research mode" |
CYBERINE_WEB_SEARCH_SEAT | (empty) | Pins the seat backend to one fleet.json seat instead of rotating over every enabled claude seat. Config key research.searchSeat, global config only |
CYBERINE_WEB_SEARCH_MODEL | haiku | --model of the seat backend's claude -p search turn. Config key research.searchModel |
CYBERINE_WEB_SEARCH_TIMEOUT_MS | 180000 | Per-search timeout of the seat backend. Config key research.searchTimeoutMs |
XAI_API_KEY | (empty) | xAI Grok direct key; enables loop-xai-build key-only worker |
XAI_BASE_URL | https://api.x.ai/v1 | xAI direct endpoint |
XAI_MODEL | grok-3 | xAI model id for loop-xai-build |
GROQ_API_KEY | (empty) | Groq direct key; enables loop-groq-build key-only worker (very low latency) |
GROQ_BASE_URL | https://api.groq.com/openai/v1 | Groq endpoint |
GROQ_MODEL | llama-3.3-70b-versatile | Groq model id for loop-groq-build |
MODEL_API_KEY | (empty) | Meta Model API key (mint at dev.meta.ai, shape `LLM |
META_BASE_URL | https://api.meta.ai/v1 | Meta Model API endpoint |
META_MODEL | muse-spark-1.3 | Meta Model API model id for loop-muse-build. Deliberately the non--contributor row |
MISTRAL_API_KEY | (empty) | Mistral direct key; enables loop-mistral-build key-only worker |
MISTRAL_BASE_URL | https://api.mistral.ai/v1 | Mistral endpoint |
MISTRAL_MODEL | mistral-large-latest | Mistral model id for loop-mistral-build |
TOGETHER_API_KEY | (empty) | Together AI direct key; enables loop-together-build key-only worker |
TOGETHER_BASE_URL | https://api.together.xyz/v1 | Together AI endpoint |
TOGETHER_MODEL | meta-llama/Llama-3.3-70B-Instruct-Turbo | Together AI model id for loop-together-build |
FIREWORKS_API_KEY | (empty) | Fireworks AI direct key; enables loop-fireworks-build key-only worker |
FIREWORKS_BASE_URL | https://api.fireworks.ai/inference/v1 | Fireworks AI endpoint |
FIREWORKS_MODEL | accounts/fireworks/models/deepseek-v3 | Fireworks AI model id for loop-fireworks-build |
AZURE_OPENAI_API_KEY | (empty) | Azure OpenAI instance key; combined with AZURE_OPENAI_ENDPOINT enables loop-azure-build and the compare-fleet azure adapter |
AZURE_OPENAI_ENDPOINT | (empty) | Azure instance endpoint (e.g. https://<name>.openai.azure.com/openai/deployments/<deployment>/) |
AZURE_OPENAI_DEPLOYMENT | gpt-4o | Azure deployment name (model id within the Azure instance) |
AZURE_OPENAI_API_VERSION | 2024-12-01-preview | Azure API version query parameter sent on every request |
ANTHROPIC_API_KEY | (empty) | consumed by the LiteLLM gateway to route anthropic/* aliases; ALSO enables the native key-only worker loop-claude-native-build (no gateway/CLI) |
ANTHROPIC_BASE_URL | https://api.anthropic.com | native Anthropic adapter base URL (override only for a proxy) |
ANTHROPIC_MODEL | claude-sonnet-4-6 | native Anthropic adapter model id for loop-claude-native-build |
CYBERINE_ANTHROPIC_FABLE_FALLBACK | false | when true, AnthropicAgentAdapter opts into Anthropic's refusal fallback: on stop_reason: "refusal" it retries the request against claude-opus-4-8 (client-side, since it also sends the server-side-fallback-2026-06-01 beta header for any backend that honors it server-side) instead of ending the run. Only meaningful when ANTHROPIC_MODEL is a Fable-tier model (claude-fable-5 / claude-mythos-5) |
OLLAMA_BASE_URL | http://localhost:11434/v1 | local Ollama server (OpenAI-compatible endpoint). Setting it (or OLLAMA_MODEL) OPTS IN the keyless loop-ollama adapter + loop-ollama-build worker |
OLLAMA_MODEL | llama3.1:8b | Ollama model id; must already be pulled (ollama pull <model>). Use a model that emits structured tool_calls (see docs/providers/ollama.md model table) |
OLLAMA_CLOUD_API_KEY | (empty) | Ollama Cloud hosted-inference key (https://ollama.com/settings/keys); enables loop-ollama-cloud (compare fleet) + loop-ollama-cloud-build key-only worker (add to CYBERINE_BUILD_FLEET). Distinct from local Ollama — cloud requires a key and uses a different base URL |
OLLAMA_CLOUD_BASE_URL | https://ollama.com/v1 | Ollama Cloud OpenAI-compatible endpoint (override only for a proxy; do NOT set to localhost) |
OLLAMA_CLOUD_MODEL | (empty) | Ollama Cloud model id. Cloud models carry a :cloud suffix, e.g. qwen3-coder:480b-cloud, gpt-oss:120b-cloud, gpt-oss:20b-cloud, deepseek-v3.1:671b-cloud. Retrieve live list: curl https://ollama.com/v1/models -H "Authorization: Bearer $OLLAMA_CLOUD_API_KEY" |
CMD_API_KEY | (empty) | Command Code Provider API key (the cmd CLI's key from ~/.commandcode/auth.json); enables the loop-commandcode-build key-only worker. Spend draws on the subscription credit windows shared with the CLI |
CMD_BASE_URL | https://api.commandcode.ai/provider/v1 | Command Code OpenAI-compatible endpoint (override only for a proxy) |
CMD_MODEL | deepseek/deepseek-v4.1-flash | Command Code model id for loop-commandcode-build. Live catalog: GET /provider/v1/models. Ids are case-insensitive; claude-* ids are refused at registration |
CYBERINE_COMMANDCODE_MODEL | deepseek/deepseek-v4.1-flash | model for the command-code CLI worker (--model). A :free / -free id is exempt from the credit-window gate and records zero cost |
CYBERINE_COMMANDCODE_MAX_TURNS | 60 | --max-turns for the command-code CLI worker; hitting it returns a partial result (exit 8) instead of an error |
COMMAND_CODE_API_KEY | (empty) | read by the command-code CLI itself; when set it counts as logged in for the command-code worker and is the only provider key passed into that worker's environment. Without it the CLI uses ~/.commandcode/auth.json |
CMD_FREE_MODEL | (empty) | Comma-separated preference order for the loop-commandcode-free-build free lane. Each entry must be a free id (:free / -free) the live catalog still lists, otherwise it is ignored with a note; free catalog ids not named follow in catalog order. Empty: the catalog's own order |
CMD_FREE_FALLBACK | 1 | 0 stops an explicit loop-commandcode-build fleet from falling through to loop-commandcode-free-build while the paid worker is parked (closed credit window or an earlier refusal) |
CMD_JUDGE_MODEL | (empty) | Command Code model the loop-commandcode-build judge backend uses (default precedence or fleet.json routing.judges). Empty: CMD_MODEL. Set it to a different open-model id than the paid implementer so the judge is not the same model it judges; an Anthropic id is refused |
LOOP_MAX_TOKENS | 16000 | max completion tokens for the model-level loop adapters. High by default so v4-pro "Think" tasks finish reasoning AND emit the answer; it is a cap, not a target. Lower it if falling back to OpenRouter on a credit-limited key |
LOOP_MAX_TOOL_ROUNDS | 25 | max tool-calling rounds for the loop adapter; raise for implementer tasks (the old default of 6 is too few for real file work) |
LOOP_EDIT_PACING_PERCENT | 40 | edit pacing for a loop implementer on a task that expects file changes: while no write tool has been called, nudge it to start writing after this percent of LOOP_MAX_TOOL_ROUNDS, and offer only the write tools once a third of the remaining budget has also gone (40 on 25 rounds: nudge after round 10, write tools only after round 15). 0 turns pacing off; blank, unparseable or outside 0-100 falls back to 40 |
LOOP_STUCK_NO_PROGRESS_ROUNDS | 4 | consecutive tool-call rounds with NO assistant text AND no reasoning_content before the loop adapter declares a worker stuck and aborts it. Raise it for a deliberation-heavy model that batches many silent tool calls between spoken turns. A thinking model's chain-of-thought now COUNTS as progress (2026-08-25): before that fix, deepseek-v4-pro with thinking on was killed at the 4th round 2/2 runs while working normally, and the abort was mislabelled cancelled by user. Unset, blank or unparseable falls back to 4; an explicit stuckNoProgressRounds constructor option beats this var |
CYBERINE_DEEPSEEK_TOOL_THINKING | auto | DeepSeek-direct thinking policy on the tool-calling path. auto leaves thinking at DeepSeek's own default (ENABLED) so loop-deepseek-* workers keep their reasoning while calling tools — correct as of T692 (2026-08-25), which measured that tool_calls and reasoning_content coexist on both v4 models. off (also 0/disabled/false) restores the pre-T692 behaviour of always sending thinking:{type:'disabled'} when tools are present — use it if DeepSeek spend matters more than reasoning quality, or to rule the change out while debugging. Two cases ignore the setting and always disable thinking because the request would otherwise break: a forcing tool_choice (required or a named function — DeepSeek 400s "Thinking mode does not support this tool_choice"), and LOOP_MAX_TOKENS below 8000 (CoT and the answer share that cap, and below ~8K a hard task can spend it all on CoT and return no tool call). Any unrecognized value falls back to auto |
CYBERINE_DIAG_FEEDBACK | 0 | LSP/compiler diagnostic feedback loop for loop adapters (opencode parity). After each file edit the adapter runs a fast in-process syntax check (P1) and optionally a live LSP pull-diagnostic (P2, when typescript-language-server is on PATH or CYBERINE_LSP_CMD is set), then injects any errors as a user turn so the model self-corrects within the same session. Values: 0/off (disabled, default — no behavior change to existing runs), 1/on (per-edit mode, fires after every write round), end (fires once after the last tool round, before the forced final answer). Only applies to LoopAgentAdapter workers (loop-*-build); CLI workers (opencode, claude, codex) manage their own LSP loop internally |
CYBERINE_DIAG_FEEDBACK_INTERVAL | 1 | when CYBERINE_DIAG_FEEDBACK=1, fire diagnostics every N write rounds instead of every one. Set to 3–5 for scaffold-heavy tasks that write many small files in quick succession to reduce noise from partially-written intermediates |
CYBERINE_DIAG_SEVERITY | error | minimum LSP severity to include in the diagnostic feedback turn. error (default) = type errors only; warning = errors + warnings; all = errors, warnings, hints, and information. Keep at error to avoid warning noise that leads the model to over-refactor |
CYBERINE_DIAG_FEEDBACK_MAX_ERRORS | 10 | cap on the number of errors included in a single diagnostic feedback turn. Prevents a pre-broken file from flooding the entire context on first write |
CYBERINE_LSP_CMD | (auto-detect) | override the language server command for LSP pull-diagnostics (CYBERINE_DIAG_FEEDBACK=1, P2). Format: cmd args... (e.g. typescript-language-server --stdio, pyright --stdio, gopls serve). When unset, auto-detects typescript-language-server or deno lsp from PATH. Setting to an empty string or an unavailable binary disables LSP; the syntaxGate (P1) still runs for .ts/.tsx/.js files |
CYBERINE_CLI_TIMEOUT_MS | 1800000 | timeout (ms) for EVERY CLI worker subprocess (claude, codex, muse, gemini, openhands, opencode). Default 30 min so a large multi-file build task is not cut short; lower it to fail fast. Primary name for the knob formerly known as OPENCODE_TIMEOUT_MS (deprecated below) |
CYBERINE_COMMIT_FORMAT | {id}: {title} | kryfv: commit message template for a landed autopilot winner; placeholders {id}, {title}, {area}, {prefix}. Config key commit.format |
CYBERINE_COMMIT_MAX_LENGTH | (empty) | kryfv: cap on the landed commit header; the title is shortened at a word boundary to fit. Config key commit.maxLength |
CYBERINE_KEEP_FAILED_WORKTREES | 3 | kmq00: how many failed beam-candidate worktrees the autopilot fleet loop keeps per loop (with their logs and snapshot under .local/runs/<loopId>/<taskId>/); 0 keeps logs and snapshots only |
CYBERINE_ON_TIMEOUT | retry-once | kyksr: fleet-engine policy for a timed-out code task: retry-once (re-dispatch once with the CLI timeout doubled), skip (board blocker, continue with the rest), stop (pre-kyksr behaviour). --on-timeout overrides it |
CYBERINE_STOP_GRACE_MS | 30000 | k7xrx: after a SIGTERM/SIGINT to cyberine autopilot --engine fleet, how long the loop may take to return (handoff written) before the worker groups are SIGKILLed and the process exits 143 |
CYBERINE_CLI_FIRST_ACTIVITY_MS | 300000 | kem49: a claude worker with no model activity (assistant/tool/thinking/result event) this many ms after spawn is killed with a named stall reason instead of running to CYBERINE_CLI_TIMEOUT_MS. 0 disables |
OPENCODE_TIMEOUT_MS | 1800000 | deprecated — alias for CYBERINE_CLI_TIMEOUT_MS above, still honoured when the new name is unset; kept for existing setups. Set both and the new name wins |
CYBERINE_RUNS_DIR | .local/runs | where the workflow engine writes run state (read by the fleet TUI) |
CYBERINE_HOME | ~/.cyberine | root of the global run registry (<CYBERINE_HOME>/runs/<runId>.json) that cyberine agents reads to list runs across all directories |
CYBERINE_SERVER_URL | (unset) | when set, cyberine run/enqueue/status/agents proxy to this server's HTTP API instead of running in-process. Loopback URLs work without a token; non-loopback requires CYBERINE_API_TOKEN |
CYBERINE_WEB_PORT | 41700 | port for cyberine web; the --port flag overrides it |
CYBERINE_WEB_HOST | 127.0.0.1 | bind host for cyberine web; the --host flag overrides it. Loopback stays open by default; non-loopback mutating routes require an API token; non-loopback reads (GET /api/*) also fail closed with 503 AUTH_SETUP_REQUIRED until an OAuth provider or CYBERINE_WEB_REQUIRE_AUTH=1 is configured (a bearer token still works). The guarantee holds for every spelling of a path (//api/runs, /api/runs/), which is canonicalised before the gate runs. An EMPTY or whitespace-only value means "unset" and resolves to 127.0.0.1 — it used to pass through to listen(), which reads it as the widest possible (wildcard :: dual-stack) bind; use 0.0.0.0 to bind every interface explicitly |
CYBERINE_API_TOKEN | (empty) | bearer token used by CLI remote-client mode when CYBERINE_SERVER_URL points at a non-loopback server |
CYBERINE_WEB_CORS_ORIGINS | (empty) | comma-separated exact origins allowed to make cross-origin requests to a non-loopback web server |
CYBERINE_WEB_RATE_LIMIT_AUTH | 30 | authentication attempts per client per minute on a non-loopback bind; 0 disables this class |
CYBERINE_WEB_RATE_LIMIT_DISPATCH | 20 | dispatch/heavy-write requests per client per minute on a non-loopback bind; 0 disables this class |
CYBERINE_WEB_RATE_LIMIT_READ | 120 | heavy-read requests per client per minute on a non-loopback bind; 0 disables this class |
CYBERINE_WEB_RATE_LIMIT_PROBE | 60 | GET /ready requests per client per minute on a non-loopback bind (its own bucket, separate from read, since it is reachable pre-auth for supervisor/load-balancer probes); 0 disables this class |
CYBERINE_WEB_RATE_LIMIT_BUS | 600 | /api/bus/* requests per client per minute on a non-loopback bind (its own bucket: a hub relays far more bus traffic than dashboard reads, so the read window would throttle legitimate spokes); 0 disables this class |
CYBERINE_WEB_TRUST_PROXY | 0 | when 1, forwarded headers are believed: per-client rate limiting/identity keys read a hop of X-Forwarded-For instead of the raw socket address, and X-Forwarded-Proto: https marks the request as TLS for cookie Secure (both are ignored when the flag is unset — a header any client can set is evidence only behind a proxy you control). The hop read is the RIGHTMOST one — the address your own proxy appended — not the leftmost, which is whatever the CLIENT sent and can be rotated per request for unlimited fresh rate-limit buckets. Opt-in only — enable ONLY behind a reverse proxy that appends/overwrites this header (never passes through a client-supplied one), or every client behind the proxy collapses onto the proxy's own address and shares one rate-limit budget in the other direction |
CYBERINE_WEB_TRUSTED_PROXY_DEPTH | 1 | how many proxies you control sit in front of this server, i.e. how many X-Forwarded-For hops at the RIGHT end were appended by your own infrastructure. 1 (the default, single reverse proxy) keys on the rightmost hop; 2 keys on the second from the right, and so on. Only read when CYBERINE_WEB_TRUST_PROXY=1. Clamped to the number of hops actually present, so a shorter chain than configured degrades to the leftmost hop instead of failing; unparseable or < 1 falls back to 1 |
CYBERINE_OPENAI_API_KEY | (empty) | bearer token required by POST /v1/chat/completions; when empty, that endpoint is disabled |
CYBERINE_WEB_ALLOW_FILE_TOOLS | 0 | when the web server is bound to a non-loopback host, the chat planner's read-only filesystem tools (read_file/grep_files/list_dir) are disabled (they expose project-root files over an unauthenticated endpoint). Set to 1 to re-enable them on a network bind. No effect on a loopback bind, where they are always available |
CYBERINE_OAUTH_GITHUB_CLIENT_ID / _CLIENT_SECRET | (empty) | GitHub OAuth app credentials for the web UI login gate; the GitHub provider is enabled only when BOTH are set |
CYBERINE_OAUTH_GOOGLE_CLIENT_ID / _CLIENT_SECRET | (empty) | Google OAuth app credentials (OIDC, PKCE S256) for the web UI login gate; the Google provider is enabled only when BOTH are set |
CYBERINE_OAUTH_ALLOWED | (empty) | comma-separated allowlist of logins/emails permitted to log in via OAuth, each optionally scoped to one provider (github:octocat, google:jane@example.com), matched case-insensitively. UNSET or empty denies every login (safe-by-default) — an operator must explicitly allowlist at least one account |
CYBERINE_WEB_REQUIRE_AUTH | 0 | force the session-or-bearer login gate on every route (including on a loopback bind); 1 to enable. Otherwise the gate auto-activates on a non-loopback bind once at least one OAuth provider is configured |
CYBERINE_WEB_SESSION_TTL_HOURS | 168 | how long a browser login session stays valid before validateWebSession treats it as expired and prunes it |
CYBERINE_WEB_SESSION_IDLE_MINUTES | 480 | idle window checked independent of the absolute TTL above — a session unused for longer than this is revoked outright by validateWebSession even though it hasn't hit its expiry yet. Bumped on every successful validation |
CYBERINE_WEB_SSE_MAX_PER_CLIENT | 8 | max concurrently-open SSE connections (GET /api/events, GET /api/runs/:id/events) per client (same identity as the rate limiter's clientKey); the next one gets 429 TOO_MANY_SSE_CONNECTIONS |
CYBERINE_WEB_SSE_MAX_GLOBAL | 200 | max concurrently-open SSE connections across all clients; the next one gets 503 SSE_CAPACITY_EXCEEDED |
CYBERINE_WEB_PUBLIC_URL | (unset) | externally-visible base URL used to build the OAuth redirect_uri (<url>/auth/callback/<provider>); required behind a reverse proxy or when the public host/port differs from the server's own bind. Falls back to http://<bound host>:<bound port> when unset |
CYBERINE_MCP_AUTH_TOKEN | (unset) | shared secret gating ALL ELEVEN dispatch/mutating/read npm run mcp tool calls (orchestrate, send_message, poll_inbox, query_runs, list_team, send_to_team, send_to_role, inspect_run, approve_run, reject_run) plus the cyberine://runs/{runId} resource read (T612, extending T602's original five). Unset (default) = fail-open, matching stdio MCP's local-child trust model; set it to require every one of those calls to pass a matching authToken argument (a ?authToken= query param for the resource read) |
CYBERINE_WEB_COOKIE_SECURE | 0 | force the Secure flag on session/CSRF cookies even when the request doesn't look like TLS (the server also auto-detects TLS via a TLSSocket or a X-Forwarded-Proto: https header) |
CYBERINE_MEMORY | 1 | long-term memory master switch; 0 disables episodic record writes AND the MEMORY preamble injection |
CYBERINE_MEMORY_DIR | <CYBERINE_HOME>/memory | root of the episodic memory store (<slug>/records/<runId>.json, issues.jsonl, index.json, embeddings.jsonl) |
CYBERINE_MEMORY_TOPK | 3 | prior-run records injected into the MEMORY preamble at dispatch / chat start |
CYBERINE_MEMORY_MAX_TOKENS | 1500 | MEMORY preamble budget (chars = 4x this value); lowest-scored records drop first |
CYBERINE_MEMORY_MODEL | (empty) | opt-in LLM distillation model for record outcomes (e.g. llama3.1:8b); empty keeps the zero-cost extractive path |
CYBERINE_MEMORY_BASE_URL | http://localhost:11434/v1 | OpenAI-compatible endpoint for the distillation call |
CYBERINE_MEMORY_API_KEY | ollama | API key for the distillation / embeddings endpoint |
CYBERINE_MEMORY_EMBEDDINGS | (empty) | opt-in embeddings: ollama (local default endpoint) or an explicit http(s):// base URL; adds a cosine axis to preamble ranking |
CYBERINE_MEMORY_EMBEDDINGS_MODEL | nomic-embed-text | embeddings model id (ollama pull nomic-embed-text first) |
CYBERINE_CARRY_MODEL | deepseek/deepseek-v4-flash | flash-tier model for the CARRY act background summarizer (T450). OpenRouter id when OPENROUTER_API_KEY is set; a bare DeepSeek id (e.g. deepseek-v4-flash) when only DEEPSEEK_API_KEY is set. Falls back to a heuristic-only capsule when no key is available |
CYBERINE_USER_MEMORY | 1 | honcho-style per-user/per-project memory master switch. 0 disables USER.md reads, writes, and the user-memory header injection in cyberine chat |
CYBERINE_USER_MEMORY_DIR | <CYBERINE_HOME>/user-memory | root of the user memory store (<project-slug>/USER.md) |
CYBERINE_NEW_SESSION_CMD | claude | command the fleet TUI opens for a "new session" (n). Space-separated cmd + leading args; the typed task is appended as the final arg. E.g. code --new-window |
CYBERINE_DEV | (empty) | 1 makes the global shim run this checkout's live src/ instead of the built dist/artifact/ snapshot — the documented opt-in for developing THIS repo (kka26). Any other value, including 0, is not an opt-in |
CYBERINE_SKIP_ARTIFACT_BUILD | (empty) | 1 skips the .githooks/post-commit and .githooks/post-merge artifact refresh. The hook never fails a commit either way; skipping just leaves the global CLI on the previous snapshot until the next cyberine build |
CYBERINE_WAIT_TIMEOUT_MS | (unset, no ceiling) | opt-in wall-clock ceiling for cyberine wait and cyberine land's wait loop. Unset or non-positive = wait tracks the run to a terminal state with no ceiling (kf11q). On expiry it exits 124 (the run is still going), distinct from 1 (the run failed) and 125 (the watcher died) |
CYBERINE_BUILD_FLEET | (empty) | comma list of WRITING workers for implement-task runs. CLI workers (need their CLI): claude, codex, muse, gemini (RETIRED), opencode-deepseek / opencode-kimi / opencode2-deepseek (all RETIRED 2026-09-07 -- opencode is being dropped; the adapter code stays as the CLI-worker reference implementation), mmx-text-build (MiniMax mmx CLI text chat; needs mmx installed + logged in, or MMX_TOKEN_KEY). Key-only loop-implementers (need only a key, sandbox-pinned, zero install): loop-deepseek-build (DEEPSEEK_API_KEY), loop-openrouter-build (OPENROUTER_API_KEY), loop-kimi-build (MOONSHOT_API_KEY), loop-mimo-build (XIAOMI_API_KEY), loop-minimax-build (MINIMAX_API_KEY), loop-openai-build (OPENAI_API_KEY), loop-gemini-build (GEMINI_API_KEY), loop-xai-build (XAI_API_KEY), loop-groq-build (GROQ_API_KEY), loop-mistral-build (MISTRAL_API_KEY), loop-muse-build (MODEL_API_KEY; RETIRED -- see its recipe), loop-together-build (TOGETHER_API_KEY), loop-fireworks-build (FIREWORKS_API_KEY), loop-azure-build (AZURE_OPENAI_API_KEY+AZURE_OPENAI_ENDPOINT), loop-copilot-build (OAuth via cyberine auth login copilot). Gateway-backed loop-implementers (need the LiteLLM gateway up): loop-claude-build (LOOP_MODEL_A), loop-gpt-build (LOOP_MODEL_B). Native Anthropic loop-implementer (key-only, no gateway/CLI): loop-claude-native-build (ANTHROPIC_API_KEY). Local Ollama loop-implementer (keyless, env opt-in): loop-ollama-build (OLLAMA_MODEL/OLLAMA_BASE_URL). Empty = ordinary runs never spawn writing agents |
CYBERINE_BUILD_FLEET_SOURCE | (unset) | set by Cyberine itself, not by you: config.json when CYBERINE_BUILD_FLEET came from a .cyberine/config.json layer, which makes the build fleet a preference resolved against fleet.json (kvr1t); cleared by --fleet, --cheap, a shell CYBERINE_BUILD_FLEET, or the router's pick |
HOST_SANDBOX_MODE | auto | host sandbox confining the CLI-worker subprocess to its worktree. auto detects best available (macOS: seatbelt; Linux: gvisor > bubblewrap > docker/podman; Windows: windows). Force with seatbelt / bubblewrap / docker / gvisor / podman / windows, or none to disable (trusted-only). Loop workers are unaffected (already sandbox-pinned) |
HOST_SANDBOX_NETWORK | allow | network policy inside the CLI-worker host sandbox. deny blocks all network egress, including the CLI worker's own model API, so it defaults to allow (most workers need their provider); read-scoping (deny-list ~/.ssh/~/.aws/.env*) is the primary exfil control. Set deny for strict isolation on network-free tasks; buildDefaultAdapters() surfaces a note when a sandbox is active and you have opted into deny |
CYBERINE_DOCKER_IMAGE | ubuntu:24.04 | image used when HOST_SANDBOX_MODE=docker, gvisor, or podman wraps the CLI worker in a container |
CYBERINE_GVISOR_AVAILABLE | (unset) | set to 1 when runsc is registered as a Docker runtime but not separately on PATH (skips the runsc-in-PATH check for gVisor availability detection) |
CYBERINE_TASK_TRUSTED | true | whether tasks are trusted. false makes a CLI worker REFUSE (HostSandboxError) when no host sandbox is available, instead of running with full host access (loop workers unaffected). false also forces the post-selection TrustGate to high risk regardless of tier/strategy AND makes the L3 adversarial gate MANDATORY (T641/T658): an untrusted winner is REJECTED when no adversarial judge is available (no LLM creds), never auto-merged on L1/L2 alone. Regression smoke: npm run selftest:trust-untrusted |
CYBERINE_TRUST_GATE_TYPECHECK | auto | TrustGate L1 typecheck mode. auto runs the typecheck the target repo actually declares and records L1 as NOT-APPLICABLE, with the reason, when it declares none -- a repo with no package.json, no tsconfig.json and no configured command used to fail L1 with typecheck failed after applying the winner diff (npm run typecheck exits 254 there), so a clean markdown-only winner reported as error. always forces npm run typecheck and treats a missing command as a genuine failure (the pre-kxp7a behaviour). off always records L1 not-applicable. Not-applicable is a third outcome: it is neither a pass nor a failure, and it never counts toward gatesPassed. |
CYBERINE_TRUST_GATE_TYPECHECK_CMD | unset | Overrides the exact command TrustGate L1 runs (for example a monorepo workspace script). Read ahead of detection under both auto and always. |
CYBERINE_EXEC_BACKEND | local | execution backend for worktree-isolated (isolate: true) workers — WHERE the worker command runs (distinct from HOST_SANDBOX_MODE which controls process confinement). local = default, no change. docker = worker runs inside a Docker container with the worktree bind-mounted; requires docker in PATH and CYBERINE_EXEC_DOCKER_IMAGE set to an image with the CLI pre-installed. ssh = worker runs on a remote host; requires ssh + rsync in PATH and CYBERINE_SSH_HOST set. Falls back to local with a stderr warning when the requested backend is unavailable |
CYBERINE_EXEC_DOCKER_IMAGE | (empty) | Docker image for the docker execution backend. Falls back to CYBERINE_DOCKER_IMAGE, then ubuntu:24.04. The image must have the worker CLI (opencode, claude, codex, etc.) pre-installed for CLI workers |
CYBERINE_SSH_HOST | (empty) | [user@]hostname of the remote machine for the ssh execution backend. Required when CYBERINE_EXEC_BACKEND=ssh; leaving it empty makes the ssh backend unavailable and triggers fallback to local |
CYBERINE_SSH_KEY | (empty) | path to an SSH identity file for the ssh execution backend (passed as ssh -i <key>). Optional — when empty the SSH client uses its default key chain |
CYBERINE_SSH_REMOTE_DIR | ~/.cyberine-exec | base directory on the remote host where per-worker worktrees are rsynced for the ssh execution backend. Each worker gets its own subdirectory; the subdirectory is removed by cleanupRemoteWorkspace after the worker finishes |
CYBERINE_EXEC_FORWARD_ENV | (empty) | comma-separated env var names to forward into the docker/ssh execution context. Useful when the worker CLI needs API keys that exist only in the current shell (e.g. OPENAI_API_KEY,DEEPSEEK_API_KEY,ANTHROPIC_API_KEY) |
CYBERINE_CLAUDE_MODEL | claude-sonnet-4-6 | model for the claude build worker (Claude Code headless) |
CYBERINE_CLAUDE_EFFORT | (empty) | one of low/medium/high/xhigh/max, passed through to the claude build worker's own --effort flag. Validated against this set in core/config.ts; an unrecognized value falls back to unset (flag omitted). Empty (default) = CC picks its own default for the model |
CYBERINE_CLAUDE_BASH_OUTPUT_MAX_CHARS | (empty) | positive integer cap on the bash-tool output the claude build worker feeds back into its own context, forwarded as inline --settings {"bashOutputMaxChars":N} (kqq2g). Live-probed on v2.1.263 in -p mode: unset, a 60,000-char command output reached the model whole (59,979 chars seen); 2000, the model saw 2,048 chars plus a truncation notice. Empty (default, incl. non-integer input) = flag omitted, CC's own cap applies. npm run selftest:claude-bash-output-cap asserts the argv |
CYBERINE_CLAUDE_MAX_WEB_SEARCHES_PER_SESSION | (empty) | positive integer override for the claude build worker's per-session WebSearch cap, injected as the CLI's own CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION env var (v2.1.212+; verified via strings on the installed binary). A non-integer/non-positive value is treated as unset. Empty (default) = CC's own 200-per-session default applies unchanged |
CYBERINE_CLAUDE_MAX_SUBAGENTS_PER_SESSION | (empty) | positive integer override for the claude build worker's per-session Task-tool subagent cap, injected as CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION (v2.1.212+). Same validation/default contract as the web-searches cap above |
CYBERINE_CLAUDE_CAPTURE_SUBAGENT_TEXT | (unset) | 1/true passes the claude build worker's own --forward-subagent-text flag and extracts the tagged messages into Result.raw.subagentText (T626, wired T656). Off by default — extra stdout volume only worth it when subagent visibility is wanted |
CYBERINE_CLAUDE_OUTPUT_SCHEMA | (empty) | JSON Schema for the claude build worker's structured output — inline JSON (starts with {) or a path to a schema file (read and inlined at config load). Forwarded to the CLI's own --json-schema flag; the validated object lands in Result.raw.structuredOutput (T628, wired T656). Unparseable value/file = treated as unset |
CYBERINE_CODEX_MODEL | (CLI default) | model for the codex build worker (omits -m when unset). Deliberately unpinned (kd7ax, 2026-09-09): unset, the worker rides Codex's own configured default (~/.codex/config.toml model, else the bundled default upstream may change -- 0.153.4 made GPT-6-Astra that default), so the operator's Codex config stays the single source of truth; the model that actually answered is read from codex exec's model: header and recorded per run as workerRuns[].model and in the provenance bundle, so run.json never says default for the answer |
CYBERINE_CODEX_OUTPUT_SCHEMA | (empty) | path to a JSON Schema FILE for the codex build worker, forwarded to codex exec's own --output-schema <FILE> flag (a file path, unlike claude's --json-schema which takes schema text). Constrains the final message to schema-conformant JSON text (T631, wired T656). Missing/unparseable file = treated as unset |
CYBERINE_GEMINI_MODEL | gemini-2.5-flash | model for the gemini build worker |
CYBERINE_OPENCODE_KIMI_MODEL | moonshotai/kimi-k2.7-code | model for the opencode-kimi build worker. Default provider is dead as of 2026-08-25 — see the "OpenCode billing surfaces" recipe |
CYBERINE_OPENHANDS_MODEL | (operator's ~/.openhands/agent_settings.json) | model for the openhands build worker (injected as LLM_MODEL into the child env). The persisted LLM at first-run setup is the default — this is a per-run override |
CYBERINE_TASK | (none) | the task text the implement-task workflow implements |
CYBERINE_IMAGES | (unset) | comma-separated image paths passed to npm run cli for vision tasks (e.g. CYBERINE_IMAGES=./screenshot.png npm run cli "describe this") |
CYBERINE_DEPTH | 2 | research workflow (src/engine/researchWorkflow.ts) sweep depth: 1 (3 angles, shallow), 2 (5 angles, default), 3 (7 angles, thorough). depth=N requires at least N loop adapters in the fleet — smaller fleets must lower it (the engine throws a clear count-mismatch error). The cyberine research --depth quick|deep|max flag sets this env before importing the workflow (quick=1, deep=2, max=3) |
CYBERINE_SKEPTICS | 3 | research workflow's verify step: per-claim independent skeptics that adversarially try to refute every Finding before it reaches the synthesizer. Strict-majority refute (default-refuted-if-unsupported). cyberine research --depth sets quick=2, deep=3, max=5; export this env to override the preset |
CYBERINE_THEME | dark | TUI palette for cyberine agents / cyberine chat: dark, light, or ansi (8/16-color terminals, no truecolor); unknown values fall back to dark |
CYBERINE_KEYBINDINGS | $CYBERINE_HOME/keybindings.json | path to a JSON file overriding BOTH fleet-TUI (fleet.*) and chat-REPL (chat.*) keybindings — one file, namespaced per app; bare keys (no dot) are back-compat shorthand for fleet.*. See "Keybindings — remap fleet + chat actions" for the full action table. Unknown actions/namespaces, malformed entries, and same-key collisions warn instead of crashing; cyberine doctor and the fleet ? help overlay reflect whatever is actually bound |
CYBERINE_CHAT_PROVIDER | (unset) | pinned chat planner provider id (deepseek/moonshot/xiaomi/openrouter). Set by cyberine setup / the chat picker, not hand-edited. Unset = pick interactively / by priority |
CYBERINE_CHAT_MODEL | (unset) | pinned chat planner model id (paired with CYBERINE_CHAT_PROVIDER; independent of that provider's worker *_MODEL). Set by cyberine setup / the chat picker |
CYBERINE_CHAT_MODELS | (unset) | comma-separated planner model ids for the chat's Ctrl+T model cycle (the mount model is always first). Unset = toggle disabled |
CYBERINE_CHAT_CONTEXT_WINDOW | 65536 | approx context window (tokens) of the chat planner model; feeds the chat status line's context bar (████░░░░ N%). Set it when the planner model has a different window |
CYBERINE_AUTOPILOT_WINDOW_TOKENS | 1000000 | context-token window cyberine tasks calibrate uses when bucketing measured autopilot actuals into the S/M/L calibration report (.local/autopilot/calibration.json). Falls back to 1000000 on an unset, zero, negative or non-integer value |
CYBERINE_AUTOPILOT_SOFT | 0.35 | task-boundary policy soft tier, as a fraction of the context window: do not START a task that will not fit, though a smaller task that fits may still be taken. Must be a fraction strictly inside (0,1), and soft < hard < emergency is validated at config load — a violation throws with the offending variable named. See "Task-boundary policy" |
CYBERINE_AUTOPILOT_HARD | 0.65 | task-boundary policy hard tier: finish the task in hand, then hand off, taking nothing new. Same (0,1) fraction and soft < hard < emergency validation |
CYBERINE_AUTOPILOT_EMERGENCY | 0.85 | task-boundary policy emergency tier: hand off NOW, even mid-task. A safety net, not an operating mode — it is only acceptable because a .local/vibe/<task>.md goal file with milestone checkboxes lets a mid-task cut resume from the last milestone. Same (0,1) fraction and soft < hard < emergency validation |
CYBERINE_AUTOPILOT_HANDOFF_RESERVE | 30000 | tokens held back from the task-boundary policy's budget so a session can always still write its handoff (budget = window - context - reserve). Integer >= 0 |
CYBERINE_AUTOPILOT_REPEAT_FAIL | 3 | sessions a task may be STARTED in before the task-boundary policy stops offering it (excluded as repeat-fail, with a repeat-fail:<id> lint) — a task that keeps eating fresh sessions is a brief defect, not a scheduling problem. Integer >= 1 |
CYBERINE_HANDOFF_WRITER_BIN | the builtin bin/cyberine-handoff.mjs | path to the handoff writer binary the handoff bridge (src/autopilot/handoffBridge.ts) shells out to for resolve and offload, and the one cyberine autopilot checks before it starts. Override for a test double or a different writer; the writerBin option on handoff() wins over this when both are set. Replaces CYBERINE_AMEMORIA_BIN, which was removed 2026-09-30. See "Handoff bridge" |
CYBERINE_AUTOPILOT_RUN_ID | (unset) | run id cyberine autopilot records its decisions, sessions and per-turn records under. Set automatically by cyberine autopilot --bg so the pid/log line the parent prints names the SAME run the detached child creates; unset means a fresh UUID per run. See "Autopilot command" |
CYBERINE_CONTEXT_BAR_SHOW_PCT | 60 | used% (0-100) of the context window at which the status line's context bar first appears (default: hidden below 60% used, i.e. ~40% remaining, matching Claude Code). Single knob: CONTEXT_BAR.showAtUsedPercent in src/tui/theme.ts |
CYBERINE_CONTEXT_BAR_WARN_PCT | 85 | used% (0-100) at which the context bar flips from the accent color to the warn (amber) tone (default: ~15% remaining). Single knob: CONTEXT_BAR.warnAtUsedPercent in src/tui/theme.ts |
CYBERINE_CHAT_MAX_TOKENS | 8192 | cap on completion tokens the chat planner requests per turn. Critical on OpenRouter: with no cap the provider reserves the model's full output budget up front and returns HTTP 402 ("requires more credits") on a credit-limited key even when the reply is tiny. Raise for long planner write-ups; lower to stretch a nearly-empty key |
CYBERINE_CHAT_MULTIMODAL | (unset = model-id heuristic) | override multimodal/vision support detection for the chat planner. Set to 1 to force-enable (e.g. when using an unlisted vision model). Set to 0 to force-disable (text-only path). Unset = auto-detect by model id (gpt-4o, claude-3/sonnet/opus, gemini, etc.). Affects how Ctrl+V-pasted images are attached to the user message on submit |
CYBERINE_CHAT_THINKING | (unset = on) | show the planner's reasoning/thinking block in the chat REPL. Set to 0 to hide it by default. The toggle can also be flipped at runtime via the exported setShowThinking(bool) function (wirable to a future /config thinking command). Only reasoning models emit a thinking block; non-reasoning models produce no thinking bubble regardless of this setting |
CYBERINE_CHAT_PERMISSION_MODE | (empty = default) | default permission mode for cyberine chat sessions. One of: default acceptEdits plan auto bypassPermissions dontAsk. Overridden per-session via --permission-mode flag; active mode persists on the session record |
CYBERINE_CHAT_VIM_MODE | false | default state of the chat InputBox's /vim modal-editing toggle (T525). Set to true to start every cyberine chat session in vim NORMAL mode. Normally not hand-edited — the in-chat /vim command flips this and writes it to .cyberine/config.json (chat.vimMode) for you |
CYBERINE_PLANS_DIR | (empty = global) | when set (any non-empty value), plan files written by plan mode go to <cwd>/.cyberine/plans/ instead of ~/.cyberine/plans/<project-slug>/ |
CYBERINE_ROUTE | auto | capability-aware routing for background AND foreground dispatches: auto picks the fleet via src/core/router.ts when CYBERINE_BUILD_FLEET is unset (a fleet.json routing map wins, minus any worker that is retired / cooling down / missing its credential); off disables. See "Capability-aware routing" and "Auto-routed implementer fleet on the foreground run" |
CYBERINE_DEBUG_HANDLES | (unset) | 1 makes cyberine run dump the process's active handles (sockets, timers, child processes) to stderr ~1.5 s after the run returns -- the diagnostic that found the LSP child keeping a foreground run alive after state: done |
CYBERINE_SMART_ROUTER | false | opt-in LLM-as-router: when true AND the deterministic router confidence is below 0.7, a cheap LLM call overrides the worker ordering and per-worker model variant. Falls back silently to the deterministic pick on any error, timeout, or hallucinated id. Default off — the zero-cost deterministic path is always the default |
CYBERINE_ROUTER_MODEL | deepseek/deepseek-v4-flash | model id for the LLM router call (used when CYBERINE_SMART_ROUTER=true). Resolved via CYBERINE_ROUTER_BASE_URL / CYBERINE_ROUTER_API_KEY; defaults to the OpenRouter endpoint when those are unset and OPENROUTER_API_KEY is set, or DeepSeek-direct when DEEPSEEK_API_KEY is set |
CYBERINE_ROUTER_BASE_URL | (empty = auto) | explicit base URL for the LLM router model call; auto-falls back to OPENROUTER_BASE_URL or DEEPSEEK_BASE_URL when unset |
CYBERINE_ROUTER_API_KEY | (empty = auto) | explicit API key for the LLM router model call; auto-falls back to OPENROUTER_API_KEY or DEEPSEEK_API_KEY when unset |
CYBERINE_CANDIDATE_RERANK | false | opt-in LLM candidate re-ranker for Act 1 SCOPE (T446): when true AND a provider key is available (OPENROUTER_API_KEY or DEEPSEEK_API_KEY) AND the combined candidate list exceeds 3 entries, one sonnet-tier LLM call filters the ~15 combined candidates (task-text extractor + git co-change ranker) down to the top-N most relevant files, removing false positives before the worker reads anything. Degrades silently to the un-reranked list on any LLM error, timeout, or missing key. Default off — never incurs provider spend without explicit opt-in |
CYBERINE_CANDIDATE_RERANK_TOP_N | 5 | how many top candidates to return after re-ranking. Only consulted when CYBERINE_CANDIDATE_RERANK=true. Default 5 |
CYBERINE_RERANK_MODEL | (auto) | model id for the candidate re-ranker call. When unset: anthropic/claude-sonnet-5 via OpenRouter, or deepseek-v4-flash via DeepSeek-direct. Use this to override with a different model on your configured provider |
CYBERINE_MAX_CONCURRENT | 6 | global cap on simultaneously-running workers (M2 concurrency governor). Workers that exceed the cap are queued with backpressure and emit a worker:queued event in events.jsonl; they resume as earlier workers finish. Set lower (e.g. 3) to cap worktree disk/CPU on large swarms, or higher to trade rate-limit risk for speed |
CYBERINE_PROVIDER_BUDGETS | (unset) | per-provider token-rate budgets for the concurrency governor. Comma-separated prefix:tokens_per_minute pairs, e.g. deepseek:150000,openrouter:60000. Workers for an over-budget provider are queued until the 60s rolling window resets. prefix is matched against the part of AgentInfo.provider before the first : (e.g. deepseek matches deepseek:deepseek-v4-pro). Unset = no rate limiting, only the CYBERINE_MAX_CONCURRENT slot cap applies |
CYBERINE_MODE | (unset) | operating mode preset: compete (full fleet race + BehaviorJudge gate) or swarm (single cheap worker + DiffJudge gate). Unset = no preset (current default behaviour). The --mode flag on cyberine run overrides. Threaded into background runs via launchBackgroundRun so workflows read it |
CYBERINE_SWARM_FLEET | (empty = default swarm worker list) | comma list of writing workers for --mode swarm runs (read by src/engine/swarmTaskWorkflow.ts). Falls back to CYBERINE_BUILD_FLEET when unset, then to the built-in swarm worker list (opencode-deepseek, opencode-kimi, claude, codex, gemini, loop-deepseek-build, loop-openrouter-build). Workers whose credentials / CLI binaries are missing are silently filtered out by buildAdapters; only survivors actually receive a chunk |
CYBERINE_SWARM_MAX_CHUNKS | `min(8, max(2, swarm fleet length | |
CYBERINE_SWARM_GROUP_BY | both | which edge sets clusterChunks uses to build the lane graph for --mode swarm (T268). files = file-overlap edges only; deps = dependsOn edges only; both = union of both (default — preserves the T263 lane invariant). Pick files when chunk deps are usually an implementation detail of one cluster; pick deps when chunk scopes are disjoint but they must run sequentially; leave both when in doubt. Unknown values fall back to both. See "Lane grouping" for the invariant and the trade-off |
CYBERINE_SWARM_LANES | 0 (auto = fleet size) | override the lane-packing cap target in packLanes (T264 / T268). When > 0, replaces the auto cap (which defaults to the swarm fleet size) with the explicit value — so the clusterer can pack more lanes than the fleet can serve if the user wants to squeeze parallelism, or fewer if worktree / disk budget is tight. 0 keeps the auto cap. Non-integer or < 1 falls back to 0 (auto). See "Lane grouping" for the packing algorithm |
CYBERINE_SWARM_MAX_LANE_SIZE | 0 (no warning) | split-warning threshold (T268). When any packed lane carries more than this many chunks, a stderr warning is emitted ([swarmTaskWorkflow] WARNING: lane <id> has N chunks (maxLaneSize=K) — consider splitting or increasing CYBERINE_SWARM_MAX_LANE_SIZE). 0 disables the warning. Use as an audit knob: set K=4 to surface lanes that may be serialising too much per worktree |
CYBERINE_SWARM_MERGE_RETRIES | 1 | per-stage integration-fix retry budget for SwarmMergeJudge when applying chunk diffs fails the merge gate (npm run typecheck by default, or CYBERINE_VERIFY_CMD if set). Set 0 to disable retries entirely — failures surface immediately, abort-the-whole-run on exhaustion. Honoured in both WorkflowEngine and orchestrator/buildJudges.ts so the env value wins wherever a SwarmMergeJudge is constructed |
CYBERINE_VERIFY_CMD | (unset) | shell command override for the merge gate in --mode compete and --mode swarm (default gate: npm run typecheck). When set, this command is run instead to decide if a worker's diff passes. Honoured in both implementTaskWorkflow.ts and swarmTaskWorkflow.ts, and as DiffJudge's gate 2 on the autonomy loop's sync-verify path (cyberine autopilot --engine fleet, cyberine loop --verify), where it replaces npm run typecheck and gives a non-JS repo an oracle (keeb9). Also settable via config.json's verify.command key (env wins). See "Apply-only verification is never done" |
CYBERINE_SWARM_LANE_RUNNER | (unset) | set to 1 to force the lane-runner path for --mode swarm. The lane runner commits each chunk's work in-tree before its dependents start (enables cross-chunk dependsOn chains). Only needed to force the path for a plan with NO dependsOn edges: a plan that declares edges is auto-routed there, and step.swarmUseLaneRunner: true in the workflow def also forces it. Value 0 forces nothing — the A/B opt-out is swarmUseLaneRunner: false on the step. See "Chunk dependsOn — auto-routing and the plan-time DAG gate" |
CYBERINE_TRUST_GATE | on | post-selection TrustGate in WorkflowEngine (T274/T275). When on (default — ON by parity with the self-evolve loop, which already requires trust-gate verification before a cycle advances), every isolate step that produces a winner diff is gated through runTrustGate AFTER the judge picks the winner: L1 (npm run typecheck) is always run, L2 (the step's verifyCmd if set) runs when distinct, L3 (adversarial skeptics) runs only on high-risk. The gate never changes which candidate the judge selects; it only catches the rare case where a judge-chosen winner fails the build/lint gate. Set off / 0 / false / no to skip — the existing DiffJudge / BehaviorJudge / SwarmMergeJudge verify step still gates the winner. The verdict is persisted on each step in run.json (steps[].trustGateVerdict) and surfaced in the cyberine wait / cyberine digest summary and the chat's run:completed envelope. See src/engine/trustGate.ts for the kernel API and src/engine/WorkflowEngine.ts:2090 for the wiring. |
CYBERINE_HIGH_RISK | false | force the L3 adversarial gate on the post-selection TrustGate, even when the route is not complex-tier (T274). Set 1 to opt in per-run; equivalent to the cyberine run --high-risk flag. Independent of CYBERINE_TRUST_GATE — you can have L1+L2 by default and opt in to L3 with this var. When unset, L3 also auto-fires on any complex-tier task (computed from the workflow's first prompt). With no LLM creds, the kernel logs the standing "no LLM creds for L3" note and advances on L1+L2 — EXCEPT for an untrusted task (CYBERINE_TASK_TRUSTED=false), where the missing judge REJECTS the winner instead (T658). |
CYBERINE_REVIEW_FIX | on | the one bounded review-fix pass of implement-task (kd8dj). When the review returns a non-approve verdict with concerns, the implement winner fixes its own diff once and the review runs once more; see "Review findings get one fix pass (kd8dj)". Set off / 0 / false to keep the review advisory only; a review that would have triggered is then recorded on steps[review].reviewFix as skipped |
CYBERINE_PREFER_CHEAP | (unset) | set to 1 to make every cyberine run behave as if --cheap was passed: pins CYBERINE_BUILD_FLEET to the curated non-premium loop fleet (CHEAP_BUILD_FLEET in src/core/workerProfiles.ts) and refuses any fleet containing claude or codex. Equivalent to the cyberine run --cheap flag; useful when you want the guard on every invocation (e.g. in ~/.cyberine/.env). |
CYBERINE_TASK_COST_CLASS | (unset) | the cost class this dispatch runs under: cheap or expensive. Normally set for you by src/launchBg.ts from the board row's model: tier and effort: (kjmft); set it yourself to pin the class for one dispatch, including a npm run wf run that carries no board task. An already-set value is never overwritten by the board lookup. Anything unrecognised is ignored and the expensive default stands. See "A task's cost class picks its step profile" |
CYBERINE_TASK_COST_CLASS_REASON | (unset) | one clause naming what decided the class above (e.g. board task k1abc: model tier sonnet + effort M). Set alongside it by the launcher; informational only -- it is recorded in the run note and run.json taskProfile.reason and changes no dispatch |
CYBERINE_SUBAGENT_NESTING_CAP | 2 | maximum nesting depth for worker-internal subagents (T313). A top-level worker is depth 0; each delegate_subtask call increments by 1. Calls that would exceed the cap are refused with an error string returned to the parent (never silently run). Default 2 allows a two-hop chain (parent -> investigator -> helper). Set to 0 to disable delegate_subtask entirely. Only applies to LoopAgentAdapter workers with enableSubagents: true (all loop-*-build workers, auto-enabled by makeLoopImplementer) |
CYBERINE_SECURITY_JUDGE | false | enable the SecurityJudge in the verdict panel (T327). Set 1 / true / yes to add a pure-heuristic security screen that runs alongside ConsensusJudge / LlmJudge / AdversarialJudge. The judge scans each candidate's diff additions (or output text when no diff is present) for: destructive file-system and git operations (rm -rf, git reset --hard on protected branches, force-push to main), cloud/database DDL (aws s3 rm, DROP TABLE), remote-code-execution pipe patterns (curl ... | sh), credential/secret exfiltration (env file reads, network POST of API keys), prompt-injection override markers, privilege escalation (chmod 777, /etc writes), data sent to known exfiltration hosts, and (kbt76) URL-packed exfiltration -- an outbound curl/wget/fetch( whose URL carries a shell expansion or a >=32-char base64/hex segment, with package-registry hosts skipped BY HOST so a tarball hash is not flagged. npm run selftest:security-judge-patterns (in the security set) holds one hostile and one benign fixture per pattern and proves each fixture depends on its own pattern. Clean candidates pass through unaffected. Flagged candidates are demoted to the tail of the ranking; when all candidates are flagged, winner is null and the rationale lists every finding. No LLM is required — always available regardless of API key configuration. |
CYBERINE_HOOKS_DISABLE | (unset) | 1 disables the lifecycle hook system entirely (no config read, no spawns). See "Lifecycle hooks" |
CYBERINE_KITTY_KEYBOARD | (off) | set to 1 to opt in to the Kitty keyboard protocol (\x1b[>1u). OFF by default: terminals that do not decode CSI-u sequences (e.g. iTerm2 + Ink 5) break Ctrl+C when the protocol is active. Shift+Enter works without this via the bare line-feed path on iTerm2; Ctrl+J is the universal fallback |
CYBERINE_ALTSCREEN | (unset) | alternate-screen buffer for the TUIs. Fleet (cyberine agents): ON by default, 0 disables. Chat (cyberine chat): OFF by default so the conversation stays in scrollback, 1 enables |
CYBERINE_AUTOCOMPACT | 1 (enabled) | chat planner auto-compaction: when the context window reaches CYBERINE_AUTOCOMPACT_THRESHOLD fill, the chat summarises and truncates the history to free space. Set to 0 to disable |
CYBERINE_AUTOCOMPACT_THRESHOLD | 0.85 | fraction of the context window (0–1) that triggers auto-compaction in the chat planner. Default 0.85 (85% fill). Requires CYBERINE_AUTOCOMPACT to be enabled |
CYBERINE_CHAT_AUTOTITLE | 1 (enabled) | background LLM-generated session titles (T526): after the first user+assistant exchange, a <=6-word title is generated via the cheapest available configured (non-premium) chat-eligible provider and replaces the immediate first-line-truncation placeholder. Set to 0 to disable — sessions keep the first-line-truncation title only. A /rename always wins regardless of this setting |
CYBERINE_MOUSE | (unset) | set to 1 to enable SGR mouse mode in the chat TUI (cyberine chat). Translates trackpad/mouse wheel events into smooth transcript scroll (a few lines per notch — see CYBERINE_WHEEL_LINES) plus drag-to-copy. Terminal state is restored on clean exit and crash. No effect on the fleet TUI |
CYBERINE_WHEEL_LINES | 3 | lines the chat transcript scrolls per mouse-wheel notch. Smaller = finer/smoother, larger = faster. Clamped to 1–10. Keyboard PageUp/PageDown still jump a quarter-page regardless |
CYBERINE_SYNTAX_HIGHLIGHT | 1 (enabled) | per-language syntax highlighting for fenced code blocks in Markdown.tsx (ts/js/tsx/jsx/json/bash/python/go/rust/sql/yaml, via lowlight). Set 0 to fall back to the generic heuristic tokenizer (dark keyword/string/number/comment coloring, same as before T541). Diff fences (```diff or unlabeled +/- hunks) always use the existing diff-line classifier, unaffected by this flag. Highlighting runs once per code-fence block (cached by block identity), never per keystroke/re-render |
CYBERINE_NOTIFICATIONS | bell | notification mechanism for the T534 local notify channel (run finished / waiting on input / long planner turn): bell (terminal BEL), system (OS notification — macOS osascript, Linux notify-send), both, or off. See "TUI/chat — local notifications" The long-handoff completion watcher (k5m91) ignores the bell default and uses system; only off silences it |
CYBERINE_BELL | (unset) | legacy narrow override: 0 strips just the bell mechanism out of whatever CYBERINE_NOTIFICATIONS mode is active (bell -> off, both -> system). Predates CYBERINE_NOTIFICATIONS |
CYBERINE_NOTIFY | (on) | legacy override: 0 disables the local notify channel entirely (both mechanisms, every trigger), regardless of CYBERINE_NOTIFICATIONS. Predates CYBERINE_NOTIFICATIONS Also silences the long-handoff completion banner (k5m91) |
CYBERINE_NO_UPDATE_CHECK | (unset) | 1 disables the T533 update-freshness check entirely (no cache read/write, no network call). See "TUI/chat — update notifier" |
CYBERINE_STATUSLINE_CMD | (unset) | shell command to customize the status line (like Claude Code's statusLine). In cyberine chat it reruns on a ~300ms debounce after session state changes (model/mode/tokens/cost/message count), receiving a JSON snapshot on stdin (model/session/cwd/mode/cost/tokens/elapsed); in the fleet hub (cyberine agents) it still polls every ~30s with no stdin. Two modes by output shape: plain text → its first line is appended as one extra · <text> segment (e.g. CYBERINE_STATUSLINE_CMD='git branch --show-current'); JSON ["row1","row2"] or {"lines":["row1","row2"]} → those rows REPLACE the built-in 2-row bar entirely (you own every row, capped at 3). Each row truncates to the terminal width. Also settable via config.json's statusline.command key (env wins). See "Custom status line" below |
CYBERINE_PROJECT_ROOTS | ~/WORK | colon/comma-separated root dirs the fleet folder picker (n) scans for git repos (~300 cap, ~ expanded). Typing a path (/, ~, .) in the picker also resolves it directly as a free-path candidate |
CYBERINE_MEMORY_BACKEND | (unset) | augmentation backend for long-term memory: local/none = local file store only; contextq = also push runs + read shared context via ContextQ. Unset = contextq when CYBERINE_CONTEXTQ is truthy, else local-only. The local store is always the canonical record store regardless |
CYBERINE_CONTEXTQ | (unset) | master switch for the ContextQ augmentation backend (truthy = on; 0/false/empty = off) |
CYBERINE_CONTEXTQ_URL | http://localhost:38200 | ContextQ (Shared Context Server) base URL (uncommon on-demand port) |
CYBERINE_CONTEXTQ_API_KEY | (empty) | ContextQ API key (sk_live_*, scope read + write); store in .local/, never commit. Sent as Authorization: Bearer |
CYBERINE_CONTEXTQ_WORKSPACE | cyberine | ContextQ workspace Cyberine writes runs/sessions into (auto-creates server-side on first write) |
CYBERINE_CONTEXTQ_AGENT | cyberine-fleet | agent slug used for ContextQ agent sessions + agent_boot |
CYBERINE_CONTEXTQ_TIMEOUT_MS | 5000 | per-request timeout for every ContextQ call so a hung server can never block a run |
CYBERINE_BUS_BACKEND | file | message-bus backend that relays run lifecycle (started/progress/completed) to a dispatching chat or parent run. file = JSONL mailboxes under <CYBERINE_HOME>/bus/; none = disabled (chat falls back to the 1s .local/runs poll). contextq lands in a later phase (degrades to file until then). http = hub-and-spoke over the cyberine web API (see "Cross-run comms over HTTP"). cyberine chat consumes it: a dispatched run's completion report appears the instant the run ends (no poll lag), and · <detail> progress milestones stream in live |
CYBERINE_BUS_HUB_URL | (unset) | base URL of the hub serving the bus when CYBERINE_BUS_BACKEND=http, e.g. http://hub.local:41700. Falls back to CYBERINE_SERVER_URL when unset. Read ONLY inside the http backend (src/store/httpMessageBus.ts) — no caller passes or learns it, and BusAddr carries no host. Unset with no fallback = every bus call is a logged no-op |
CYBERINE_BUS_HUB_TOKEN | (unset) | Cyberine API bearer token the http backend sends to the hub (cyberine api-token issue on the hub). Falls back to CYBERINE_API_TOKEN. Required whenever the hub enforces auth (any non-loopback bind, or CYBERINE_WEB_REQUIRE_AUTH=1); a wrong token is refused with the standard 401 envelope and the backend degrades silently |
CYBERINE_CREDIT_MIN_USD | 0.50 | minimum estimated-remaining balance (USD) below which a provider's workers are down-ranked in the fleet. Providers with no ledger entry are unaffected. Default $0.50 |
CYBERINE_SPEND_CAP_USD | 0 (disabled) | opt-in HARD ceiling (USD) on total accounted+reserved spend across ALL providers, race-free via an append-then-verify reservation at every dispatch (src/store/spendCap.ts, T482/T575). Gates both dispatch choke points (Orchestrator.dispatch and WorkflowEngine.runWorker) identically; cumulative spend is tracked by spendCap.ts itself, no credits set balance required. Distinct from the soft, per-provider CYBERINE_CREDIT_MIN_USD above. 0/unset = disabled — zero overhead, no file written. See "Hard spend cap" |
CYBERINE_SPEND_CAP_TTL_MS | 600000 (10 min) | reservation TTL for the hard spend cap above — an unreleased reservation (e.g. a crashed dispatch) stops counting against the cap once it expires. Only meaningful when CYBERINE_SPEND_CAP_USD is set |
CYBERINE_SPENDCAP_ROTATION_BYTES | 262144 (256 KB) | rotation threshold (bytes) for spendcap-events.jsonl before it is folded into spendcap-summary.json (T575), mirroring creditLedger.ts's CYBERINE_CREDIT_ROTATION_BYTES. Only meaningful when CYBERINE_SPEND_CAP_USD is set |
CYBERINE_QUOTA_COOLDOWN | (on) | set to 0 to disable the quota cooldown feature entirely (no recording, no filtering). Default on |
CYBERINE_FLEET_AUTO_DISABLE | (on) | set to 0 to stop a billing (402 / out of credits) or auth (401 / 403 / not logged in) refusal from writing enabled: false into the fleet.json in effect. Refusals still record their cooldown; nothing is written to fleet.json and no re-enable command is printed. Default on — see "Auto-disable a worker that refused for billing or auth" |
CYBERINE_QUOTA_COOLDOWN_RATELIMIT_MS | 1800000 | cooldown TTL (ms) after a rate-limit (HTTP 429 / too-many-requests) signal. Default 30 minutes |
CYBERINE_QUOTA_COOLDOWN_CREDITS_MS | 86400000 | cooldown TTL (ms) after an out-of-credits (HTTP 402 / insufficient balance) signal. Default 24 hours |
CYBERINE_QUOTA_COOLDOWN_CONNECTION_MS | 300000 | cooldown TTL (ms) after a connection-failure (ECONNREFUSED / unreachable endpoint / DNS miss / timeout) signal. Short by design (5 min) so a transiently-down local gateway or Ollama drops out of the fleet after one failure instead of erroring every dispatch, then rejoins once reachable |
CYBERINE_FALLBACK_MODELS | (empty) | global ordered fallback model chain for LoopAgentAdapter workers; comma-separated list of up to 3 model ids. On a 429/402/5xx/overload error the adapter retries with each model in order before failing; the model that served the result is recorded in run.json raw.servedByModel. Empty = no fallback (default; behavior unchanged) |
CYBERINE_STREAM_WATCHDOG_MS | 300000 | idle-stream watchdog (T562, Claude Code v2.1.196 parity): aborts a request when no stream event has arrived for this many ms. LoopAgentAdapter (fleet workers) retries — first on the SAME model (one same-connection retry), then via the fallback-model chain (CYBERINE_FALLBACK_MODELS) if configured, using the identical 429/402/5xx overload retry path. plannerTurn (interactive chat, T570) does NOT auto-retry or switch models — it surfaces a clear stall error instead. 0 disables the watchdog entirely (opt-out) on both surfaces |
CYBERINE_MCP_SERVERS | (unset) | inline JSON of external MCP servers to consume as tools — a spec array or a .mcp.json-style { "mcpServers": {...} } object. Empty = no MCP tools |
CYBERINE_MCP_CONFIG | (unset) | path to a .mcp.json-style file listing MCP servers to consume (alternative to CYBERINE_MCP_SERVERS) |
CYBERINE_PLUGINS_DIR | <CYBERINE_HOME>/plugins | trusted root the plugin loader scans for installed plugins (cyberine plugin ...). The whole security boundary for code plugins — never widened to a project/cwd path |
CYBERINE_PLUGINS_DISABLED | (unset) | comma-separated plugin names to skip loading (parity with a per-plugin .disabled marker). Empty = load every installed plugin |
CYBERINE_MEMORY_MCP_SERVER | (unset) | when CYBERINE_MEMORY_BACKEND=mcp, a JSON McpServerSpec for the knowledge server. Unset = ContextQ's own /mcp endpoint (from CYBERINE_CONTEXTQ_URL + key) |
CYBERINE_MEMORY_MCP_SAVE_TOOL | ctx_save | MCP tool name the mcp backend calls to save a run |
CYBERINE_MEMORY_MCP_SEARCH_TOOL | ctx_search | MCP tool name the mcp backend calls to fetch shared context |
CYBERINE_CC_MEMORY | (cascade) | Claude Code memory bridge. Unset = auto-cascade (.claude/memory/ in cwd → ~/.claude/memory/ → autoMemoryDirectory in ~/.claude/settings.json). Set to an explicit path to override cascade step 1. Set to 0 to disable the bridge entirely (no CC preamble read, no handoff write). Read side auto-skips for any dispatch not classified code-large (T553) regardless of this setting |
NF_TASKS_AGENT | <user>@<pid> | agent tag written to the third column of .local/tasks/status.log on every cyberine status flip (setStatus honours this env var; whitespace is sanitised to _). Same provenance column the Claude Code nf-tasks skill uses, so the overlay file shows who flipped each id (cyberine chat /dispatch vs. CC oc-tasks done vs. an external script). Unset = user@pid fallback |
NF_TASKS_MACHINE | (unset) | optional machine tag appended to the automatic from: stamp of cyberine tasks draft, after the source repo slug; no hostname is added by default |
CYBERINE_WAIT_TIMEOUT_MS | (unset, no ceiling) | opt-in ceiling (ms) for cyberine wait <runId> to block on a run's completion before giving up with exit 124; unset means no ceiling — wait tracks the run to its terminal state |
CYBERINE_STUCK_IDLE_MS | 600000 | idle timeout for cyberine reap: how long a live engine process may emit no events.jsonl progress before being flagged as stuck (ms, default 10 min) |
CYBERINE_STUCK_WALL_MS | 7200000 | wall-clock hard cap for cyberine reap: runs older than this are always reaped (ms, default 2 h) |
CYBERINE_STUCK_GRACE_MS | 5000 | grace window between SIGTERM and SIGKILL during cooperative teardown in cyberine reap (ms, default 5 s) |
CYBERINE_WF_BUDGET | (unset) | token ceiling for an imperative workflow script (npm run wf -- <script>); the runtime's agent() stops running once cumulative output tokens reach it, and host.budget reports total/spent()/remaining(). Unset = unbounded |
CYBERINE_PERSONA | cyberine | chat planner persona. cyberine (default) prepends the Cyberine persona preamble above the operational instructions. none or '' disables the persona so the operational instructions stand alone. See "Persona" recipe and docs/design/persona.md |
CYBERINE_LOOP_MAX_ITER | 100 | autonomy loop (cyberine loop): max iterations before the loop stops |
CYBERINE_LOOP_BLOCKED_THRESHOLD | 3 | autonomy loop: consecutive no-progress iterations before stopping |
CYBERINE_LOOP_SYNC_VERIFY | 0 | autonomy loop: set to 1 to enable synchronous-verify mode (same as --verify). Dispatches in-process and gates on DiffJudge / non-code verify. Required for beam-search forks. |
CYBERINE_LOOP_DEAD_FORK_LIMIT | 2 | autonomy loop (sync-verify): consecutive forks producing no candidate at all before the run stops with a dead fleet: reason naming the worker and error class. 0 disables the backstop |
CYBERINE_BEAM_WIDTH | 2 | autonomy loop beam-search: number of competing candidate worktrees per correctness/quality fork (hard cap: 5) |
CYBERINE_LOOP_TOKEN_BUDGET | 0 (disabled) | autonomy loop: safety-rails cumulative output-token budget; 0 = unlimited. On breach the task is blocked and the loop stops (never silently raised). Written to the audit ledger. |
CYBERINE_LOOP_ITERATION_CAP | 0 (disabled) | autonomy loop: safety-rails hard iteration cap checked before each dispatch, independent of CYBERINE_LOOP_MAX_ITER. 0 = disabled. On breach the task is blocked and the loop stops. |
CYBERINE_MAX_BUDGET_USD | 0 (disabled) | fleet budget: per-WORKER USD cap (CLI/npm run wf fallback for Task.maxBudgetUsd). Checked between tool rounds against the worker's live costUsd; on breach that worker checkpoints to status='partial' (siblings keep running). 0 = disabled. A per-task Task.maxBudgetUsd set via the SDK wins over this env. |
CYBERINE_FLEET_ROWS | (unset = enabled) | set to 0 or false to stop every launchBackgroundRun / autopilot --bg dispatch from creating a claude fleet row: launchAsFleetRow skips the capability probe entirely and takes the detached background path, silently (no fallback note on stderr). For TEST runs — npm run sweep sets it for every smoke it spawns so a sweep leaves no cyberine-run-* rows behind. Inherited by child dispatches through the detached spawn's environment. Unset (the default) is unchanged: the fleet row is tried first. See "Watch and steer a run from the fleet" |
CYBERINE_FLEET_USD_CAP | 0 (disabled) | fleet budget: per-FLEET aggregate USD cap across all in-flight workers of one dispatch. On breach the remaining in-flight workers are aborted (finished workers + the judge verdict are preserved). Distinct from CYBERINE_DAILY_USD_CAP (cross-run, dispatch-time) and CYBERINE_MAX_BUDGET_USD (per-worker). 0 = disabled. |
CYBERINE_EVOLVE_AUTONOMOUS | false | self-evolve loop: run unattended to a stop condition (no per-cycle human gate). Same as --mode autonomous |
CYBERINE_EVOLVE_GROW | false | self-evolve re-plan: propose net-new feature backlog items from each cycle's diff (continuous-evolution). Same as --grow |
CYBERINE_EVOLVE_AUTO_GROW | false | self-evolve: auto-promote proposed features to open (skip the human confirm). Only meaningful with grow enabled |
CYBERINE_EVOLVE_MAX_CYCLES | 10 | self-evolve: absolute backstop on the number of loop cycles |
CYBERINE_EVOLVE_PAUSE_SECS | 0 | self-evolve human-in-loop: seconds to wait at each cycle boundary for an operator steer/stop before continuing (0 = no wait) |
CYBERINE_EVOLVE_BACKLOG | (empty) | self-evolve --from-backlog: directory to read the seed backlog from (defaults to the current working directory) |
CYBERINE_EVOLVE_SKILL_WRITE | false | self-evolve self-improve: after a cycle clears the trust gate, write a reusable procedural skill doc to .cyberine/skills/evolve-<slug>/SKILL.md (picked up by the on-demand skill loader). Opt-in; only verified cycles are persisted |
CYBERINE_CRON_STORE | <CYBERINE_HOME>/cron.json | path to the persisted cron job JSON file. Override to put scheduled jobs in a custom location |
CYBERINE_CRON_DISABLED | (unset) | set to 1 or true to make cyberine cron tick skip all jobs (global kill switch). Useful for maintenance windows or when you want to inspect/audit without accidental dispatches |
CYBERINE_PROFILE | (unset) | 1 enables per-phase timing instrumentation. On cyberine chat startup prints a checkpoint table to stderr after the TUI exits: session-resolve, planner-resolve, and render phases. On cyberine agents / npm run tui (the fleet TUI), prints a checkpoint table to stderr on quit (e.g. mount-prefetch timing) — not on the interactive-session handoff round-trip, only on genuine exit. On loop runs prints per-round TTFT (time to first token) and per-tool execution durations after each successful run. Off by default — zero allocation overhead when unset |
CYBERINE_SKILLS_DIR | ~/.claude/skills | target base directory for cyberine skill install. Override to install skills into a custom location or a temporary directory for testing |
CYBERINE_WAKE_ON_MESSAGE | (unset) | set to 1 to enable the wake-on-message respawn scanner (option B of the durable-teammate feature) inside cyberine daemon. When a note/steer message arrives at a terminal run's inbox, a new background run is dispatched seeded with the message text and carrying lineage to the original run. Deduplicated by envelope id (persisted under <CYBERINE_HOME>/bus/seen-wake-ids.json). Default OFF — no existing behaviour is affected. |
CYBERINE_WAKE_SCAN_MS | 10000 | poll interval (ms) for the wake-on-message scanner inside cyberine daemon (minimum 1000). Only active when CYBERINE_WAKE_ON_MESSAGE=1. |
CYBERINE_TEAM | (unset) | optional team tag on the presence record a run or cyberine chat session announces on start (src/store/presence.ts). Drives resolveAddr({ team }) / /team send <team> broadcast-by-team routing and shows in /team list / list_team's team column. A cyberine chat session can also set/clear this per-session via /team join <team> / /team leave without restarting |
CYBERINE_AGENT_NAME | chat-<8-char session id> (chat); unset (run) | optional human-readable name on the presence record, used by resolveAddr({ name }) / /team send <name> for a directed (non-broadcast) send and shown in /team list / list_team |
CYBERINE_WEB_ALLOW_SESSION_MESSAGING | 0 (loopback binds allow it anyway) | allow the web chat planner to call message_session -- publish a note or a steer into another local session's inbox -- when the server is bound to a NON-loopback address. Off by default for the same reason as CYBERINE_WEB_ALLOW_FILE_TOOLS: anyone who can reach the endpoint could otherwise message or steer local sessions. Enforced twice (the tool is withheld from the offered list AND refused by the executor) |
CYBERINE_AGENT_HANDLE | minted adjective-noun from the session / run id | pin this process's unique addressable handle (k511d) instead of letting src/store/sessionHandle.ts mint one. Normalized on read (lowercased, invalid characters collapsed to -, max 32 chars) and still collision-resolved against the live roster, so a pinned handle already held by a live incumbent becomes <handle>-2. A cyberine chat session can change it per-session with /handle <new> |
Background shell jobs inside a worker (run_bash background + bash_jobs)
A loop worker can start a long-running shell command without blocking its tool round: runbash with background: true starts the command immediately and returns a job id; bashjobs with action="list"...
Generated reference (do not edit by hand)
Regenerate with npm run docs:catalog. npm run docs:catalog:check fails (non-zero exit, writes nothing) when source has drifted from these tables -- e.g. a new tool or env var was added and this...