Claude Code Settings.json: Complete Reference Guide

settings.json is the most important configuration file in Claude Code. It controls which model runs, what permissions Claude has, which hooks fire on tool events, and what environment variables apply. Understanding the five settings scopes, merge rules, and the full field list transforms Claude Code from a personal tool into a governed, reproducible engineering platform.

Claude Code Settings.json: Complete Reference Guide — title card

settings.json: What You’ll Learn

Mastering settings.json means you can enforce security policies across a team, lock down dangerous commands, automate quality checks through hooks, and ensure every developer gets the same baseline experience. You will learn the five-tier settings hierarchy, the permissions model, hook configuration, environment variables, sandbox rules, and managed enterprise controls. By the end, you will be able to configure a project from scratch with confidence.

This tutorial assumes you have run Claude Code a few times and understand the basics. If you are new, start with the getting-started guide, then return here. You may also find the Claude Code CLI Reference Guide useful for understanding the command-line flags that interact with settings.json values.

What Is settings.json?

settings.json is a JSON configuration file that Claude Code reads at startup to determine its behavior. It is not a single file in a single location. Instead, Claude Code supports five distinct scopes, each in a different filesystem path, each with a different level of authority. The settings from all five scopes are merged according to deterministic rules to produce the final effective configuration for your session.

This layered design solves a real problem: how do you let individual developers customize their experience while still enforcing organizational security policies? The answer is that higher scopes always override lower ones. An IT administrator’s managed settings cannot be overridden by a developer’s personal preferences, but a developer’s project-level settings do override their own global defaults.

Think of settings.json as the control panel for Claude Code. Every meaningful behavioral knob, from the default model to whether bash commands require confirmation, is expressed here. Getting the configuration right means your team works faster and safer. Getting it wrong means either friction from excessive permission prompts or risk from overly permissive defaults.

The Five Settings Scopes

Claude Code recognizes five settings scopes, ordered from highest authority to lowest. Each scope corresponds to a specific file path on disk. Understanding this hierarchy is essential because it determines which file wins when two scopes define the same key.

ScopeFile PathWho Controls ItCommitted?
ManagedOS-level path (see below)IT / organization adminsDeployed by IT
Command line flagsPassed at launchCurrent user, per-invocationN/A
Local project.claude/settings.local.jsonIndividual developerNo (gitignored)
Project.claude/settings.jsonTeam (repo owners)Yes (committed)
User~/.claude/settings.jsonIndividual developerN/A (global)

The hierarchy flows downward: managed settings at the top cannot be overridden by anything below. Command-line flags override file-based settings except for managed ones. Local project settings override project settings, which override user-level settings. This design means a developer can set personal defaults globally, override them per-project for team alignment, keep personal overrides locally without polluting the repo, and IT can lock down everything from the top.

Managed Settings File Locations

Managed settings live in operating-system-specific paths. On macOS, the path is /Library/Application Support/ClaudeCode/managed-settings.json. On Linux, it is /etc/claude-code/managed-settings.json. On Windows, it is C:Program FilesClaudeCodemanaged-settings.json. These paths require elevated privileges to write, which is intentional: only an administrator with root or admin access can deploy or modify managed settings.

Managed settings are the enforcement mechanism for organizational policy. If your security team requires that no developer can enable bypass permissions mode, they set disableBypassPermissionsMode: true in the managed settings file, and no amount of project or user configuration can override it. This is the single most powerful governance tool in the settings.json hierarchy.

Merge Rules: How Scopes Combine

When multiple scopes define the same setting, Claude Code merges them according to three simple rules based on the data type of the field. These rules are deterministic, meaning the final effective configuration is always predictable once you know what each scope contains.

For scalar values, strings, numbers, and booleans, the higher scope wins outright. If managed settings specify "model": "claude-sonnet-4" and user settings specify "model": "claude-opus-4", the managed value wins and Sonnet is used. For objects, Claude Code performs a deep merge. Each key inside the object is resolved recursively, so a project setting can override one nested key while inheriting the rest from the user scope.

For arrays, particularly the permission rule arrays like permissions.allow and permissions.deny, Claude Code concatenates entries from all scopes and deduplicates them. This means deny rules from managed, project, and user settings all apply simultaneously. The critical override rule is that deny always wins over allow and ask at every scope, regardless of where the deny originates.

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "model": "claude-sonnet-4",
  "permissions": {
    "allow": ["Read(*)", "Bash(npm run *)"],
    "deny": ["Bash(rm -rf *)", "Read(.env*)"],
    "defaultMode": "default"
  }
}

Always include the $schema field at the top of your settings.json files. It enables IDE autocompletion and validation in editors like VS Code, catching typos and invalid field names before they cause runtime issues. The schema is published at https://json.schemastore.org/claude-code-settings.json and reflects the latest supported fields.

The Permissions Object

The permissions object is the heart of settings.json for most teams. It controls which tools Claude Code can use freely, which require confirmation, and which are blocked entirely. Getting permissions right means balancing productivity, where common safe operations run without interruption, against security, where dangerous or sensitive operations are gated or blocked.

ModeBehaviorUse Case
defaultAsk for confirmation on tools not in allow listEveryday interactive use
acceptEditsAuto-accept file edits, ask for everything elseTrusted refactoring sessions
planRead-only, no writes or commands until approvedExploration and review
autoAuto-approve allowed tools without promptingStreamlined trusted workflows
dontAskDo not ask, silently skip disallowed toolsControlled pipelines
bypassPermissionsSkip all permission checks entirelySandboxed or disposable environments

The defaultMode field sets the baseline behavior. The allow array lists tool uses that are automatically approved without prompting. The deny array lists tool uses that are blocked entirely and can never be overridden by allow rules at any scope. The ask array forces confirmation even in auto or acceptEdits modes, giving you a targeted override for sensitive operations.

{
  "permissions": {
    "allow": [
      "Read(*)",
      "Edit(src/**)",
      "Bash(npm run test*)",
      "Bash(git status)",
      "Bash(git diff*)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(sudo *)",
      "Read(.env*)",
      "Read(**/secrets/*)"
    ],
    "ask": [
      "Bash(git push*)",
      "Bash(npm publish*)"
    ],
    "defaultMode": "default",
    "additionalDirectories": ["../shared-lib"],
    "disableBypassPermissionsMode": true,
    "disableAutoMode": false
  }
}

The additionalDirectories field grants Claude Code access to directories outside the current working directory. Without it, Claude is sandboxed to the project root. The disableBypassPermissionsMode and disableAutoMode fields are security switches that prevent developers from escalating their own permissions beyond what the settings allow.

Choosing the Right Default Mode

Selecting the correct defaultMode depends on your trust level and workflow. The default mode is the safest starting point: Claude asks for confirmation before any tool not in your allow list. This is ideal when exploring a new codebase, working with unfamiliar tools, or operating in a security-sensitive environment. The friction of confirmation prompts is intentional and protective.

The acceptEdits mode is the sweet spot for active development. File edits proceed without interruption, which keeps your flow state intact during refactoring, but bash commands and other tools still require confirmation. This mode trusts Claude to modify files, which is its core competency, while maintaining a gate around command execution where the risk profile is higher.

The plan mode is read-only by design. Claude can explore the codebase, read files, and propose changes, but cannot execute writes or commands until you explicitly approve them. This is perfect for architecture reviews, code audits, or any scenario where you want Claude’s analysis without its hands on the keyboard. The auto mode skips prompts for allowed tools entirely, which is useful in CI pipelines or when running a well-tested workflow.

The bypassPermissions mode should be used with extreme caution. It disables all permission checks, letting Claude run any tool freely. The only safe use case is inside a fully sandboxed environment where the blast radius of any action is contained. If your managed settings have disableBypassPermissionsMode: true, this mode cannot be activated regardless of local configuration.

Permission Rule Syntax

Permission rules use a compact string syntax that matches tools and their arguments. The general form is Tool to match all uses of a tool, or Tool(specifier) to match specific uses. Understanding this syntax lets you write precise rules that approve safe operations while blocking dangerous ones.

For Bash, the specifier uses command prefixes with wildcards. Bash(npm run *) matches any npm run command. Bash(git status) matches exactly that command with no arguments. Bash(git diff *) matches git diff with any arguments. The wildcard * matches any continuation of the command string, so position it carefully.

For Read and Edit, the specifier uses gitignore-style glob patterns against file paths. Read(.env) blocks reading the .env file. Read(.env*) blocks .env, .env.local, .env.production, and similar. Edit(src/**) allows editing any file under the src directory recursively. Read(**/secrets/*) blocks reading any file inside a secrets directory at any depth.

For WebFetch, the specifier uses a domain filter: WebFetch(domain:example.com). For MCP tools, use the mcp__ prefix: mcp__github__create_issue matches a specific MCP tool from the github server. Other tools like Glob, Grep, WebSearch, Write, and Agent accept the bare tool name to match all uses.

{
  "permissions": {
    "allow": [
      "Read(*)",
      "Glob(*)",
      "Grep(*)",
      "Edit(src/**)",
      "Edit(tests/**)",
      "Write(src/generated/**)",
      "Bash(npm *)",
      "Bash(node *)",
      "Bash(git add*)",
      "Bash(git commit*)",
      "WebFetch(domain:registry.npmjs.org)",
      "mcp__github__*"
    ],
    "deny": [
      "Edit(config/**)",
      "Edit(.github/workflows/**)",
      "Bash(curl *)",
      "Bash(wget *)"
    ]
  }
}

Notice the pattern: broad allow rules for productive tools, targeted deny rules for sensitive paths and network operations. This balance lets developers work freely in source code while protecting infrastructure configuration and preventing unauthorized outbound requests. The deny rules cannot be overridden by any scope below the one that declares them.

Hooks: Automating Quality Checks

Hooks let you run custom logic before or after tool events. They are the automation layer of settings.json, enabling everything from linting on save to blocking commits that fail tests. A hook is configured as an object with an event type, a hook type, and a configuration specific to that type.

Claude Code supports thirteen hook events. PreToolUse fires before any tool executes, letting you block or modify the call. PostToolUse fires after successful completion, useful for formatting or logging. PostToolUseFailure fires when a tool errors. UserPromptSubmit fires when the user sends a message. Stop and SubagentStop fire when the main agent or a subagent finishes.

Session lifecycle hooks include SessionStart and SessionEnd for setup and teardown. ConfigChange fires when settings are modified during a session. PermissionRequest and PermissionDenied fire on permission interactions. MessageDisplay fires before a message is shown. PreCompact fires before context compaction, letting you capture state.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write $CLAUDE_FILE_PATH"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo $CLAUDE_TOOL_INPUT | jq '.command' | xargs audit-script.sh"
          }
        ]
      }
    ]
  }
}

Hook Events in Detail

Each hook event serves a distinct purpose in the tool lifecycle. PreToolUse is your gatekeeper: it fires before a tool executes and can block the call entirely if the hook returns a denial. Use it to validate bash commands against a security policy, prevent writes to protected paths, or require additional context before allowing a network request. The matcher field lets you scope the hook to specific tools using a pipe-separated pattern like Edit|Write.

PostToolUse fires after a tool completes successfully. It is ideal for running formatters, updating documentation, logging changes, or triggering builds. Because it fires on success, you can safely assume the tool produced a valid result. Pair it with the PostToolUseFailure event to handle errors, where you can log failures, send alerts, or attempt recovery logic.

UserPromptSubmit fires when the user sends a message, before Claude processes it. This is useful for injecting context, validating prompts against policies, or logging user activity for audit trails. The SessionStart and SessionEnd events bracket the entire session, letting you set up and tear down resources, load credentials from a vault, or flush accumulated state to persistent storage.

The Stop event fires when the main agent finishes its response, which is useful for triggering follow-up actions like running tests or notifying a CI system. SubagentStop fires when a delegated subagent completes, giving you visibility into background work. The PreCompact event fires before context compaction, letting you capture important state to external storage before it gets summarized.

The Five Hook Types

Each hook entry specifies a type that determines how it executes. The command type runs a shell command (bash on Unix, PowerShell on Windows). This is the most common type for formatting, linting, and validation scripts. The command receives environment variables with tool details like $CLAUDE_TOOL_NAME, $CLAUDE_FILE_PATH, and $CLAUDE_TOOL_INPUT. The exit code determines the outcome: zero means proceed, non-zero means block.

The prompt type sends the tool input to an LLM for evaluation. The LLM can approve, block, or modify the action. This is useful for semantic checks that a script cannot perform, like evaluating whether a code change introduces a security vulnerability or whether a bash command matches the user’s stated intent. The agent type extends this with multi-turn reasoning and tool access for complex evaluations that require investigation.

The http type sends a webhook to an external service, which can respond with approve or block decisions. This integrates Claude Code with enterprise approval systems, ticketing tools, or audit loggers. The endpoint receives a JSON payload with tool details and responds with a structured decision. The mcp_tool type calls a tool on a configured MCP server, bridging Claude Code’s hook system with the broader MCP ecosystem for maximum extensibility.

A Practical Hook Configuration

The most common production hook setup combines auto-formatting with security validation. After every file edit or write, run Prettier or your language’s formatter to keep code consistent without manual intervention. Before any bash command, run a validation script that checks against a denylist of dangerous patterns. This combination ensures both quality and safety without slowing developers down with constant prompts.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "npx prettier --write $CLAUDE_FILE_PATH" },
          { "type": "command", "command": "npx eslint --fix $CLAUDE_FILE_PATH" }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "scripts/validate-bash.sh" }
        ]
      }
    ],
    "SessionStart": [
      {
        "hooks": [
          { "type": "command", "command": "scripts/load-secrets.sh" }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "npm run test -- --silent" }
        ]
      }
    ]
  }
}

Environment Variables

The env field in settings.json sets environment variables that Claude Code and its spawned processes inherit. This is cleaner than exporting variables in your shell profile because it applies only to Claude Code sessions and can be scoped per-project. Environment variables control authentication, model selection, timeouts, and feature flags.

{
  "env": {
    "ANTHROPIC_MODEL": "claude-sonnet-4",
    "MAX_THINKING_TOKENS": "10000",
    "CLAUDE_CODE_EFFORT_LEVEL": "medium",
    "API_TIMEOUT_MS": "60000",
    "BASH_DEFAULT_TIMEOUT_MS": "30000",
    "BASH_MAX_TIMEOUT_MS": "300000",
    "DISABLE_AUTOUPDATER": "1",
    "DISABLE_AUTO_COMPACT": "0",
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1"
  }
}

Several environment variable categories matter for most teams. Authentication variables include ANTHROPIC_API_KEY for direct API access and CLAUDE_CODE_USE_BEDROCK or CLAUDE_CODE_USE_VERTEX for routing through AWS Bedrock or Google Vertex AI respectively. Model control variables include ANTHROPIC_MODEL for the default model and MAX_THINKING_TOKENS to cap extended thinking depth.

Timeout variables prevent runaway operations. API_TIMEOUT_MS caps how long a single API call can take. BASH_DEFAULT_TIMEOUT_MS sets the default timeout for bash commands, and BASH_MAX_TIMEOUT_MS sets the absolute ceiling that cannot be exceeded even with explicit timeout arguments. Feature flags like DISABLE_AUTOUPDATER, DISABLE_AUTO_COMPACT, and CLAUDE_CODE_DISABLE_THINKING toggle built-in behaviors on or off.

Telemetry variables control observability. CLAUDE_CODE_ENABLE_TELEMETRY turns on OpenTelemetry-compatible tracing, which integrates with Datadog, Honeycomb, or any OTLP collector. This is essential for teams monitoring agent behavior in production. The full environment variable list exceeds one hundred entries; the variables above cover the categories most teams configure.

Cloud Provider Routing

Teams operating within AWS or Google Cloud can route Claude Code traffic through their existing cloud provider agreements. Setting CLAUDE_CODE_USE_BEDROCK to 1 routes all requests through AWS Bedrock, which means you pay through your AWS account and benefit from AWS-native authentication, logging, and compliance controls. Setting CLAUDE_CODE_USE_VERTEX to 1 does the same through Google Vertex AI. Only one cloud provider can be active at a time.

When using cloud provider routing, the ANTHROPIC_API_KEY is typically not needed because authentication flows through your cloud provider’s identity system, such as IAM roles or service accounts. This simplifies credential management for teams already invested in a cloud ecosystem and centralizes billing within existing cloud accounts. Consult your cloud provider’s documentation for the specific permissions and roles Claude Code needs.

Timeouts and Safety Limits

Timeouts prevent runaway operations from consuming resources indefinitely. The API_TIMEOUT_MS variable caps how long Claude Code waits for a single API response before retrying or failing. The BASH_DEFAULT_TIMEOUT_MS sets the default timeout applied to every bash command, and BASH_MAX_TIMEOUT_MS sets the absolute ceiling that cannot be exceeded even if a command requests a longer timeout explicitly. Set these conservatively for CI environments where you want predictable runtimes, and more generously for interactive sessions where long builds are expected.

API Key Helper

For teams that rotate API keys frequently or pull credentials from a secrets manager, the apiKeyHelper field is invaluable. It specifies a shell command that outputs an authentication value. Claude Code calls this command, takes the output, and sends it as the X-Api-Key header on every API request.

{
  "apiKeyHelper": "/usr/local/bin/fetch-claude-api-key.sh",
  "env": {
    "CLAUDE_CODE_API_KEY_HELPER_TTL_MS": "300000"
  }
}

The CLAUDE_CODE_API_KEY_HELPER_TTL_MS environment variable controls how often Claude Code refreshes the key by re-running the helper command. The default refresh interval is five minutes, or 300,000 milliseconds. Set a shorter TTL for high-security environments where keys expire quickly, or a longer TTL to reduce helper invocation overhead. This pattern integrates cleanly with HashiCorp Vault, AWS Secrets Manager, or any command-line accessible secrets store.

MCP Server Configuration

A common point of confusion is where MCP servers are configured. They are not defined in settings.json. Instead, MCP servers live in .mcp.json at the project root for project-scoped servers, or in ~/.claude.json for user-scoped servers. The settings.json file controls how Claude Code treats these servers through approval settings.

{
  "enableAllProjectMcpServers": false,
  "enabledMcpjsonServers": ["github", "filesystem"],
  "disabledMcpjsonServers": ["legacy-tools"]
}

The enableAllProjectMcpServers field, when true, automatically trusts and enables every server defined in the project’s .mcp.json. This is convenient for solo projects but risky for teams, since a malicious or buggy MCP server could gain tool access. The preferred approach for teams is to use enabledMcpjsonServers to whitelist specific servers and disabledMcpjsonServers to explicitly block others.

Do Not Confuse .claude.json with settings.json

The file ~/.claude.json stores OAuth session tokens, per-project trust decisions, and user-scoped MCP server definitions. It is a runtime state file, not a configuration file. Placing its keys into settings.json triggers schema validation errors because those keys are not part of the settings schema. Keep these files separate: settings.json is for configuration you author, and .claude.json is for state that Claude Code manages.

Sandbox Configuration

The sandbox feature lets you run bash commands in an isolated environment with restricted filesystem and network access. This is a powerful security layer that complements the permissions system. While permissions control which commands Claude can attempt, the sandbox controls what those commands can actually do when they run.

{
  "sandbox": {
    "enabled": true,
    "failIfUnavailable": true,
    "autoAllowBashIfSandboxed": true,
    "filesystem": {
      "allowWrite": ["src/**", "tests/**", "build/**"],
      "denyWrite": ["config/**", ".github/**"],
      "denyRead": [".env*", "**/secrets/*"],
      "allowRead": ["*"]
    },
    "network": {
      "allowedDomains": ["registry.npmjs.org", "github.com"]
    }
  }
}

The enabled field turns the sandbox on. failIfUnavailable ensures that if the sandbox cannot be initialized for any reason, bash commands fail rather than running unsandboxed. This is critical for security-sensitive environments where running without isolation is worse than not running at all. The autoAllowBashIfSandboxed field, when true, automatically approves bash commands that run inside the sandbox, since the sandbox itself provides the safety boundary.

The filesystem object defines read and write boundaries. allowWrite restricts writes to specified paths, denyWrite blocks writes to sensitive directories even if they are in the allow list, and denyRead prevents reading secrets and configuration files. The network object with allowedDomains restricts outbound network access to a whitelist, preventing data exfiltration through curl or wget.

Managed-Only Settings

Certain settings can only be set in the managed settings file. They are ignored if placed in project, local, or user settings. This restriction exists because these fields are governance controls that should only be modifiable by administrators, not by individual developers or repository owners.

{
  "allowManagedHooksOnly": true,
  "allowManagedMcpServersOnly": true,
  "allowManagedPermissionRulesOnly": true,
  "requiredMinimumVersion": "2.1.190",
  "requiredMaximumVersion": "2.2.0",
  "forceLoginOrgUUID": "your-org-uuid-here"
}

The allowManagedHooksOnly field, when true, disables all hooks defined in non-managed settings. This prevents developers from defining their own hooks that might bypass security controls. Similarly, allowManagedMcpServersOnly restricts MCP server definitions to the managed scope, and allowManagedPermissionRulesOnly does the same for permission rules.

Version pinning is available through requiredMinimumVersion and requiredMaximumVersion. These fields force Claude Code to refuse to start if its version falls outside the specified range. This is useful for enterprise environments that need predictable behavior across upgrades. The forceLoginOrgUUID field locks sessions to a specific organization, preventing developers from using personal accounts on company machines.

Key Settings Fields Reference

Beyond permissions, hooks, env, and sandbox, settings.json supports a range of behavioral fields. Knowing these lets you fine-tune Claude Code’s operation without environment variables or command-line flags.

{
  "model": "claude-sonnet-4",
  "statusLine": "padding: 1 | text: Ready | color: white",
  "attribution": true,
  "effortLevel": "medium",
  "alwaysThinkingEnabled": false,
  "autoCompactEnabled": true,
  "cleanupPeriodDays": 30,
  "autoUpdatesChannel": "stable",
  "language": "en",
  "includeGitInstructions": true,
  "askUserQuestionTimeout": 300,
  "disableClaudeAiConnectors": false
}

The model field sets the default model. The statusLine field customizes the status bar shown in the terminal interface, letting you display context-relevant information like git branch or token count. The attribution field controls whether Claude Code attribution appears in generated content.

The effortLevel field sets the reasoning depth, with options like low, medium, and high. The alwaysThinkingEnabled field forces extended thinking on every turn. The autoCompactEnabled field toggles automatic context compaction. The cleanupPeriodDays field controls how long old session transcripts are retained before cleanup.

Recent additions include askUserQuestionTimeout (added in version 2.1.200) which sets a timeout for user question prompts, the manual mode alias (also 2.1.200) which is equivalent to default, disableClaudeAiConnectors (version 2.1.182) which disables connector integrations, and sandbox.credentials (version 2.1.191) which configures credential handling inside the sandbox.

Using the JSON Schema for Validation

The official JSON Schema for Claude Code settings is published at https://json.schemastore.org/claude-code-settings.json. Adding the $schema field to your settings.json files enables real-time validation in modern code editors. VS Code, JetBrains IDEs, and other editors that support JSON Schema will highlight invalid fields, suggest valid values, and autocomplete field names as you type.

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "model": "claude-sonnet-4",
  "permissions": {
    "allow": ["Read(*)", "Edit(src/**)"],
    "deny": ["Read(.env*)"]
  }
}

Schema validation catches common mistakes before they cause problems. If you misspell permissions as permission, the schema flags it. If you put a string where an array is expected, the schema catches the type mismatch. This is especially valuable for teams where multiple people edit settings.json, since the schema acts as a built-in reviewer. For the complete and authoritative field reference, always consult the official Claude Code settings documentation.

A Worked Example

Let us walk through configuring a team project from scratch using settings.json. Imagine you are setting up Claude Code for a ten-developer team building a Node.js API. The repository is shared, developers use different operating systems, and your security team requires that no one can run destructive shell commands or read environment secrets. You want to balance productivity with governance.

You start at the user scope. Each developer creates ~/.claude/settings.json with their personal defaults: a preferred model, their typical effort level, and common allow rules for tools they use across all projects. This file is not committed to any repository, so personal preferences stay personal. A developer who prefers Opus for complex reasoning sets that here, while another who wants speed sets Sonnet.

Next, you create the project-level settings at .claude/settings.json in the repository root. This file is committed, so every developer on the team inherits it. You define the permissions that make sense for the project: allow reading all files, allow editing source and test directories, deny reading .env files and secrets, deny running rm with recursive flags, and require confirmation for git push and npm publish. You add PostToolUse hooks that run Prettier and ESLint automatically after every edit.

Then you add .claude/settings.local.json to the project’s .gitignore file. This is where developers put personal overrides for this specific project without affecting teammates. A developer working on database migrations might add a local allow rule for Bash(psql *) commands, while another developer experimenting with a new tool adds it locally first before proposing it for the project settings.

Finally, your IT team deploys managed settings to all developer machines. They set disableBypassPermissionsMode: true to prevent anyone from escalating permissions, requiredMinimumVersion: 2.1.190 to ensure everyone runs a patched version, and forceLoginOrgUUID to bind sessions to the corporate organization. They also add a deny rule for known dangerous commands that applies to all projects, not just this one.

The result is a layered configuration where personal preferences live at the user scope, team conventions live in the committed project settings, individual overrides stay local and uncommitted, and organizational policy is enforced immutably from the managed scope. A new developer cloning the repository gets sensible defaults immediately, can customize locally without friction, and cannot accidentally weaken security controls. This is the settings.json hierarchy working as designed.

settings.json: Common Mistakes to Avoid

Even experienced teams stumble on the same configuration pitfalls. These mistakes are subtle because settings.json is forgiving: invalid fields are often silently ignored rather than causing errors. Recognizing these patterns helps you catch misconfigurations before they cause security gaps or productivity friction.

  • Putting MCP server definitions in settings.json: MCP servers belong in .mcp.json or ~/.claude.json, not in settings.json. The settings file only controls approval behavior. Defining servers in settings.json silently fails because the schema does not recognize those keys.
  • Confusing .claude.json with settings.json: The file ~/.claude.json stores runtime state like OAuth tokens and trust decisions. It is not a configuration file. Copying its keys into settings.json causes schema validation errors and does not work as intended.
  • Forgetting to commit settings.local.json to gitignore: The local settings file is meant to be personal and uncommitted. If you forget to add it to .gitignore, developers accidentally commit machine-specific paths and personal overrides, creating noise in code reviews and potential information leakage.
  • Relying on allow rules without deny rules: Allow lists improve productivity, but without explicit deny rules for sensitive paths and dangerous commands, a permissive default mode can let Claude access secrets or run destructive operations. Always pair broad allows with targeted denies for defense in depth.
Claude Code Settings.json: Complete Reference Guide — key concepts card

settings.json: Best Practices

  • Always include the $schema field pointing to the official JSON Schema URL at the top of every settings.json file to enable IDE validation, autocomplete, and early detection of typos or invalid field names.
  • Use the project scope for team-wide conventions and reserve the local scope for personal overrides. Keep settings.local.json in .gitignore so machine-specific configuration never pollutes the repository history.
  • Pair broad allow rules with targeted deny rules. Deny rules for sensitive files like .env* and dangerous commands like rm -rf * provide defense in depth that survives even if a developer enables an aggressive default mode locally.
  • Deploy managed settings for organizational policy enforcement. Fields like disableBypassPermissionsMode, version pinning, and forced organization login only work in the managed scope, so IT teams should own that layer exclusively.
  • Test settings changes in a branch before merging. Use the JSON Schema validation in your IDE, run a quick Claude Code session to confirm behavior, and document non-obvious configuration decisions in comments or a companion README within the .claude/ directory.
Claude Code Settings.json: Complete Reference Guide — best practices card

Settings.json: Knowledge Check

Test your understanding of Claude Code settings.json configuration.

1 / 5

Which permission rule always wins over allow and ask?

2 / 5

What is ~/.claude.json NOT used for?

3 / 5

How are arrays like permissions.allow merged across scopes?

4 / 5

Where are MCP servers configured (NOT in settings.json)?

5 / 5

What is the settings precedence order (highest to lowest)?

0%

settings.json: Frequently Asked Questions

What is the difference between settings.json and .claude.json?

settings.json is a configuration file you author with behavioral settings like model, permissions, and hooks. The file ~/.claude.json stores runtime state like OAuth tokens, project trust, and user-scoped MCP server definitions. They serve different purposes and have different schemas.

Which settings scope wins when there is a conflict?

Managed settings always win. Below that, command-line flags override file settings, local project overrides project, and project overrides user. For arrays like permission rules, all scopes concatenate and deduplicate. Deny always wins over allow at any scope.

Where do MCP servers go, in settings.json or elsewhere?

MCP servers are defined in .mcp.json for project scope or ~/.claude.json for user scope. The settings.json file controls approval through fields like enableAllProjectMcpServers, enabledMcpjsonServers, and disabledMcpjsonServers, but server definitions themselves do not belong in settings.json.

Can I validate my settings.json before deploying?

Yes. Add $schema pointing to https://json.schemastore.org/claude-code-settings.json at the top of the file. Modern editors like VS Code validate against this schema automatically, highlighting invalid fields and suggesting valid values as you type.

What settings can only be set by administrators?

Fields like allowManagedHooksOnly, allowManagedMcpServersOnly, allowManagedPermissionRulesOnly, requiredMinimumVersion, requiredMaximumVersion, and forceLoginOrgUUID only take effect in the managed settings file. They are ignored in project, local, or user scopes to prevent developers from weakening governance controls.

settings.json gives you five scopes, deterministic merge rules, and granular control over permissions, hooks, environment variables, MCP approval, and sandboxing. Master the hierarchy, always pair allow rules with deny rules, use the JSON Schema for validation, and deploy managed settings for organizational governance. For deeper command-line context, see the Claude Code CLI Reference Guide.