Claude Code uses four settings scopes, applied from highest to lowest priority:
Priority
Scope
Location
Shared?
Purpose
1
Managed
Server, MDM profile, registry, or system managed-settings.json
Yes (IT-deployed)
Org-wide policies, cannot be overridden
2
Command line
-- flags at startup
No
Temporary session overrides
3
Local
.claude/settings.local.json
No (gitignored)
Personal project-specific
4
Project
.claude/settings.json
Yes (committed)
Team-shared settings
5
User
~/.claude/settings.json
No
Global personal defaults
Array merging: Settings like permissions.allow, sandbox.filesystem.allowWrite, and allowedHttpHookUrls are concatenated and deduplicated across scopes — not replaced.
Deny precedence:permissions.deny rules always take effect regardless of allow/ask rules at any scope.
Managed settings delivery methods:
Server-managed (Claude.ai admin console)
macOS MDM: com.anthropic.claudecode plist
Windows registry: HKLM\SOFTWARE\Policies\ClaudeCode
Other config:~/.claude.json stores OAuth session, MCP server configs, per-project trust state, and preferences like editorMode. Do not put ~/.claude.json keys into settings.json — it will trigger schema validation errors.
JSON Schema URL for IDE validation and autocomplete. Add "https://json.schemastore.org/claude-code-settings.json" to enable inline validation in VS Code, Cursor, and other editors.
Override the default model for all sessions. Accepts aliases ("sonnet", "opus", "haiku", "opusplan") or full model IDs like "claude-sonnet-4-6". The ANTHROPIC_MODEL environment variable takes precedence.
Run the main thread as a named subagent. Applies that agent’s system prompt, tool restrictions, and model. Value must match an agent defined in .claude/agents/. Also available via --agent CLI flag.
Sessions inactive longer than this number of days are deleted at startup. Setting to 0 deletes all existing transcripts at startup and disables session persistence entirely — no .jsonl files are written, /resume shows no conversations, and hooks receive an empty transcript_path.
Include built-in commit and PR workflow instructions and a git status snapshot in the system prompt. Set to false when using a custom git workflow skill. The CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS env var takes precedence.
When true, fast mode does not persist across sessions. Each session starts with fast mode off, requiring users to enable it with /fast. The user’s preference is still saved.
Environment variables applied to every session. Use this instead of wrapper scripts to set variables. See the Environment Variables section for all supported keys.
Type: string
Scope: user / local / managed
Default: none
Custom directory for auto-memory storage. Accepts ~/-expanded paths. Not accepted in project settings (.claude/settings.json) to prevent shared repos from redirecting memory writes to sensitive locations.
Type: string
Scope: all
Default: none
Values:"disable"
Set to "disable" to prevent bypassPermissions mode from being activated. Disables the --dangerously-skip-permissions flag. Most useful in managed settings.
Rules follow the format Tool or Tool(specifier). Evaluation order: deny first, then ask, then allow. The first matching rule wins.
Tool
Pattern
Example
Bash
Command pattern with wildcards
Bash(npm run *), Bash(git *)
Read
File path pattern
Read(.env), Read(./secrets/**)
Edit
File path pattern
Edit(src/**), Edit(*.ts)
Write
File path pattern
Write(*.md)
WebFetch
domain:hostname
WebFetch(domain:example.com)
WebSearch
No specifier
WebSearch
Task
Agent name
Task(Explore)
Agent
Agent name
Agent(researcher)
MCP
mcp__server__tool or MCP(server:tool)
mcp__memory__*
Path prefixes for Read/Edit rules:
Prefix
Meaning
//
Absolute path from filesystem root
~/
Relative to home directory
/
Relative to project root
./ or none
Relative path (current directory)
Bash wildcard notes:* matches at any position. Bash(ls *) (space before *) matches ls -la but NOT lsof. Bash(*) is equivalent to Bash (matches all commands). The legacy :* suffix (e.g., Bash(npm:*)) is deprecated.
{
"permissions": {
"allow": ["Edit(*)", "Bash(npm run *)", "Bash(git *)"],
Configure custom commands to run at lifecycle events. See the hooks documentation and §7.1 of the guide for the full set of 30 hook events, exit codes, and environment variables.
Type: array of strings
Scope: all
Default: none (no restriction)
Allowlist of URL patterns that HTTP hooks may target. Supports * as a wildcard. When defined, hooks with non-matching URLs are silently blocked. Empty array blocks all HTTP hooks. Arrays merge across settings sources.
Type: array of strings
Scope: all
Default: none (no restriction)
Allowlist of environment variable names that HTTP hooks can interpolate into header values. Each hook’s effective allowedEnvVars is the intersection with this list. Arrays merge across settings sources.
Type: array
Scope: managed only
Default: none (no restrictions)
Allowlist of MCP servers users can configure. Each entry matches by serverName, serverCommand, or serverUrl. Undefined = no restrictions, empty array = lockdown.
When true, only allowedMcpServers from managed settings are respected. Users can still add MCP servers, but only admin-defined servers are usable. deniedMcpServers still merges from all sources.
Allowlist of channel plugins that may push messages. Replaces the default Anthropic allowlist when set. Requires channelsEnabled: true. Empty array blocks all channel plugins.
Exit with an error at startup if sandbox.enabled is true but the sandbox cannot start (missing dependencies, unsupported platform). When false, a warning is shown and commands run unsandboxed. Useful in managed deployments that require sandboxing as a hard gate.
Auto-approve bash commands when sandboxed. When the sandbox is active, bash commands that would normally require confirmation are automatically approved.
Commands that bypass the sandbox and run directly in your environment.
Use the glob form, not the bare name. A bare entry such as "git" matches only the zero-argument string git, so it never fires on a real invocation and the command stays sandboxed. Write "git *" instead. The bare form is what the published JSON schema suggests, which is why this is easy to get wrong: you configure something that does nothing, notice the command is still sandboxed, and only then find the glob form (anthropics/claude-code#10524). Verified on 2.1.220: "git" had no effect, "git *" worked immediately.
A match unsandboxes the entire Bash invocation. When an entry matches anywhere in a compound command, every other command in that same call runs unsandboxed too, including commands that execute before the excluded one. With "git *" present, git status && cat ~/.ssh/id_ed25519 reads the key, because filesystem.denyRead, credentials, and the network allowlist are all suspended for that call (anthropics/claude-code#81157, open as of 2026-07-25 on 2.1.220).
Scope entries to the subcommands that genuinely need to leave the sandbox rather than the whole binary. Git over SSH is the common case: only the network operations need an exception, so list those and leave local git confined.
This keeps git status, git diff, git log, git add, and git commit inside the sandbox, so the bypass window only opens on the calls that actually talk to a remote.
Allow commands to opt out of the sandbox via the dangerouslyDisableSandbox parameter. Set to false for strict sandboxing where all commands must run inside the sandbox or be in excludedCommands.
(macOS only) Allow access to the system TLS trust service (com.apple.trustd.agent). Required for Go-based tools like gh, gcloud, and terraform when using httpProxyPort with a MITM proxy and custom CA. Reduces security.
When true, only allowedDomains and WebFetch(domain:...) allow rules from managed settings are respected. Non-allowed domains are blocked without prompting. Denied domains are still respected from all sources.
Additional paths where sandboxed commands can write. Merged across all settings scopes. Also merged with paths from Edit(...) allow permission rules.
Path prefix conventions:/ = absolute, ~/ = home-relative, ./ or no prefix = project-relative in project settings / ~/.claude-relative in user settings.
Paths to re-allow read access within denyRead regions. Takes precedence over denyRead. Arrays merge across all settings scopes.
When read rules overlap, the more specific path wins in both directions: denyRead: ["~/"] with allowRead: ["~/projects"] opens only that subtree, and allowRead: ["~/"] with denyRead: ["~/.env"] keeps that one file blocked. A broad allow cannot silently re-expose a secret an exact deny covers.
Skip filesystem isolation while keeping network isolation. Sandboxed commands get unrestricted read and write access to the host, and their egress stays confined to allowedDomains. Use when the point of sandboxing is controlling where commands connect rather than what they write.
Turning the layer off also disables filesystem.denyRead, credentials.files, and the protection on Claude Code’s own settings files, and stops the $TMPDIR override. credentials.envVars still applies, since environment scrubbing is independent of the filesystem layer.
Project settings cannot set it, so a checked-out repository cannot switch filesystem isolation off. When managed settings configure sandbox.filesystem at all, or list any credentials.files entry, only managed settings can set it. CLAUDE_CODE_SUBPROCESS_ENV_SCRUB makes Claude Code ignore it from every source.
With the filesystem layer off and commands auto-allowed, a sandboxed command can write shell startup files, executables on $PATH, or ~/.claude/settings.json, and use them to widen its own access on the next run. Set it only for workloads you trust not to escalate.
Type: array of { path, mode }Scope: all (deny narrows only, so any scope may add one)
Default:[]Since: v2.1.187
Credential files to hide from sandboxed commands. mode accepts only "deny", which blocks reads the same way filesystem.denyRead does.
This matters more than its placement suggests. The sandbox’s default read policy covers the entire machine, and there is no built-in credential denylist, so ~/.ssh and ~/.aws/credentials are readable by every sandboxed command until you list them. Paths follow the same prefix rules as sandbox.filesystem.*, and deny entries merge across every scope: any scope can add one, no scope can remove one another scope added.
{
"sandbox": {
"credentials": {
"files": [
{ "path": "~/.ssh", "mode": "deny" },
{ "path": "~/.aws", "mode": "deny" },
{ "path": "~/.gnupg", "mode": "deny" },
{ "path": "~/.config/gh", "mode": "deny" }
]
}
}
}
Verified on 2.1.220: with the entry in place, ls ~/.ssh from a sandboxed command returns Operation not permitted while the directory still appears in a listing of the home directory.
Type: array of { name, mode, injectHosts? }Scope:deny from all scopes; mask from user, managed, --settings only
Default:[]Since: v2.1.187 (deny), v2.1.199 (mask)
Environment variables to withhold from sandboxed commands. Sandboxed commands otherwise inherit the parent environment as-is, credentials included, which is the gap a credentials.files entry alone leaves open.
deny unsets the variable before each sandboxed command runs. It affects sandboxed Bash only, so MCP servers keep their credentials: they run as separate processes, not as sandboxed commands.
mask protects the credential while keeping the tool that authenticates with it working. The command sees a per-session sentinel; when a request leaves the sandbox for one of the credential’s injectHosts, the proxy substitutes the real value. The command and anything it logs never hold the real credential. Each injectHosts entry must itself be covered by allowedDomains, and network.tlsTerminate is required because the proxy has to see request contents to substitute. Without it, masking fails closed: the sentinel reaches the server unchanged and authentication fails, and Claude Code reports the misconfiguration at startup.
deny wins when the same variable appears with both modes in any scope. Start with deny and move a variable to mask only when a CLI actually breaks without it, since mask requires TLS termination and authorizes the proxy to send the real credential to the listed hosts.
To strip Anthropic and cloud provider credentials from all subprocesses regardless of sandboxing, set CLAUDE_CODE_SUBPROCESS_ENV_SCRUB instead.
Make the built-in proxy terminate TLS itself. Required by credentials.envVarsmask entries. It enables credential substitution; it does not add content filtering.
Deny sandboxed commands any host outside the allowlist instead of prompting. The allowlist is allowedDomains plus domains from WebFetch(domain:...) allow rules, or only the managed entries when allowManagedDomainsOnly is set. Applies to sandboxed commands only: in-process tools such as WebFetch still follow their permission rules.
Enable it last, once the domain list has survived a week of real work. Before that it converts every missing domain from a one-time prompt into a hard failure.
Allow Apple Events on macOS, which the sandbox blocks by default. Fixes open, osascript, and browser-based auth flows failing with error -600.
Enabling it removes code-execution isolation: sandboxed commands can launch other applications unsandboxed with no prompt, and send AppleScript to running applications, subject to the macOS automation-consent prompt. Prefer adding the specific command to excludedCommands.
Custom message appended to the plugin trust warning shown before installation. Use for org-specific context like confirming plugins from an internal marketplace are vetted.
Type: string
Scope: all
Default:"medium"Values:"low" | "medium" | "high"
Persist the effort level across sessions. Controls reasoning depth. Written automatically when you run /effort low|medium|high. Supported on Opus 4.6+ and Sonnet 4.6+. The CLAUDE_CODE_EFFORT_LEVEL env var takes precedence.
Map Anthropic model IDs to provider-specific model IDs (e.g., Bedrock inference profile ARNs). Each key is a model picker entry name; each value is the provider model ID.
Configure a custom status line. The command receives a JSON object on stdin with fields like context_window.used_percentage, rate_limits.five_hour.used_percentage, etc.
Configure a custom script for @ file path autocomplete. The command receives JSON on stdin with a query field and outputs newline-separated file paths (max 15).
"Learning" — pauses at key steps, inserts TODO(human) markers, asks you to write the meaningful pieces (pair-programming mode)
Custom styles: reference any filename (without .md) from .claude/styles/.
{ "outputStyle": "Explanatory" }
{ "outputStyle": "strict-reviewer" }
Setting persists across sessions. Explanatory and Learning increase output tokens; prompt caching offsets the cost after the first request. See Section 9.7 for full documentation and custom style examples.
Customize the action verbs shown in the spinner and turn duration messages. Set mode to "replace" to use only your verbs, or "append" to add to defaults.
Shell script path (executed in /bin/sh) that outputs an auth token sent as X-Api-Key and Authorization: Bearer headers for model requests. Useful for short-lived credentials.
Set in your shell before launching claude, or configure under the env key in settings.json to apply to every session. When an env var and an equivalent settings field both apply, the env var takes precedence (e.g. ANTHROPIC_MODEL overrides the model setting). Changes take effect on the next claude launch.
Set to 1 in subprocesses Claude Code spawns (Bash/PowerShell tools, tmux sessions, hook commands, status line commands, stdio MCP subprocesses). Use to detect when a script runs inside Claude Code
DEBUG
Set to 1 (or true/yes/on) to enable debug mode. Logs written to ~/.claude/debug/<session-id>.txt. Namespace patterns like DEBUG=express:* do not trigger it
CLAUDE_CODE_DEBUG_LOGS_DIR
Override the debug log file path (file path, not a directory). Requires debug mode enabled separately
CLAUDE_CODE_DEBUG_LOG_LEVEL
Minimum log level for the debug file: verbose, debug (default), info, warn, error
CLAUDE_CODE_SHELL
Override automatic shell detection
CLAUDE_CODE_SHELL_PREFIX
Command prefix prepended to all shell commands Claude Code spawns
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR
Return to the original working directory after each Bash command in the main session (1 to enable)
CLAUDE_CODE_NEW_INIT
Set to 1 to make /init run an interactive setup flow asking which files to generate
CLAUDE_CODE_SIMPLE
Run with minimal system prompt and only Bash, file read, and file edit tools. Equivalent to --bare
CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT
Set to 1 to use a shorter system prompt and abbreviated tool descriptions. Set to 0/false/no/off to opt out
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB
Set to 1 to strip Anthropic and cloud provider credentials from subprocess environments (Bash, hooks, MCP stdio servers)
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD
Set to 1 to load CLAUDE.md files from directories specified with --add-dir
CLAUDE_CODE_TMPDIR
Override the temp directory used for internal temp files
CLAUDE_CODE_GIT_BASH_PATH
Windows only: path to Git Bash executable when not in PATH
CLAUDE_CODE_GLOB_HIDDEN
Set to false to exclude dotfiles from Glob tool results (dotfiles included by default)
CLAUDE_CODE_GLOB_NO_IGNORE
Set to false to make the Glob tool respect .gitignore patterns
CLAUDE_CODE_GLOB_TIMEOUT_SECONDS
Glob tool file discovery timeout in seconds (default: 20, 60 on WSL)
CLAUDE_CODE_USE_NATIVE_FILE_SEARCH
Set to 1 to discover commands/subagents using Node.js file APIs instead of ripgrep
CLAUDE_CODE_PERFORCE_MODE
Set to 1 to enable Perforce-aware write protection (edits fail on files lacking owner-write bit)
CLAUDE_CODE_POWERSHELL_RESPECT_EXECUTION_POLICY
Set to 1 to stop Claude Code from passing -ExecutionPolicy Bypass when spawning PowerShell
CLAUDE_CODE_FORK_SUBAGENT
Set to 1 to make forked subagents the default: spawned agents inherit full conversation context instead of starting fresh
CLAUDE_CODE_AUTO_BACKGROUND_TASKS
Set to 1 to force-enable automatic backgrounding of long-running agent tasks
CLAUDE_CODE_REMOTE
Set automatically to true when running as a cloud session
CLAUDE_CODE_REMOTE_SESSION_ID
Set automatically in cloud sessions to the current session ID
CLAUDE_CODE_SESSION_ID
Set automatically to the current session ID in Bash/PowerShell subprocesses, hook commands, and MCP stdio subprocesses
CLAUDE_EFFORT
Set automatically in Bash/hook subprocesses to the active effort level: low, medium, high, xhigh, or max
CLAUDE_ENV_FILE
Path to a shell script run before each Bash command. Also populated dynamically by SessionStart, Setup, CwdChanged, and FileChanged hooks
USE_BUILTIN_RIPGREP
Set to 0 to use system-installed rg instead of the one bundled with Claude Code
Auto-compact trigger threshold as a percentage (1-100). Default ~95%. Lower values trigger compaction earlier
CLAUDE_CODE_AUTO_COMPACT_WINDOW
Context capacity in tokens used for compaction calculations. Defaults to model’s context window (200K standard, 1M for extended). Lower value on a 1M model treats it as smaller for compaction purposes
CLAUDE_CODE_DISABLE_1M_CONTEXT
Set to 1 to disable 1M token context window support
DISABLE_AUTO_COMPACT
Set to 1 to disable automatic compaction when approaching the context limit. Manual /compact remains available
DISABLE_COMPACT
Set to 1 to disable all compaction, including manual /compact
CLAUDE_CODE_DISABLE_THINKING
Set to 1 to force-disable extended thinking regardless of model support
DISABLE_INTERLEAVED_THINKING
Set to 1 to prevent sending the interleaved-thinking beta header. Use when your gateway does not support it
Standard OTEL exporter variables (OTEL_METRICS_EXPORTER, OTEL_LOGS_EXPORTER, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_EXPORTER_OTLP_HEADERS, OTEL_METRIC_EXPORT_INTERVAL, OTEL_RESOURCE_ATTRIBUTES, and signal-specific variants) are supported. CLAUDE_CODE_ENABLE_TELEMETRY=1 is required to activate OTel collection.
Variable
Description
OTEL_LOG_RAW_API_BODIES
Emit API request/response JSON as log events. Set to 1 for inline bodies (truncated at 60 KB), or file:<dir> to write full bodies to disk
OTEL_LOG_TOOL_CONTENT
Set to 1 to include tool input/output content in OTel span events. Disabled by default
OTEL_LOG_TOOL_DETAILS
Set to 1 to include tool input arguments, MCP server names, and raw error strings in OTel traces. Disabled by default
OTEL_LOG_USER_PROMPTS
Set to 1 to include user prompt text in OTel traces. Disabled by default
OTEL_METRICS_INCLUDE_ACCOUNT_UUID
Set to false to exclude account UUID from metrics attributes (default: included)
OTEL_METRICS_INCLUDE_ENTRYPOINT
Set to true to include session entrypoint in metrics attributes (default: excluded). Added in v2.1.152
OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES
Set to false to exclude OTEL_RESOURCE_ATTRIBUTES keys from metric datapoint labels (default: included). Added in v2.1.161
OTEL_METRICS_INCLUDE_SESSION_ID
Set to false to exclude session ID from metrics attributes (default: included)
OTEL_METRICS_INCLUDE_VERSION
Set to true to include Claude Code version in metrics attributes (default: excluded)
CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS
Timeout in ms for flushing pending OTel spans on shutdown (default: 5000)
CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MS
Timeout in ms for the OTel exporter to finish on exit (default: 2000)
CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS
Refresh interval in ms for dynamic OTel headers (default: 1740000, 29 minutes)
CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL
Set to 1 to route session quality survey ratings to your OTel collector instead of Anthropic
CLAUDE_CODE_PROPAGATE_TRACEPARENT
Set to 1 to propagate W3C trace context when ANTHROPIC_BASE_URL points at a custom proxy. Added in v2.1.152