Claude Code Managed Settings: Policy That Actually Holds

In the system directory for the operating system: /Library/Application Support/ClaudeCode/ on macOS, /etc/claude-code/ on Linux and WSL, and C:\Program Files\ClaudeCode\ on Windows. The legacy Windows ProgramData path is no longer read. The same directory also holds an optional managed-settings.d drop-in directory and managed-mcp.json.
Almost always because a higher-priority managed source is present. Claude Code uses the first source that delivers at least one policy key — remote settings, then MDM or OS policy, then files, then the user registry — and ignores the rest without any warning. Run /status and read the Setting sources line to see which source it actually selected.
No, with a small exception. Claude Code selects one source and ignores the others rather than merging. A few cross-source keys are read from every admin source anyway — the sandbox locks, some sandbox controls, and since v2.1.223 the env block, which merges per variable so lower sources fill in variables the higher ones leave unset.
Not through settings files, but four things sit outside the rule. A managed model value is a default rather than a lock, so use availableModels to restrict choice. A local administrator can edit the managed source itself. An edit to the server-managed cache lasts until the next fetch. And managed settings bind Claude Code, not other tools calling the API.
Claude Code repairs individual entries where it can, drops top-level keys that still fail, and keeps enforcing everything valid. Several enforcement keys fail closed instead — an invalid MCP or model allowlist is enforced as empty. The version floor and ceiling deliberately fail open, so a bad policy push cannot stop Claude Code from starting.

Key Takeaway
Claude Code managed settings apply above every other settings level, so no user, project or local value overrides them. When more than one managed source delivers a policy, Claude Code uses the first one that contains a policy key and ignores the others entirely rather than merging them, and it shows no warning for the sources it skipped.
An administrator I spoke to had deployed a careful managed settings file to every machine, verified the JSON, verified the path, and could not work out why none of it applied. The file was fine. Their organisation had also configured server-managed settings months earlier, and that source outranks a file — so Claude Code was reading the remote policy and silently ignoring the one they had just shipped.
Managed settings are the mechanism that makes Claude Code deployable in an organisation with rules, and the thing that makes them confusing is that they do not behave like the rest of the settings system. This post covers the four delivery mechanisms, the winner-takes-all precedence and its exceptions, the keys only a managed source can set, what happens when a value is invalid, and the two commands that answer whether a policy is actually in force.
Every mechanism carries the same policy keys as an ordinary settings file, so the settings reference applies to all of them. What differs is where the policy is stored and when Claude Code reads it. The file and MDM rows are together called endpoint-managed, because the policy sits on the device; server-managed is the row where Claude Code fetches it instead.
Pick by how you already manage devices:
| Mechanism | When Claude Code reads it | Use it when |
|---|---|---|
| Server-managed settings | Fetched at startup, polled hourly | You want one place to change policy without touching machines |
| MDM or OS-level policy | At startup, rechecked every 30 minutes | You already run Jamf, Intune or Group Policy |
| A managed settings file | At startup, reloaded when the file changes | Machines without MDM, Linux hosts, images you build |
| The user registry on Windows | At startup, rechecked every 30 minutes | You cannot write the machine-level key |
# managed-settings.json goes in the system directory for the OS.
# Note that the legacy Windows ProgramData path is NOT read.
macOS /Library/Application Support/ClaudeCode/
Linux and WSL /etc/claude-code/
Windows C:\Program Files\ClaudeCode\
# Same directory also holds an optional drop-in directory and
# the managed MCP configuration:
# managed-settings.d/*.json
# managed-mcp.json
# Drop-ins let several teams own parts of one policy. Claude Code
# merges managed-settings.json first, then every .json file in the
# directory in ALPHABETICAL order — so prefix them:
# 10-telemetry.json
# 20-security.jsonThis is the section worth reading twice. Claude Code checks the sources in a fixed order and uses the first that delivers at least one policy key. It does not merge the rest — it ignores them, without a warning:
A source that contains only the WSL inheritance control does not count as delivering a policy key, and Claude Code moves on to the next source. That is the one deliberate exception to the counting rule, and it exists so the control can be set without accidentally claiming the whole policy slot.
A small set of keys breaks the winner-takes-all rule, because they are locks or safety controls where a stricter value from anywhere should win. Claude Code reads these from every admin source — which excludes the user-writable registry:
Most managed-only keys are locks. The value a lock governs — permission rules, sandbox domains — is an ordinary key any level can set; the lock tells Claude Code to honour only the managed value. Deploying rules without the corresponding lock is the most common way a policy ends up advisory rather than binding.
// A managed policy that actually constrains something.
{
"permissions": {
"deny": ["Read(./.env)", "Read(./secrets/**)"],
"disableBypassPermissionsMode": "disable"
},
// Without this, a developer's own allow rules still apply
// alongside yours. With it, ONLY managed rules count — and
// --allowedTools is ignored too.
"allowManagedPermissionRulesOnly": true
}
# Confirm it landed on one machine before the fleet:
/status # look for the "Setting sources" line
# Enterprise managed settings (file)
# ... (remote) (plist) (HKLM) (drop-ins) (HKCU)
# ... (parent process) (helper)
claude doctor # lists every entry Claude Code DROPPED, with
# its source and fieldThere is a long list of managed-only keys beyond permissions: controls for which hooks may run, which MCP servers are admitted, which plugin marketplaces are permitted, whether command-sourced plugins run at all, whether the sideload flags are rejected at startup, and whether skills, agents, hooks and MCP servers may come from user and project sources at all. The settings reference marks each one, and the scope line is the field to read.
Claude Code is deliberately tolerant with managed settings: it repairs what it can, drops top-level keys that still fail, and keeps enforcing everything valid. A handful of enforcement keys refuse to be dropped, because dropping them would be the insecure outcome:
That last one is the design decision worth appreciating. Every other enforcement key fails closed, but the version constraints fail open, because a typo in a minimum-version field that bricked every developer's CLI would be a far worse outcome than a temporarily unenforced version floor. It is a good instinct to copy in your own policy tooling.
Managed settings are strong, and it is worth being honest about the four things that sit outside them, because a security review will ask:
If several teams own parts of one policy, use the drop-in directory rather than a shared file. Claude Code merges the main file first, then every JSON file in the directory alphabetically, so numeric prefixes control the order. Lists combine with duplicates removed, nested blocks merge key by key, and single values are replaced by the later file — which means two teams can own genuinely separate concerns without editing the same file.
Two commands settle every version of this question. The status command's setting-sources line names the managed source Claude Code selected, in parentheses, so you learn both that a policy is active and which of your four mechanisms won. A missing line means no source delivered a policy key at all; a line naming a different source means a higher-priority one was present and yours was ignored.
The doctor command answers the other half: what got dropped. When a file, profile, registry value or server payload fails schema validation, Claude Code skips the individual entries it can repair with a warning each, then drops any top-level key whose value still fails. Interactive sessions show a dialog at startup, non-interactive runs print to standard error, and the doctor command lists each invalid entry with its source and field.
The rule to carry away is that managed settings are not a merge, they are a selection. Decide which of the four mechanisms is your source of truth, deploy only through it, and verify with the status line on one machine before touching the fleet. Then pair every rule with the lock that makes it binding, because a permission rule without its lock is a suggestion — and a suggestion is not what anyone deploying managed settings is trying to ship.
Sources & further reading