diff --git a/package.json b/package.json
index b2f3953..d5e6704 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "swisscode",
"version": "0.4.0",
- "description": "Drop-in launcher for Claude Code, Kilo & OpenCode. Run multiple Claude Pro/Max accounts, check usage limits and switch accounts without /login \u2014 or point any coding CLI at Ollama (local, no key), OpenRouter, z.ai/GLM, DeepSeek & Qwen. No proxy, no daemon.",
+ "description": "Drop-in launcher for Claude Code, Kilo & OpenCode. Run multiple Claude Pro/Max accounts, check usage limits and switch accounts without /login — or point any coding CLI at Ollama (local, no key), OpenRouter, z.ai/GLM, DeepSeek & Qwen. No proxy, no daemon.",
"type": "module",
"bin": {
"swisscode": "./bin/swisscode.js"
@@ -26,7 +26,8 @@
"prepublishOnly": "node build.js",
"size": "node scripts/size-budget.js",
"dev:web": "vite --config web/vite.config.ts",
- "typecheck:web": "tsc --noEmit -p web/tsconfig.json"
+ "typecheck:web": "tsc --noEmit -p web/tsconfig.json",
+ "extract:claude-env": "node scripts/extract-claude-env.mjs > src/adapters/agents/claude-code/env-catalog.ts"
},
"keywords": [
"claude",
diff --git a/scripts/extract-claude-env.mjs b/scripts/extract-claude-env.mjs
new file mode 100644
index 0000000..86db78e
--- /dev/null
+++ b/scripts/extract-claude-env.mjs
@@ -0,0 +1,256 @@
+// Extract every environment variable a Claude Code build references.
+//
+// WHY A SCRIPT AND NOT A PASTED SNAPSHOT. The catalog it produces is committed
+// (the build must not require Claude Code to be installed), so without this it
+// would be a list nobody could regenerate, aging silently against a binary that
+// ships weekly. Re-run it against a newer Claude Code and diff.
+//
+// node scripts/extract-claude-env.mjs > src/adapters/agents/claude-code/env-catalog.ts
+//
+// WHAT THIS CANNOT DO, stated up front because the output is a UI surface:
+// it reads STRINGS OUT OF A BINARY. That yields names, and nothing else. It
+// cannot yield meaning, defaults, accepted values, or whether a variable is
+// still wired to anything. Every description in the output comes from the
+// hand-maintained table below — never from the binary — and anything absent
+// from that table ships explicitly marked as undocumented rather than given a
+// plausible-sounding guess. A wrong description is worse than no description:
+// it is a claim someone will act on.
+
+import { execFileSync } from 'node:child_process'
+import { existsSync, readdirSync, statSync } from 'node:fs'
+import { homedir } from 'node:os'
+import { join } from 'node:path'
+
+/** Where the native installer puts versioned binaries. */
+function findBinary() {
+ const explicit = process.argv[2]
+ if (explicit) return explicit
+ const dir = join(homedir(), '.local', 'share', 'claude', 'versions')
+ if (!existsSync(dir)) return null
+ const versions = readdirSync(dir)
+ .filter((v) => /^\d+\.\d+\.\d+$/.test(v))
+ .sort((a, b) => {
+ const pa = a.split('.').map(Number)
+ const pb = b.split('.').map(Number)
+ for (let i = 0; i < 3; i++) if (pa[i] !== pb[i]) return pb[i] - pa[i]
+ return 0
+ })
+ for (const v of versions) {
+ const candidate = join(dir, v)
+ if (existsSync(candidate) && statSync(candidate).isFile()) return candidate
+ }
+ return null
+}
+
+const binary = findBinary()
+if (!binary) {
+ console.error(
+ 'extract-claude-env: no Claude Code binary found. Pass one explicitly:\n' +
+ ' node scripts/extract-claude-env.mjs /path/to/claude',
+ )
+ process.exit(2)
+}
+
+const version = binary.split('/').pop()
+
+const raw = execFileSync('strings', ['-a', binary], {
+ encoding: 'utf8',
+ maxBuffer: 1024 * 1024 * 1024,
+})
+
+// Anthropic's two prefixes. `CLAUDE_` alone is deliberately excluded: it also
+// matches CLAUDE_CONFIG_DIR-style host variables and a long tail of one-off
+// internal names, and widening the net does not make the result more useful.
+const names = [...new Set(raw.match(/\b(?:CLAUDE_CODE|ANTHROPIC)_[A-Z0-9_]+\b/g) ?? [])].sort()
+
+/**
+ * Names that clearly are not a user-facing knob, by SHAPE rather than by
+ * judgement about any individual one.
+ *
+ * Each rule is something you can check yourself against the list, which matters
+ * because this classification is the only thing standing between a browsable
+ * catalog and 428 undifferentiated strings.
+ */
+const INTERNAL = [
+ { re: /_FOR_TESTING$|^CLAUDE_CODE_TEST_|_FIXTURE$/, why: 'test hook' },
+ { re: /^CLAUDE_CODE_(MOCK|SIMULATE|FORCE_TIP_ID|OVERRIDE_DATE)/, why: 'test hook' },
+ { re: /^CLAUDE_CODE_(BENCH|PERFETTO|FRAME_TIMING|PROFILE_(QUERY|STARTUP)|DEBUG_REPAINTS)/, why: 'profiling' },
+ { re: /^ANTHROPIC_(BEDROCK|VERTEX|FOUNDRY|AWS|GOOGLE_CLOUD)/, why: 'third-party cloud provider' },
+ { re: /^CLAUDE_CODE_(USE_BEDROCK|USE_VERTEX|USE_FOUNDRY|USE_MANTLE|USE_ANTHROPIC_AWS|USE_ANTHROPIC_GOOGLE_CLOUD|SKIP_.*_AUTH|SKIP_AWS_CRED_CACHE)/, why: 'third-party cloud provider' },
+]
+
+/**
+ * Two unrelated words joined by an underscore, with nothing else in the name.
+ *
+ * Anthropic ships unreleased features behind codenames — ALDER_WICKET,
+ * BISON_CAIRN, PEWTER_OWL, THISTLE_GREBE. They are indistinguishable from real
+ * knobs by name alone, they appear and vanish between releases, and a user who
+ * sets one is configuring something nobody can describe. Matched structurally
+ * so the rule keeps working on names that do not exist yet.
+ */
+const CODENAME = /^CLAUDE_CODE_[A-Z]+_[A-Z]+$/
+
+// Words that make a two-word name a real knob rather than a codename. Without
+// this, TMUX_PREFIX and MAX_RETRIES would be classified as codenames.
+const REAL_WORDS =
+ /(MAX|MIN|DISABLE|ENABLE|SKIP|FORCE|USE|API|OAUTH|TOKEN|MODEL|PROXY|TIMEOUT|SESSION|DEBUG|LOG|DIR|PATH|FILE|URL|KEY|MODE|TMUX|SHELL|PLUGIN|SYNC|IDE|OTEL|MCP|OUTPUT|CONTEXT|TOOL|AGENT|MEMORY|REMOTE|SANDBOX|TELEMETRY|VERSION|PROMPT|RETRY|RETRIES|CACHE|GLOB|EFFORT|SUBAGENT|TERMINAL|ARTIFACT|WORKFLOW|ENTRYPOINT|EMAIL|UUID|ID)/
+
+/**
+ * The hand-written half. NOTHING HERE COMES FROM THE BINARY.
+ *
+ * Every entry is a variable whose behaviour is documented by Anthropic, visible
+ * in `claude --help`, or already relied on by swisscode's own adapter — which
+ * is to say, one somebody can be held to. Everything not in this table ships as
+ * `undocumented`, name only.
+ */
+const DESCRIBED = {
+ ANTHROPIC_API_KEY: ['credential', 'The API key Claude Code authenticates with. swisscode sets this per profile; it is cleared for any launch not going to first-party Anthropic.'],
+ ANTHROPIC_AUTH_TOKEN: ['credential', 'Bearer-token form of the credential, used by most gateways. swisscode picks this or ANTHROPIC_API_KEY based on the provider descriptor.'],
+ ANTHROPIC_BASE_URL: ['endpoint', 'The Anthropic-compatible endpoint to talk to. swisscode sets this from the profile’s provider; a bare host, with no /v1.'],
+ ANTHROPIC_MODEL: ['model', 'Overrides the model for the session. Prefer the per-tier ANTHROPIC_DEFAULT_*_MODEL variables, which is what swisscode pins.'],
+ ANTHROPIC_SMALL_FAST_MODEL: ['model', 'The model used for cheap background work. Superseded by ANTHROPIC_DEFAULT_HAIKU_MODEL on current builds.'],
+ ANTHROPIC_DEFAULT_OPUS_MODEL: ['model', 'Model id for the opus tier. Accepts a [1m] suffix to request the extended context window.'],
+ ANTHROPIC_DEFAULT_SONNET_MODEL: ['model', 'Model id for the sonnet tier.'],
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: ['model', 'Model id for the haiku tier, used for background and summarisation work.'],
+ ANTHROPIC_DEFAULT_FABLE_MODEL: ['model', 'Model id for the fable tier.'],
+ ANTHROPIC_CUSTOM_HEADERS: ['endpoint', 'Extra HTTP headers on every API request, as newline-separated Name: Value pairs.'],
+ ANTHROPIC_BETAS: ['endpoint', 'Beta headers to include in API requests. API-key users only.'],
+ ANTHROPIC_LOG: ['debug', 'Log verbosity for the API client.'],
+ CLAUDE_CONFIG_DIR: ['session', 'Which directory holds the login and settings. THE BRANCH IS ON WHETHER THIS IS SET, not on its value — setting it to the default ~/.claude is a different, empty login.'],
+ CLAUDE_CODE_MAX_OUTPUT_TOKENS: ['limits', 'Ceiling on tokens the model may produce in one response.'],
+ CLAUDE_CODE_MAX_CONTEXT_TOKENS: ['limits', 'Ceiling on the context window Claude Code will fill before compacting.'],
+ CLAUDE_CODE_MAX_RETRIES: ['limits', 'How many times a failed API request is retried.'],
+ CLAUDE_CODE_MAX_TURNS: ['limits', 'Maximum agent turns before the session stops on its own.'],
+ CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS: ['limits', 'How many subagents may run at once.'],
+ CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY: ['limits', 'How many tool calls may run in parallel within one turn.'],
+ CLAUDE_CODE_SUBAGENT_MODEL: ['model', 'Model subagents run on. Pinning it matters on gateways: subagents 404 when the id is not one the endpoint serves. swisscode sets this for OpenRouter.'],
+ CLAUDE_CODE_AUTO_COMPACT_WINDOW: ['limits', 'Fraction of the context window at which auto-compaction triggers.'],
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: ['traffic', 'Stops background requests an endpoint may not serve. ALSO disables gateway model discovery, so every tier must be pinned explicitly.'],
+ CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING: ['compat', 'Works around gateways that reject the adaptive thinking input tag with 400.'],
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: ['compat', 'Works around gateways that reject unknown beta fields with "Extra inputs are not permitted".'],
+ CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK: ['compat', 'Skips the organisation check that reports fast mode as disabled on non-first-party endpoints.'],
+ CLAUDE_CODE_ATTRIBUTION_HEADER: ['traffic', 'Set to 0 to drop the attribution header, which improves prompt-cache hit rate through some gateways.'],
+ CLAUDE_CODE_DISABLE_1M_CONTEXT: ['limits', 'Turns off the 1M context window request.'],
+ CLAUDE_CODE_DISABLE_THINKING: ['behaviour', 'Disables extended thinking.'],
+ CLAUDE_CODE_DISABLE_TERMINAL_TITLE: ['ui', 'Stops Claude Code rewriting the terminal window title.'],
+ CLAUDE_CODE_DISABLE_MOUSE: ['ui', 'Disables mouse reporting, which some terminals and multiplexers handle badly.'],
+ CLAUDE_CODE_DISABLE_AUTO_MEMORY: ['behaviour', 'Stops automatic memory capture.'],
+ CLAUDE_CODE_DISABLE_CLAUDE_MDS: ['behaviour', 'Stops CLAUDE.md files being discovered and loaded.'],
+ CLAUDE_CODE_DISABLE_BACKGROUND_TASKS: ['behaviour', 'Disables background task execution.'],
+ CLAUDE_CODE_ENABLE_TELEMETRY: ['telemetry', 'Enables OpenTelemetry export.'],
+ CLAUDE_CODE_SAFE_MODE: ['behaviour', 'Set by --safe-mode. Disables customisations — CLAUDE.md, skills, plugins, hooks, MCP servers — for troubleshooting a broken configuration.'],
+ CLAUDE_CODE_SIMPLE: ['behaviour', 'Set by --bare. Skips hooks, LSP, plugin sync, auto-memory, keychain reads and CLAUDE.md discovery.'],
+ CLAUDE_CODE_EFFORT_LEVEL: ['behaviour', 'Effort level for the session: low, medium, high, xhigh, max. Also settable with --effort.'],
+ CLAUDE_CODE_SHELL: ['environment', 'Which shell the Bash tool uses.'],
+ CLAUDE_CODE_TMPDIR: ['environment', 'Temporary directory Claude Code writes to.'],
+ CLAUDE_CODE_GIT_BASH_PATH: ['environment', 'Path to Git Bash on Windows.'],
+ CLAUDE_CODE_HTTP_PROXY: ['network', 'HTTP proxy for Claude Code’s own requests.'],
+ CLAUDE_CODE_HTTPS_PROXY: ['network', 'HTTPS proxy for Claude Code’s own requests.'],
+ CLAUDE_CODE_CLIENT_CERT: ['network', 'Client certificate for mTLS.'],
+ CLAUDE_CODE_CLIENT_KEY: ['network', 'Client key for mTLS.'],
+ CLAUDE_CODE_ENTRYPOINT: ['environment', 'How Claude Code was started. swisscode does not set this; the agent uses it for its own telemetry.'],
+ CLAUDE_CODE_VERSION: ['environment', 'The running Claude Code version.'],
+ CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY: ['traffic', 'Lets Claude Code ask a gateway which models it serves. Disabled as a side effect of CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC.'],
+ CLAUDE_CODE_API_KEY_HELPER_TTL_MS: ['credential', 'How long a credential from apiKeyHelper is cached.'],
+ CLAUDE_CODE_OAUTH_TOKEN: ['credential', 'OAuth access token. Written by /login; swisscode reads it only to measure subscription usage, and never refreshes it.'],
+ CLAUDE_CODE_SUBSCRIPTION_TYPE: ['credential', 'The plan behind the current login, e.g. max.'],
+ CLAUDE_CODE_DEBUG_LOG_LEVEL: ['debug', 'Verbosity of debug logging. Also settable with --debug.'],
+ CLAUDE_CODE_DEBUG_LOGS_DIR: ['debug', 'Where debug logs are written.'],
+ CLAUDE_CODE_SESSION_ID: ['session', 'The current session id. Also settable with --session-id.'],
+ CLAUDE_CODE_MANAGED_SETTINGS_PATH: ['environment', 'Path to admin-managed policy settings.'],
+ ENABLE_TOOL_SEARCH: ['compat', 'Enables MCP tool search, which is off by default away from first-party Anthropic.'],
+ API_FORCE_IDLE_TIMEOUT: ['compat', 'Set to 0 to stop the client giving up on slow or locally hosted models.'],
+ MAX_THINKING_TOKENS: ['limits', 'Ceiling on tokens spent on extended thinking.'],
+ DISABLE_TELEMETRY: ['telemetry', 'Disables telemetry reporting.'],
+ DISABLE_ERROR_REPORTING: ['telemetry', 'Disables error reporting.'],
+ DISABLE_AUTOUPDATER: ['behaviour', 'Stops Claude Code updating itself.'],
+}
+
+// Variables swisscode itself writes, so the UI can say "this one is already
+// yours to set from a profile" instead of listing it as inert trivia.
+const SWISSCODE_SETS = new Set([
+ 'ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN', 'ANTHROPIC_BASE_URL', 'CLAUDE_CONFIG_DIR',
+ 'ANTHROPIC_DEFAULT_OPUS_MODEL', 'ANTHROPIC_DEFAULT_SONNET_MODEL',
+ 'ANTHROPIC_DEFAULT_HAIKU_MODEL', 'ANTHROPIC_DEFAULT_FABLE_MODEL',
+ 'CLAUDE_CODE_SUBAGENT_MODEL', 'CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC',
+ 'CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING', 'CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS',
+ 'CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK', 'CLAUDE_CODE_ATTRIBUTION_HEADER',
+ 'ENABLE_TOOL_SEARCH', 'API_FORCE_IDLE_TIMEOUT',
+])
+
+function classify(name) {
+ // THE HAND-WRITTEN TABLE OUTRANKS EVERY HEURISTIC, and the order here is the
+ // whole point rather than a detail. A description in DESCRIBED means somebody
+ // verified the variable; a regex is a guess about a name's shape. Running the
+ // guesses first got `CLAUDE_CODE_ATTRIBUTION_HEADER` — a variable swisscode
+ // sets itself — filed as an "unreleased feature codename", because it happens
+ // to be two words. Caught by the catalog's own tests, not by reading.
+ if (DESCRIBED[name]) return { kind: 'documented' }
+ for (const rule of INTERNAL) if (rule.re.test(name)) return { kind: 'internal', why: rule.why }
+ if (CODENAME.test(name) && !REAL_WORDS.test(name)) {
+ return { kind: 'internal', why: 'unreleased feature codename' }
+ }
+ return { kind: 'undocumented' }
+}
+
+// Names swisscode knows about that the binary does not spell with a prefix we
+// scan for (ENABLE_TOOL_SEARCH, MAX_THINKING_TOKENS, …). Included so the
+// catalog is not narrower than the adapter it describes.
+const extra = Object.keys(DESCRIBED).filter((n) => !names.includes(n))
+const all = [...names, ...extra].sort()
+
+const entries = all.map((name) => {
+ const c = classify(name)
+ const described = DESCRIBED[name]
+ return {
+ name,
+ kind: c.kind,
+ ...(c.why ? { why: c.why } : {}),
+ ...(described ? { category: described[0], description: described[1] } : {}),
+ ...(SWISSCODE_SETS.has(name) ? { managed: true } : {}),
+ }
+})
+
+const counts = entries.reduce((acc, e) => ({ ...acc, [e.kind]: (acc[e.kind] ?? 0) + 1 }), {})
+
+process.stdout.write(`// GENERATED by scripts/extract-claude-env.mjs — do not edit by hand.
+//
+// Every environment variable referenced by Claude Code ${version}, extracted
+// from the shipped binary, plus the ones swisscode's own adapter sets.
+//
+// READ THE 'kind' FIELD BEFORE TRUSTING AN ENTRY. Extraction yields NAMES AND
+// NOTHING ELSE — no meaning, no defaults, no accepted values, and no evidence
+// that a name is still wired to anything. So:
+//
+// documented ${String(counts.documented ?? 0).padStart(3)} described by hand from Anthropic's docs, \`claude --help\`,
+// or swisscode's own adapter. Safe to act on.
+// undocumented ${String(counts.undocumented ?? 0).padStart(3)} the name is real; the meaning is NOT KNOWN. Shipped
+// without a description on purpose — a plausible guess is
+// worse than a blank, because someone will act on it.
+// internal ${String(counts.internal ?? 0).padStart(3)} test hooks, profiling switches, third-party cloud
+// auth, and unreleased feature codenames. Present for
+// completeness; not knobs.
+//
+// Regenerate against a newer Claude Code and diff:
+// node scripts/extract-claude-env.mjs > src/adapters/agents/claude-code/env-catalog.ts
+
+/** How much is actually known about an entry. */
+export type ClaudeEnvKind = 'documented' | 'undocumented' | 'internal'
+
+export type ClaudeEnvVar = {
+ name: string
+ kind: ClaudeEnvKind
+ /** why it was classified internal; absent otherwise */
+ why?: string
+ category?: string
+ /** hand-written, never extracted; absent for undocumented and internal */
+ description?: string
+ /** swisscode's own adapter sets this one from a profile */
+ managed?: boolean
+}
+
+/** The Claude Code build this was extracted from. */
+export const CATALOG_SOURCE = ${JSON.stringify({ agent: 'claude-code', version })} as const
+
+export const CLAUDE_ENV_CATALOG: readonly ClaudeEnvVar[] = Object.freeze(${JSON.stringify(entries, null, 2)})
+`)
diff --git a/src/adapters/agents/claude-code/env-catalog.ts b/src/adapters/agents/claude-code/env-catalog.ts
new file mode 100644
index 0000000..432cddc
--- /dev/null
+++ b/src/adapters/agents/claude-code/env-catalog.ts
@@ -0,0 +1,2254 @@
+// GENERATED by scripts/extract-claude-env.mjs — do not edit by hand.
+//
+// Every environment variable referenced by Claude Code 2.1.217, extracted
+// from the shipped binary, plus the ones swisscode's own adapter sets.
+//
+// READ THE 'kind' FIELD BEFORE TRUSTING AN ENTRY. Extraction yields NAMES AND
+// NOTHING ELSE — no meaning, no defaults, no accepted values, and no evidence
+// that a name is still wired to anything. So:
+//
+// documented 60 described by hand from Anthropic's docs, `claude --help`,
+// or swisscode's own adapter. Safe to act on.
+// undocumented 338 the name is real; the meaning is NOT KNOWN. Shipped
+// without a description on purpose — a plausible guess is
+// worse than a blank, because someone will act on it.
+// internal 97 test hooks, profiling switches, third-party cloud
+// auth, and unreleased feature codenames. Present for
+// completeness; not knobs.
+//
+// Regenerate against a newer Claude Code and diff:
+// node scripts/extract-claude-env.mjs > src/adapters/agents/claude-code/env-catalog.ts
+
+/** How much is actually known about an entry. */
+export type ClaudeEnvKind = 'documented' | 'undocumented' | 'internal'
+
+export type ClaudeEnvVar = {
+ name: string
+ kind: ClaudeEnvKind
+ /** why it was classified internal; absent otherwise */
+ why?: string
+ category?: string
+ /** hand-written, never extracted; absent for undocumented and internal */
+ description?: string
+ /** swisscode's own adapter sets this one from a profile */
+ managed?: boolean
+}
+
+/** The Claude Code build this was extracted from. */
+export const CATALOG_SOURCE = {"agent":"claude-code","version":"2.1.217"} as const
+
+export const CLAUDE_ENV_CATALOG: readonly ClaudeEnvVar[] = Object.freeze([
+ {
+ "name": "ANTHROPIC_API_KEY",
+ "kind": "documented",
+ "category": "credential",
+ "description": "The API key Claude Code authenticates with. swisscode sets this per profile; it is cleared for any launch not going to first-party Anthropic.",
+ "managed": true
+ },
+ {
+ "name": "ANTHROPIC_AUTH_TOKEN",
+ "kind": "documented",
+ "category": "credential",
+ "description": "Bearer-token form of the credential, used by most gateways. swisscode picks this or ANTHROPIC_API_KEY based on the provider descriptor.",
+ "managed": true
+ },
+ {
+ "name": "ANTHROPIC_AWS_API_KEY",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_AWS_BASE_URL",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_AWS_WORKSPACE_ID",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_BASE_URL",
+ "kind": "documented",
+ "category": "endpoint",
+ "description": "The Anthropic-compatible endpoint to talk to. swisscode sets this from the profile’s provider; a bare host, with no /v1.",
+ "managed": true
+ },
+ {
+ "name": "ANTHROPIC_BEDROCK_BASE_URL",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_BEDROCK_MANTLE_BASE_URL",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_BEDROCK_SERVICE_TIER",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_BETAS",
+ "kind": "documented",
+ "category": "endpoint",
+ "description": "Beta headers to include in API requests. API-key users only."
+ },
+ {
+ "name": "ANTHROPIC_CONFIG_DIR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_CUSTOM_HEADERS",
+ "kind": "documented",
+ "category": "endpoint",
+ "description": "Extra HTTP headers on every API request, as newline-separated Name: Value pairs."
+ },
+ {
+ "name": "ANTHROPIC_CUSTOM_MODEL_OPTION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_CUSTOM_MODEL_OPTION_NAME",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_FABLE_MODEL",
+ "kind": "documented",
+ "category": "model",
+ "description": "Model id for the fable tier.",
+ "managed": true
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_FABLE_MODEL_DESCRIPTION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_FABLE_MODEL_NAME",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_FABLE_MODEL_SUPPORTED_CAPABILITIES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_HAIKU_MODEL",
+ "kind": "documented",
+ "category": "model",
+ "description": "Model id for the haiku tier, used for background and summarisation work.",
+ "managed": true
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_OPUS_MODEL",
+ "kind": "documented",
+ "category": "model",
+ "description": "Model id for the opus tier. Accepts a [1m] suffix to request the extended context window.",
+ "managed": true
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_OPUS_MODEL_NAME",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_SONNET_MODEL",
+ "kind": "documented",
+ "category": "model",
+ "description": "Model id for the sonnet tier.",
+ "managed": true
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_SONNET_MODEL_NAME",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_ENVIRONMENT_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_ENVIRONMENT_KEY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_FEDERATION_RULE_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_FOUNDRY_API_KEY",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_FOUNDRY_AUTH_TOKEN",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_FOUNDRY_BASE_URL",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_FOUNDRY_RESOURCE",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_GOOGLE_CLOUD_BASE_URL",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_GOOGLE_CLOUD_LOCATION",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_GOOGLE_CLOUD_PROJECT",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_GOOGLE_CLOUD_WORKSPACE_ID",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_IDENTITY_TOKEN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_IDENTITY_TOKEN_FILE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_LOG",
+ "kind": "documented",
+ "category": "debug",
+ "description": "Log verbosity for the API client."
+ },
+ {
+ "name": "ANTHROPIC_MODEL",
+ "kind": "documented",
+ "category": "model",
+ "description": "Overrides the model for the session. Prefer the per-tier ANTHROPIC_DEFAULT_*_MODEL variables, which is what swisscode pins."
+ },
+ {
+ "name": "ANTHROPIC_ORGANIZATION_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_PROFILE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_SCOPE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_SERVICE_ACCOUNT_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_SESSION_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_SMALL_FAST_MODEL",
+ "kind": "documented",
+ "category": "model",
+ "description": "The model used for cheap background work. Superseded by ANTHROPIC_DEFAULT_HAIKU_MODEL on current builds."
+ },
+ {
+ "name": "ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_UNIX_SOCKET",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_VERTEX_BASE_URL",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_VERTEX_PROJECT_ID",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "ANTHROPIC_WEBHOOK_SIGNING_KEY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_WORKSPACE_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "ANTHROPIC_WORK_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "API_FORCE_IDLE_TIMEOUT",
+ "kind": "documented",
+ "category": "compat",
+ "description": "Set to 0 to stop the client giving up on slow or locally hosted models.",
+ "managed": true
+ },
+ {
+ "name": "CLAUDE_CODE_3P_PROBE_WROTE_OPUS_DEFAULT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_3P_PROBE_WROTE_SONNET_DEFAULT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ACCESSIBILITY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ACCOUNT_TAGGED_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ACCOUNT_UUID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ACTION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ACT_DONT_REDERIVE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ADDITIONAL_PROTECTION",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_AGENT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AGENT_PROXY_GH_SHIM",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AGENT_PROXY_GIT_CONFIG",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AGENT_RULE_DISABLED",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AGENT_VIEW_RELAUNCH",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ALDER_WICKET",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_ALTGR_AS_TEXT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ALWAYS_ENABLE_EFFORT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AMBER_ASTROLABE",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_API_BASE_URL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_API_KEY_FILE_DESCRIPTOR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_API_KEY_HELPER_TTL_MS",
+ "kind": "documented",
+ "category": "credential",
+ "description": "How long a credential from apiKeyHelper is cached."
+ },
+ {
+ "name": "CLAUDE_CODE_ARTIFACT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ARTIFACTS_API_BASE_URL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ARTIFACT_AUTO_OPEN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ARTIFACT_DIRECT_UPLOAD",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ARTIFACT_MCP",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ATTRIBUTION_HEADER",
+ "kind": "documented",
+ "category": "traffic",
+ "description": "Set to 0 to drop the attribution header, which improves prompt-cache hit rate through some gateways.",
+ "managed": true
+ },
+ {
+ "name": "CLAUDE_CODE_AUTH_FAIL_EXIT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_BACKGROUND_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_COMPACT_WINDOW",
+ "kind": "documented",
+ "category": "limits",
+ "description": "Fraction of the context window at which auto-compaction triggers."
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_CONNECT_IDE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_CLASSIFY_EDITS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_EDIT_REMOVAL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_EDIT_REMOVAL_CAP",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_EXTERNAL_PERMISSIONS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_GIT_STATUS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_GIT_STATUS_LIMIT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_GIT_STATUS_UPLOADS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_MODEL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_OUTCOME_CODES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_PRIOR_ASSISTANT_CONTEXT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_REPO_VISIBILITY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_SIBLING_CONTEXT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AUTO_MODE_TEMPERATURE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_AWS_CHAIN_RESOLVE_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_BASALT_COVE",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_BASE_REF",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_BASE_REFS",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_BASH_SANDBOX_SHOW_INDICATOR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_BENCH_LIVE_COUNTS",
+ "kind": "internal",
+ "why": "profiling"
+ },
+ {
+ "name": "CLAUDE_CODE_BG_CLASSIFIER_MODEL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_BG_TASKS_REPORT_RUNNING",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_BISON_CAIRN",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_BLOCKING_LIMIT_OVERRIDE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_BRIDGE_SESSION_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_BRIEF",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_BRIEF_UPLOAD",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_BS_AS_CTRL_BACKSPACE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_BUBBLEWRAP",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_BYOC_ENABLE_DATADOG",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_CERT_STORE",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_CHILD_SESSION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_CLASSIFIER_SUMMARY",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_CLIENT_CERT",
+ "kind": "documented",
+ "category": "network",
+ "description": "Client certificate for mTLS."
+ },
+ {
+ "name": "CLAUDE_CODE_CLIENT_KEY",
+ "kind": "documented",
+ "category": "network",
+ "description": "Client key for mTLS."
+ },
+ {
+ "name": "CLAUDE_CODE_CLIENT_KEY_PASSPHRASE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_COLD_COMPACT",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_COMMIT_LOG",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_CONTAINER_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_COORDINATOR_EXTRA_TOOLS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_COORDINATOR_MODE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_COORDINATOR_PROPAGATE_NESTED_MEMORY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_CUSTOM_OAUTH_URL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DAEMON_COLD_START",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DATADOG_FLUSH_INTERVAL_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DD_ERROR_TRACKING_FLUSH_INTERVAL_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DEBUG_LOGS_DIR",
+ "kind": "documented",
+ "category": "debug",
+ "description": "Where debug logs are written."
+ },
+ {
+ "name": "CLAUDE_CODE_DEBUG_LOG_LEVEL",
+ "kind": "documented",
+ "category": "debug",
+ "description": "Verbosity of debug logging. Also settable with --debug."
+ },
+ {
+ "name": "CLAUDE_CODE_DEBUG_REPAINTS",
+ "kind": "internal",
+ "why": "profiling"
+ },
+ {
+ "name": "CLAUDE_CODE_DECSTBM",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DESIGN_OAUTH_CLIENT_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DEV_RAW_CHANGELOG_URL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DIAGNOSTICS_FILE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_1M_CONTEXT",
+ "kind": "documented",
+ "category": "limits",
+ "description": "Turns off the 1M context window request."
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING",
+ "kind": "documented",
+ "category": "compat",
+ "description": "Works around gateways that reject the adaptive thinking input tag with 400.",
+ "managed": true
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_ADVISOR_TOOL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_AGENT_VIEW",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_ARTIFACT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_ATTACHMENTS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_AUTO_MEMORY",
+ "kind": "documented",
+ "category": "behaviour",
+ "description": "Stops automatic memory capture."
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_BACKGROUND_TASKS",
+ "kind": "documented",
+ "category": "behaviour",
+ "description": "Disables background task execution."
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_BEDROCK_CONTENT_TYPE_GUARD",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_BG_EXIT_HANDOFF",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_BUNDLED_SKILLS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_CLAUDE_API_SKILL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_CLAUDE_CODE_SKILL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_CLAUDE_MDS",
+ "kind": "documented",
+ "category": "behaviour",
+ "description": "Stops CLAUDE.md files being discovered and loaded."
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_CRON",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS",
+ "kind": "documented",
+ "category": "compat",
+ "description": "Works around gateways that reject unknown beta fields with \"Extra inputs are not permitted\".",
+ "managed": true
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_EXPLORE_INHERIT_CAP",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_EXPLORE_PLAN_AGENTS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_FAST_MODE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_LAUNCH_COMPOSER",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_LEGACY_MODEL_REMAP",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_MEMORY_BULK_INFLATE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_MEMORY_PERIODIC_RESYNC",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_MEMORY_STREAM_LIST",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_MOUSE",
+ "kind": "documented",
+ "category": "ui",
+ "description": "Disables mouse reporting, which some terminals and multiplexers handle badly."
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_MOUSE_CLICKS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_NESTED_CHAIN_IDLE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC",
+ "kind": "documented",
+ "category": "traffic",
+ "description": "Stops background requests an endpoint may not serve. ALSO disables gateway model discovery, so every tier must be pinned explicitly.",
+ "managed": true
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_NOTIFICATION_PRESENCE_CHECK",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_ORG_MEMORY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_POLICY_SKILLS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_PRECOMPACT_SKIP",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_REFUSAL_FALLBACK",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_TERMINAL_TITLE",
+ "kind": "documented",
+ "category": "ui",
+ "description": "Stops Claude Code rewriting the terminal window title."
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_THINKING",
+ "kind": "documented",
+ "category": "behaviour",
+ "description": "Disables extended thinking."
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_VIRTUAL_SCROLL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_WORKFLOWS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DISABLE_WORKING_SYNC",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DONT_INHERIT_ENV",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_DOWNLOAD_DEADLINE_MS_FOR_TESTING",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_EAGER_FLUSH",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_EFFORT_LEVEL",
+ "kind": "documented",
+ "category": "behaviour",
+ "description": "Effort level for the session: low, medium, high, xhigh, max. Also settable with --effort."
+ },
+ {
+ "name": "CLAUDE_CODE_EMIT_SESSION_STATE_EVENTS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_EMIT_TOOL_USE_SUMMARIES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_APPEND_SUBAGENT_PROMPT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_AUTO_MODE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_AWAY_SUMMARY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_CFC",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_DESIGN_SYNC",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_EXPERIMENTAL_ADVISOR_TOOL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY",
+ "kind": "documented",
+ "category": "traffic",
+ "description": "Lets Claude Code ask a gateway which models it serves. Disabled as a side effect of CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC."
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_LAUNCH_COMPOSER",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_MENU_KIND_LANES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_PROXY_AUTH_HELPER",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_REFRESH_MCP_TOOLS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_REMOTE_RECAP",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_TASKS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_TELEMETRY",
+ "kind": "documented",
+ "category": "telemetry",
+ "description": "Enables OpenTelemetry export."
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_TOKEN_USAGE_ATTACHMENT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENABLE_XAA",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENHANCED_TELEMETRY_BETA",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ENTRYPOINT",
+ "kind": "documented",
+ "category": "environment",
+ "description": "How Claude Code was started. swisscode does not set this; the agent uses it for its own telemetry."
+ },
+ {
+ "name": "CLAUDE_CODE_ENVIRONMENT_KIND",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_ENVIRONMENT_RUNNER_VERSION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_EXECPATH",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_EXIT_AFTER_FIRST_RENDER",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_EXIT_AFTER_STOP_DELAY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_EXTRA_BODY",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_EXTRA_METADATA",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_FABLE_BRIDGE_DIALOG_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FILE_READ_MAX_OUTPUT_TOKENS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FLEETVIEW_SIMPLE",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_FLEET_PAST_SESSIONS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_BRIDGE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_EVALUATE_MEMORY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_FULLSCREEN_UPSELL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_FULL_LOGO",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_MEMORY_SURVEY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_MID_CONVERSATION_SYSTEM",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_RC_LONG_TURN_NUDGE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_SANDBOX",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_SESSION_PERSISTENCE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_STRIKETHROUGH",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_SYNC_OUTPUT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_TIP_ID",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_FORCE_WINDOWS_CREDMAN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORK_SUBAGENT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FORWARD_SUBAGENT_TEXT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_FRAME_TIMING_LOG",
+ "kind": "internal",
+ "why": "profiling"
+ },
+ {
+ "name": "CLAUDE_CODE_FRAME_TIMING_SAMPLE_EVERY",
+ "kind": "internal",
+ "why": "profiling"
+ },
+ {
+ "name": "CLAUDE_CODE_GAULT_KESTREL",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_GB_BASE_URL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_GB_DISK_CACHE_WHEN_TELEMETRY_OFF",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_GB_REFRESH_INTERVAL_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_GIT_BASH_PATH",
+ "kind": "documented",
+ "category": "environment",
+ "description": "Path to Git Bash on Windows."
+ },
+ {
+ "name": "CLAUDE_CODE_GLOB_HIDDEN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_GLOB_NO_IGNORE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_GLOB_TIMEOUT_SECONDS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_GZIP_REQUEST_BODIES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_HERON_TALLOW",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_HFI_BEARER_TOKEN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_HIDE_CWD",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_HIDE_SETTINGS_HINT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_HOST_AUTH_ENV_VAR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_HOST_AUTH_REFRESH_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_HOST_CREDS_FILE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_HOST_HTTP_PROXY_PORT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_HOST_PLATFORM",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_HOST_SOCKS_PROXY_PORT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_HTTPS_PROXY",
+ "kind": "documented",
+ "category": "network",
+ "description": "HTTPS proxy for Claude Code’s own requests."
+ },
+ {
+ "name": "CLAUDE_CODE_HTTP_PROXY",
+ "kind": "documented",
+ "category": "network",
+ "description": "HTTP proxy for Claude Code’s own requests."
+ },
+ {
+ "name": "CLAUDE_CODE_IDE_HOST_OVERRIDE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_IDE_SKIP_VALID_CHECK",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_IDLE_THRESHOLD_MINUTES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_IDLE_TOKEN_THRESHOLD",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_INCLUDE_PARTIAL_MESSAGES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_INVESTIGATE_FIRST",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_INVOKED_SKILLS",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_IS_COWORK",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_JSONL_TRANSCRIPT",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_KB_COHESION_FIXES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_LANTERN_PRISM",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_LARCH_CISTERN",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_LOOP_KEEPALIVE",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_LOOP_PERSISTENT",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_MANAGED_SETTINGS_PATH",
+ "kind": "documented",
+ "category": "environment",
+ "description": "Path to admin-managed policy settings."
+ },
+ {
+ "name": "CLAUDE_CODE_MARL_CORMORANT",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS",
+ "kind": "documented",
+ "category": "limits",
+ "description": "How many subagents may run at once."
+ },
+ {
+ "name": "CLAUDE_CODE_MAX_CONTEXT_TOKENS",
+ "kind": "documented",
+ "category": "limits",
+ "description": "Ceiling on the context window Claude Code will fill before compacting."
+ },
+ {
+ "name": "CLAUDE_CODE_MAX_OUTPUT_TOKENS",
+ "kind": "documented",
+ "category": "limits",
+ "description": "Ceiling on tokens the model may produce in one response."
+ },
+ {
+ "name": "CLAUDE_CODE_MAX_RETRIES",
+ "kind": "documented",
+ "category": "limits",
+ "description": "How many times a failed API request is retried."
+ },
+ {
+ "name": "CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY",
+ "kind": "documented",
+ "category": "limits",
+ "description": "How many tool calls may run in parallel within one turn."
+ },
+ {
+ "name": "CLAUDE_CODE_MAX_TURNS",
+ "kind": "documented",
+ "category": "limits",
+ "description": "Maximum agent turns before the session stops on its own."
+ },
+ {
+ "name": "CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_MCP_ALLOWLIST_ENV",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_MCP_SERVER_NAME",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_MCP_SERVER_URL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_MEMORY_PUSH_DELETE_MODE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_MOCK_REMOTE_SETTINGS",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_MOCK_TRIAL",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_NANKEEN_KESTREL",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_NATIVE_CURSOR",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_NEW_INIT",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_NO_FLICKER",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_NO_MODEL_FALLBACK",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OAUTH_401_WAIT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OAUTH_CLIENT_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OAUTH_REFRESH_TOKEN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OAUTH_SCOPES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OAUTH_TOKEN",
+ "kind": "documented",
+ "category": "credential",
+ "description": "OAuth access token. Written by /login; swisscode reads it only to measure subscription usage, and never refreshes it."
+ },
+ {
+ "name": "CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ORGANIZATION_UUID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OTEL_DIAG_STDERR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_OVERRIDE_DATE",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PARKED_PERMISSION_WAIT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PERFETTO_TRACE",
+ "kind": "internal",
+ "why": "profiling"
+ },
+ {
+ "name": "CLAUDE_CODE_PERFETTO_WRITE_INTERVAL_S",
+ "kind": "internal",
+ "why": "profiling"
+ },
+ {
+ "name": "CLAUDE_CODE_PERFORCE_MODE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PEWTER_OWL",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_PEWTER_OWL_TOOL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PLAN_MODE_REQUIRED",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PLAN_V2_AGENT_COUNT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PLAN_V2_EXPLORE_AGENT_COUNT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PLUGIN_BINARY_ASSETS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PLUGIN_CACHE_DIR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PLUGIN_PREFER_HTTPS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PLUGIN_SEED_DIR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PLUGIN_USE_ZIP_CACHE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_POST_FOR_SESSION_INGRESS_V2",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_POWERSHELL_RESPECT_EXECUTION_POLICY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_POWERUP_ONBOARDING",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PROACTIVE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PROCESS_WRAPPER",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_PROFILE_QUERY",
+ "kind": "internal",
+ "why": "profiling"
+ },
+ {
+ "name": "CLAUDE_CODE_PROFILE_STARTUP",
+ "kind": "internal",
+ "why": "profiling"
+ },
+ {
+ "name": "CLAUDE_CODE_PROPAGATE_TRACEPARENT",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PROXY_AUTHENTICATE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PROXY_AUTH_HELPER_TTL_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PROXY_HOST",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PROXY_RESOLVES_HOSTS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PROXY_URL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_PWSH_PARSE_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_QUESTION_PREVIEW_FORMAT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_RATE_LIMIT_TIER",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_RC_PERMISSION_NUDGE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REFUSAL_FALLBACK_CATCH_ALL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_RELAUNCH_TERMINAL_SIZE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REMOTE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REMOTE_ENVIRONMENT_TYPE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REMOTE_HERMETIC_MODE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REMOTE_MEMORY_DIR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REMOTE_RAW_EVENTS_FILE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REMOTE_SEND_KEEPALIVES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REMOTE_SESSION_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REMOTE_SESSION_ORIGIN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REMOTE_SETTINGS_PATH",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REMOTE_SETTINGS_POLL_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REPL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_REPORT_FINDINGS",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_REPO_CHECKOUTS",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_RESUME_FROM_SESSION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_RESUME_INTERRUPTED_TURN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_RESUME_INTERRUPTED_TURN_MAX_AGE_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_RESUME_PROMPT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_RESUME_SOURCE_ALIVE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_RESUME_THRESHOLD_MINUTES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_RESUME_TOKEN_THRESHOLD",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_RETRY_WATCHDOG",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SAFE_MODE",
+ "kind": "documented",
+ "category": "behaviour",
+ "description": "Set by --safe-mode. Disables customisations — CLAUDE.md, skills, plugins, hooks, MCP servers — for troubleshooting a broken configuration."
+ },
+ {
+ "name": "CLAUDE_CODE_SANDBOXED",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SCRIPT_CAPS",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_SCROLL_SPEED",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_SDK_HAS_HOST_AUTH_REFRESH",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SDK_HAS_OAUTH_REFRESH",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SEND_FEEDBACK",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SESSION_ACCESS_TOKEN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SESSION_ID",
+ "kind": "documented",
+ "category": "session",
+ "description": "The current session id. Also settable with --session-id."
+ },
+ {
+ "name": "CLAUDE_CODE_SESSION_KIND",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SESSION_LOG",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SESSION_NAME",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SHELL",
+ "kind": "documented",
+ "category": "environment",
+ "description": "Which shell the Bash tool uses."
+ },
+ {
+ "name": "CLAUDE_CODE_SHELL_PREFIX",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SIMPLE",
+ "kind": "documented",
+ "category": "behaviour",
+ "description": "Set by --bare. Skips hooks, LSP, plugin sync, auto-memory, keychain reads and CLAUDE.md discovery."
+ },
+ {
+ "name": "CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SIMULATE_PROXY_USAGE",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_SKILL_NAME",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_ANTHROPIC_GOOGLE_CLOUD_AUTH",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_AWS_CRED_CACHE",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_BEDROCK_AUTH",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_FAST_MODE_NETWORK_ERRORS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK",
+ "kind": "documented",
+ "category": "compat",
+ "description": "Skips the organisation check that reports fast mode as disabled on non-first-party endpoints.",
+ "managed": true
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_FOUNDRY_AUTH",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_HFI_VERSION_CHECK",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_MANTLE_AUTH",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_PLUGIN_MCP_SERVERS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_PLUGIN_MCP_SERVERS_EXCEPT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_PROJECT_BACKFILL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_PROMPT_HISTORY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_REPO_UPLOAD",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SKIP_VERTEX_AUTH",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_SLOW_OPERATION_THRESHOLD_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SPAWN_TIMESTAMP_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SSE_PORT",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_STALL_TIMEOUT_MS_FOR_TESTING",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_STOP_HOOK_BLOCK_CAP",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SUBAGENT_CACHE_EVICT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SUBAGENT_MODEL",
+ "kind": "documented",
+ "category": "model",
+ "description": "Model subagents run on. Pinning it matters on gateways: subagents 404 when the id is not one the endpoint serves. swisscode sets this for OpenRouter.",
+ "managed": true
+ },
+ {
+ "name": "CLAUDE_CODE_SUBPROCESS_ENV_SCRUB",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SUBSCRIPTION_TYPE",
+ "kind": "documented",
+ "category": "credential",
+ "description": "The plan behind the current login, e.g. max."
+ },
+ {
+ "name": "CLAUDE_CODE_SUPERVISED",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SUPPRESS_SESSION_ATTRIBUTION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_PLUGINS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_PLUGINS_BUFFERED_DOWNLOAD",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_PLUGINS_DOWNLOAD_STALL_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_PLUGINS_INSTALL_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_PLUGINS_MCP_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_PLUGIN_INSTALL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_SESSION_REFS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_SKILLS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_SKILLS_INSTALL_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNC_SKILLS_WAIT_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_SYNTAX_HIGHLIGHT",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_SYSTEM_PROMPT_GB_FEATURE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TAGS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TAG_ISMETA_MESSAGES",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TASK_LIST_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TEAMMATE_COMMAND",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_TEAM_TEARDOWN_PARK_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TEE_SDK_STDOUT",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TERMINAL_MCP_TOOLS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TERMINAL_RECORDING",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TEST_FIXTURES_ROOT",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_TEST_FORCE_DENY",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_TEST_NO_GIT_BASH",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_TEST_NO_PWSH",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_THISTLE_GREBE",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_TMPDIR",
+ "kind": "documented",
+ "category": "environment",
+ "description": "Temporary directory Claude Code writes to."
+ },
+ {
+ "name": "CLAUDE_CODE_TMUX_PREFIX",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TMUX_PREFIX_CONFLICTS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TMUX_SESSION",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TMUX_TRUECOLOR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TODO_REMINDER_MODE",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TOTAL_TOKENS_REMINDER",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TOTAL_TOKENS_REMINDER_AFTER_USER_TURN",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TOTAL_TOKENS_REMINDER_BUDGET",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TRANSCRIPT_LOCAL_GC",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TRIGGER_ID",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TUI_JUST_SWITCHED",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_TWO_STAGE_CLASSIFIER",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_ULTRAREVIEW_PREFLIGHT_FIXTURE",
+ "kind": "internal",
+ "why": "test hook"
+ },
+ {
+ "name": "CLAUDE_CODE_USER_DIALOG_TIMEOUT_MS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_USER_EMAIL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_USE_ANTHROPIC_AWS",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_USE_ANTHROPIC_GOOGLE_CLOUD",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_USE_BEDROCK",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_USE_COWORK_PLUGINS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_USE_FOUNDRY",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_USE_GATEWAY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_USE_MANTLE",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_USE_NATIVE_FILE_SEARCH",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_USE_POWERSHELL_TOOL",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_USE_VERTEX",
+ "kind": "internal",
+ "why": "third-party cloud provider"
+ },
+ {
+ "name": "CLAUDE_CODE_VERSION",
+ "kind": "documented",
+ "category": "environment",
+ "description": "The running Claude Code version."
+ },
+ {
+ "name": "CLAUDE_CODE_VOICE_FORWARD_INTERIMS_TYPED",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_WALNUT_SPIRE",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_WEBFETCH_USE_CCR_PROXY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_WEBSEARCH_USE_CCR_PROXY",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_WEBSOCKET_AUTH_FILE_DESCRIPTOR",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_WORKER_EPOCH",
+ "kind": "internal",
+ "why": "unreleased feature codename"
+ },
+ {
+ "name": "CLAUDE_CODE_WORKFLOWS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_WORKFLOW_SIZE_WARNING_AGENTS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_WORKFLOW_SIZE_WARNING_TOKENS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CODE_WORKSPACE_HOST_PATHS",
+ "kind": "undocumented"
+ },
+ {
+ "name": "CLAUDE_CONFIG_DIR",
+ "kind": "documented",
+ "category": "session",
+ "description": "Which directory holds the login and settings. THE BRANCH IS ON WHETHER THIS IS SET, not on its value — setting it to the default ~/.claude is a different, empty login.",
+ "managed": true
+ },
+ {
+ "name": "DISABLE_AUTOUPDATER",
+ "kind": "documented",
+ "category": "behaviour",
+ "description": "Stops Claude Code updating itself."
+ },
+ {
+ "name": "DISABLE_ERROR_REPORTING",
+ "kind": "documented",
+ "category": "telemetry",
+ "description": "Disables error reporting."
+ },
+ {
+ "name": "DISABLE_TELEMETRY",
+ "kind": "documented",
+ "category": "telemetry",
+ "description": "Disables telemetry reporting."
+ },
+ {
+ "name": "ENABLE_TOOL_SEARCH",
+ "kind": "documented",
+ "category": "compat",
+ "description": "Enables MCP tool search, which is off by default away from first-party Anthropic.",
+ "managed": true
+ },
+ {
+ "name": "MAX_THINKING_TOKENS",
+ "kind": "documented",
+ "category": "limits",
+ "description": "Ceiling on tokens spent on extended thinking."
+ }
+])
diff --git a/src/adapters/ui/ModelPicker.tsx b/src/adapters/ui/ModelPicker.tsx
index 08e0041..dae9bf1 100644
--- a/src/adapters/ui/ModelPicker.tsx
+++ b/src/adapters/ui/ModelPicker.tsx
@@ -3,6 +3,7 @@ import type { ReactNode } from 'react'
import { Box, Text, useInput } from 'ink'
import { filterModels } from '../../core/catalog.ts'
import { formatContext, formatPrice } from '../../core/format.ts'
+import { tone } from './theme.tsx'
import type { Tier } from '../../ports/provider.ts'
import type {
CatalogCapabilities,
@@ -19,12 +20,16 @@ const LEFT_WIDTH = 40
* publish tool support" can never be rendered as a confirmed "no".
*/
function Badge({ state, children }: { state: boolean | null; children: ReactNode }) {
- // Tri-state. "unknown" must not look like "no" and must not look like "yes".
+ // Tri-state. "unknown" must not look like "no" and must not look like "yes",
+ // so it gets its own ROLE as well as its own glyph: `?` in warn against a `✓`
+ // in ok and a dim `·`. The glyph used to carry that distinction alone, which
+ // meant a catalog publishing nothing looked identical to one publishing a no
+ // to anybody reading at a glance.
if (state === null || state === undefined) {
- return ? {children}
+ return ? {children}
}
return (
-
+
{state ? '✓' : '·'} {children}{' '}
)
@@ -37,10 +42,10 @@ function Score({ label, value }: { label: string; value: number | null }) {
return (
- {label}
+ {label}
- {'█'.repeat(filled)}
- {'░'.repeat(20 - filled)}
+ {'█'.repeat(filled)}
+ {'░'.repeat(20 - filled)}
{value}
)
@@ -60,10 +65,10 @@ function PriceRow({ label, value }: { label: string; value: number }) {
return (
- {label}
+ {label}
{formatPrice(value)}
- / M tokens
+ / M tokens
)
}
@@ -76,14 +81,14 @@ type DetailsProps = {
function Details({ model, capabilities }: DetailsProps) {
if (!model) {
- return No model matches this filter.
+ return No model matches this filter.
}
return (
-
+
{model.name}
-
+
{model.id}
@@ -99,16 +104,16 @@ function Details({ model, capabilities }: DetailsProps) {
) : null}
>
) : (
- pricing not published by this catalog
+ pricing not published by this catalog
)}
{model.context ? (
- context
+ context
{formatContext(model.context)}
{model.maxOutput ? (
- {` (max out ${formatContext(model.maxOutput)})`}
+ {` (max out ${formatContext(model.maxOutput)})`}
) : null}
) : null}
@@ -119,10 +124,13 @@ function Details({ model, capabilities }: DetailsProps) {
reasoning
{model.tools === false ? (
- Claude Code needs tool calling — this model will not work.
+ Claude Code needs tool calling — this model will not work.
) : null}
+ {/* Warn, not muted: the same reasoning as the `?` badge above. An
+ unpublished capability is a caveat the user has to act on, and dimming
+ it filed it with the decoration. */}
{model.tools === null ? (
-
+
tool support is not published here; Claude Code needs it, so try a short
prompt before relying on this model.
@@ -130,7 +138,7 @@ function Details({ model, capabilities }: DetailsProps) {
{capabilities.benchmarks && model.benchmarks ? (
- artificial analysis
+ artificial analysis
@@ -139,7 +147,7 @@ function Details({ model, capabilities }: DetailsProps) {
{model.description ? (
-
+
{model.description.slice(0, 260).trim()}
{model.description.length > 260 ? '…' : ''}
@@ -251,14 +259,14 @@ export function ModelPicker({ tier, current, catalog, onSelect, onCancel }: Mode
})
if (state.loading) {
- return Loading models from {catalog.label}…
+ return Loading models from {catalog.label}…
}
if (state.models.length === 0) {
return (
- Could not reach {catalog.label}: {state.error}
- Press esc to go back and type the model id by hand.
+ Could not reach {catalog.label}: {state.error}
+ Press esc to go back and type the model id by hand.
)
}
@@ -281,14 +289,14 @@ export function ModelPicker({ tier, current, catalog, onSelect, onCancel }: Mode
return (
- model for
- {tier}
- · search:
+ model for
+ {tier}
+ · search:
{query}
- ▌
+ ▌
-
+
{visible.length}/{state.models.length} shown
{toolsOnly && capabilities.toolSupportKnown ? ' · tools only' : ''}
{freeOnly && capabilities.pricing ? ' · free only' : ''}
@@ -300,17 +308,13 @@ export function ModelPicker({ tier, current, catalog, onSelect, onCancel }: Mode
{window.length === 0 ? (
- no matches
+ no matches
) : (
window.map((m) => {
const active = visible[cursor]?.id === m.id
return (
-
+
{active ? '› ' : ' '}
{m.id === current ? '● ' : ''}
{m.id}
@@ -326,7 +330,7 @@ export function ModelPicker({ tier, current, catalog, onSelect, onCancel }: Mode
- {hints.join(' · ')}
+ {hints.join(' · ')}
)
diff --git a/src/adapters/ui/ProfilePicker.tsx b/src/adapters/ui/ProfilePicker.tsx
index b8f4cb8..a0ff880 100644
--- a/src/adapters/ui/ProfilePicker.tsx
+++ b/src/adapters/ui/ProfilePicker.tsx
@@ -1,8 +1,8 @@
import React from 'react'
import { Box, Text } from 'ink'
-import SelectInput from 'ink-select-input'
import { TIERS } from '../../core/tiers.ts'
import { resolveProfileRefs } from '../../core/resolve.ts'
+import { Select, tone } from './theme.tsx'
import type { ResolvedProfile, State } from '../../ports/config-store.ts'
/**
@@ -71,21 +71,21 @@ export function ProfilePicker({ state, onPick, onNew }: ProfilePickerProps) {
return (
- Profiles · ★ is the default · enter to open
+ Profiles · ★ is the default · enter to open
{names.map((name) => (
- {name}
+ {name}
-
+
{summarize(resolvedOrUndefined(state, name), bindingCounts.get(name) ?? 0)}
))}
- (item.value === '__new' ? onNew() : onPick(item.value))}
/>
@@ -148,10 +148,10 @@ export function ProfileActions({ name, state, cwd, onAction }: ProfileActionsPro
return (
- Profile {name}
+ Profile {name}
- onAction(item.value)} />
+
)
@@ -172,15 +172,15 @@ export type ConfirmDeleteProps = {
export function ConfirmDelete({ name, bindings, onConfirm, onCancel }: ConfirmDeleteProps) {
return (
- Delete profile "{name}"?
- Its API key is removed from config.json and cannot be recovered.
+ Delete profile "{name}"?
+ Its API key is removed from config.json and cannot be recovered.
{bindings.length > 0 ? (
-
+
{bindings.length} directory binding{bindings.length === 1 ? '' : 's'} will be removed too.
) : null}
- =>
function Frame({ children }: { children: ReactNode }) {
return (
-
+
-
- swisscode
-
- · esc to cancel
+ swisscode
+ · esc to cancel
{children}
@@ -62,9 +66,9 @@ function Row({ label, value, dim }: { label: string; value: string; dim?: boolea
return (
- {label}
+ {label}
- {value}
+ {value}
)
}
@@ -136,6 +140,18 @@ type Step =
| 'perms'
| 'saveError'
+/**
+ * The one-line banner above the profile list, and the tone to read it in.
+ *
+ * The tone travels WITH the text because only the site that produced the
+ * message knows which it is. `bindPath` refusing a directory puts its `reason`
+ * here, and while this was a bare string that refusal rendered in the same
+ * green as "…is now the default profile" — a failure wearing the success
+ * colour, which is the exact class of silent-wrong-answer the rest of the
+ * codebase is built to make impossible.
+ */
+type Notice = { text: string; tone: 'ok' | 'warn' }
+
export type AppProps = {
mode?: AppMode | undefined
/** pre-loaded config document; null means read it from the store */
@@ -256,7 +272,7 @@ export function App({
// `undefined` is in this type deliberately: a throw carrying no `.message`
// stores undefined. Ink renders undefined and null identically (nothing).
const [saveError, setSaveError] = useState(null)
- const [notice, setNotice] = useState(null)
+ const [notice, setNotice] = useState(null)
const providers = registry.all()
const provider = registry.byId(providerId)
@@ -298,7 +314,7 @@ export function App({
return false
}
setDoc(next)
- if (message) setNotice(message)
+ if (message) setNotice({ text: message, tone: 'ok' })
return true
}
@@ -343,7 +359,7 @@ export function App({
// writing down an existing one.
const result = bindPath(doc, cwdKey as string, name)
if (!result.ok) {
- setNotice(result.reason)
+ setNotice({ text: result.reason, tone: 'warn' })
return setStep('profiles')
}
persist(result.state, `${result.key} now uses "${name}".`)
@@ -468,10 +484,10 @@ export function App({
if (step === 'saveError') {
return (
- Could not save your configuration.
- {saveError}
+ Could not save your configuration.
+ {saveError}
- Press any key to close. Nothing was launched.
+ Press any key to close. Nothing was launched.
)
@@ -480,7 +496,7 @@ export function App({
if (step === 'profiles') {
return (
- {notice ? {notice} : null}
+ {notice ? {notice.text} : null}
{
@@ -549,11 +565,11 @@ export function App({
return (
Name for the new profile:
-
+
`swisscode {newName.trim() || ''}` in any directory will use it.
- ›
+ ›
{
@@ -564,7 +580,7 @@ export function App({
onSubmit={submit}
/>
- {nameError ? {nameError} : null}
+ {nameError ? {nameError} : null}
)
}
@@ -574,10 +590,10 @@ export function App({
const index = Math.max(0, providers.findIndex((p) => p.id === providerId))
return (
- {editingName ? profile: {editingName} : null}
+ {editingName ? profile: {editingName} : null}
Which provider should Claude Code talk to?
- chooseProvider(item.value)}
@@ -593,7 +609,7 @@ export function App({
Base URL for the Anthropic-compatible endpoint:
- ›
+ ›
- API key ({provider!.credentialEnv})
+ API key ({provider!.credentialEnv})
- {provider!.hints?.keyHint ? {provider!.hints.keyHint} : null}
- {provider!.hints?.note ? {provider!.hints.note} : null}
+ {provider!.hints?.keyHint ? {provider!.hints.keyHint} : null}
+ {provider!.hints?.note ? {provider!.hints.note} : null}
- ›
+ ›
- stored at ~/.config/swisscode/config.json (chmod 600)
+ stored at ~/.config/swisscode/config.json (chmod 600)
)
@@ -686,9 +702,9 @@ export function App({
return (
- Pick a model per tier · enter to browse
+ Pick a model per tier · enter to browse
- {
if (item.value === '__done') return setStep('perms')
@@ -705,14 +721,16 @@ export function App({
return (
- Model for each tier · enter to advance
+ Model for each tier · enter to advance
{/* `provider!` — same step-machine invariant as the apiKey screen. */}
- {provider!.hints?.modelHint ? {provider!.hints.modelHint} : null}
+ {provider!.hints?.modelHint ? (
+ {provider!.hints.modelHint}
+ ) : null}
{TIERS.map((t, i) => (
-
+
{i === tier ? '› ' : ' '}
{t}
@@ -736,9 +754,9 @@ export function App({
Pass --dangerously-skip-permissions by default?
- override per run with --safe or --yolo
+ override per run with --safe or --yolo
- ` a role is allowed to set.
+ *
+ * Narrow on purpose. `italic`, `underline` and `strikethrough` are rendered by
+ * some emulators and silently dropped by others, so a role built on one would
+ * be invisible exactly where its second channel is needed most.
+ * `backgroundColor` is worse than unreliable — see `selected`.
+ */
+type ToneProps = Pick
+
+/**
+ * The one accent hue, spelled once.
+ *
+ * Two roles use it and the difference between them is emphasis, not meaning,
+ * which is the sort of thing that stops being true the moment the string is
+ * written twice.
+ */
+const ACCENT = 'cyan'
+
+export const tone = {
+ /**
+ * Labels, hints, footers, stated absences — everything the eye should skip on
+ * its way to the answer. The web's `content.tertiary`.
+ */
+ muted: { dimColor: true },
+
+ /**
+ * The subject of a screen: the model you are inspecting, the profile you are
+ * acting on, the wordmark. WEIGHT, NOT HUE, because that is what the web does
+ * — a heading there is `fontWeight: 'title'` over the ordinary text colour —
+ * and because spending the accent on text that cannot be interacted with is
+ * what stops `›` and the cursor row from meaning anything.
+ */
+ heading: { bold: true },
+
+ /**
+ * An affordance: the `›` you type after, the `▌` marking the live cursor, the
+ * filled part of a meter. Reserved for things that are interactive or are
+ * tracking the interaction.
+ */
+ accent: { color: ACCENT },
+
+ /**
+ * The row the cursor is on.
+ *
+ * The web slides a `surface.panel` background under its selected row. A
+ * terminal must not: the background belongs to the user's colour scheme, and
+ * painting one is how a UI ends up with unreadable text under a theme its
+ * author never ran. Hue and weight do that work here, and every list using
+ * this also dims its other rows and prefixes the active one with `›`, so the
+ * selection survives with no colour at all.
+ */
+ selected: { color: ACCENT, bold: true },
+
+ /** Something the user asked for happened. */
+ ok: { color: 'green', bold: true },
+
+ /**
+ * Proceed, but know this: a binding the core refused, a capability the
+ * catalog declines to publish. Distinct from `muted`, which says "not
+ * important" — an unknown is important precisely because it is unknown, and
+ * rendering the two the same is how a caveat gets read as decoration.
+ */
+ warn: { color: 'yellow', bold: true },
+
+ /** It failed, or it is going to. */
+ danger: { color: 'red', bold: true },
+} satisfies Record
+
+/**
+ * The wizard's frame, which `` takes as a bare colour rather
+ * than as `` props.
+ *
+ * The accent, not the recessive hairline the web draws around a panel. A
+ * browser separates a panel from the page with a background it paints; this
+ * border is the only thing dividing the wizard from the scrollback above it, so
+ * it does the job `surface.panel` does there. It is also the surface that
+ * currently holds focus, and an accent-coloured edge on the focused thing is
+ * what the web draws too (`_focus: { borderColor: 'accent.default' }`).
+ */
+export const frameBorder = ACCENT
+
+/**
+ * `ink-select-input` renders every menu in the wizard, and it hardcodes `blue`
+ * for both the pointer and the highlighted label.
+ *
+ * That is one meaning — "this is the row you are on" — wearing a second colour,
+ * on the most-looked-at pixel of the first screen a new user ever sees, right
+ * next to hand-rolled lists that spell the same idea in `selected`. The library
+ * anticipates this and takes `indicatorComponent` / `itemComponent`, so the
+ * menus join the table rather than sitting outside it.
+ *
+ * Unselected rows get NO props, not `muted`. Every row here is a live choice;
+ * dimming the ones the cursor happens to be off would file the user's options
+ * with the footnotes. The hand-rolled lists dim their inactive rows because
+ * those are reference data — the tier you are not editing, the model you are
+ * not on — and that difference is the reason there is no single "list row"
+ * role.
+ */
+function ThemedIndicator({ isSelected = false }: IndicatorProps) {
+ return (
+
+ {/* The library reaches for `figures.pointer`, which degrades to `>` on a
+ console with no Unicode. `figures` is its dependency and not ours, and
+ adding one to a project that advertises four is not a trade worth
+ making for a fallback the wizard already forfeited everywhere else —
+ `›`, `★`, `✓`, `▌` and `█` all ship unguarded. Same glyph, one hue
+ moved. */}
+ {isSelected ? ❯ : }
+
+ )
+}
+
+function ThemedItem({ isSelected = false, label }: ItemProps) {
+ return {label}
+}
+
+/**
+ * A `SelectInput` that knows the palette. Every menu in the wizard goes through
+ * here.
+ *
+ * The props type is read off the library's own component rather than restated,
+ * so this stays a pass-through: a wrapper that redeclared the interface would
+ * be inventing a contract, and would drift the first time the library added an
+ * option. `typeof SelectInput` instantiates the generic, so `onSelect` still
+ * hands back the caller's own value type — which is what keeps the models step
+ * able to test `item.value === '__done'` and narrow the rest to a `Tier`
+ * without an assertion.
+ */
+export function Select(props: Parameters>[0]) {
+ return
+}
diff --git a/src/adapters/web/api.ts b/src/adapters/web/api.ts
index 22ab685..14793e2 100644
--- a/src/adapters/web/api.ts
+++ b/src/adapters/web/api.ts
@@ -14,6 +14,7 @@ import { toCustomProvider, validateCustomProvider } from '../../core/provider-de
import { TIERS } from '../../core/tiers.ts'
import { accountsUsedBy, validateAccount } from '../../core/account.ts'
import { COMPAT_ENV, CREDENTIAL_ENVS } from '../agents/claude-code/env.ts'
+import { CATALOG_SOURCE, CLAUDE_ENV_CATALOG } from '../agents/claude-code/env-catalog.ts'
import type {
AgentProfile,
ConfigStorePort,
@@ -357,6 +358,14 @@ export function handleApi(req: ApiRequest, deps: ApiDeps): ApiResponse {
})
}
+ // Every environment variable Claude Code references, for the browser to
+ // search. Its own route rather than a field on `bootstrap`: it is ~57 kB of
+ // static data that only one screen wants, and paying for it on every cold
+ // start would be a tax on people who never open that screen.
+ if (resource === 'claude-env' && req.method === 'GET') {
+ return json(200, { source: CATALOG_SOURCE, variables: CLAUDE_ENV_CATALOG })
+ }
+
if (resource === 'profiles') {
const name = rest[0] ? decodeURIComponent(rest[0]) : null
if (!name) return fail(400, 'profile name is required')
diff --git a/src/adapters/web/security.ts b/src/adapters/web/security.ts
index 74f24ca..729cea8 100644
--- a/src/adapters/web/security.ts
+++ b/src/adapters/web/security.ts
@@ -20,6 +20,8 @@
* the attacker's page is forbidden by the same-origin policy from reading our
* response body to learn it.
*/
+import { createHash } from 'node:crypto'
+
export type WebSecurityOptions = {
token: string
/** the port the server actually bound, needed to validate Host exactly */
@@ -168,6 +170,52 @@ export function guardDocumentRequest(
* `Cache-Control: no-store` because the document carries the session token, and
* a token in a disk cache outlives the server that issued it.
*/
+/**
+ * The CSP for a document, with the hashes of the inline scripts it contains.
+ *
+ * WHY HASHES AND NOT `unsafe-inline`. The page needs exactly one inline script:
+ * the theme resolver, which must run BEFORE first paint or every dark-mode user
+ * gets a white flash on load. Deferring it to React is what causes that flash,
+ * and moving it to a file makes the document depend on a second request to look
+ * right. So it stays inline — and the CSP names its exact bytes.
+ *
+ * This is TIGHTER than it looks, not a loosening. `unsafe-inline` would allow
+ * any injected script to run; a hash allows one specific script and nothing
+ * else, so an attacker who manages to inject a `