export type EnvVarType = 'string' | 'number' | 'boolean' | 'json'; export type EnvVarCategory = 'model' | 'auth' | 'telegram' | 'paths' | 'debug' | 'daemon' | 'worktree' | 'mcp' | 'routing' | 'browser' | 'process' | 'display' | 'misc'; export interface EnvVarMeta { readonly name: string; readonly description: string; readonly type: EnvVarType; readonly required: boolean; readonly default?: string; readonly example?: string; readonly category: EnvVarCategory; readonly describedTodo?: boolean; readonly secret?: boolean; } export declare const ENV_REGISTRY: readonly [{ readonly name: "AFK_COMPACT_KEEP_LAST_TURNS"; readonly description: "Number of recent turns the compactor keeps verbatim during /compact. Default tuned in compact-handler.ts."; readonly type: "number"; readonly required: false; readonly example: "6"; readonly category: "model"; }, { readonly name: "AFK_COMPACT_MODEL"; readonly description: "Override the model used by the /compact summarizer. Falls back to a cheap default (haiku-class)."; readonly type: "string"; readonly required: false; readonly example: "claude-haiku-4-5"; readonly category: "model"; }, { readonly name: "AFK_COMPACT_SHRINK_FRACTION"; readonly description: "Context-fullness fraction (0–1, exclusive) at/above which /compact and auto-compaction relax the keep-window so a short-but-full session (few turns, huge tool exchanges) can still be summarized instead of no-oping on turn count. Default 0.7 (see shared/compaction.ts DEFAULT_COMPACT_SHRINK_THRESHOLD)."; readonly type: "number"; readonly required: false; readonly example: "0.8"; readonly category: "model"; }, { readonly name: "AFK_DEFAULT_SUBAGENT_MODEL"; readonly description: "Override the default model used when a subagent is dispatched without an explicit model."; readonly type: "string"; readonly required: false; readonly example: "sonnet"; readonly category: "model"; }, { readonly name: "AFK_DISABLE_PROMPT_CACHE"; readonly description: "Disable Anthropic prompt caching when set to 1/true/yes/on. Unset = caching enabled."; readonly type: "boolean"; readonly required: false; readonly default: "0"; readonly example: "1"; readonly category: "model"; }, { readonly name: "AFK_DISABLE_BASH_INTERPRETER_GUARD"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly default: "0"; readonly example: "1"; readonly category: "process"; }, { readonly name: "AFK_DISABLE_PATH_APPROVAL"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly default: "0"; readonly example: "1"; readonly category: "process"; }, { readonly name: "AFK_DISABLE_SPINE_UPDATE"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly default: "0"; readonly example: "1"; readonly category: "misc"; }, { readonly name: "AFK_FORCE_BASH_INTERPRETER_GUARD"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly default: "0"; readonly example: "1"; readonly category: "process"; }, { readonly name: "AFK_EFFORT"; readonly description: "Effort hint guiding adaptive-thinking depth, forwarded as Anthropic output_config.effort (model-gated; ignored where unsupported). Accepts low | medium | high | xhigh | max."; readonly type: "string"; readonly required: false; readonly example: "medium"; readonly category: "model"; }, { readonly name: "AFK_MAX_BUDGET_USD"; readonly description: "Cumulative USD budget ceiling for the session. Aborts the turn when the running cost crosses this."; readonly type: "number"; readonly required: false; readonly default: "5.00"; readonly example: "10.00"; readonly category: "model"; }, { readonly name: "AFK_MAX_CONCURRENT_SAFE_TOOL_CALLS"; readonly description: "Maximum concurrency-safe tool calls run simultaneously within one dispatcher batch. Default 8; accepted range 1-32; out-of-range or unparseable input falls back to the default."; readonly type: "number"; readonly required: false; readonly default: "8"; readonly example: "4"; readonly category: "process"; }, { readonly name: "AFK_MAX_CONCURRENT_SUBAGENT_CALLS"; readonly description: "Maximum subagent calls run simultaneously from one compose/DAG layer or skill wave. Default 8; accepted range 1-32; out-of-range or unparseable input falls back to the default."; readonly type: "number"; readonly required: false; readonly default: "8"; readonly example: "2"; readonly category: "process"; }, { readonly name: "AFK_MAX_CONCURRENT_BACKGROUND_JOBS"; readonly description: "Maximum background subagent jobs running simultaneously in one registry. Default 10; accepted range 1-64; out-of-range or unparseable input falls back to the default."; readonly type: "number"; readonly required: false; readonly default: "10"; readonly example: "5"; readonly category: "process"; }, { readonly name: "AFK_MAX_NESTING_DEPTH"; readonly description: string; readonly type: "number"; readonly required: false; readonly default: "3"; readonly example: "2"; readonly category: "model"; }, { readonly name: "AFK_MAX_CONCURRENT_CHILDREN_PER_AGENT"; readonly description: string; readonly type: "number"; readonly required: false; readonly example: "4"; readonly category: "model"; }, { readonly name: "AFK_MAX_CONCURRENT_AGENTS"; readonly description: string; readonly type: "number"; readonly required: false; readonly example: "16"; readonly category: "model"; }, { readonly name: "AFK_MAX_TOTAL_AGENTS"; readonly description: string; readonly type: "number"; readonly required: false; readonly example: "48"; readonly category: "model"; }, { readonly name: "AFK_MAX_OUTPUT_TOKENS"; readonly description: string; readonly type: "number"; readonly required: false; readonly example: "8192"; readonly category: "model"; }, { readonly name: "AFK_MAX_TOKENS"; readonly description: "Deprecated and inert: not read by the generation path. Use AFK_MAX_OUTPUT_TOKENS (or --max-output-tokens) to cap per-response output tokens; falls back to the model output ceiling when unset."; readonly type: "number"; readonly required: false; readonly default: "4096"; readonly example: "8192"; readonly category: "model"; }, { readonly name: "AFK_MAX_TOOL_USE_ITERATIONS"; readonly description: string; readonly type: "number"; readonly required: false; readonly default: "0"; readonly example: "150"; readonly category: "model"; }, { readonly name: "AFK_MEMORY_EVIDENCE_GATE"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly default: "1"; readonly example: "0"; readonly category: "misc"; }, { readonly name: "AFK_MICROCOMPACT_KEEP_LAST"; readonly description: "Number of the most-recent tool_result blocks that tool-result microcompaction keeps intact regardless of size, so the agent does not lose the tool output it is actively reasoning over. Older results are the safe ones to trim. Default 4 (see shared/compaction.ts DEFAULT_MICROCOMPACT_KEEP_LAST). Values <= 0 protect nothing."; readonly type: "number"; readonly required: false; readonly default: "4"; readonly example: "3"; readonly category: "model"; }, { readonly name: "AFK_MICROCOMPACT_TOOL_RESULT_BYTES"; readonly description: "Byte threshold (tool_result content length) at/above which a tool_result block becomes a microcompaction candidate. When /compact and auto-compaction would otherwise no-op on a short-but-full session, microcompaction clears large/old tool_result CONTENT in place (largest first) — replacing it with a short placeholder, never removing the block — to reclaim context deterministically (no LLM call). Blocks below this size are left intact. Default 2048 (see shared/compaction.ts DEFAULT_MICROCOMPACT_TOOL_RESULT_BYTES)."; readonly type: "number"; readonly required: false; readonly default: "2048"; readonly example: "4096"; readonly category: "model"; }, { readonly name: "AFK_MICROCOMPACT_DELEGATION_BYTES"; readonly description: "Byte threshold for delegation tool results (agent/compose/skill). These results carry pre-compressed subagent findings that are expensive to re-derive -- clearing them destroys irreplaceable synthesized knowledge. A delegation tool result must be at least this large before microcompaction considers clearing it. Default 16384 (16KB, vs 2KB for ordinary tools). Set to match AFK_MICROCOMPACT_TOOL_RESULT_BYTES to disable the elevated threshold."; readonly type: "number"; readonly required: false; readonly default: "16384"; readonly example: "32768"; readonly category: "model"; }, { readonly name: "AFK_MODEL"; readonly description: "Default model for agent turns. Accepts slot names (local, small, medium, large), fixed-identity aliases (opus, sonnet, haiku, fable), or full model IDs. Migration: AFK_MODEL=sonnet now pins the fixed Sonnet identity rather than following a rebound medium tier."; readonly type: "string"; readonly required: false; readonly default: "medium"; readonly example: "claude-opus-5"; readonly category: "model"; }, { readonly name: "AFK_MODEL_TTFB_TIMEOUT_MS"; readonly description: string; readonly type: "number"; readonly required: false; readonly default: "180000"; readonly example: "120000"; readonly category: "model"; }, { readonly name: "AFK_MODEL_STALL_TIMEOUT_MS"; readonly description: string; readonly type: "number"; readonly required: false; readonly default: "1200000"; readonly example: "600000"; readonly category: "model"; }, { readonly name: "AFK_SUBAGENT_TIMEOUT_MS"; readonly description: string; readonly type: "number"; readonly required: false; readonly default: "2700000"; readonly example: "3600000"; readonly category: "model"; }, { readonly name: "AFK_SUBAGENT_IDLE_TIMEOUT_MS"; readonly description: string; readonly type: "number"; readonly required: false; readonly default: "480000"; readonly example: "300000"; readonly category: "model"; }, { readonly name: "AFK_VISION_MODELS"; readonly description: "Comma-separated override for image (vision) capability detection on the openai-compatible provider. Each token force-enables a model id by exact or substring match (e.g. \"qwen2.5-vl\" matches a local VL id); prefix a token with \"!\" to force-disable. Use to send images to a local vision-language model AFK does not recognise by name, or to blacklist a mis-detected id. Built-in detection already covers gpt-4o/4.1/5.x, o1/o3/o4-mini, Claude, and common VL families."; readonly type: "string"; readonly required: false; readonly example: "qwen2.5-vl,!gpt-4o-mini"; readonly category: "model"; }, { readonly name: "AFK_MODEL_LOCAL"; readonly description: "Bind the \"local\" capability tier (cheapest/fastest, user-configured) to a model id. Overrides afk.config.json models.local. Point at a local Ollama, LM Studio, or any OpenAI-compatible shim."; readonly type: "string"; readonly required: false; readonly example: "llama3.2:3b"; readonly category: "model"; }, { readonly name: "AFK_MODEL_LOCAL_API_KEY"; readonly description: "Per-slot API key for the \"local\" tier. Overrides global credentials for this tier only."; readonly type: "string"; readonly required: false; readonly category: "model"; readonly secret: true; }, { readonly name: "AFK_MODEL_LOCAL_BASE_URL"; readonly description: "Per-slot endpoint base URL for the \"local\" tier. Anthropic Messages base or OpenAI-compatible base per the tier provider."; readonly type: "string"; readonly required: false; readonly example: "http://localhost:11434/v1"; readonly category: "model"; }, { readonly name: "AFK_MODEL_LARGE"; readonly description: "Bind the \"large\" capability tier (most capable) to a model id/alias. Overrides afk.config.json models.large."; readonly type: "string"; readonly required: false; readonly example: "claude-opus-5"; readonly category: "model"; }, { readonly name: "AFK_MODEL_LARGE_API_KEY"; readonly description: "Per-slot API key for the \"large\" tier (Stage 2). Overrides global credentials for this tier only."; readonly type: "string"; readonly required: false; readonly category: "model"; readonly secret: true; }, { readonly name: "AFK_MODEL_LARGE_BASE_URL"; readonly description: "Per-slot endpoint base URL for the \"large\" tier (Stage 2). Anthropic Messages base or OpenAI-compatible base per the tier provider."; readonly type: "string"; readonly required: false; readonly example: "http://localhost:8080/v1"; readonly category: "model"; }, { readonly name: "AFK_MODEL_MEDIUM"; readonly description: "Bind the \"medium\" capability tier (general-use) to a model id/alias. Overrides afk.config.json models.medium."; readonly type: "string"; readonly required: false; readonly example: "claude-sonnet-5"; readonly category: "model"; }, { readonly name: "AFK_MODEL_MEDIUM_API_KEY"; readonly description: "Per-slot API key for the \"medium\" tier (Stage 2). Overrides global credentials for this tier only."; readonly type: "string"; readonly required: false; readonly category: "model"; readonly secret: true; }, { readonly name: "AFK_MODEL_MEDIUM_BASE_URL"; readonly description: "Per-slot endpoint base URL for the \"medium\" tier (Stage 2). Anthropic Messages base or OpenAI-compatible base per the tier provider."; readonly type: "string"; readonly required: false; readonly example: "http://localhost:8080/v1"; readonly category: "model"; }, { readonly name: "AFK_MODEL_SMALL"; readonly description: "Bind the \"small\" capability tier (cheap/fast) to a model id/alias. Overrides afk.config.json models.small."; readonly type: "string"; readonly required: false; readonly example: "gpt-4o-mini"; readonly category: "model"; }, { readonly name: "AFK_MODEL_SMALL_API_KEY"; readonly description: "Per-slot API key for the \"small\" tier (Stage 2). Overrides global credentials for this tier only."; readonly type: "string"; readonly required: false; readonly category: "model"; readonly secret: true; }, { readonly name: "AFK_MODEL_SMALL_BASE_URL"; readonly description: "Per-slot endpoint base URL for the \"small\" tier (Stage 2). Anthropic Messages base or OpenAI-compatible base per the tier provider."; readonly type: "string"; readonly required: false; readonly example: "http://localhost:8080/v1"; readonly category: "model"; }, { readonly name: "AFK_OVERLOAD_PAUSE_MS"; readonly description: "Wall-clock ceiling (ms) for the bounded pause after a mid-stream overload (529) exhausts its retry budget. Overrides the per-surface default for ALL surfaces: 0 disables the pause (fail fast). Interactive surfaces (cli/repl/telegram) default to 600000; daemon/cron default to 0 so an always-on runner never silently parks on upstream capacity."; readonly type: "number"; readonly required: false; readonly example: "600000"; readonly category: "model"; }, { readonly name: "AFK_PROMPT_CACHE_TTL"; readonly description: "TTL for Anthropic prompt-cache blocks. Accepts 5m or 1h."; readonly type: "string"; readonly required: false; readonly default: "1h"; readonly example: "1h"; readonly category: "model"; }, { readonly name: "AFK_SUGGEST_ENABLED"; readonly description: "Enable the LLM-backed ghost-text suggestion tier in the interactive REPL. On by default. Set to 0/false/no/off to disable."; readonly type: "boolean"; readonly required: false; readonly default: "1"; readonly example: "0"; readonly category: "model"; }, { readonly name: "AFK_SUGGEST_PROMPT"; readonly description: "Enable LLM-generated empty-prompt suggestions — a proposed next action shown as ghost text when the prompt is blank, accepted with Tab or Right-arrow. Fires only after a turn has completed in the session: the startup prompt (and the prompt right after /clear) is left clean because there is no session context to ground a proposal in. On by default. Set to 0/false/no/off to disable. Requires AFK_SUGGEST_ENABLED (it reuses the same suggestion model and provider)."; readonly type: "boolean"; readonly required: false; readonly default: "1"; readonly example: "0"; readonly category: "model"; }, { readonly name: "AFK_SUGGEST_GHOST"; readonly description: "Enable REPL ghost-text inline suggestions (Tier-1 history/dropdown + optional Tier-2 LLM). 1 = on (default), 0 = off. Set 0/false/off/no to disable all ghost text. Tier-2 LLM is separately gated by AFK_SUGGEST_ENABLED."; readonly type: "boolean"; readonly required: false; readonly default: "1"; readonly example: "0"; readonly category: "model"; }, { readonly name: "AFK_SUGGEST_MODEL"; readonly description: "Override the small model used for REPL ghost-text suggestions. Falls back to AFK_COMPACT_MODEL or haiku-class for anthropic, or the session model for other providers."; readonly type: "string"; readonly required: false; readonly category: "model"; }, { readonly name: "AFK_TASK_BUDGET"; readonly description: "Per-task token budget ceiling. Aborts when cumulative usage would exceed it."; readonly type: "number"; readonly required: false; readonly default: "100000"; readonly example: "200000"; readonly category: "model"; }, { readonly name: "AFK_TEMPERATURE"; readonly description: "Numeric temperature override for model sampling. Provider default if unset."; readonly type: "number"; readonly required: false; readonly example: "0.7"; readonly category: "model"; }, { readonly name: "AFK_THINKING"; readonly description: "Extended-thinking mode. Accepts adaptive | disabled | max | enabled: | enabled:max. Defaults to the model-appropriate mode when unset (adaptive on current models)."; readonly type: "string"; readonly required: false; readonly default: "adaptive"; readonly example: "adaptive"; readonly category: "model"; }, { readonly name: "AFK_THINKING_UI"; readonly description: string; readonly type: "string"; readonly required: false; readonly default: "live"; readonly example: "digest"; readonly category: "misc"; }, { readonly name: "AFK_TIMEOUT_MS"; readonly description: "Per-turn timeout in milliseconds. Provider/SDK default if unset."; readonly type: "number"; readonly required: false; readonly example: "120000"; readonly category: "model"; }, { readonly name: "AFK_WORKSPACE_DISABLED"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly default: "0"; readonly example: "1"; readonly category: "model"; }, { readonly name: "CLAUDE_MODEL"; readonly description: "Legacy alias for AFK_MODEL — supported for back-compat with pre-AFK_* deployments."; readonly type: "string"; readonly required: false; readonly example: "sonnet"; readonly category: "model"; }, { readonly name: "AFK_SYSTEM_PROMPT"; readonly description: "Raw operator-overlay prompt. Highest-priority overlay (over afk.config.json and AFK.md). Appended on top of the framework base (system-prompt.md) under an \"# Operator configuration\" header — it augments, never replaces, the base."; readonly type: "string"; readonly required: false; readonly example: "You are a helpful agent."; readonly category: "model"; }, { readonly name: "AFK_DUMP_PROMPT"; readonly description: "Write the resolved system prompt to a file at startup. Accepts a path or 1 for default location."; readonly type: "string"; readonly required: false; readonly example: "/tmp/afk-prompt.txt"; readonly category: "debug"; }, { readonly name: "ANTHROPIC_API_KEY"; readonly description: "Anthropic API key. Tier-1 credential — overrides keychain OAuth and CLAUDE_CODE_OAUTH_TOKEN."; readonly type: "string"; readonly required: false; readonly category: "auth"; readonly secret: true; }, { readonly name: "CLAUDE_CODE_OAUTH_TOKEN"; readonly description: "Claude Code OAuth token. Tier-2 credential — used when ANTHROPIC_API_KEY is unset; falls back to keychain."; readonly type: "string"; readonly required: false; readonly category: "auth"; readonly secret: true; }, { readonly name: "OPENAI_API_KEY"; readonly description: "OpenAI API key for the openai-compatible provider (gpt-*, o1*, o3*, o4* models)."; readonly type: "string"; readonly required: false; readonly category: "auth"; readonly secret: true; }, { readonly name: "CODEX_API_KEY"; readonly description: "Fallback OpenAI API key for the openai-compatible provider, read after OPENAI_API_KEY. Legacy name from the removed @openai/codex-sdk integration — prefer OPENAI_API_KEY."; readonly type: "string"; readonly required: false; readonly category: "auth"; readonly secret: true; }, { readonly name: "XAI_API_KEY"; readonly description: "xAI API key for the xai provider (Grok models) in API-key mode. Metered; distinct from SuperGrok / SuperGrok Heavy / X Premium+ OAuth."; readonly type: "string"; readonly required: false; readonly category: "auth"; readonly secret: true; }, { readonly name: "AFK_XAI_BASE_URL"; readonly description: "Base URL for xAI API-key mode. Default https://api.x.ai/v1. The OpenAI SDK appends /chat/completions."; readonly type: "string"; readonly required: false; readonly example: "https://api.x.ai/v1"; readonly category: "model"; }, { readonly name: "AFK_XAI_OAUTH_BASE_URL"; readonly description: "Base URL for xAI SuperGrok / SuperGrok Heavy / X Premium+ OAuth inference. Default https://cli-chat-proxy.grok.com/v1 (subscription path). Some accounts work on https://api.x.ai/v1 with OAuth — override if needed. Distinct from AFK_XAI_BASE_URL (API-key mode)."; readonly type: "string"; readonly required: false; readonly example: "https://cli-chat-proxy.grok.com/v1"; readonly category: "model"; }, { readonly name: "AFK_XAI_GROK_CLIENT_VERSION"; readonly description: "Override the semver sent as x-grok-client-version to the xAI OAuth CLI chat proxy. Use only if the proxy raises its required Grok CLI version before agent-afk is updated; invalid values fall back to the official Grok Build version file or built-in compatible default."; readonly type: "string"; readonly required: false; readonly example: "1.0.6"; readonly category: "model"; }, { readonly name: "AFK_LOCAL_API_KEY"; readonly description: "Placeholder API key for local Anthropic-compatible servers (vllm-mlx, etc.). Set when AFK_LOCAL_BASE_URL is configured."; readonly type: "string"; readonly required: false; readonly default: "local"; readonly example: "local"; readonly category: "auth"; readonly secret: true; }, { readonly name: "AFK_LOCAL_BASE_URL"; readonly description: "Base URL for a self-hosted Anthropic-compatible server. When set, routes traffic away from api.anthropic.com."; readonly type: "string"; readonly required: false; readonly example: "http://127.0.0.1:8080"; readonly category: "model"; }, { readonly name: "AFK_OPENAI_BASE_URL"; readonly description: "Base URL override for the OpenAI-compatible provider. Used for local shims (mlx_lm.server, Ollama, vLLM, LM Studio). The OpenAI SDK appends `/chat/completions` itself — a value ending in `/chat/completions` will be stripped at config-load time with a one-shot warning."; readonly type: "string"; readonly required: false; readonly example: "http://127.0.0.1:8000/v1"; readonly category: "model"; }, { readonly name: "AFK_OPENAI_USE_RESPONSES"; readonly description: "Opt the OpenAI-compatible provider into the OpenAI Responses API instead of Chat Completions for API-key sessions. Truthy values: 1, true, yes, on. The ChatGPT-subscription OAuth path uses Responses automatically regardless of this flag."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "model"; }, { readonly name: "AFK_OPENAI_CHATGPT_OAUTH"; readonly description: "Use ChatGPT-subscription OAuth credentials from ~/.codex/auth.json (auth_mode: chatgpt) as OpenAI provider auth. Off by default. Set to 1/true/yes/on to enable. READ-ONLY: AFK never refreshes these tokens — re-run codex when the access token expires. Routes requests over the Responses API to the private ChatGPT backend (chatgpt.com/backend-api)."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "model"; }, { readonly name: "AFK_PROVIDER"; readonly description: "Force provider selection (anthropic | anthropic-direct | openai | openai-compatible | openai-codex | xai | xai-oauth). Overrides the model-name heuristic. Same surface as the --provider CLI flag; CLI flag wins when both are set."; readonly type: "string"; readonly required: false; readonly example: "openai-compatible"; readonly category: "model"; }, { readonly name: "EXA_API_KEY"; readonly description: "Exa (exa.ai) search API key, enabling web_scrape search mode. Free tier (20k requests/month) available at https://exa.ai. When unset, search mode returns an actionable error; markdown and raw modes are unaffected."; readonly type: "string"; readonly required: false; readonly category: "auth"; readonly secret: true; }, { readonly name: "TELEGRAM_BOT_TOKEN"; readonly description: "Telegram bot token from @BotFather. Required to run the Telegram bot surface."; readonly type: "string"; readonly required: false; readonly category: "telegram"; readonly secret: true; }, { readonly name: "AFK_TELEGRAM_BOT_TOKEN"; readonly description: "Alternative env var name for the Telegram bot token, accepted by the setup wizard."; readonly type: "string"; readonly required: false; readonly category: "telegram"; readonly secret: true; }, { readonly name: "AFK_TELEGRAM_ALLOWED_CHAT_IDS"; readonly description: "Comma-separated list of Telegram chat IDs allowed to interact with the bot. Required when the bot is running."; readonly type: "string"; readonly required: false; readonly example: "123456789,987654321"; readonly category: "telegram"; }, { readonly name: "AFK_TELEGRAM_TAG_ONLY_CHAT_IDS"; readonly description: "Comma-separated list of Telegram chat IDs where the bot answers only when addressed (a reply to the bot, an @mention of the bot, or a text_mention resolving to the bot). Slash-commands are unaffected; chats not listed behave as usual. The afk.config.json telegram.tagOnlyChats block takes precedence. Requires Telegram privacy mode OFF (BotFather /setprivacy Disable) for non-addressed group messages to reach the bot."; readonly type: "string"; readonly required: false; readonly example: "-100987654321,123456789"; readonly category: "telegram"; }, { readonly name: "AFK_TELEGRAM_PRIMARY_CHAT_ID"; readonly description: "Default chat ID for outbound notifications (primary-mode routing). When unset, notifications go to the first private/DM chat in AFK_TELEGRAM_ALLOWED_CHAT_IDS. The afk.config.json telegram.notify block takes precedence."; readonly type: "string"; readonly required: false; readonly example: "123456789"; readonly category: "telegram"; }, { readonly name: "AFK_TELEGRAM_NOTIFY_MODE"; readonly description: "Outbound notification fan-out: primary (default — one chat), broadcast (every allowed chat), or custom (afk.config.json telegram.notify.targets). The afk.config.json telegram.notify.mode takes precedence."; readonly type: "string"; readonly required: false; readonly example: "broadcast"; readonly category: "telegram"; }, { readonly name: "TELEGRAM_DATA_DIR"; readonly description: "Override the directory where Telegram bot state is stored. Defaults to ~/.afk/state/telegram/."; readonly type: "string"; readonly required: false; readonly category: "telegram"; }, { readonly name: "TELEGRAM_VERBOSE"; readonly description: "Set to a truthy value ('1'/'true'/'yes'/'on', case-insensitive) to log per-message details from the Telegram bot — chat IDs, message text, latency."; readonly type: "boolean"; readonly required: false; readonly example: "true"; readonly category: "telegram"; }, { readonly name: "TMUX"; readonly description: string; readonly type: "string"; readonly required: false; readonly example: "/tmp/tmux-501/default,12345,0"; readonly category: "process"; }, { readonly name: "AFK_TELEGRAM_TRACE"; readonly description: "Set to 1 to dump raw bridge traffic between the agent and the Telegram bot — debugging only."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "AFK_TELEGRAM_CWD"; readonly description: "Override the working directory used by the Telegram bot when spawning agent sessions."; readonly type: "string"; readonly required: false; readonly category: "telegram"; }, { readonly name: "AFK_TELEGRAM_SESSION_IDLE_MS"; readonly description: "Milliseconds of inactivity after which an idle AgentSession is closed and its memory freed. sessionData (model/cwd preferences) is kept in-memory and reloaded on demand from disk. Default: 14400000 (4 hours)."; readonly type: "number"; readonly required: false; readonly default: "14400000"; readonly example: "3600000"; readonly category: "telegram"; }, { readonly name: "AFK_HOME"; readonly description: "Override the AFK home directory. Default: ~/.afk/."; readonly type: "string"; readonly required: false; readonly default: "~/.afk"; readonly example: "/opt/afk"; readonly category: "paths"; }, { readonly name: "AFK_STATE_DIR"; readonly description: "Override the entire AFK state tier (sessions/, todos/, transcripts/, memory/, daemon/, etc.), not just one subdirectory. Must be an absolute path (not /). Default: $AFK_HOME/state/."; readonly type: "string"; readonly required: false; readonly category: "paths"; }, { readonly name: "AFK_FRAMEWORK_DIR"; readonly description: "Override the AFK agent-framework directory used for telemetry and briefs. Default: $AFK_HOME/agent-framework/."; readonly type: "string"; readonly required: false; readonly category: "paths"; }, { readonly name: "AFK_COMPANION_PRIMER"; readonly description: "Opt-in: absolute path to a single companion-primer file. When set, its content is bounded (capped, fenced as ) and appended to the system prompt at session start for top-level sessions (chat/REPL/telegram/daemon), as lower-authority \"reflections, not facts\" context. Unset (default) = no-op. Only the one named file is ever read — never a directory or repo walk."; readonly type: "string"; readonly required: false; readonly example: "/Users/me/Projects/afk-companion/PRIMER.md"; readonly category: "paths"; }, { readonly name: "HOME"; readonly description: "Standard Unix home directory. Used as the fallback when AFK_HOME is unset."; readonly type: "string"; readonly required: false; readonly category: "process"; }, { readonly name: "PATH"; readonly description: "System PATH. Read for executable resolution (git, gh, etc.) in tool handlers."; readonly type: "string"; readonly required: false; readonly category: "process"; }, { readonly name: "APPDATA"; readonly description: "Windows %APPDATA% (Roaming). Used for VS Code/Cursor settings discovery and credential denylist paths."; readonly type: "string"; readonly required: false; readonly category: "process"; }, { readonly name: "LOCALAPPDATA"; readonly description: "Windows %LOCALAPPDATA%. Used for browser credential denylist paths (Chrome, Firefox, Edge, etc.)."; readonly type: "string"; readonly required: false; readonly category: "process"; }, { readonly name: "USERPROFILE"; readonly description: "Windows %USERPROFILE%. Used for credential denylist paths (.ssh, .aws, .gnupg) on win32."; readonly type: "string"; readonly required: false; readonly category: "process"; }, { readonly name: "AFK_DAEMON_CWD"; readonly description: "Working directory used by the daemon process for spawned agent sessions."; readonly type: "string"; readonly required: false; readonly category: "daemon"; }, { readonly name: "AFK_DAEMON_TASK"; readonly description: "Default task description for the daemon. Falls back to afk.config.json daemon.task."; readonly type: "string"; readonly required: false; readonly category: "daemon"; }, { readonly name: "AFK_DAEMON_TASK_ID"; readonly description: "Task identifier the daemon uses to scope its state directory and telemetry."; readonly type: "string"; readonly required: false; readonly category: "daemon"; }, { readonly name: "AFK_DAEMON_HOST"; readonly description: "Bind address for the daemon control HTTP surface. Defaults to 127.0.0.1 (loopback only). The control surface is unauthenticated, so bind a non-loopback address such as 0.0.0.0 only on a trusted or firewalled network. Overridden by the --host flag."; readonly type: "string"; readonly required: false; readonly category: "daemon"; }, { readonly name: "AFK_SESSIONSTART_COOLDOWN_MS"; readonly description: "Cooldown in milliseconds between SessionStart trigger fires in the daemon. Prevents thundering-herd on rapid restarts."; readonly type: "number"; readonly required: false; readonly category: "daemon"; }, { readonly name: "AFK_DAEMON_SHELL_TIMEOUT_MS"; readonly description: "Wall-clock timeout in milliseconds for executor:shell scheduled tasks. Defaults to 300000 (5 minutes). The child process is killed on timeout."; readonly type: "number"; readonly required: false; readonly category: "daemon"; }, { readonly name: "AFK_WEB_PORT"; readonly description: "Port for the `afk web` browser surface. Defaults to 4141; falls back to an ephemeral port when taken. Overridden by --port."; readonly type: "number"; readonly required: false; readonly example: "4141"; readonly category: "daemon"; }, { readonly name: "AFK_WEB_HOST"; readonly description: "Bind address for the `afk web` browser surface. Defaults to 127.0.0.1. Unlike the daemon control surface, a non-loopback bind is REFUSED unless AFK_WEB_TOKEN (or --token) is also set, because this surface can submit prompts and approve tool use. Overridden by --host."; readonly type: "string"; readonly required: false; readonly example: "127.0.0.1"; readonly category: "daemon"; }, { readonly name: "AFK_WEB_TOKEN"; readonly description: "Bearer token for the `afk web` surface. When unset, a random per-run token is minted and printed in the startup URL. Setting this explicitly is also what permits a non-loopback bind."; readonly type: "string"; readonly required: false; readonly category: "daemon"; readonly secret: true; }, { readonly name: "AFK_WORKTREE_AUTONAME"; readonly description: "Auto-rename worktree branches based on the first user message in interactive mode. 1 = on (default), 0 = off."; readonly type: "boolean"; readonly required: false; readonly default: "1"; readonly example: "0"; readonly category: "worktree"; }, { readonly name: "AFK_WORKTREE_BRANCH_PREFIX"; readonly description: "Branch-name prefix for AFK-managed worktrees. Default afk/. Set to empty string to drop the prefix."; readonly type: "string"; readonly required: false; readonly default: "afk/"; readonly example: "wt/"; readonly category: "worktree"; }, { readonly name: "AFK_WORKTREE_BASE"; readonly description: "Override the base git ref for worktrees created with --worktree. By default AFK bases worktrees on the remote's default branch (e.g. origin/main), fetched fresh. Set this to pin a different ref, or to HEAD to base on the local checkout. Overridden per-session by --worktree-base."; readonly type: "string"; readonly required: false; readonly example: "origin/main"; readonly category: "worktree"; }, { readonly name: "AFK_WORKTREE_ON_EXIT"; readonly description: "Clean-worktree quit policy for interactive --worktree sessions: ask, keep, or remove."; readonly type: "string"; readonly required: false; readonly example: "ask"; readonly category: "worktree"; }, { readonly name: "AFK_WORKTREE_BOOT_PRUNE"; readonly description: "When set, the daemon prunes stale worktrees at boot in addition to the cron-driven sweep."; readonly type: "boolean"; readonly required: false; readonly category: "worktree"; }, { readonly name: "AFK_WORKTREE_PRUNE_DISABLE"; readonly description: "Disable the worktree prune job entirely. Useful for long-running tests."; readonly type: "boolean"; readonly required: false; readonly category: "worktree"; }, { readonly name: "AFK_WORKTREE_MAX_AGE_CLEAN"; readonly description: "Maximum age (in days) before a clean worktree is auto-pruned. Default 14."; readonly type: "number"; readonly required: false; readonly default: "14"; readonly category: "worktree"; }, { readonly name: "AFK_WORKTREE_MAX_AGE_DIRTY"; readonly description: "Maximum age (in days) before a dirty worktree is auto-pruned. Default 30."; readonly type: "number"; readonly required: false; readonly default: "30"; readonly category: "worktree"; }, { readonly name: "AFK_WORKTREE_SWEEP_ROOT"; readonly description: "Override the root directory under which AFK worktrees are tracked for pruning."; readonly type: "string"; readonly required: false; readonly category: "worktree"; }, { readonly name: "AFK_ALLOW_PROJECT_MCP"; readonly description: "Opt-in to loading + spawning MCP servers declared in /.mcp.json. Fail-closed: when unset (or 0), project-local servers are NOT spawned; set to a truthy value (1/true/yes/on) to load them. A project-local .mcp.json spawns arbitrary commands on session start, so it is off by default to prevent code execution when entering an untrusted repo (issue #571). Skipped servers are listed in a startup warning with the opt-in instruction."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "mcp"; }, { readonly name: "AFK_AUTO_ROUTING"; readonly description: "Auto-route bare slash inputs to matching skills. Applies to interactive, chat, telegram, and daemon surfaces."; readonly type: "boolean"; readonly required: false; readonly example: "true"; readonly category: "routing"; }, { readonly name: "AFK_INTERNAL"; readonly description: "Tier gate. Set to exactly `1` to unlock — only the literal string \"1\" unlocks (other truthy values like \"true\"/\"yes\" leave the tier locked). When unlocked, skills tagged `audience: 'internal'` (e.g. /audit-fit, harvest/distill plugins) become visible at end-user surfaces (slash-command list, --help, tab-complete, system-prompt skill manifest). Default unset = public tier — internal skills are hidden. Not an access-control boundary; it gates surfacing, not the underlying registry."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "routing"; }, { readonly name: "AFK_SHELL_PASSTHROUGH"; readonly description: "Enable the interactive REPL `!cmd` / `!&cmd` shell-passthrough feature. On by default. Set to 0, false, off, or no (case-insensitive) to disable, so inputs beginning with ! are sent to the model as literal text instead of being executed as shell commands. Equivalent to the --no-shell-passthrough flag."; readonly type: "boolean"; readonly required: false; readonly default: "1"; readonly example: "0"; readonly category: "misc"; }, { readonly name: "AFK_BG_AUTO_DELIVER"; readonly description: "Auto-deliver background subagent results into the model context on the next user turn (interactive REPL). On by default. Set to 0, false, off, or no (case-insensitive) to disable, restoring the manual /bgsub:join retrieval flow."; readonly type: "boolean"; readonly required: false; readonly default: "1"; readonly example: "0"; readonly category: "misc"; }, { readonly name: "AFK_BASH_PREVIEW_HEAD_LINES"; readonly description: string; readonly type: "number"; readonly required: false; readonly default: "0"; readonly example: "3"; readonly category: "misc"; }, { readonly name: "AFK_BASH_PREVIEW_TAIL_LINES"; readonly description: string; readonly type: "number"; readonly required: false; readonly default: "7"; readonly example: "10"; readonly category: "misc"; }, { readonly name: "AFK_BANNER_PLAIN"; readonly description: "Suppress the ANSI-colored banner at REPL startup. Useful for non-TTY captures and CI logs."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "misc"; }, { readonly name: "AFK_PLAIN_OUTPUT"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "misc"; }, { readonly name: "AFK_SPINNER_TIPS"; readonly description: "Show rotating tips in the loading spinner during long calls. 1 = on, 0 = off."; readonly type: "boolean"; readonly required: false; readonly category: "misc"; }, { readonly name: "AFK_GOBLIN_SPINNER"; readonly description: "Goblin-themed working spinner (olive frames + goblin verbs) while the agent runs tools. 1 = on (default), 0 = classic dim spinner."; readonly type: "boolean"; readonly required: false; readonly example: "0"; readonly category: "misc"; }, { readonly name: "AFK_GOBLIN_MASCOT"; readonly description: "Reacting goblin mini-sprite in the reserved footer band while the agent runs tools (3 rows, animated). 1 = on, unset/0 = off (default). Claims terminal rows, so it is opt-in."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "misc"; }, { readonly name: "AFK_TERM_TITLE"; readonly description: "Set the terminal/tab title (OSC 2) to reflect afk state — \"afk — · running\" during a turn, \"afk — \" when idle, cleared on exit. 1 = on (default when stdout is a TTY), 0 = leave the title alone. TTY-only."; readonly type: "boolean"; readonly required: false; readonly example: "0"; readonly category: "misc"; }, { readonly name: "AFK_NOTIFY"; readonly description: "Emit a desktop completion notification (OSC 9) on turn completion, for terminals that map OSC 9 to system notifications (iTerm2, kitty, WezTerm). Opt-in and off by default (intrusive). 1 = on. TTY-only."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "misc"; }, { readonly name: "AFK_SHOW_DIFFS"; readonly description: "Show inline diffs in the tool-lane output for edit/write tool calls. 1 = on, 0 = off."; readonly type: "boolean"; readonly required: false; readonly category: "misc"; }, { readonly name: "AFK_TURN_SEPARATOR"; readonly description: "Render a dim horizontal rule between conversation turns in the REPL. 0 = off, unset/1 = on (default). TTY-only: piped/one-shot output (afk chat) never emits the rule."; readonly type: "boolean"; readonly required: false; readonly example: "0"; readonly category: "misc"; }, { readonly name: "AFK_STREAM_BUFFER_MS"; readonly description: "Input buffer window for TUI streaming in milliseconds. When set to a positive value, incoming tokens are micro-batched before parsing and rendering, producing smoother visual output. The first token after idle always passes through immediately (leading-edge). 0 = disabled (every token is parsed individually). Reasonable range: 8-50."; readonly type: "number"; readonly required: false; readonly default: "0"; readonly example: "16"; readonly category: "display"; }, { readonly name: "AFK_SKILL_STREAM_VERBOSE"; readonly description: "Verbose streaming output when a skill is dispatched. Logs sub-agent setup, intermediate events, and final result."; readonly type: "boolean"; readonly required: false; readonly category: "debug"; }, { readonly name: "FORCE_COLOR"; readonly description: "Standard Node convention. Force-enable ANSI color output even when stdout is not a TTY."; readonly type: "string"; readonly required: false; readonly example: "1"; readonly category: "process"; }, { readonly name: "NO_COLOR"; readonly description: "Standard convention (https://no-color.org). When set to any non-empty value, disables ANSI color output."; readonly type: "string"; readonly required: false; readonly example: "1"; readonly category: "process"; }, { readonly name: "AFK_THEME"; readonly description: string; readonly type: "string"; readonly required: false; readonly default: "dark"; readonly example: "light"; readonly category: "misc"; }, { readonly name: "AFK_TEXT_MEASURE"; readonly description: string; readonly type: "string"; readonly required: false; readonly default: "100"; readonly example: "full"; readonly category: "misc"; }, { readonly name: "AFK_PROSE_MEASURE"; readonly description: string; readonly type: "string"; readonly required: false; readonly default: "80"; readonly example: "72"; readonly category: "misc"; }, { readonly name: "COLORFGBG"; readonly description: string; readonly type: "string"; readonly required: false; readonly example: "15;0"; readonly category: "process"; }, { readonly name: "COLORTERM"; readonly description: string; readonly type: "string"; readonly required: false; readonly example: "truecolor"; readonly category: "process"; }, { readonly name: "AFK_DEBUG"; readonly description: "Enable verbose debug logging across the codebase. Accepts 1 to enable."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "AFK_DEBUG_CLIPBOARD"; readonly description: "Debug bracketed-paste and image-paste handling in the interactive REPL."; readonly type: "boolean"; readonly required: false; readonly category: "debug"; }, { readonly name: "AFK_DEBUG_COMPOSITOR"; readonly description: "Gate compositor phase-boundary traces to stderr; any truthy value enables."; readonly type: "boolean"; readonly required: false; readonly category: "debug"; }, { readonly name: "AFK_TRACE_DISABLED"; readonly description: "Disable the agent trace subsystem entirely. Set to 1 to skip trace file writes."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "AFK_WITNESS_RETENTION_DISABLE"; readonly description: "Disable the witness-tree retention sweep entirely, so no session directory is ever evicted."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "AFK_WITNESS_MAX_AGE_DAYS"; readonly description: "Evict a witness session directory once its newest content is older than this many days. Default 30."; readonly type: "number"; readonly required: false; readonly default: "30"; readonly category: "debug"; }, { readonly name: "AFK_WITNESS_MAX_BYTES"; readonly description: "Aggregate byte cap for the witness tree; oldest session directories are evicted first once exceeded. Default 2147483648 (2 GiB)."; readonly type: "number"; readonly required: false; readonly default: "2147483648"; readonly category: "debug"; }, { readonly name: "AFK_SESSION_RETENTION_DISABLE"; readonly description: "Disable the session sidecar retention sweep entirely, so no state/sessions/*.json file is ever evicted."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "AFK_SESSION_MAX_AGE_DAYS"; readonly description: "Evict a session sidecar file once it is older than this many days (based on savedAt). Default 30."; readonly type: "number"; readonly required: false; readonly default: "30"; readonly category: "debug"; }, { readonly name: "AFK_SESSION_MAX_COUNT"; readonly description: "Count-based safety valve: evict oldest session sidecars first once the total exceeds this number. Default 1000."; readonly type: "number"; readonly required: false; readonly default: "1000"; readonly category: "debug"; }, { readonly name: "AFK_WAVE_MANIFEST_DISABLED"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly default: "0"; readonly example: "1"; readonly category: "misc"; }, { readonly name: "AFK_WAVE_MANIFEST_TTL_HOURS"; readonly description: string; readonly type: "number"; readonly required: false; readonly default: "48"; readonly example: "24"; readonly category: "misc"; }, { readonly name: "AFK_WAVE_RESUME_UNATTENDED"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly default: "0"; readonly example: "1"; readonly category: "misc"; }, { readonly name: "AFK_SESSION_LEDGER_DISABLED"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "AFK_RUN_RECEIPT_DISABLED"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "AFK_CAPTURE_SUBAGENT_PROMPTS"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "AFK_CAPTURE_SUBAGENT_OUTPUT"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "AFK_SUBAGENT_RESULT_CAP_BYTES"; readonly description: string; readonly type: "number"; readonly required: false; readonly default: "32768"; readonly example: "16384"; readonly category: "model"; }, { readonly name: "AFK_SUBAGENT_LOG"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "DEBUG"; readonly description: "Standard Node `debug`-package convention. When set to 1, enables verbose logging in several modules alongside AFK_DEBUG."; readonly type: "string"; readonly required: false; readonly category: "debug"; }, { readonly name: "AGENT_AFK_ASCII"; readonly description: "Force the interactive REPL tool-lane renderer to ASCII-only glyphs instead of the default Unicode box-drawing set. Accepts 1/true/yes (case-insensitive). Useful for terminals whose font lacks ┃├╰├ glyphs."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "debug"; }, { readonly name: "AGENT_SURFACE"; readonly description: string; readonly type: "string"; readonly required: false; readonly default: "afk"; readonly example: "afk"; readonly category: "process"; }, { readonly name: "CI"; readonly description: "Standard CI-detection convention. Auto-set by GitHub Actions, CircleCI, etc. Used to switch off TTY-only UX."; readonly type: "string"; readonly required: false; readonly example: "true"; readonly category: "process"; }, { readonly name: "NODE_ENV"; readonly description: "Standard Node environment marker. test | development | production. Used by routing-telemetry.ts to suppress test-time writes."; readonly type: "string"; readonly required: false; readonly example: "production"; readonly category: "process"; }, { readonly name: "VITEST"; readonly description: "Set automatically by Vitest. Used at runtime to short-circuit code paths that should not fire in tests."; readonly type: "string"; readonly required: false; readonly category: "process"; }, { readonly name: "NO_UPDATE_NOTIFIER"; readonly description: "Disable the update-available notifier on CLI startup. Standard convention shared with many Node CLIs."; readonly type: "boolean"; readonly required: false; readonly category: "process"; }, { readonly name: "AFK_BROWSER_HEADLESS"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "browser"; }, { readonly name: "AFK_BROWSER_ALLOWED_DOMAINS"; readonly description: string; readonly type: "string"; readonly required: false; readonly example: "github.com,*.atlassian.net"; readonly category: "browser"; }, { readonly name: "AFK_BROWSER_BLOCKED_DOMAINS"; readonly description: string; readonly type: "string"; readonly required: false; readonly example: "*.ads.example.com"; readonly category: "browser"; }, { readonly name: "AFK_BROWSER_DOM_SNAPSHOTS"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "browser"; }, { readonly name: "AFK_BROWSER_BACKEND"; readonly description: string; readonly type: "string"; readonly required: false; readonly default: "auto"; readonly example: "agent-browser"; readonly category: "browser"; }, { readonly name: "AFK_BROWSER_CONFIG"; readonly description: string; readonly type: "string"; readonly required: false; readonly example: "/path/to/browser.json"; readonly category: "browser"; }, { readonly name: "AFK_BROWSER_DEFAULT_PROFILE"; readonly description: string; readonly type: "string"; readonly required: false; readonly example: "work"; readonly category: "browser"; }, { readonly name: "AFK_WRITE_DENYLIST"; readonly description: "Comma-separated list of additional path globs that the write_file tool refuses to write to."; readonly type: "string"; readonly required: false; readonly example: "**/.env,**/secrets/**"; readonly category: "misc"; }, { readonly name: "AFK_READ_DENYLIST"; readonly description: "Colon-separated list of additional absolute paths the read_file/grep/glob/list_directory tools refuse to read, and that the bash-restriction hook refuses to let a shell command reference on interactive surfaces (REPL, Telegram) — on headless surfaces (afk chat, daemon) bash fails open regardless of this list. A leading ~/ is expanded (~user/ is not — spell those absolutely). Built-in credential entries (~/.ssh, ~/.aws, ~/.afk/config, …) always apply on top and cannot be removed. One built-in exception exists: ~/.afk/config/mcp.json (the MCP registry) IS readable — paths listed here outrank that carve-out, so set this to ~/.afk/config/mcp.json if your registry holds inline secrets rather than ${VAR} placeholders."; readonly type: "string"; readonly required: false; readonly example: "/Users/me/project/.env:/Users/me/secrets"; readonly category: "misc"; }, { readonly name: "AFK_WRITE_DIFF"; readonly description: "Show a diff preview before each write_file tool call. Defaults provider-controlled when unset."; readonly type: "boolean"; readonly required: false; readonly category: "misc"; }, { readonly name: "AFK_RATE_LIMIT_ADMISSION_DISABLED"; readonly description: "Bypass the process-wide rate-limit admission gate (issue #941). Set to 1 to skip pre-request capacity checks. Default 0 (gate active). OAuth subscription accounts already pass through automatically when no per-minute headers are returned."; readonly type: "boolean"; readonly required: false; readonly default: "0"; readonly example: "1"; readonly category: "model"; }, { readonly name: "AFK_RATE_LIMIT_STAGGER_MAX_MS"; readonly description: "Jitter ceiling (ms) for the rate-limit admission bucket: each waiter at a window boundary wakes at reset + random(0..ceiling) to avoid re-storming the API. Default 500. Set to 0 in tests for deterministic timing."; readonly type: "number"; readonly required: false; readonly default: "500"; readonly example: "0"; readonly category: "model"; }, { readonly name: "AFK_WEB_ALLOW_PRIVATE_HOSTS"; readonly description: string; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "misc"; }, { readonly name: "AFK_DEMO_CLEAN"; readonly description: "Explicit opt-in to capture-mode. When set to 1, suppresses high-frequency repaint drivers (spinner ticker, live thinking-preview) so recorded artifacts contain each state once instead of once per timer tick."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "misc"; }, { readonly name: "SCRIPT"; readonly description: "Set by script(1) on BSD/macOS/Linux to the typescript filename while a terminal session is being recorded. Presence of a non-empty value triggers capture-mode."; readonly type: "string"; readonly required: false; readonly example: "/tmp/typescript"; readonly category: "process"; }, { readonly name: "ASCIINEMA_REC"; readonly description: "Set to 1 by asciinema rec while a session is being recorded. Triggers capture-mode."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "process"; }, { readonly name: "AFK_SESSION_ID"; readonly description: string; readonly type: "string"; readonly required: false; readonly default: "default"; readonly example: "session-abc123"; readonly category: "browser"; }, { readonly name: "SHELL"; readonly description: "Standard POSIX env var pointing to the user's login shell binary. Used by shell-init and worktree commands to auto-detect the correct shell syntax for emitted wrapper code."; readonly type: "string"; readonly required: false; readonly example: "/bin/zsh"; readonly category: "process"; }, { readonly name: "PAGER"; readonly description: "Standard POSIX env var naming the user's preferred pager (with optional flags). Used by /transcript to render the full session in a scrollable viewer; falls back to `less -R` when unset."; readonly type: "string"; readonly required: false; readonly example: "less -R"; readonly category: "process"; }, { readonly name: "VISUAL"; readonly description: "Standard POSIX env var naming the user's preferred full-screen editor (with optional flags). Consulted FIRST by the /editor slash command (and its key chord) to compose a long prompt externally; takes precedence over EDITOR. No fallback editor is assumed — if neither VISUAL nor EDITOR is set, /editor prints a hint instead of guessing."; readonly type: "string"; readonly required: false; readonly example: "nvim"; readonly category: "process"; }, { readonly name: "EDITOR"; readonly description: "Standard POSIX env var naming the user's preferred editor (with optional flags). Consulted by the /editor slash command AFTER VISUAL, as the standard fallback. No default editor is assumed when both are unset — /editor prints a hint telling the user to set one."; readonly type: "string"; readonly required: false; readonly example: "vim"; readonly category: "process"; }, { readonly name: "AFK_DIFF_LINES"; readonly description: "Maximum number of diff lines shown in the inline diff render during write_file tool calls. Set to 0 for no cap. Non-integer values are silently ignored and the default applies."; readonly type: "number"; readonly required: false; readonly example: "50"; readonly category: "misc"; }, { readonly name: "AFK_SHELL_WRAPPER"; readonly description: "Set to 1 or true by the optional afk shell wrapper function (installed via `afk shell-init`). Signals that the parent shell has the wrapper active so the post-exit cd can fire."; readonly type: "boolean"; readonly required: false; readonly example: "1"; readonly category: "process"; }, { readonly name: "AFK_USER_CARD_MAX_ROWS"; readonly description: "Maximum number of visual rows emitted by renderUserCard before collapsing the remainder into a dim \"…(N lines collapsed)\" summary row. Defaults to 24. Non-integer or non-positive values are silently ignored and the default applies."; readonly type: "number"; readonly required: false; readonly example: "24"; readonly category: "misc"; }, { readonly name: "AFK_LEASE_TTL_MS"; readonly description: string; readonly type: "number"; readonly required: false; readonly example: "600000"; readonly category: "misc"; }]; export type EnvObject = { readonly [K in (typeof ENV_REGISTRY)[number]['name']]: string | undefined; }; export declare const env: EnvObject; export declare function isPlainOutputRequested(): boolean; export type EnvVarName = keyof EnvObject; export { getEnvVarMeta, getMissingRequiredEnvVars, isEnvVarSet, getEnvVarValue, isExplicitlyDisabled, isExplicitlyEnabled, } from './env-helpers.js';