Claude/Code/Settings/Override
Properties
- see-also
- Claude/Code/Settings
Claude Code Settings Override & Precedence
Overview
- When the same key appears in more than one Claude Code configuration file, the result is decided by two separate mechanisms that are easy to conflate:
- 1.
settings.jsonscopes — a fixed set of locations (user, project, local, managed) combined by a precedence order. There is no directory walk; each scope is a known path. - 2.
CLAUDE.md/ rules — instruction files that Claude Code discovers by walking up the directory tree and concatenating, rather than overriding.
- 1.
- "Override" therefore means different things depending on which mechanism is in play. The headline rule for
settings.json: most keys are replaced by the highest-precedence scope that defines them — they are not deep-merged. A handful of keys are deliberate exceptions (permissions, some arrays, and plugin enablement).
- When the same key appears in more than one Claude Code configuration file, the result is decided by two separate mechanisms that are easy to conflate:
The
settings.jsonscopes- Managed / enterprise policy — system locations (
managed-settings.json), plus MDM/OS policy and amanaged-settings.d/drop-in directory. Cannot be overridden by anything below. - User —
~/.claude/settings.json. Applies to every project on the machine. - Project (shared) —
.claude/settings.json. Checked into source control and shared with the team. - Project (local) —
.claude/settings.local.json. Personal, not checked in; Claude Code configures git to ignore it on creation.
- Managed / enterprise policy — system locations (
Precedence order (highest → lowest)
- 1. Managed — can't be overridden by anything.
- 2. Command-line arguments — temporary, session-only overrides.
- 3. Local (
.claude/settings.local.json) — overrides project and user. - 4. Project (
.claude/settings.json) — overrides user. - 5. User (
~/.claude/settings.json) — applies when nothing more specific does. - The official phrasing: "When the same setting appears in multiple scopes, Claude Code applies them in priority order."
What "override" actually does: replace vs. merge
Default: replace
Exception: permission rules merge
Exception: a few arrays merge
Counter-example:
fallbackModeldoes not mergeManaged drop-in directory deep-merges
- Within managed settings,
managed-settings.jsonis the base andmanaged-settings.d/*.jsonare merged on top alphabetically: "Later files override earlier ones for scalar values; arrays are concatenated and de-duplicated; objects are deep-merged." This deep-merge is specific to the managed drop-in layer, not to the user/project/local layers.
- Within managed settings,
Plugins: resolved per-plugin across scopes
- Plugin configuration is the case most relevant to a shared project file, and it behaves more like permissions than like a replaced scalar — each plugin's state is tracked per-plugin, per-scope (the Installed tab in
/plugingroups plugins by the scope that enabled them). enabledPlugins- An object mapping
"plugin-id@marketplace-id"→ boolean. - json
{ "enabledPlugins": { "code-formatter@team-tools": true, "deployment-tools@team-tools": true, "experimental-features@personal": false } } - Because resolution is per-plugin, a higher scope only overrides the specific plugins it names — you do not have to restate the whole map. Project settings take precedence over user settings, so setting a plugin to
falsein~/.claude/settings.jsondoes not disable one the project's.claude/settings.jsonenables; to opt out on your machine, set that pluginfalsein.claude/settings.local.json.
- An object mapping
extraKnownMarketplaces- An object mapping a marketplace name → a
sourceconfig. Used in a project's.claude/settings.jsonso teammates automatically have the required plugin sources (they're prompted to install once they trust the folder). - json
{ "extraKnownMarketplaces": { "my-team-tools": { "source": { "source": "github", "repo": "your-org/claude-plugins" } } } } - Source shapes include
github(repo, optionalref/path),git(url),url,npm,file, anddirectory. Prefergithub/gitfor anything checked in — a localdirectorypath won't resolve on a teammate's machine or in a fresh container.
- An object mapping a marketplace name → a
What
/pluginwrites/plugin install plugin@marketplaceinstalls to user scope (~/.claude/settings.json) by default.- The interactive UI (and
--scope) let you choose project scope (writes to.claude/settings.json, shared) or local scope (writes to.claude/settings.local.json, personal to the repo)./plugin enable//plugin disabletoggle the correspondingenabledPluginsentry.
- Plugin configuration is the case most relevant to a shared project file, and it behaves more like permissions than like a replaced scalar — each plugin's state is tracked per-plugin, per-scope (the Installed tab in
Does Claude walk up parent directories?
settings.json: no. The scopes are fixed, known paths (user home, the project's.claude/, managed locations). Claude Code does not climb parent directories hunting for asettings.json; it reads the four scopes and applies the precedence above.CLAUDE.md/CLAUDE.local.md: yes. "Claude Code reads CLAUDE.md files by walking up the directory tree from your current working directory, checking each directory along the way." All discovered files are concatenated (root → cwd order), not overridden — so a parentCLAUDE.mdand a nested one both apply. Files in subdirectories load on demand when Claude reads files there..claude/rules/*.mdfollow the same model.
Worked example: one shared Codespace, different plugins per person
- Goal: everyone shares an identical checked-in
.claude/settings.json, but each person enables a different mix of plugins. - 1. In the shared
.claude/settings.json, register the marketplace viaextraKnownMarketplaces(github source) and enable only the universal baseline inenabledPlugins. - 2. Each person puts their personal plugin toggles in
.claude/settings.local.json(gitignored). SinceenabledPluginsresolves per-plugin, local only needs the deltas — additional plugins settrue, and any baseline plugin they want off setfalse. - 3. Because local > project > user, the local file wins for exactly the plugins it names and leaves the rest of the shared config untouched. Pushing customization into
settings.local.json(rather than~/.claude/settings.json) is what makes per-person opt-out of a project-enabled plugin possible.
- Goal: everyone shares an identical checked-in
See also
- Claude/Code/Settings — full settings reference (keys, env vars, the precedence list).
- Claude/Code/Plugin/Marketplace — marketplace
marketplace.jsonstructure. - Claude/Code/Plugin
Sources
- Claude Code settings — settings files, precedence, replace-vs-merge.
- Discover and install prebuilt plugins —
enabledPlugins, scopes,/plugin installdefaults. - Create and distribute a plugin marketplace —
extraKnownMarketplaces, team marketplaces. - How Claude remembers your project —
CLAUDE.mddirectory-tree traversal and concatenation.