---
title: "Claude Code settings.json: Hierarchy, Precedence and env Setup"
description: "Where Claude Code's four settings.json files live, which wins on conflict, what env proxy and base URL variables affect, and how to check with /status."
url: https://cdnping.org/en/blog/claude-code-settings-json-guide
language: en
published: 2026-10-22
category: "Developer tools"
tags: ["Claude Code","config files","environment variables","developer tools","team workflow"]
source: cdnping.org
license: Free to quote and summarize with a link to the url above.
---
# Claude Code settings.json: Hierarchy, Precedence and env Setup

Claude Code settings.json lives in four places: the user-level `~/.claude/settings.json`, the project-shared `.claude/settings.json`, the project-local `.claude/settings.local.json`, and a managed policy file pushed down by an administrator. When the same field appears in more than one place, the one closer to "this machine, this project" wins, and managed policy wins over everything. Variables such as the API endpoint and proxy go in the `env` field. After you write them, check the effective values with `/status` instead of guessing.

The sections below follow this order: where the files are, who overrides whom, what to put in them, and how to verify. Field names and paths follow the [official Anthropic settings docs](https://docs.anthropic.com/en/docs/claude-code/settings). Claude Code updates often, so if anything here differs from the docs, trust the current version of the docs.

## How many settings.json files are there, and where do they go?

| Level | Path | Who it applies to | Committed to the repo? |
|---|---|---|---|
| Managed policy | macOS: `/Library/Application Support/ClaudeCode/managed-settings.json`; Linux / WSL: `/etc/claude-code/managed-settings.json`; Windows: see the official docs | Pushed out centrally by company IT or an administrator | Not in the repo |
| User | `~/.claude/settings.json` | You, in all projects | No |
| Project shared | `<project>/.claude/settings.json` | Everyone on the team | Yes |
| Project local | `<project>/.claude/settings.local.json` | You, in this project only | No |

A few points that are easy to mix up:

- `~/.claude.json` (note: no subdirectory) is a state file that Claude Code maintains itself. It holds login state, project history, MCP servers and similar data. It is not a settings.json, and you generally don't need to edit it by hand.
- `CLAUDE.md` is a project description for the model to read. It counts as "memory", not configuration. Don't put permissions or environment variables in CLAUDE.md; they won't be applied as settings.
- When Claude Code creates `settings.local.json`, it configures git to ignore it automatically. If you created it by hand, check your `.gitignore` yourself.

## When several files conflict, which one wins?

The official docs give this precedence, from highest to lowest:

1. Managed policy (managed-settings.json)
2. Command-line arguments (for example `--model`, `--settings <file>`, `--permission-mode`)
3. Project local `.claude/settings.local.json`
4. Project shared `.claude/settings.json`
5. User `~/.claude/settings.json`

This is the "five-layer precedence" people often mention. The order alone is easy to misread, so keep two more rules in mind.

**Scalar fields are overridden by precedence.** If `model` is set to one value at the user level and another in the project-local file, the project-local value takes effect. Variables with the same name inside `env` work the same way: the higher layer wins.

**Permission rules are merged, not overridden.** Arrays such as `permissions.allow` and `permissions.deny` are combined across layers when rules are evaluated, and `deny` takes priority over `allow`. So if your team denies `Bash(curl:*)` in the shared project config, allowing it locally does nothing. A deny in managed policy cannot be undone by the user at any layer.

## Common fields at a glance

| Field | What it does | Example | Recommended layer |
|---|---|---|---|
| `env` | Environment variables set automatically for every session | `{"HTTPS_PROXY": "http://127.0.0.1:7890"}` | Depends on the variable; see the next section |
| `permissions.allow` / `deny` / `ask` | Rules that allow, block, or require confirmation for tool calls | `"Bash(npm run test:*)"`, `"Read(./.env)"` | Team conventions in project shared; personal habits in local |
| `permissions.defaultMode` | Default permission mode | `"acceptEdits"` | User or local |
| `permissions.additionalDirectories` | Paths outside the working directory that Claude may access | `["../shared-lib"]` | Local |
| `model` | Default model | A model alias or ID | User or local |
| `apiKeyHelper` | Generates the auth value with a script so the key is never written to a file | `"~/bin/get-key.sh"` | User |
| `hooks` | Run commands before or after tool calls, for example auto-formatting | See the official hooks docs | Team standards in project shared |
| `includeCoAuthoredBy` | Whether git commits carry a Claude co-author line | `false` | Project shared |
| `cleanupPeriodDays` | How many days to keep local session transcripts | `30` | User |
| `statusLine` | Customizes the status line at the bottom | A command config | User |

Before you start writing, you can add `"$schema": "https://json.schemastore.org/claude-code-settings.json"` as the first line of the file. Editors such as VS Code use it for field completion and validation, so a misspelled field name shows up immediately.

## What does env do for the API endpoint and proxy, and how far does it reach?

`env` has the same effect as `export`ing those variables for you before Claude Code starts. It applies to the Claude Code process itself, and commands that Claude Code runs through the Bash tool can generally read them too. It does not change your system environment, and it does not affect programs you run by hand in another terminal.

The common variables fall into three groups, and each belongs in a different place:

| Category | Variables | Where to put them | Why |
|---|---|---|---|
| API endpoint and auth | `ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_API_KEY` | User level or `settings.local.json` | They contain secrets and must never go into the repo |
| Network proxy | `HTTPS_PROXY`, `HTTP_PROXY`, `NO_PROXY` | User level or local | Everyone's network is different |
| Behavior switches | `DISABLE_TELEMETRY`, `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`, `API_TIMEOUT_MS`, `BASH_DEFAULT_TIMEOUT_MS` | Team-wide ones can go in project shared | They contain no personal information |

A few things that tend to bite in practice:

**Proxy variables are inherited by child commands.** If you set `HTTPS_PROXY` in `env`, then `npm install` and `git fetch` run by Claude Code also go through that proxy. If an internal repository or a domestic mirror in China should not go through the proxy, list it in `NO_PROXY`, for example `"NO_PROXY": "localhost,127.0.0.1,.internal.example.com"`.

**If only one project needs a different endpoint, put it in the local file.** Say you normally use the official endpoint, but one project has to go through a company gateway. Write `ANTHROPIC_BASE_URL` into that project's `.claude/settings.local.json` and other projects are unaffected. For how to fill in the endpoint, and where the equivalents for Codex and OpenCode go, see [Configuring a custom API endpoint for Claude Code, Codex and OpenCode](/en/blog/configure-custom-api-endpoint-claude-code-codex). It is not repeated here.

**If the shell sets a variable with the same name, trust `/status`.** Per the official docs, `env` in settings is applied to every session, but how a variable already present in your shell interacts with a same-named one in settings may differ between versions. When you hit "I changed it and nothing happened", the first step is the verification list below, not editing the file again and again.

**Variables that must be read when the process starts belong in the shell.** Something like `NODE_EXTRA_CA_CERTS` (for a company's self-signed certificate) is read by Node.js during startup, so putting it in the settings `env` may be too late. The safer approach is to `export` it in your shell config.

## After a change, how do you confirm which layer took effect?

Work through these checks in order:

1. Validate the JSON syntax. A single stray comma can cause the whole file to be ignored:
   ```bash
   for f in ~/.claude/settings.json .claude/settings.json .claude/settings.local.json; do
     [ -f "$f" ] && (python3 -m json.tool "$f" >/dev/null && echo "OK  $f" || echo "BAD $f")
   done
   ```
2. Restart the session. Settings are read at startup, and a session that is already open may not reload `env`. Exit and run `claude` again.
3. Run `/status` inside the session. It shows the current auth method, model, API endpoint and similar information, and some versions also list which settings sources were read. Check that the endpoint and proxy are the values you expect.
4. Run `/permissions` to list the allow / deny rules currently in effect. If a rule seems to do nothing, see whether a deny from another layer is covering it.
5. Run `/config` to open the settings UI, where you can view and change commonly used user-level options. Pay attention to which layer's file it modifies, and if you're unsure, go back to step 3 to cross-check.
6. Ask Claude to print the environment variables. Have it run `env | grep -iE 'proxy|anthropic'` and look at the values the Bash tool sees. The output may contain secrets, so view it only on your own machine and don't paste it into a group chat or an issue.
7. When something goes wrong, run `/doctor`. It checks the installation and configuration, and some versions flag invalid fields in settings files.

If `/status` shows everything is correct but requests still time out or fail, the problem is most likely not in the config files but in the network or on the server side. In that case work through [Troubleshooting Claude Code connection timeouts and errors: a four-layer network checklist](/en/blog/claude-code-connection-troubleshooting) layer by layer. You can also open [Is Claude Code down?](/en/down/claude-code) and [Anthropic API status](/en/status/anthropic) to see whether the service currently has an outage, so you rule out their side before investigating yours. To check whether the proxy is actually in effect and where your exit IP is, use [IP and environment check](/en/ip).

## How do you split team-shared config from personal config?

A fairly safe split: the repo holds only what everyone should have identically, and anything tied to a person, a machine, or a secret stays local.

Project shared `.claude/settings.json` (committed to the repo), example:

```json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test:*)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)"
    ]
  },
  "env": {
    "DISABLE_TELEMETRY": "1"
  },
  "includeCoAuthoredBy": false
}
```

Project local `.claude/settings.local.json` (not committed), example:

```json
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://api.example.com",
    "ANTHROPIC_AUTH_TOKEN": "replace with your own key",
    "HTTPS_PROXY": "http://127.0.0.1:7890",
    "NO_PROXY": "localhost,127.0.0.1"
  },
  "permissions": {
    "additionalDirectories": ["../my-scratch"]
  }
}
```

The addresses, ports and directories above are examples. Replace them with your own values.

Add this to `.gitignore`:

```gitignore
# Claude Code personal config, keep out of the repo
.claude/settings.local.json
# If anyone likes to keep a CLAUDE.local.md in the project, ignore that too
CLAUDE.local.md
```

Before committing, double-check once more:

```bash
git check-ignore -v .claude/settings.local.json   # should print the matching ignore rule
git ls-files .claude/                              # settings.local.json should not appear
```

If a key has already been committed, adding it to `.gitignore` is not enough. You need to revoke that key in the provider's console and create a new one. Before handing your code and config to a third-party endpoint, read its data policy first; see [Can your code and conversations be seen when you use a third-party AI API?](/en/blog/ai-api-data-privacy-policy)

## Frequently asked questions

### I changed settings.json and nothing happened?

Check in this order: is the JSON valid, did you restart the session, does a higher layer override the same field, does the shell set a variable with the same name, and what value does `/status` show. Most cases are settled in the first three steps.

### Can I switch to a different config for just one launch?

Yes. Use `claude --settings ./some-file.json` to load an extra settings file. Its precedence sits at the command-line-argument level, above project and user config, which makes it handy for temporarily testing another endpoint or model without touching your usual files.

### The config is right, but it's slow?

Then it's not a config problem. Latency usually comes from the network path, the proxy node, or server-side queuing; see [Claude Code responses are slow: where latency comes from and how to diagnose and reduce it](/en/blog/claude-code-slow-response-fix). For which domains and ports to allow, see [Network requirements for Claude Code and Codex](/en/blog/claude-code-vs-codex-network-requirements). In a browser you can also use the [cdnping online speed test](/en) to look at first-connection and round-trip times to each vendor's API, as a reference.

One last reminder: when you use Claude Code through a proxy or a third-party endpoint, follow Anthropic's terms of service and the laws where you are. Regional availability is as stated by the official documentation.
