Языки: EN RU

Settings and Configuration Hierarchy

Every time you launch Claude Code, you operate within a four-level settings system — even if you have never explicitly touched a single settings.json. Understanding this hierarchy matters for two reasons: it determines what the agent is and is not allowed to do, and it decides which settings apply to the entire team versus which remain strictly personal.


The Four Levels and Their Locations

Read the table from bottom to top: each higher level overrides the one below it.

LevelFileScopeIn git?
Managed (enterprise)/etc/claude-code/managed-settings.json (Linux)All users on the machineNo — deployed by IT
Local.claude/settings.local.jsonOnly you, in this repoNo (gitignore)
Project.claude/settings.jsonThe whole team in the repoYes
User~/.claude/settings.jsonYou, across all projectsNo

CLI flags (--model, --allowedTools, etc.) override everything except managed settings — and they only apply for the duration of a single run.

Full priority order, from lowest to highest:

User → Project → Local → CLI flags → Managed

In practice this means: if managed-settings.json sets a Bash(curl *) deny rule, no settings.local.json can override it. And settings in .claude/settings.json are automatically applied to everyone who clones the repository.

flowchart TD M["🏢 Managed settings\n/etc/claude-code/managed-settings.json\n(set by IT, cannot be overridden)"] --> U U["👤 User settings\n~/.claude/settings.json\n(personal, all projects)"] --> P P["📁 Project settings\n.claude/settings.json\n(team, in git)"] --> L L["💻 Local settings\n.claude/settings.local.json\n(you only, gitignored)"] --> C C["⚡ CLI flags\n--model, --allowedTools\n(current run)"] style M fill:#ff6b6b,color:#fff style U fill:#ffa94d,color:#fff style P fill:#51cf66,color:#fff style L fill:#339af0,color:#fff style C fill:#cc5de8,color:#fff
flowchart TD
    M["🏢 Managed settings\n/etc/claude-code/managed-settings.json\n(set by IT, cannot be overridden)"] --> U
    U["👤 User settings\n~/.claude/settings.json\n(personal, all projects)"] --> P
    P["📁 Project settings\n.claude/settings.json\n(team, in git)"] --> L
    L["💻 Local settings\n.claude/settings.local.json\n(you only, gitignored)"] --> C
    C["⚡ CLI flags\n--model, --allowedTools\n(current run)"]

    style M fill:#ff6b6b,color:#fff
    style U fill:#ffa94d,color:#fff
    style P fill:#51cf66,color:#fff
    style L fill:#339af0,color:#fff
    style C fill:#cc5de8,color:#fff
Claude Code settings hierarchy: each level overrides the previous one; CLI flags take highest priority

Быстрое повторение
Какой порядок приоритета настроек Claude Code от наименьшего к наибольшему?

File Structure

All four files share the same JSON schema. A minimal working example:

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": ["Bash(npm run lint)", "Bash(npm run test *)"],
    "deny": ["Read(./.env)", "Read(./secrets/**)", "Bash(curl *)"]
  },
  "model": "claude-sonnet-4-6"
}
}

The schema is available on JSON Schema Store — editors with JSON Schema support (VS Code and JetBrains) will provide autocompletion and validation directly in the file.

VS Code displays autocomplete and validation for the JSON settings file thanks to JSON Schema support.Источник: code.visualstudio.com
Проверь себя
You added `"model": "claude-opus-4-5"` to `.claude/settings.json` (project level), while a colleague has `"model": "claude-haiku-4-5"` in their `~/.claude/settings.json` (user level). Which model will be used for the colleague?

The Permissions System

Permissions are the most critical part of the configuration. Claude Code asks for confirmation before every potentially dangerous action (writing a file, executing a command), and permissions is what determines what is silently allowed, what is always denied, and what requires a prompt.

"permissions": {
  "allow": [
    "Bash(npm run lint)",
    "Bash(npm run test *)",
    "Bash(git *)",
    "Read(~/.zshrc)"
  ],
  "deny": [
    "Bash(curl *)",
    "Bash(rm -rf *)",
    "Read(./.env)",
    "Read(./.env.*)",
    "Read(./secrets/**)",
    "WebFetch(*)"
  ]
}

Rule format. Each rule is a string of the form ToolName(glob-pattern). Supported tools: Bash, Read, Edit, Write, WebFetch, mcp__ServerName__ToolName.

Glob characters work in the standard way:

  • * — any characters except /
  • ** — any characters including / (recursive)
  • npm run * — allow any script via npm run

Processing order. Deny always wins over allow — this does not depend on the order of entries in the file. If one rule allows Bash(curl *) and another denies Bash(curl *), the request will be rejected.

Level merging. Permissions from all files are concatenated, not overwritten. If the user settings have allow: ["Bash(git *)"] and the project settings have allow: ["Bash(npm run test)"], the resulting allow list contains both rules. Deny lists are also merged — and if even one level denies an action, it is denied.

Проверь себя
Project settings has `allow: ["Bash(curl *)"]`. Managed settings has `deny: ["Bash(curl *)"]`. What happens when Claude attempts to run `curl https://api.example.com`?

Быстрое повторение
Если в permissions одно правило разрешает Bash(curl *), а другое запрещает то же самое, что выигрывает?

What Goes Where: A Practical Split

The most common mistake is putting everything in one file. Here is a working approach:

~/.claude/settings.json (user) — personal preferences needed across all projects:

{
  "editorMode": "vim",
  "permissions": {
    "allow": [
      "Bash(git *)",
      "Read(~/.zshrc)",
      "Read(~/.gitconfig)"
    ]
  }
}

.claude/settings.json (project) — team rules, committed to the repo:

{
  "model": "claude-sonnet-4-6",
  "permissions": {
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test *)",
      "Bash(npm run build)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Read(./.env*)",
      "Read(./secrets/**)"
    ]
  },
  "attribution": {
    "commit": "🤖 Claude Code"
  }
}

.claude/settings.local.json (local) — personal overrides for this repo that your teammates don't need:

{
  "model": "claude-opus-4-5",
  "permissions": {
    "allow": ["Bash(./scripts/dev-reset.sh)"]
  }
}

Important: .claude/settings.local.json must be added to .gitignore. If it isn't, Claude Code will warn you about this the first time the file is created.

Проверь себя
You need to add `DATABASE_URL` for development in Claude Code, but you don't want to commit that URL to the repo. Which file and which field is the right place to put it?

Быстрое повторение
Когда класть настройки в ~/.claude/settings.json, а когда в .claude/settings.json?

Environment Variables

Some settings are more convenient to keep in environment variables rather than JSON — especially secrets and CI/CD parameters:

VariablePurpose
ANTHROPIC_API_KEYAPI key (required without OAuth)
ANTHROPIC_MODELDefault model
CLAUDE_CODE_EFFORT_LEVELEffort level: low, medium, high, xhigh
MAX_THINKING_TOKENSExtended thinking token budget
DISABLE_AUTOUPDATERDisable auto-update (1)
CLAUDE_CODE_DISABLE_AUTO_MEMORYDisable auto-memory (1)
CLAUDE_CODE_ENABLE_TELEMETRYOpenTelemetry telemetry (1)
CLAUDE_CODE_SKIP_PROMPT_HISTORYDo not write transcripts (1)

In addition, settings.json has an env field that passes variables to child processes and tools:

{
  "env": {
    "NODE_ENV": "development",
    "DATABASE_URL": "postgres://localhost:5432/mydb",
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1"
  }
}

This is useful when you need to ensure that Claude always runs npm run test with specific variables — without having to export them manually in every terminal session.


When Changes Take Effect

Not all settings are applied immediately:

Hot reload (no restart required):

  • permissions — allow/deny rules are updated immediately after saving the file
  • hooks — changes are picked up on the fly
  • apiKeyHelper and credential helpers

Only after a restart:

  • model — the selected model is locked in at startup
  • outputStyle — output style
  • editorMode — editor mode

If Claude keeps using the old model after you edit model in settings.json, that is expected behavior — just restart the session.


Enterprise: Managed Settings and MDM

For enterprise deployments there is a managed-settings level that no user can override:

/Library/Application Support/ClaudeCode/managed-settings.json  # macOS
/etc/claude-code/managed-settings.json                         # Linux
C:\Program Files\ClaudeCode\managed-settings.json              # Windows

IT departments can also distribute settings via Jamf, Kandji (macOS), or Windows Group Policy (registry key HKLM\SOFTWARE\Policies\ClaudeCode). A typical configuration:

{
  "forceLoginOrgUUID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "allowManagedMcpServersOnly": true,
  "deniedMcpServers": [{"serverName": "filesystem"}],
  "availableModels": ["claude-sonnet-4-6", "claude-haiku-4-5"],
  "enforceAvailableModels": true,
  "companyAnnouncements": ["Use only internal company MCP servers"]
}

To verify configuration correctness before deployment: claude doctor.

Modular merge via managed-settings.d/ allows different teams to contribute separate policies without conflicts — files are processed in alphabetical order, arrays are concatenated, and objects are deep-merged.


Quick Recipe: Initial Setup for a New Project

# 1. Create the directory
mkdir -p .claude

# 2. Add the local file to gitignore
echo '.claude/settings.local.json' >> .gitignore
echo '.claude/CLAUDE.local.md' >> .gitignore

# 3. Create project settings
cat > .claude/settings.json << 'EOF'
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(git status)",
      "Bash(git diff *)"
    ],
    "deny": [
      "Read(./.env*)",
      "Read(./secrets/**)",
      "Bash(git push --force*)",
      "Bash(rm -rf *)"
    ]
  }
}
EOF

# 4. Commit
git add .claude/settings.json
git commit -m "feat: add Claude Code project settings"

After this, everyone who clones the repository and launches Claude Code will get the same baseline permissions. Personal overrides go in settings.local.json; global preferences go in ~/.claude/settings.json.


See also

  • CLAUDE.md and the Memory System — CLAUDE.md is read on top of settings.json and supplements the configuration with text-based instructions
  • Managing the Context Window — autoMemoryEnabled in settings.json controls auto-memory, which is loaded into the context
  • Hooks — Lifecycle Events — hooks can be defined directly in settings.json via the hooks field; they support hot reload
  • Connecting MCP Servers in Claude Code — .mcp.json lives alongside .claude/settings.json and manages MCP servers at the project level
  • Model Selection and Thinking Modes — model, effortLevel, and alwaysThinkingEnabled are fields from settings.json
  • The Permissions Model, Security, and Trust — more detail on bypassPermissions modes and protection against prompt injection

Источники

  1. Claude Code Settings — code.claude.com