# Claude Code Settings Hierarchy: Configuring the 5-Level Override Chain

> Master the Claude Code 5-level settings hierarchy managed CLI args local project project user global. Understand how settings override for optimal configuration.

- Repository: [Shayan Rais/claude-code-best-practice](https://github.com/shanraisshan/claude-code-best-practice)
- Tags: internals
- Published: 2026-03-12

---

**Claude Code resolves settings through a five-level hierarchy (CLI arguments → local project → project → user-global local → user-global), with managed policy settings enforced at the highest priority, and array values merged across all levels rather than replaced.**

Claude Code, the AI coding assistant from Anthropic, implements a sophisticated configuration system defined in the `shanraisshan/claude-code-best-practice` repository. Understanding the **Claude Code settings hierarchy** is essential for teams who need to balance version-controlled defaults with individual developer preferences and organizational security policies.

## The Five-Level Settings Override Chain

The configuration system evaluates settings from highest to lowest priority, with the first value found for any key winning. According to the source code analysis in [`best-practice/claude-settings.md`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/best-practice/claude-settings.md), the hierarchy works as follows:

### Level 1: Command-Line Arguments

CLI flags provide session-specific overrides that take precedence over all file-based configurations. For example, `--model=sonnet` immediately changes the model for that session.

```bash
claude --model=sonnet

```

### Level 2: Local Project Settings (.claude/settings.local.json)

Personal per-project tweaks stored in [`.claude/settings.local.json`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/.claude/settings.local.json) apply to the specific repository but are git-ignored. This is ideal for individual model preferences or local environment variables.

```json
{
  "model": "haiku",
  "spinnerVerbs": {
    "mode": "replace",
    "verbs": ["Refactoring", "Testing", "Documenting"]
  }
}

```

### Level 3: Project Settings (.claude/settings.json)

Team-wide defaults committed to version control in [`.claude/settings.json`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/.claude/settings.json) provide the baseline configuration for all repository collaborators.

```json
{
  "model": "opus",
  "agent": "code-reviewer"
}

```

### Level 4: User-Global Local Settings (~/.claude/settings.local.json)

Personal overrides stored in the home directory's `~/.claude/settings.local.json` apply across all projects for that user.

### Level 5: User-Global Settings (~/.claude/settings.json)

Global defaults in `~/.claude/settings.json` serve as the fallback configuration for the entire user environment.

```json
{
  "model": "sonnet",
  "env": {
    "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "70"
  }
}

```

## The Managed Policy Layer (Highest Priority)

Before evaluating the five-level chain, Claude Code checks [`managed-settings.json`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/managed-settings.json) settings delivered via MDM profiles (macOS) or Windows Registry. These **cannot be overridden** by any user-writable configuration.

This layer enforces organizational security policies, with `deny` rules taking precedence over `allow` or `ask` rules according to the Settings Hierarchy documentation in [`best-practice/claude-settings.md`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/best-practice/claude-settings.md).

## How Array Values Merge Across Levels

Unlike scalar values where the first match wins, **array-type settings are merged across all configuration levels**. For example, `permissions.allow` accumulates entries from managed settings, project settings, and local settings.

If [`.claude/settings.json`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/.claude/settings.json) contains:

```json
{
  "permissions": {
    "allow": ["Edit(*)", "Write(*)"]
  }
}

```

And [`.claude/settings.local.json`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/.claude/settings.local.json) contains:

```json
{
  "permissions": {
    "allow": ["Bash(git *)"]
  }
}

```

The effective permission list becomes: `["Edit(*)", "Write(*)", "Bash(git *)"]`.

## Summary

- Claude Code uses a **five-level hierarchy** (CLI args → local project → project → user-global local → user-global) with a **managed policy layer** at the top.
- **Managed settings** ([`managed-settings.json`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/managed-settings.json)) enforced via MDM or Registry cannot be overridden by users.
- **Array values** (like `permissions.allow`) are merged across all levels rather than replaced.
- **Scalar values** follow strict priority: the first level containing the key wins.
- Use [`.claude/settings.local.json`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/.claude/settings.local.json) for personal project preferences and `~/.claude/settings.local.json` for global personal preferences.

## Frequently Asked Questions

### What happens if the same setting is defined in both project and user-global configuration?

The project-level setting wins. According to the hierarchy defined in [`best-practice/claude-settings.md`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/best-practice/claude-settings.md), project settings (Level 3) take precedence over user-global settings (Levels 4 and 5). The CLI argument would override both.

### How do I prevent my personal settings from being committed to git?

Store personal overrides in [`.claude/settings.local.json`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/.claude/settings.local.json) or `~/.claude/settings.local.json`. Both files are git-ignored by default in the repository structure, ensuring your local tweaks remain private to your machine.

### Can organization policy override my CLI arguments?

Yes. The managed-settings layer ([`managed-settings.json`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/managed-settings.json)) delivered via MDM profiles or Windows Registry sits above even CLI arguments in the priority chain. If an organization sets a `deny` rule in managed settings, it cannot be bypassed by any user configuration.

### Why are my permissions not being overridden when I set them in a local file?

Array-type settings like `permissions.allow` are merged across all configuration levels rather than replaced. If you want to completely replace the permission list, you must use the `"mode": "replace"` directive within the setting, as shown with `spinnerVerbs` in the configuration examples.