Skip to content

Latest commit

 

History

History
620 lines (471 loc) · 66.1 KB

environment-variables.md

File metadata and controls

620 lines (471 loc) · 66.1 KB

Environment Variables (Current Runtime Reference)

This reference is derived from current code paths in:

  • packages/coding-agent/src/**
  • packages/ai/src/** (provider/auth resolution used by coding-agent)
  • packages/utils/src/** and packages/tui/src/** where those vars directly affect coding-agent runtime

It documents only active behavior.

Resolution model and precedence

Most runtime lookups use $env from @gajae-code/utils (packages/utils/src/env.ts).

$env loading order:

  1. Existing process environment (Bun.env)
  2. Project .env ($PWD/.env) for keys not already set
  3. Agent .env (~/.gjc/agent/.env, respecting GJC_CONFIG_DIR / GJC_CODING_AGENT_DIR) for keys not already set
  4. Config-root .env (~/.gjc/.env, respecting GJC_CONFIG_DIR) for keys not already set
  5. Home .env (~/.env) for keys not already set
  6. Login shell rc files (~/.zshenv, ~/.zprofile, ~/.zshrc, ~/.bash_profile, ~/.bashrc) for keys not already set

Step 6 does not execute those files. Each is scanned line by line for literal export NAME=value or NAME=value assignments, and surrounding quotes are stripped. Values that are not literal are dropped rather than resolved: a command substitution such as export FOO=$(...) is discarded.

Because the scan is per line and has no notion of shell block structure, it does not reflect whether an assignment would actually run. An assignment nested in an if or a function body is read exactly like a top-level one, so a value you guarded behind something like if [ -n "$CI" ] in ~/.zshrc still reaches $env unconditionally. Only assignments that do not start their own line — for example one packed after case ... in on the same line — are missed.

Keys are used exactly as written. A PI_-prefixed key in a .env file is not mirrored to its GJC_ counterpart, or the reverse — where both spellings are accepted it is because the reading code asks for both names.


1) Model/provider authentication

These are consumed via getEnvApiKey() (packages/ai/src/stream.ts) unless noted otherwise.

Core provider credentials

Variable Used for Required when Notes / precedence
ANTHROPIC_OAUTH_TOKEN Anthropic API auth Using Anthropic with OAuth token auth Takes precedence over ANTHROPIC_API_KEY for provider auth resolution
ANTHROPIC_API_KEY Anthropic API auth Using Anthropic without OAuth token Fallback after ANTHROPIC_OAUTH_TOKEN
ANTHROPIC_FOUNDRY_API_KEY Anthropic via Azure Foundry / enterprise gateway CLAUDE_CODE_USE_FOUNDRY enabled Takes precedence over ANTHROPIC_OAUTH_TOKEN and ANTHROPIC_API_KEY when Foundry mode is enabled
OPENAI_API_KEY OpenAI auth Using OpenAI-family providers without explicit apiKey argument Used by OpenAI Completions/Responses providers
GEMINI_API_KEY Google Gemini auth Using google provider models Primary key for Gemini provider mapping
GOOGLE_API_KEY Gemini image tool auth fallback Using gemini_image tool without GEMINI_API_KEY Used by coding-agent image tool fallback path
GROQ_API_KEY Groq auth Using Groq models
CEREBRAS_API_KEY Cerebras auth Using Cerebras models
DEEPINFRA_API_KEY DeepInfra auth Using deepinfra provider OpenAI-compatible Chat Completions endpoint; use serviceTier: priority for DeepInfra priority inference
FIREWORKS_API_KEY Fireworks auth Using Fireworks models
TOGETHER_API_KEY Together auth Using together provider
HUGGINGFACE_HUB_TOKEN Hugging Face auth Using huggingface provider Primary Hugging Face token env var
HF_TOKEN Hugging Face auth Using huggingface provider Fallback when HUGGINGFACE_HUB_TOKEN is unset
SYNTHETIC_API_KEY Synthetic auth Using Synthetic models
NVIDIA_API_KEY NVIDIA auth Using nvidia provider
NANO_GPT_API_KEY NanoGPT auth Using nanogpt provider
VENICE_API_KEY Venice auth Using venice provider
LITELLM_API_KEY LiteLLM auth Using litellm provider OpenAI-compatible LiteLLM proxy key
LM_STUDIO_API_KEY LM Studio auth (optional) Using lm-studio provider with authenticated hosts Local LM Studio usually runs without auth; any non-empty token works when a key is required
OLLAMA_API_KEY Ollama auth (optional) Using ollama provider with authenticated hosts Local Ollama usually runs without auth; any non-empty token works when a key is required
LLAMA_CPP_API_KEY llama.cpp auth (optional) Using llama.cpp provider with authenticated hosts Local llama.cpp usually runs without auth; any non-empty token works when a key is configured
XIAOMI_API_KEY Xiaomi MiMo auth Using xiaomi provider
MOONSHOT_API_KEY Moonshot auth Using moonshot provider
XAI_API_KEY xAI auth Using xAI models
OPENROUTER_API_KEY OpenRouter auth Using OpenRouter models Also used by image tool when preferred/auto provider is OpenRouter
MISTRAL_API_KEY Mistral auth Using Mistral models
ZAI_API_KEY z.ai auth Using z.ai models Also used by z.ai web search provider
JUNIE_API_KEY JetBrains AI (Junie) auth Using jetbrains-junie models Access token from junie.jetbrains.com/cli; sent as Authorization: Bearer
MINIMAX_API_KEY MiniMax auth Using minimax provider
AZURE_OPENAI_API_KEY Azure OpenAI auth Using azure-openai / azure-openai-responses models Pair with AZURE_OPENAI_BASE_URL or AZURE_OPENAI_RESOURCE_NAME
MINIMAX_CODE_API_KEY MiniMax Code auth Using minimax-code provider
MINIMAX_CODE_CN_API_KEY MiniMax Code CN auth Using minimax-code-cn provider
OPENCODE_API_KEY OpenCode auth Using opencode-go / opencode-zen models
QIANFAN_API_KEY Qianfan auth Using qianfan provider
QWEN_OAUTH_TOKEN Qwen Portal auth Using qwen-portal with OAuth token Takes precedence over QWEN_PORTAL_API_KEY
QWEN_PORTAL_API_KEY Qwen Portal auth Using qwen-portal with API key Fallback after QWEN_OAUTH_TOKEN
ZENMUX_API_KEY ZenMux auth Using zenmux provider Used for ZenMux OpenAI and Anthropic-compatible routes
OPENGATEWAY_API_KEY OpenGateway (by Sionic AI) auth Using opengateway provider OpenAI-compatible gateway; models discovered via /v1/models
BIZROUTER_API_KEY BizRouter auth Using bizrouter provider Korean enterprise LLM gateway; OpenAI-compatible, models discovered via /v1/models
MARA_API_KEY Mara Cloud auth Using mara provider OpenAI-compatible enterprise inference platform; models discovered via /v1/models
VLLM_API_KEY vLLM auth/discovery opt-in Using vllm provider (local OpenAI-compatible servers) Any non-empty value works for no-auth local servers
CURSOR_ACCESS_TOKEN Cursor provider auth Using Cursor provider
AI_GATEWAY_API_KEY Vercel AI Gateway auth Using vercel-ai-gateway provider
CLOUDFLARE_AI_GATEWAY_API_KEY Cloudflare AI Gateway auth Using cloudflare-ai-gateway provider Base URL must be configured as https://gateway.ai.cloudflare.com/v1/<account>/<gateway>/anthropic
ALIBABA_TOKEN_PLAN_API_KEY Alibaba Token Plan auth Using alibaba-token-plan provider
CLINE_API_KEY Cline API / ClinePass auth Using the cline-pass provider preset Create under Settings > API Keys in the Cline dashboard
CMD_API_KEY Command Code Provider API auth Using the commandcode-goat provider preset The GOAT coding plan may use this API according to its plan entitlement
DEEPSEEK_API_KEY DeepSeek auth Using DeepSeek models
KILO_API_KEY Kilo auth Using Kilo models
OLLAMA_CLOUD_API_KEY Ollama Cloud auth Using ollama-cloud provider
GITLAB_TOKEN GitLab Duo auth Using gitlab-duo provider

GitHub/Copilot token chains

Variable Used for Chain
COPILOT_GITHUB_TOKEN GitHub Copilot provider auth COPILOT_GITHUB_TOKEN → GH_TOKEN → GITHUB_TOKEN
GH_TOKEN Copilot fallback; GitHub API auth in web scraper In web scraper: GITHUB_TOKEN → GH_TOKEN
GITHUB_TOKEN Copilot fallback; GitHub API auth in web scraper In web scraper: checked before GH_TOKEN

Auth broker / auth gateway (remote credential vault)

When the broker is enabled, the local SQLite credential store is bypassed and all OAuth refresh / access tokens live on the broker host. See auth-broker-gateway.md for the full protocol, CLI surface, and 5-min/15-s usage cache layering.

Variable Used for Required when Notes / precedence
GJC_AUTH_BROKER_URL Base URL of the remote auth-broker (e.g. https://broker.tailnet:8765); selects broker mode Resolving credentials through a broker; also required by gjc auth-gateway serve (the gateway is itself a broker client) Wins over auth.broker.url in config.yml. When set with no resolvable token, resolveAuthBrokerConfig() hard-errors instead of falling back to local SQLite.
GJC_AUTH_BROKER_TOKEN Bearer token sent on every broker endpoint except /v1/healthz GJC_AUTH_BROKER_URL is set and no token is available from auth.broker.token or <config-dir>/auth-broker.token Resolution: this env → auth.broker.token ($ENV_NAME indirection supported) → <config-dir>/auth-broker.token (mode 0600). <config-dir> is ~/.gjc/ (respecting GJC_CONFIG_DIR).

The gateway has no dedicated env vars — it inherits GJC_AUTH_BROKER_*. Its own inbound bearer token lives at <config-dir>/auth-gateway.token and is managed via gjc auth-gateway token.

Multi-account credential ranking

When more than one OAuth credential is stored for the same provider (e.g. several Anthropic accounts), AuthStorage ranks them at session start to pick which one serves the session. This env var selects the ranking strategy; it is fully opt-in and does not change the default.

Variable Used for Required when Notes / precedence
GJC_CREDENTIAL_RANKING_MODE Multi-account OAuth credential selection strategy Never (opt-in) balanced (default) prefers the least-drained account (spreads load, keeps burst headroom). earliest-reset prefers the soonest-to-reset non-blocked account (earliest-expiry-first) so perishable tumbling-window quota (e.g. Claude 5h/7d) is drained before reset. Unset/unknown → balanced. Only affects session-start ranking; blocked/exhausted accounts still sort last.

External CLI credential import roots

gjc setup credentials, the TUI "import existing credentials" action, and the startup auto-import discover Claude Code and Codex CLI credentials on disk. Both CLIs relocate their own config root through the environment, so gjc follows the same variables instead of assuming the home-directory default. This is what makes an account selected by an external account switcher (which launches the shell with these variables set) the account gjc imports.

Variable Used for Required when Notes / precedence
CLAUDE_CONFIG_DIR Directory holding Claude Code's .credentials.json Claude Code's config root is not ~/.claude Read through $credentialEnv (project .env cannot redirect it). Must be absolute; relative or blank values fall back to ~/.claude.
CODEX_HOME Directory holding Codex CLI's auth.json Codex CLI's home is not ~/.codex Read through $credentialEnv (project .env cannot redirect it). Must be absolute; relative or blank values fall back to ~/.codex.

Redacted summaries name the variable (Claude Code ($CLAUDE_CONFIG_DIR/.credentials.json)), never the resolved path. macOS Keychain discovery is unaffected: it is still only consulted when no credential file is found.


2) Provider-specific runtime configuration

Anthropic Foundry Gateway (Azure / enterprise proxy)

When CLAUDE_CODE_USE_FOUNDRY is enabled, Anthropic requests switch to Foundry mode:

  • Base URL resolves from FOUNDRY_BASE_URL (fallback remains model/default base URL if unset).
  • API key resolution for provider anthropic becomes: ANTHROPIC_FOUNDRY_API_KEY → ANTHROPIC_OAUTH_TOKEN → ANTHROPIC_API_KEY.
  • ANTHROPIC_CUSTOM_HEADERS is parsed as comma/newline-separated key: value pairs and merged into request headers.
  • TLS client/server material can be injected from env values: NODE_EXTRA_CA_CERTS, CLAUDE_CODE_CLIENT_CERT, CLAUDE_CODE_CLIENT_KEY. Each accepts either:
    • a filesystem path to PEM content, or
    • inline PEM (including escaped \n sequences).
Variable Value type Behavior
CLAUDE_CODE_USE_FOUNDRY Boolean-like string (1, true, yes, on) Enables Foundry mode for Anthropic provider
FOUNDRY_BASE_URL URL string Anthropic endpoint base URL in Foundry mode
ANTHROPIC_FOUNDRY_API_KEY Token string Used for Authorization: Bearer <token>
ANTHROPIC_CUSTOM_HEADERS Header list string Extra headers; format header-a: value, header-b: value or newline-separated
NODE_EXTRA_CA_CERTS PEM path or inline PEM Extra CA chain for server certificate validation
CLAUDE_CODE_CLIENT_CERT PEM path or inline PEM mTLS client certificate
CLAUDE_CODE_CLIENT_KEY PEM path or inline PEM mTLS client private key (must be paired with cert)

Amazon Bedrock

Variable Default / behavior
AWS_REGION Primary region source
AWS_DEFAULT_REGION Fallback if AWS_REGION is unset
AWS_BEARER_TOKEN_BEDROCK Uses bearer-token authentication (Authorization: Bearer <token>) instead of SigV4
AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY + optional AWS_SESSION_TOKEN Static environment credentials for SigV4 authentication
AWS_PROFILE Selects a named ~/.aws/credentials / ~/.aws/config profile; static, SSO, and credential_process profiles are supported
AWS_SHARED_CREDENTIALS_FILE / AWS_CONFIG_FILE Override the named profile credentials and config file paths
AWS_EC2_METADATA_DISABLED Set to true to disable the final EC2 IMDSv2 credential fallback
AWS_BEDROCK_SKIP_AUTH Truthy values (1, y, true, yes, or on, case-insensitive) use dummy SigV4 credentials for non-auth proxy scenarios
HTTPS_PROXY Honored by Bun's native HTTPS proxy support

Region fallback in provider code: options.region → AWS_REGION → AWS_DEFAULT_REGION → us-east-1.

Authentication uses AWS_BEARER_TOKEN_BEDROCK when set; otherwise credential fallback order is complete static environment credentials, the selected named profile (static, SSO, or credential_process), then EC2 IMDSv2 unless AWS_EC2_METADATA_DISABLED=true. Region and IMDS controls use the normal merged environment, including project cwd/.env; bearer tokens, static credentials, profiles, and credential file selectors use the credential environment, so project cwd/.env credential values are excluded. ECS task credentials and IRSA/web-identity credentials are not implemented. models.yml Bedrock entries use api: bedrock-converse-stream and do not require apiKey or apiKeyEnv because the provider authenticates through this AWS chain.

Azure OpenAI Responses

Variable Default / behavior
AZURE_OPENAI_API_KEY Required unless API key passed as option
AZURE_OPENAI_API_VERSION Default v1
AZURE_OPENAI_BASE_URL Direct base URL override
AZURE_OPENAI_RESOURCE_NAME Used to construct base URL: https://<resource>.openai.azure.com/openai/v1
AZURE_OPENAI_DEPLOYMENT_NAME_MAP Optional mapping string: modelId=deploymentName,model2=deployment2

Base URL resolution: option azureBaseUrl → env AZURE_OPENAI_BASE_URL → option/env resource name → model.baseUrl.

Model provider base URL overrides

Built-in model provider base URLs resolve with this precedence:

  1. models.yml / model config provider baseUrl
  2. provider-specific base URL environment variable
  3. bundled provider default

Supported aliases:

Provider Variables
OpenAI OPENAI_BASE_URL
Anthropic ANTHROPIC_BASE_URL
Google Gemini GOOGLE_BASE_URL, GEMINI_BASE_URL
Google Antigravity GOOGLE_ANTIGRAVITY_BASE_URL, then GOOGLE_BASE_URL, then GEMINI_BASE_URL
Google Gemini CLI GOOGLE_GEMINI_CLI_BASE_URL, then GOOGLE_BASE_URL, then GEMINI_BASE_URL
Google Vertex GOOGLE_VERTEX_BASE_URL, then GOOGLE_BASE_URL, then GEMINI_BASE_URL
Any provider id derived <PROVIDER_ID>_BASE_URL, uppercased with non-alphanumerics converted to _ (for example my-proxy → MY_PROXY_BASE_URL)

OpenAI-compatible proxy note: the built-in openai provider keeps its bundled API transport (openai-responses). Setting OPENAI_BASE_URL changes the host but still calls <baseUrl>/responses. If your proxy only supports Chat Completions, configure a custom models.yml provider with api: openai-completions instead of using the built-in OpenAI provider override:

providers:
  openai-compatible:
    baseUrl: https://proxy.example.com/v1
    apiKey: OPENAI_API_KEY
    api: openai-completions
    models:
      - id: gpt-4o
        name: GPT-4o via proxy
        api: openai-completions

For OpenRouter traffic, GJC explicitly sends User-Agent: Gajae-Code/<package version> plus OpenRouter attribution headers. For the built-in OpenAI Responses transport and generic OpenAI-compatible Chat Completions transport, GJC passes model/provider headers through the OpenAI JavaScript SDK and does not set a GJC user-agent unless the provider-specific code adds one.

OpenAI-compatible proxy provider config

For OpenAI-compatible proxies that only implement Chat Completions, prefer a custom models.yml provider over OPENAI_BASE_URL:

providers:
  openai-compatible:
    baseUrl: https://proxy.example.com/v1
    apiKeyEnv: OPENAI_API_KEY
    api: openai-completions
    auth: apiKey
    headers:
      User-Agent: curl/8.7.1
    models:
      - id: gpt-4o
        name: GPT-4o via proxy
        reasoning: false
        input: [text]
        cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }

models.yml is strict: unsupported provider/model keys fail validation before the provider request is dispatched.

GJC workflow bridge commands

gjc ralplan, gjc deep-interview, and gjc state are private runtime bridge commands. They require GJC_RUNTIME_BINARY (or legacy GJC_LEGACY_RUNTIME_BINARY) to point at the private runtime executable; public bundled workflow use remains through /skill:ralplan and /skill:deep-interview inside a GJC session.

Variable Behavior
GJC_RUNTIME_BINARY Private runtime bridge binary for gjc ralplan, gjc deep-interview, and gjc state
GJC_LEGACY_RUNTIME_BINARY Legacy fallback bridge binary name

Interactive --tmux startup and scroll/mouse profile

gjc --tmux launches the interactive TUI inside a fresh GJC-managed tmux session. Plain gjc --tmux does not auto-attach a scoped managed session from the same project/branch; use gjc --tmux --continue or gjc session attach <session> when you intend to continue existing tmux context. gjc --tmux --resume still reaches the inner GJC session resolver, so value-less resume shows the session picker and --resume <id> honors that target instead of reusing a branch tmux session. Older-version sessions are not auto-attached after upgrades. When GJC creates a session it applies a profile that is scoped to the GJC session only (it never runs set -g / global tmux options), including:

  • mouse on — enables tmux copy-mode scrolling when GJC mouse support is disabled.
  • set-clipboard on and a readable copy-mode mode-style.
  • GJC ownership/identity tags (@gjc-profile, version, branch/project markers).

This profile is applied on macOS, Linux, WSL (Linux), and native Windows when a compatible tmux provider is available. It is applied only to sessions GJC itself creates. If you start tmux yourself and then run gjc inside it, GJC leaves your tmux configuration untouched. GJC's own mouse support is disabled by default, so the host terminal or tmux retains wheel and selection behavior. Add set -g mouse on to your own ~/.tmux.conf when you want tmux copy-mode scrolling.

Set mouse.enabled: true to let GJC capture the wheel for virtual session scrolling (three rows per notch, not a full page). When GJC owns mouse input, dragging across rendered text highlights the selection and copies it to the system clipboard on release.

Variable Behavior
GJC_LAUNCH_POLICY Launch policy for --tmux startup: tmux (default) or direct (skip the tmux session)
GJC_TMUX_SESSION Explicit tmux session name override for --tmux startup. Use a unique value (for example GJC_TMUX_SESSION=gjc-fresh-$(date +%s) gjc --tmux) to force a fresh named session.
GJC_TMUX_COMMAND tmux binary/name override for every GJC tmux flow (GJC_TEAM_TMUX_COMMAND is honored as a team-path alias). This is not a shell command line; include only the executable path/name, not flags.
GJC_TMUX_PROFILE Set 0/false/off to apply only the required ownership tags and skip the scroll/mouse/clipboard profile
GJC_MOUSE Set 0/false/off to skip the managed profile's tmux mouse on; this does not disable GJC's own mouse support
GJC_PSMUX_COMMAND Identifies a psmux wrapper for Windows alias resolution. The value must resolve to the same executable identity as the selected tmux command; unresolved or conflicting evidence fails closed.
GJC_PSMUX_DETECTION Set 0/false/off to skip banner-based psmux detection. Executable-name and alias-identity safety checks still apply.
GJC_PSMUX_FORCE_DETECT Set 1/true/on to re-probe the multiplexer on every call instead of caching the per-process verdict.

Windows psmux detection boundary

On native Windows, psmux may be installed as psmux.exe, pmux.exe, or a tmux.exe alias. The alias can report only a generic tmux 3.3.6 banner, so GJC compares the selected tmux.exe executable identity with resolved psmux.exe / pmux.exe companions. A matching identity is classified as psmux; distinct identities preserve native-tmux semantics.

If the selected command, an explicit GJC_PSMUX_COMMAND, or a resolved companion cannot be identified consistently, GJC reports gjc_tmux_provider_ambiguous and refuses before applying native-tmux target or mutation semantics. Correct PATH, set GJC_TMUX_COMMAND to a verified executable, or make GJC_PSMUX_COMMAND resolve to the same wrapper identity.

GJC-managed Windows psmux flows persist a ProviderAuthority for each owner generation. It binds the resolved absolute executable's identity and GJC's isolated server namespace; a missing, changed, or ambiguous identity fails closed. GJC recovery reads and re-proves that persisted authority rather than using an ambient multiplexer.

Windows psmux namespace boundary

psmux follows tmux-style server semantics: new-session -c <path>, new-window -c <path>, and GJC's gjc --tmux cwd only choose the start directory for the session/window/pane. They do not create a per-project server namespace. For a managed Windows psmux owner, GJC creates and persists an isolated namespace and invokes the bound executable with -L <namespace> on every operation.

GJC does not expose a GJC_TMUX_NAMESPACE runtime knob or parse flags from GJC_TMUX_COMMAND. Do not set GJC_TMUX_COMMAND="psmux -L my-project" and do not recover with ambient tmux/psmux or a manually supplied -L value; GJC_TMUX_COMMAND is one executable path/name. Use the GJC session or lifecycle operation so it reuses the persisted ProviderAuthority. If that authority cannot be read and re-proved, GJC refuses the operation.

WSL / Windows Terminal scrolling

GJC's SGR mouse support is disabled by default, so tmux or Windows Terminal retains wheel ownership. In a GJC-managed tmux session, the default profile's mouse on enters tmux copy-mode and scrolls pane history.

Set mouse.enabled: true to make the wheel scroll GJC's virtual session viewport three rows at a time, including inside gjc --tmux. PageUp/PageDown page the visible transcript lane, moving by its height minus one row. Set GJC_MOUSE=off as well as leaving GJC mouse support disabled to skip tmux mouse capture and let Windows Terminal handle its native scrollback. Keyboard fallback for tmux copy-mode remains Ctrl-b [, followed by PgUp/arrows; press q to exit.

Team tmux backend, dry-run, and state paths

gjc team ... starts tmux worker panes from the current tmux-backed leader session. Start that leader with gjc --tmux first; gjc team intentionally does not create or attach the leader session itself.

gjc team ... --dry-run --json creates the same machine-readable state tree as a team launch without starting tmux panes. By default that state is written under <cwd>/.gjc/state/team/<team>/; treat it as ephemeral smoke-test/review state. Do not commit generated .gjc/state/team contents. Remove the generated team directory after a dry-run when the harness no longer needs it.

Variable Behavior
GJC_TEAM_STATE_ROOT Overrides the team state root (default <cwd>/.gjc/state/team)
GJC_TEAM_TMUX_COMMAND tmux binary/command override for team launch
GJC_TEAM_WORKER_COMMAND Worker GJC command override
GJC_TEAM_WORKER_CLI Team worker CLI selector; accepted values are auto or gjc
GJC_TEAM_WORKER_CLI_MAP Comma-separated worker CLI selector map; entries must be auto or gjc
GJC_TEAM_AUTO_CONTINUE_STALLED_WORKERS Default-off stalled-worker continuation for the mutating gjc team monitor path; only exact value 1 enables it. A nudge is fenced to a running non-dry-run team, stale heartbeat, live recorded non-leader pane in the recorded tmux target, a proven-absent shutdown authority record, ready/working lifecycle with a valid non-terminal worker status, one current matching in-progress claim, and a lease that covers the hold. Valid-present or invalid/unreadable shutdown authority vetoes continuation but does not suppress normal stale-claim recovery. It uses at most two immutable journaled attempts (30s, then 120s) and fails closed on restart/unknown outcome. It sends a fixed prompt only to that pane on verified native tmux transport; psmux and native Windows send-keys fallback transports record a skipped outcome and send no continuation input. It does not replay providers, inspect/inject dynamic pane content or cross panes, kill/relaunch/split workers, or alter claims.
GJC_TEAM_HEARTBEAT_STALE_MS Stale-heartbeat threshold in milliseconds. Defaults to 120000; a non-numeric value falls back to that default, a positive value below 3 is clamped to 3, and a non-positive value disables stale-heartbeat detection (and with it the worker's own heartbeat publishing). A GJC worker session publishes a runtime-owned heartbeat every third of this window (minimum 1ms, capped at 30s) while an agent turn or owned background job is active, and gjc team exports the configured value into worker panes, which do not inherit the launching shell's environment.

Hermes MCP bridge

gjc mcp-serve coordinator exposes a GJC-native outward MCP bridge for Hermes-style coordinators. gjc mcp-serve hermes is a compatibility alias for the same bridge. The bridge is read-only by default and fails closed until roots and mutation classes are explicitly configured.

Coordinator MCP currently exposes durable polling/await tools, not push subscriptions. Consume gjc_coordinator_read_coordination_status, gjc_coordinator_read_turn, or bounded gjc_coordinator_await_turn for state changes.

Variable Behavior
GJC_COORDINATOR_MCP_WORKDIR_ROOTS Required allowlist for workdir and artifact paths. gjc setup hermes renders absolute normalized paths joined with the platform path delimiter (: on POSIX, ; on Windows). The bridge parser also accepts commas, semicolons, and newlines for legacy manual configs.
GJC_COORDINATOR_MCP_MUTATIONS Enables mutating tool classes as a comma-separated list (sessions, questions, reports) or all. sessions covers session startup, prompt delivery, durable turn journal updates, queue, and force operations. Per-call allow_mutation: true is still required.
GJC_COORDINATOR_MCP_ARTIFACT_BYTE_CAP Max bytes returned by artifact reads (default 65536, capped at 1048576).
GJC_COORDINATOR_MCP_STATE_ROOT Bridge coordination state root (default <cwd>/.gjc/state/coordinator-mcp).
GJC_COORDINATOR_MCP_PROFILE Optional profile namespace for session/question/report state. Missing scope never widens to global session enumeration.
GJC_COORDINATOR_MCP_REPO Optional repo namespace for session/question/report state. Missing scope never widens to global session enumeration.
GJC_COORDINATOR_MCP_SESSION_COMMAND Optional typed SDK lifecycle selector, never a shell command that the coordinator executes. The only supported values are exactly gjc and gjc --worktree [name]; the latter optionally selects the GJC-managed worktree name. Wrapper binaries, shell syntax, model/provider flags, tmux flags, and other legacy command shapes fail closed before session creation. gjc setup hermes renders gjc --worktree by default. When omitted, SDK lifecycle creation still uses the requested coordinator workdir; no coordinator-owned tmux startup or prompt injection is performed.
GJC_COORDINATOR_MCP_SETUP_MANAGED_BY Marker written by gjc setup hermes for safe managed config updates.
GJC_COORDINATOR_MCP_SETUP_SCHEMA_VERSION Managed setup schema version written by gjc setup hermes.
GJC_COORDINATOR_MCP_SETUP_SIGNATURE Deterministic managed setup signature used to detect safe updates versus unmanaged conflicts.

Google Vertex AI

Variable Required? Notes
GOOGLE_CLOUD_PROJECT Yes (unless passed in options) Fallback: GCLOUD_PROJECT
GCLOUD_PROJECT Fallback Used as alternate project ID source
GOOGLE_CLOUD_PROJECT_ID OAuth login helper only Used by Gemini CLI OAuth project discovery
GOOGLE_CLOUD_LOCATION Yes (unless passed in options) No default in provider
GOOGLE_CLOUD_API_KEY Conditional Direct Vertex API-key auth; otherwise ADC fallback can authenticate when project and location are set
GOOGLE_APPLICATION_CREDENTIALS Conditional If set, file must exist; otherwise ADC fallback path is checked (~/.config/gcloud/application_default_credentials.json)

Kimi

Variable Default / behavior
KIMI_CODE_OAUTH_HOST Primary OAuth host override
KIMI_OAUTH_HOST Fallback OAuth host override
KIMI_CODE_BASE_URL Overrides Kimi usage endpoint base URL (usage/kimi.ts)

OAuth host chain: KIMI_CODE_OAUTH_HOST → KIMI_OAUTH_HOST → https://auth.kimi.com.

Gemini CLI compatibility

Variable Default / behavior
GJC_AI_GEMINI_CLI_VERSION Overrides Gemini CLI user-agent version tag (0.49.0 if unset). PI_AI_GEMINI_CLI_VERSION remains supported as a legacy fallback.

OpenAI code provider responses (feature/debug controls)

Variable Behavior
GJC_OPENAI_CODE_DEBUG 1/true enables OpenAI code provider debug logging
GJC_NO_STRICT Global bypass for OpenAI-style strict schema enforcement (adaptSchemaForStrict); legacy alias PI_NO_STRICT
GJC_OPENAI_CODE_WEBSOCKET 1/true enables websocket transport preference
GJC_OPENAI_CODE_WEBSOCKET_V2 1/true enables websocket v2 path
GJC_OPENAI_CODE_WEBSOCKET_IDLE_TIMEOUT_MS Positive integer override (default 300000)
GJC_OPENAI_CODE_WEBSOCKET_RETRY_BUDGET Non-negative integer override (default 5)
GJC_OPENAI_CODE_WEBSOCKET_RETRY_DELAY_MS Positive integer base backoff override (default 500)
GJC_OPENAI_STREAM_IDLE_TIMEOUT_MS Positive integer OpenAI stream idle timeout override

Cursor provider debug

Variable Behavior
DEBUG_CURSOR Enables provider debug logs; 2/verbose for detailed payload snippets
DEBUG_CURSOR_LOG Optional file path for JSONL debug log output

Prompt cache compatibility switch

Variable Behavior
GJC_CACHE_RETENTION If long, enables long retention where supported (anthropic, openai-responses, Bedrock retention resolution); any other value forces short. The Anthropic provider already defaults to long (1h) when unset, so this is mainly an opt-out (short) or a way to extend long retention to other providers.

3) Web search subsystem

Search provider credentials

Variable Used by
EXA_API_KEY Exa search provider
BRAVE_API_KEY Brave search provider
PERPLEXITY_API_KEY Perplexity search provider API-key mode
PERPLEXITY_COOKIES Perplexity cookie-auth search mode
TAVILY_API_KEY Tavily search provider
ZAI_API_KEY z.ai search provider (also checks stored OAuth in agent.db)
OPENAI_API_KEY / OpenAI code OAuth in DB OpenAI code search provider availability/auth
GJC_OPENAI_CODE_WEB_SEARCH_MODEL OpenAI code search provider model override
MOONSHOT_SEARCH_API_KEY / KIMI_SEARCH_API_KEY Kimi/Moonshot search provider env auth
MOONSHOT_SEARCH_BASE_URL / KIMI_SEARCH_BASE_URL Kimi/Moonshot search endpoint override
KAGI_API_KEY Kagi search provider
JINA_API_KEY Jina search provider
PARALLEL_API_KEY Parallel search provider
SEARXNG_ENDPOINT, SEARXNG_TOKEN SearXNG endpoint and optional bearer token
SEARXNG_BASIC_USERNAME, SEARXNG_BASIC_PASSWORD SearXNG HTTP Basic Auth credentials

SearXNG also reads the equivalent searxng.endpoint, searxng.token, searxng.basicUsername, and searxng.basicPassword settings from ~/.gjc/agent/config.yml; environment variables are fallbacks.

Anthropic web search auth chain

Anthropic web search uses findAnthropicAuth() from packages/ai/src/utils/anthropic-auth.ts in this order:

  1. ANTHROPIC_SEARCH_API_KEY (+ optional ANTHROPIC_SEARCH_BASE_URL)
  2. ANTHROPIC_FOUNDRY_API_KEY when CLAUDE_CODE_USE_FOUNDRY is enabled
  3. Anthropic OAuth credentials from agent.db (must not expire within 5-minute buffer)
  4. Anthropic API-key credentials from agent.db
  5. Generic Anthropic env fallback: provider key (ANTHROPIC_FOUNDRY_API_KEY in Foundry mode, otherwise ANTHROPIC_OAUTH_TOKEN/ANTHROPIC_API_KEY) + optional ANTHROPIC_BASE_URL (FOUNDRY_BASE_URL when Foundry mode is enabled)

Related vars:

Variable Default / behavior
ANTHROPIC_SEARCH_API_KEY Highest-priority explicit search key
ANTHROPIC_SEARCH_BASE_URL Defaults to https://api.anthropic.com when omitted
ANTHROPIC_SEARCH_MODEL Defaults to anthropic-model-haiku-4-5
ANTHROPIC_BASE_URL Generic fallback base URL for tier-4 auth path

Perplexity OAuth flow behavior flag

Variable Behavior
GJC_AUTH_NO_BORROW If set, disables macOS native-app token borrowing path in Perplexity login flow

4) Python tooling and kernel runtime

Variable Default / behavior
GJC_PY Eval backend override: 0/bash=JavaScript only, 1/py=Python only, mix/both=both; invalid values ignored
GJC_PYTHON_SKIP_CHECK If 1, skips Python interpreter availability checks (subprocess runner still starts on demand)
GJC_PYTHON_INTEGRATION If 1, opts gated integration tests in (e.g. python-runner.integration.test.ts) into running against real Python
GJC_PYTHON_IPC_TRACE If 1, logs NDJSON frames exchanged with the Python runner subprocess
VIRTUAL_ENV Highest-priority venv path for Python runtime resolution

Extra conditional behavior:

  • If BUN_ENV=test or NODE_ENV=test, Python availability checks are treated as OK and warming is skipped.
  • Python env filtering denies common API keys and allows safe base vars + LC_, XDG_, GJC_ prefixes.

5) Agent/runtime behavior toggles

Variable Default / behavior
GJC_SMOL_MODEL Ephemeral model-role override for smol (CLI --smol takes precedence)
GJC_SLOW_MODEL Ephemeral model-role override for slow (CLI --slow takes precedence)
GJC_PLAN_MODEL Ephemeral model-role override for plan (CLI --plan takes precedence)
GJC_NO_TITLE If set (any non-empty value), disables auto session title generation on first user message
GJC_NO_CMUX_RENAME If set (any non-empty value), disables renaming the containing cmux workspace to the current session name
NULL_PROMPT If true, system prompt builder returns empty string
GJC_BLOCKED_AGENT Blocks a specific subagent type in task tool
GJC_SUBPROCESS_CMD Overrides subagent spawn command (gjc / gjc.cmd resolution bypass)
GJC_TASK_MAX_OUTPUT_BYTES Max captured output bytes per subagent (default 500000)
GJC_TASK_MAX_OUTPUT_LINES Max captured output lines per subagent (default 5000)
GJC_TIMING If set (any non-empty value), prints a hierarchical timing-span tree to stderr via logger.printTimings(). In interactive mode the tree prints once the agent is ready (before the TUI starts); in print mode it prints after the whole prompt batch completes. Print-mode prompts are wrapped in print:prompt:initial / print:prompt:next spans so each user message shows up as its own row. GJC_TIMING=x exits the process with code 0 right after printing in interactive mode (use to measure cold startup only). GJC_TIMING=full lists every module-load entry instead of just the top N.
GJC_PACKAGE_DIR Overrides package asset base dir resolution (docs/examples/changelog path lookup)
GJC_DISABLE_LSPMUX Canonical lspmux opt-out. A truthy value disables lspmux probing and wrapping; PI_DISABLE_LSPMUX is a supported compatibility alias with the same effect.
PI_DISABLE_LSPMUX Supported compatibility alias for GJC_DISABLE_LSPMUX; a truthy value also disables lspmux probing and wrapping.
SMITHERY_URL Smithery web URL override (default https://smithery.ai)
SMITHERY_API_URL Smithery API base URL override (default https://api.smithery.ai)
PUPPETEER_EXECUTABLE_PATH Browser tool Chromium executable override
LM_STUDIO_BASE_URL Default implicit LM Studio discovery base URL override (http://127.0.0.1:1234/v1 if unset)
OLLAMA_BASE_URL Default implicit Ollama discovery base URL override (http://127.0.0.1:11434 if unset)
LLAMA_CPP_BASE_URL Default implicit Llama.cpp discovery base URL override (http://127.0.0.1:8080 if unset)
GJC_EDIT_VARIANT Forces edit tool variant (patch, replace, hashline, vim, apply_patch). The force beats edit.modelVariants, edit.mode, and automatic model-family routing; invalid values fail fast at startup. PI_EDIT_VARIANT is the legacy alias.
GJC_FORCE_IMAGE_PROTOCOL Forces supported image protocol (kitty, iterm2/iterm, sixel, none) where used
GJC_ALLOW_SIXEL_PASSTHROUGH Allows SIXEL passthrough when GJC_FORCE_IMAGE_PROTOCOL=sixel
GJC_NO_PTY If 1, disables interactive PTY path for bash tool
GJC_SESSION_CONTEXT_BUDGET_BYTES Overrides the synchronous session-context materialization budget in bytes (default 536870912 = 512 MiB, ceiling 8589934592 = 8 GiB). Only a canonical positive-integer value is honored; anything invalid (empty, non-numeric, negative, zero, overflowing a safe integer, or above the ceiling) fail-closes to the 512 MiB default with a warning. Raise it above your measured session size to suppress the SessionContextTooLargeError preflight, or lower it to restore the old tight bound.

LSP project configuration may control declarative matching, activation, and capabilities, but it cannot define a command, arguments, executable, client factory, initialization options, or opaque server settings. Trusted user-wide configuration outside the project—including the recommended ~/.gjc/agent/lsp.* files and supported legacy user locations—can override LSP launches and server options; automatic discovery uses trusted external executables and rejects project-owned lexical paths as well as symlink-resolved project binaries.

GJC_NO_PTY is also set internally when CLI --no-pty is used.


6) Storage and config root paths

These are consumed via @gajae-code/utils/dirs and affect where coding-agent stores data.

Variable Default / behavior
GJC_CONFIG_DIR Config root dirname under home (default .gjc)
GJC_CODING_AGENT_DIR Full override for agent directory (default ~/<GJC_CONFIG_DIR or .gjc>/agent)
PWD Used when matching canonical current working directory in path helpers

7) Shell/tool execution environment

(From packages/utils/src/procmgr.ts and coding-agent bash tool integration.)

Variable Behavior
GJC_BASH_NO_CI Suppresses automatic CI=true injection into spawned shell env
PI_BASH_NO_CI Legacy alias fallback for GJC_BASH_NO_CI
CLAUDE_BASH_NO_CI Legacy alias fallback for GJC_BASH_NO_CI
GJC_BASH_NO_LOGIN Disables login-shell mode; shell args become ['-c'] instead of ['-l','-c']
PI_BASH_NO_LOGIN Legacy alias fallback for GJC_BASH_NO_LOGIN
CLAUDE_BASH_NO_LOGIN Legacy alias fallback for GJC_BASH_NO_LOGIN
PI_SHELL_PREFIX Optional command prefix wrapper
CLAUDE_CODE_SHELL_PREFIX Legacy alias fallback for PI_SHELL_PREFIX
VISUAL Preferred external editor command
EDITOR Fallback external editor command

Current implementation: GJC_BASH_NO_CI and GJC_BASH_NO_LOGIN are resolved first, then the PI_* and CLAUDE_* aliases above. Both are boolean-like: only 1/Y/TRUE/YES/ON (case-insensitive) enable them, so an explicit GJC_BASH_NO_LOGIN=0 keeps the login shell even when a legacy alias is truthy. The shell prefix is read from PI_SHELL_PREFIX/CLAUDE_CODE_SHELL_PREFIX only; GJC_SHELL_PREFIX is not currently honored.


8) UI/theme/session detection (auto-detected env)

These are read as runtime signals; they are usually set by the terminal/OS rather than manually configured.

Variable Used for
COLORTERM, TERM, WT_SESSION Color capability detection (theme color mode)
COLORFGBG Terminal background light/dark auto-detection
TERM_PROGRAM, TERM_PROGRAM_VERSION, TERMINAL_EMULATOR Terminal identity in system prompt/context
KDE_FULL_SESSION, XDG_CURRENT_DESKTOP, DESKTOP_SESSION, XDG_SESSION_DESKTOP, GDMSESSION, WINDOWMANAGER Desktop/window-manager detection in system prompt/context
KITTY_WINDOW_ID, TMUX_PANE, TERM_SESSION_ID, WT_SESSION Stable per-terminal session breadcrumb IDs
SHELL, ComSpec, TERM_PROGRAM, TERM System info diagnostics
APPDATA, XDG_CONFIG_HOME lspmux config path resolution
HOME Path shortening in command UI

9) TUI runtime flags (shared package, affects coding-agent UX)

Variable Behavior
GJC_NOTIFICATIONS 0 is a hard notification runtime opt-out; 1 explicitly enables the generic current-session path even without a globally configured adapter.
GJC_NOTIFICATIONS_TOKEN An explicit generic current-session opt-in token. It has the same runtime precedence as GJC_NOTIFICATIONS=1; it does not supply or override global Telegram credentials.
GJC_NOTIFICATIONS_STREAM 1 forces live assistant-output streaming for this process; 0 / off / false disables it. Unset or unknown values defer to the global notifications.telegram.streaming.enabled preference, which defaults to true and activates durable streaming only for a configured Telegram adapter.
GJC_NOTIFICATIONS_STREAM_INTERVAL_MS Minimum interval between live Telegram stream edits; defaults to 500 and clamps to at least 200.
GJC_NOTIFICATIONS_TURN_MAX Optional finalized turn-text cap for notification streaming; defaults to the bounded full-turn ceiling for split-capable clients.
GJC_NOTIFY off / 0 / false suppresses the notification control surface for this process, including completion notifications; global config is untouched and child processes inherit it. It wins over explicit notification opt-in. Use it for non-interactive runs (gjc -p --no-session) that must remain silent.
GJC_TUI_WRITE_LOG If set, logs TUI writes to file
GJC_HARDWARE_CURSOR If 1, enables hardware cursor mode
GJC_CLEAR_ON_SHRINK If 1, clears empty rows when content shrinks
GJC_DEBUG_REDRAW If 1, enables redraw debug logging
GJC_TUI_DEBUG If 1, enables deep TUI debug dump path
GJC_FORCE_IMAGE_PROTOCOL Forces terminal image protocol detection (kitty, iterm2/iterm, sixel, none)
GJC_TUI_KEYBOARD_PROTOCOL Enhanced keyboard input (Kitty keyboard protocol + xterm modifyOtherKeys). Enabled by default; set 0 / false to leave the keyboard in its default mode. Use this when a terminal (e.g. Android Termius) breaks IME/Hangul composition while these enhanced modes are active.
GJC_TUI_SYNCHRONIZED_OUTPUT Synchronized-output framing (CSI ?2026h/l) is enabled by default. Set 0 / false / off / no before starting or restarting GJC to remove that framing for terminal parsers that render it incorrectly. This is a process-wide compatibility and diagnostic switch, not tmux/Byobu client detection or per-client negotiation. Disabling it may expose visible tearing; return to the default after diagnosis unless the client requires the workaround.

10) Commit generation controls

Variable Behavior
GJC_COMMIT_TEST_FALLBACK If true (case-insensitive), force commit fallback generation path
GJC_COMMIT_NO_FALLBACK If true, disables fallback when agent returns no proposal
GJC_COMMIT_MAP_REDUCE If false, disables map-reduce commit analysis path
DEBUG If set, commit agent error stack traces are printed

11) ACP permission handling

Variable Values Default Behavior
GJC_ACP_PERMISSION_MODE prompt, auto, always-allow prompt Controls whether ACP tool calls use the client's permission prompt or the SDK allow policy. auto and always-allow both allow gated tool calls without prompting. Invalid values fail safely to prompt.

ACP client metadata at _meta.gjc.permissionHandling takes precedence when the client supplies that field; the process environment is the fallback. JetBrains Air custom agents can set the fallback per agent in acp.json:

{
  "agent_servers": {
    "Gajae-Local-Opus": {
      "command": "/absolute/path/to/gjc",
      "args": ["acp", "--mpreset", "opus-codex"],
      "env": {
        "GJC_ACP_PERMISSION_MODE": "always-allow"
      }
    }
  }
}

Use always-allow only for workspaces and tool configurations you trust. It removes the approval boundary for gated shell, monitor, eval, delete, and move operations. Changes apply to newly launched ACP agent processes. GJC does not expose a separate ACP --yolo flag.

See External control readiness for the Air setup flow.


12) Removed ingress modes

--mode rpc, --mode rpc-ui, and --mode bridge have been removed. The retired bridge-prefixed variables and GJC_RPC_EMIT_TITLE are not runtime configuration variables. Use the SDK machine interface for external machine control.


Security-sensitive variables

Treat these as secrets; do not log or commit them:

  • Provider/API keys and OAuth/bearer credentials (all *_API_KEY, *_TOKEN, OAuth access/refresh tokens)
  • Cloud credentials (AWS_*, GOOGLE_APPLICATION_CREDENTIALS path may expose service-account material)
  • Search/provider auth vars (EXA_API_KEY, BRAVE_API_KEY, PERPLEXITY_API_KEY, Anthropic search keys)
  • Foundry mTLS material (CLAUDE_CODE_CLIENT_CERT, CLAUDE_CODE_CLIENT_KEY, NODE_EXTRA_CA_CERTS when it points to private CA bundles)
  • Credential-root redirects (CLAUDE_CONFIG_DIR, CODEX_HOME) — not secrets themselves, but they select which account's credential file the import path reads

Python runtime also explicitly strips many common key vars before spawning kernel subprocesses (packages/coding-agent/src/eval/py/runtime.ts).