Claude Code settings: which file actually wins
Five settings layers, and your personal file is the bottom one. Why your team's committed settings beat your own, which keys a repository file can never set, which ones wait for workspace trust, and the security keys where the strictest value wins no matter who set it.
You set a key, restart, and Claude Code behaves as if you had not. The reason is almost always precedence, and the stack has one feature that inverts most people's intuition.
Highest to lowest:
- Managed settings (
managed-settings.json, MDM, or the claude.ai console) - Command line (
claude --settings) - Project local (
.claude/settings.local.json) - Shared project (
.claude/settings.json) - User (
~/.claude/settings.json)
Your personal file is the bottom of the stack. A committed team file beats ~/.claude/settings.json. That is the opposite of how most tools work, and it is the single most common reason a setting "does not apply." To get your value back in one project, put it in that project's .claude/settings.local.json, which sits above the shared file.
/status prints which files loaded and names the managed source that applies to you. Start there rather than guessing.
Lists merge, values override
When the same list key appears in several files, Claude Code combines them rather than picking one. permissions.allow from your user file, your team's file, and managed settings all apply together. This is why your organization's allow rules keep working alongside yours, unless they set allowManagedPermissionRulesOnly.
Four model keys deliberately do not merge, because position or completeness carries meaning:
fallbackModelis an ordered chain, so the whole value comes from the highest file that defines it.modelPickeris one ordered list plus a replace flag. It is taken whole from the highest of managed,--settings, and user settings, and ignored entirely in project and local settings.availableModelsfrom managed settings applies as-is and ignores your additions. Across non-managed scopes it merges normally.modelSettingsresolves one model at a time.
Environment variables are not a level
They do not sit anywhere in that stack. Each variable and key pair is decided on its own terms. ANTHROPIC_MODEL exported in your shell wins over the model key from any file. ANTHROPIC_DEFAULT_MODEL applies only when no file sets model. Same subject, opposite behavior, and the only way to know is the reference for that specific pair.
An env block inside a settings file is just an ordinary key and follows the five levels normally.
Three things a repository file cannot do
This matters if you maintain a shared .claude/settings.json and keep wondering why teammates do not get what you committed.
Some keys never apply from a repository file at all. The settings index marks these in its Scope column as User, local, or managed, User or managed, Managed, or Global config. Most relevant in practice: permissions.defaultMode values auto and bypassPermissions do not take effect from project or local settings. Set them in user or managed settings, or pass --permission-mode for one session. If you have been reading about what the bypass mode turns off, this is the reason a checked-in file cannot switch it on for everyone.
There is one asymmetric exception worth knowing: autoContinueAtUsageLimit. A repository file cannot turn it on, but while the file sets the key and no user, --settings, or managed value does, Claude Code reads it as off. A repo can disable the wait-and-continue behavior even though it cannot enable it.
Some keys wait for workspace trust. permissions.allow, permissions.additionalDirectories, extraKnownMarketplaces, and most env values apply only after each teammate trusts the folder. Until then they still get prompts and do not get plugins from a marketplace the file declares.
Note the shape of that rule: deny and ask rules apply right away. A repository you have not trusted can restrict you immediately but cannot grant itself anything. That is the correct direction, and it is the same principle as the classifier refusing to read autoMode from project files, which we covered in the auto mode post. Treat the repository as input, not authority.
Cloud sessions read a different subset. A cloud session runs on a fresh clone, so .claude/settings.json is read because it is in the clone, while ~/.claude/settings.json and .claude/settings.local.json are not read at all. Only server-managed settings reach it; a managed-settings.json file or MDM profile on your device does not.
The security keys where strict wins over managed
Normally nothing overrides managed settings. For a handful of keys whose values restrict a session, Claude Code honors the restrictive value from a lower scope anyway:
| Key | Honored value |
|---|---|
disableClaudeAiConnectors |
true from any scope |
enableArtifact |
false from any scope, and disableArtifact: true |
isolatePeerMachines |
true from any scope |
remoteControlAtStartup |
false from project or local settings |
crossSessionInbound |
a stricter value from project or local, on accept < hold < refuse |
useAutoModeDuringPlan |
false from managed, --settings, user, or local |
syncClaudeAiSkills |
false from the same four |
maxEffortLevel |
the lowest cap from any scope |
Two of those have a wrinkle: useAutoModeDuringPlan and syncClaudeAiSkills accept a false from your local file but ignore one in the shared project file. Committing false for your team does nothing; each person needs it in their own local or user file.
Why "don't ask again" keeps asking
A specific confusion worth its own section, because everyone hits it.
Choosing "Yes, and don't ask again" saves an allow rule to .claude/settings.local.json. If a project or managed file has an ask rule for the same tool, you still get prompted, because an allow rule in your local file does not outrank an ask rule from those scopes. Permission rules combine by their own order, not purely by file level.
In the VS Code extension the approval card lets you choose the destination file, including the shared project file, which changes the rule for everyone. In the CLI, Claude Code only ever writes to your local file.
Where the local file actually lives
Two details that cause "I edited it and nothing changed":
In a git repository, the local file lives at the repository root, not in the subdirectory you started from, and permission approvals apply across the whole repo. In a worktree it uses the main checkout's root. It stays beside .claude/settings.json instead when you are outside a repository, when the repo root is your home directory, on Windows, or when the root's ownership does not match your user.
Claude Code gitignores it globally, not locally. The first time it writes the file in a repository that does not already ignore it, it adds **/.claude/settings.local.json to your global git excludes file, so the pattern covers every repository on the machine. Nothing appears in the project's .gitignore. If you created the file by hand and Claude Code has not written to it yet, that has not happened, and you should add it yourself.
The five-minute triage
When a setting does not apply, in this order:
/statusto see which files loaded and whether a managed source applies.- Check for a higher level setting the same key. Remember your user file is the bottom.
- Check for a variable or flag on that specific key, since those are decided per pair rather than by level.
- Check whether the file is allowed to set it. Project files cannot set
autoorbypassPermissionsas a default mode, and cannot grant allow rules before trust. - Check the JSON is valid. A broken file makes Claude Code skip the file or the entry, quietly.
The organizing idea is worth holding onto, because it explains the exceptions rather than making you memorize them: settings resolve so that the party with less authority can always make a session more restricted and never less. Managed beats you on ordinary keys, you beat managed on keys that only tighten, an untrusted repository can deny but not allow, and a project file can turn off unattended continuation but not turn it on. Once that clicks, most of the table above stops needing to be a table.