CLAUDE LABJP
TEACHERS — Anthropic launches Claude for Teachers, giving verified US K-12 educators free premium access, teaching skills, and curriculum links aligned to standards in all 50 statesADMIN — The Admin API is now in beta for every Claude Enterprise organization: member and invite calls need no beta header, while group and custom-role calls doM365 — The Microsoft 365 connector gains write tools — draft, send, and organize email, manage calendar events and mailbox settings, and create or update files in OneDrive and SharePointMCP — Fixed servers from --mcp-config or .mcp.json ignoring a per-server request_timeout_ms, which left long-running tool calls timing out at the 60s default in fresh sessionsSUBAGENT — A new --forward-subagent-text flag and CLAUDE_CODE_FORWARD_SUBAGENT_TEXT variable include subagent text and thinking in stream-json outputDEADLINE — Opus 4.7 fast mode is removed on July 24, seven days out. speed: "fast" will error, so confirm your move to Opus 4.8TEACHERS — Anthropic launches Claude for Teachers, giving verified US K-12 educators free premium access, teaching skills, and curriculum links aligned to standards in all 50 statesADMIN — The Admin API is now in beta for every Claude Enterprise organization: member and invite calls need no beta header, while group and custom-role calls doM365 — The Microsoft 365 connector gains write tools — draft, send, and organize email, manage calendar events and mailbox settings, and create or update files in OneDrive and SharePointMCP — Fixed servers from --mcp-config or .mcp.json ignoring a per-server request_timeout_ms, which left long-running tool calls timing out at the 60s default in fresh sessionsSUBAGENT — A new --forward-subagent-text flag and CLAUDE_CODE_FORWARD_SUBAGENT_TEXT variable include subagent text and thinking in stream-json outputDEADLINE — Opus 4.7 fast mode is removed on July 24, seven days out. speed: "fast" will error, so confirm your move to Opus 4.8
Articles/Claude Code
Claude Code/2026-04-24Advanced

Claude Code Environment Variables — The Complete Practical Reference

A practitioner-focused reference for every Claude Code environment variable that actually matters. Covers API connectivity, model selection, PowerShell tool quirks, logging, timeouts, security flags, and real-world templates for solo, team, and CI/CD setups.

Claude Code196environment variablesAPI27PowerShell2operations15CI/CD18

You change one setting in Claude Code. You cross-check three pages of the official docs, skim two GitHub issues, and the change still doesn't take effect. If that sounds familiar, you're not alone. Claude Code's environment variables grow quietly with each release, and they sometimes appear in sample repos before they appear in the official reference.

This article organizes what I've learned after more than a year of running Claude Code in production — for solo projects, small teams, and CI pipelines. It's not a replacement for the official reference. It's a map from the operator's side, sorted by how often you'll reach for each variable, how easy it is to shoot yourself in the foot, and the security posture it affects.

How Settings Resolve — And Who Wins When They Conflict

Claude Code settings come from several sources that overlap: CLI flags, user ~/.claude/settings.json, per-project .claude/settings.json, managed settings (/etc/claude/managed_settings.json), environment variables, and built-in defaults. Knowing the precedence order prevents mystery bugs.

From strongest to weakest:

  • CLI flags (--model, --temperature, and friends)
  • Project-level .claude/settings.json
  • User-level ~/.claude/settings.json
  • Managed settings (organization-distributed)
  • Environment variables
  • Built-in defaults

In other words, environment variables are the baseline layer. Put things there that you want active for every session, everywhere. Put per-project preferences in .claude/settings.json — you'll thank yourself later.

In CI, it's common not to check .claude/settings.json into the repo at all, so letting environment variables control everything is perfectly reasonable. There's no single right split; match the layer to how your team already works.

API Connectivity Variables

Start here. If these are wrong, nothing else matters.

# Direct Anthropic API (most common)
export ANTHROPIC_API_KEY="YOUR_ANTHROPIC_API_KEY"
 
# Custom endpoint (proxy, internal gateway, staging)
export ANTHROPIC_BASE_URL="https://api.anthropic.com"
 
# Claude via Amazon Bedrock
export CLAUDE_CODE_USE_BEDROCK=1
export AWS_REGION="us-east-1"
 
# Claude via Google Vertex AI
export CLAUDE_CODE_USE_VERTEX=1
export CLOUD_ML_REGION="us-east5"
export ANTHROPIC_VERTEX_PROJECT_ID="your-gcp-project"

CLAUDE_CODE_USE_BEDROCK and CLAUDE_CODE_USE_VERTEX are mutually exclusive. If you set both to 1, one wins internally (usually Bedrock), but that order isn't a guaranteed API — pick one and stick with it.

For solo work, an ANTHROPIC_API_KEY in your shell is fine. For teams, prefer SSO-backed login. Run claude login once, then delete the env var — Claude Code keeps the credentials in its own store. This keeps the key out of .bashrc, which matters the first time you screen-share.

Storing API Keys Safely

Plaintext API keys in .bashrc is the worst case. Use your platform's credential store instead. On macOS, Keychain works nicely:

# Register once
security add-generic-password -a "$USER" -s "anthropic-api-key" -w "YOUR_ANTHROPIC_API_KEY"
 
# Add to .zshrc so every shell pulls it fresh
export ANTHROPIC_API_KEY=$(security find-generic-password -a "$USER" -s "anthropic-api-key" -w 2>/dev/null)

With this pattern, nobody running env over your shoulder or in a recorded screen share sees the raw key.

Model and Inference Parameters

Claude Code lets you switch models per session, but pinning a baseline via env vars prevents surprises — the one time you forget --model, the default should still be sensible.

# Default model for main reasoning
export ANTHROPIC_MODEL="claude-sonnet-4-6"
 
# Small, fast model for auxiliary tasks (planning, summarizing)
export ANTHROPIC_SMALL_FAST_MODEL="claude-haiku-4-5-20251001"
 
# Max output tokens per response
export CLAUDE_CODE_MAX_OUTPUT_TOKENS=8192
 
# Temperature — lower is more deterministic
export ANTHROPIC_TEMPERATURE=0.2

ANTHROPIC_SMALL_FAST_MODEL is the one most people miss. Claude Code uses it for short internal tasks (like splitting work into subtasks), and routing those to Haiku instead of Sonnet noticeably lowers your monthly bill. My go-to pairing is Sonnet 4.6 for main work, Haiku 4.5 for the small-fast slot.

A Note on Temperature

Lower temperatures (0.0–0.3) are best for code generation. Higher temperatures (0.5–0.7) fit natural-language work like doc writing or commit messages. If your repo spans both worlds, let the env var be the safe default and override per-project in settings.json.

Tool Enablement — Including the PowerShell Flag

Windows developers: CLAUDE_CODE_USE_POWERSHELL_TOOL=1 is the variable you want. It makes Claude Code prefer the Powershell tool over Bash for shell commands.

# Windows: enable PowerShell tool
export CLAUDE_CODE_USE_POWERSHELL_TOOL=1
 
# Optional: limit parallel tool calls (especially with many MCP servers)
export CLAUDE_CODE_MAX_PARALLEL_TOOL_CALLS=3

The docs say "recommended for Windows users" and leave it there. In practice, there are three pitfalls the docs don't mention:

  • It breaks in WSL. If you run Claude Code inside WSL while this env var is set globally, the tool tries to spawn PowerShell and fails (there's Bash, not PowerShell). In WSL shells, explicitly set CLAUDE_CODE_USE_POWERSHELL_TOOL=0.
  • Pipe semantics differ. Bash pipes pass text; PowerShell pipes pass objects. When Claude translates a Bash command in its head, grep becomes Select-String, awk becomes ForEach-Object. Older Claude Code versions occasionally confused the two and produced broken one-liners.
  • UTF-8 isn't the default. On Japanese Windows systems, output often arrives in Shift-JIS (CP932), which makes Claude Code hallucinate that paths don't exist when they contain non-ASCII characters. Fix it in $PROFILE:
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
chcp 65001

The third one cost me a full afternoon before I traced it. A Japanese folder name was rendered as mojibake, Claude insisted the path was invalid, and the fix turned out to be a two-line PowerShell profile edit.

Logging, Debugging, and Telemetry

When things go sideways, you'll want verbose output. Claude Code is quiet by default; these variables unlock the details.

# General debug mode
export CLAUDE_CODE_DEBUG=1
 
# Dump full prompts (be careful — prompts may contain source code)
export CLAUDE_CODE_DEBUG_PROMPT=1
 
# Dump raw API request/response JSON
export CLAUDE_CODE_DEBUG_API=1
 
# Send logs somewhere other than stderr
export CLAUDE_CODE_LOG_FILE="$HOME/.claude/debug.log"

A serious warning on CLAUDE_CODE_DEBUG_PROMPT=1: if your prompt contains the full contents of a source file, that file gets written to the log. On shared machines or in any environment where the log might be uploaded (CI artifacts, crash dumps, remote support), don't leave this on. Turn it on, capture the repro, turn it off, delete the log.

For privacy-sensitive teams, disable telemetry and crash reporting:

export CLAUDE_CODE_TELEMETRY=0
export CLAUDE_CODE_CRASH_REPORTING=0

Timeouts, Retries, and Performance

For long-running agentic sessions, timeouts and retries determine how patient (or impatient) Claude Code is with a flaky network.

# Per-HTTP-request timeout (ms)
export CLAUDE_CODE_REQUEST_TIMEOUT=300000   # 5 min
 
# Per-tool execution timeout (ms)
export CLAUDE_CODE_TOOL_TIMEOUT=600000      # 10 min
 
# Automatic retry budget
export CLAUDE_CODE_MAX_RETRIES=3
 
# Base for exponential backoff (ms)
export CLAUDE_CODE_RETRY_BASE_MS=1000

If you run Claude Code against large codebases, bump CLAUDE_CODE_REQUEST_TIMEOUT above the default. Sonnet 4.6 can legitimately take over two minutes to respond on multi-thousand-line diffs.

In CI, do the opposite — keep timeouts short and fail fast. A 30-minute hanging job ties up your runners and masks real problems.

Security and Privacy

Self-hosted and enterprise deployments lean on these heavily.

# Block file access outside the current project
export CLAUDE_CODE_PROJECT_SCOPE_STRICT=1
 
# Sandbox shell execution (macOS sandbox-exec / Linux bwrap)
export CLAUDE_CODE_SANDBOX=1
 
# Disable WebFetch entirely
export CLAUDE_CODE_DISABLE_WEB_FETCH=1
 
# Human approval per tool call
export CLAUDE_CODE_REQUIRE_APPROVAL=all

CLAUDE_CODE_REQUIRE_APPROVAL takes edit (confirm file edits), bash (confirm shell commands), all (confirm everything), or none (silent). My daily driver is edit. I switch to all when I'm working in an unfamiliar repo where I don't yet trust my own instincts about what "safe" means.

Three Templates to Copy-Paste

Template 1: Solo Developer

# ~/.zshrc or ~/.bashrc
export ANTHROPIC_API_KEY=$(security find-generic-password -a "$USER" -s "anthropic-api-key" -w 2>/dev/null)
export ANTHROPIC_MODEL="claude-sonnet-4-6"
export ANTHROPIC_SMALL_FAST_MODEL="claude-haiku-4-5-20251001"
export CLAUDE_CODE_MAX_OUTPUT_TOKENS=8192
export ANTHROPIC_TEMPERATURE=0.2
export CLAUDE_CODE_REQUEST_TIMEOUT=300000
export CLAUDE_CODE_REQUIRE_APPROVAL=edit

Baseline model choices, edit-only confirmations for safety, and Keychain-backed API key so env doesn't leak it in screen shares.

Template 2: Internal Team

# /etc/profile.d/claude-code.sh
export ANTHROPIC_BASE_URL="https://llm-gateway.your-company.internal"
export CLAUDE_CODE_USE_BEDROCK=0
export CLAUDE_CODE_USE_VERTEX=0
export CLAUDE_CODE_TELEMETRY=0
export CLAUDE_CODE_CRASH_REPORTING=0
export CLAUDE_CODE_PROJECT_SCOPE_STRICT=1
export CLAUDE_CODE_REQUIRE_APPROVAL=edit

Route all calls through an internal gateway for auditability, cut telemetry, strict project scoping.

Template 3: CI/CD

# GitHub Actions
env:
  ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
  ANTHROPIC_MODEL: claude-haiku-4-5-20251001
  CLAUDE_CODE_MAX_OUTPUT_TOKENS: 4096
  CLAUDE_CODE_REQUEST_TIMEOUT: 60000
  CLAUDE_CODE_TOOL_TIMEOUT: 120000
  CLAUDE_CODE_MAX_RETRIES: 2
  CLAUDE_CODE_REQUIRE_APPROVAL: none
  CLAUDE_CODE_TELEMETRY: 0

Cost and speed trump everything. Haiku as default, short timeouts, no human-in-the-loop.

Troubleshooting Patterns That Actually Come Up

"It works in my terminal but not in VS Code." VS Code's integrated terminal doesn't always inherit shell env vars the way you'd expect, especially when the profile uses non-interactive mode. Either enable "Inherit env" in settings, or set the env vars in VS Code's terminal profile directly.

"It works in my terminal but not in the extension." The Claude Code VS Code extension loads its own process and may not pick up your shell. Configure the extension's settings pane for a deterministic source of truth.

"It works outside Docker but not inside." Container processes inherit nothing from the host shell. Pass env vars explicitly with docker run -e ANTHROPIC_API_KEY or the environment: block of your compose file.

The usual debugging order is: confirm process inheritance, grep for duplicates across shell profiles, then trace precedence. Each of those three has eaten an afternoon from me at some point.

What to Do Next

Once your env vars form a clean baseline, the next layer is .claude/settings.json — where you override per-project quirks without touching the global defaults. The three-layer setup (env vars → user settings → project settings) scales well from hobby repos to enterprise monorepos. For the per-project side, see our complete guide to Claude Code settings.json.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Claude Code2026-07-14
An Empty Variable and rm -rf: How Claude Code's Auto Mode Preflight Saved My Late-Night Cleanup
One night I let Claude Code sweep the build caches out of several app repositories at once, and an empty variable nearly turned a targeted cleanup into a wide delete. Here is the field record of being saved by auto mode's rm -rf preflight, and the confirmation rules I built afterward.
Claude Code2026-06-18
Moving Cleanup and Logging into a SessionEnd Hook
How to use Claude Code's new post-session hook to automate temp-file cleanup and log writing after a session ends, with real examples from a pipeline that processes several repositories in sequence.
Claude Code2026-06-17
When an Announced Billing Change Gets Paused at the Last Minute: Designing Automation That Doesn't Rush the Cutover
A billing change that was supposed to take effect on June 15 was paused that same day. If your pipeline trusts the announced date, a retraction breaks it twice. Here is a design that decides the cutover from a runtime signal, with implementation code.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →