LEARN · PHASE 17 · LESSON 115

Managing Settings at Scale

You can put one policy on every machine and prove it applied — and say which

Type
Learn
Prerequisites
Lesson 114, Sandboxing and Security Model
Time
~40 minutes

Learning Objectives

  • Name the four ways managed settings reach a machine and their rank
  • Read /status and tell an unapplied policy from an overridden one
  • Choose between first-wins and merge, and predict which source supplies a key
  • Recognise the keys that fail closed and why that is deliberate
  • Split a policy across files without creating a merge accident

The Problem

You rolled out managed-settings.json to the fleet. A developer says the policy is not applying. You open the file on their machine: it is there, valid JSON, the right path. You redeploy it. Still nothing.

The file is not the problem. Either a higher-ranked source is present and winning — an MDM profile, or server-managed settings from the admin console — or the file is real but contains only control keys and no actual policy, so it does not count as a source at all. Neither failure is visible by looking harder at the file you deployed.

The pain: managed settings have their own precedence, different from the four-file order you learned in Lesson 34. The fix is to read which source was selected, not to deploy again.


The Concept

Managed settings sit above every other layer: user, project, and local files and even the --settings flag cannot override them, apart from a small set of security-sensitive exceptions where a stricter lower value still counts.

But "above everything" is only half the story. Managed settings have four delivery mechanisms that outrank each other.

flowchart TB
    R["1. Remote<br/>server-managed (claude.ai / gateway)<br/>fetched, polled hourly"] --> M["2. MDM / OS policy<br/>macOS plist, Windows HKLM<br/>checked every 30 min"]
    M --> F["3. Files<br/>managed-settings.json<br/>+ managed-settings.d/"]
    F --> H["4. HKCU registry<br/>Windows user-writable fallback"]
    R --> P[The policy for this session]
    M --> P
    F --> P
    H --> P
Mermaid source — renders as a diagram where mermaid.js is available

The default behaviour is first-wins: Claude Code uses the highest-ranked source that delivers at least one policy key and ignores the rest. A policy key is any settings key other than the two control keys (managedSourcesBehavior, wslInheritsWindowsSettings). A file containing only control keys is not a source, and Claude Code moves down the list.

If you want every source to contribute, set managedSourcesBehavior to "merge" in the highest-ranked source you deploy. Under "merge", lists combine, locks take the strictest value, and most other keys take the value from the highest-ranked source that sets them. The user-writable HKCU registry never merges with another source.

Where the files live

OSDirectoryPowerShell / shell
WindowsC:\Program Files\ClaudeCode\managed-settings.json, managed-settings.d\, managed-mcp.json
macOS/Library/Application Support/ClaudeCode/same file names
Linux / WSL/etc/claude-code/same file names

The Windows HKCU fallback is a Settings value under HKCU\SOFTWARE\Policies\ClaudeCode. The legacy path C:\ProgramData\ClaudeCode\managed-settings.json is not read.

Splitting the file across teams

Rather than one shared file everyone edits, put each team's part in managed-settings.d/. Claude Code merges managed-settings.json first, then every *.json in that directory in alphabetical order — so numeric prefixes set the order:

managed-settings.json
managed-settings.d/
├── 10-telemetry.json
└── 20-security.json

When two files set the same key: single values are replaced by the later file, lists are combined (duplicates removed), and nested blocks merge key by key. Same rule as everywhere else in this course — arrays merge, scalars are replaced.

Fail closed, or fail open

Managed settings are more forgiving than your own files, in two opposite ways.

  • Invalid JSON refuses to start. If a managed file, MDM plist, or HKLM value is present but cannot be parsed, Claude Code exits with an error naming the source rather than running with a partial policy.
  • Individual bad entries are repaired or dropped, with a warning, instead of failing the whole file.
  • Some keys fail closed. A restrictive single-value key that is present but invalid reads as its restrictive value until you fix it, so a broken restriction never silently becomes an open gate: allowManagedPermissionRulesOnly, disableAutoMode, and skipDangerousModePermissionPrompt all behave this way, and allowedMcpServers falls back to an empty allowlist that admits no user-added servers. A few keys fail open deliberately — requiredMinimumVersion is dropped rather than enforced when invalid.

This asymmetry is on purpose: a bad list should not silently grant access, but a bad rollout should not brick every machine either.

Keys only a managed source can set

A handful of keys have no effect in user, project, or local files — they are read only from a managed source. These are the levers that make a rollout a rollout, not a suggestion: things like allowManagedPermissionRulesOnly, managedMcpServers, availableModels, and the sandbox locks from Lesson 114 (such as sandbox.network.allowManagedDomainsOnly). The settings reference marks each key's scope.

When a source names you in /status, it can also be computed: a policyHelper is an executable a managed source names, and Claude Code runs it at startup to produce the managedSettings object.

The reframe: a policy is two things — the file on the machine, and the

rank that lets it win. Deploying harder only ever fixes the first.

A note on versions. The managed-settings surface adds keys and combine-rules regularly — managedSourcesBehavior, per-source locking, and several fail-closed keys are version-gated. Treat the ranking in this lesson as the durable part and check the managed settings docs before depending on a specific key.


Build It

You need administrator rights to write the system directory. If you do not have them, do steps 1–2 with the --settings flag to rehearse and note where the real mechanism differs.

  1. Deploy a minimal policy. Create the file at your OS path — on Windows:

``json { "permissions": { "deny": ["Read(./.env)"] }, "allowManagedPermissionRulesOnly": true } ``

Save it as C:\Program Files\ClaudeCode\managed-settings.json (or the macOS/Linux path from the table above). Include at least one policy key, not just a control key.

  1. Confirm it applied. Start Claude Code and run /status. The Setting sources line should show Enterprise managed settings (file). ✅ You pass when that exact label appears.
  1. Break it on purpose — control keys only. Replace the file with { "managedSourcesBehavior": "merge" } and restart. Run /status again. The managed line should be missing, because a control-only file is not a policy source.
  1. See a skip. If you can also add an MDM-style source (a second machine or a lab box), do. Otherwise reason it through from the ranking and check for a Skipped sources line in /status on a machine with two sources. ✅ You pass when you can say which source was selected and which was skipped.
  1. Split the policy. Move one team's keys into managed-settings.d/10-telemetry.json and another's into 20-security.json. Confirm the merged result via /status and by testing a behaviour each file sets.
  1. Watch a fail-closed key. Set allowedMcpServers to something invalid and run claude doctor. ✅ You pass when the report names the key and the value it fell back to.

Use It

ThingWhen you reach for it
managed-settings.jsonThe simplest rollout — one policy file in the OS directory
managed-settings.d/*.jsonSeveral teams own parts of one policy; numeric prefixes set order
Server-managed settingsOne place to change policy for a claude.ai org without touching machines
MDM / OS policy (plist, HKLM)You already manage devices with Jamf, Intune, or Group Policy
managedSourcesBehavior: "merge"You want every deployed source to contribute, not just the top one
policyHelperThe policy must be computed at startup, not stored
allowManagedPermissionRulesOnlyOnly the org's permission rules may apply
managedMcpServers / sandbox.* locksDeliver and lock servers or sandbox boundaries
/statusFind which managed source was selected, and which were skipped
claude doctorFind the entries Claude Code dropped as invalid

Exercises

  1. Diagnose from the line, not the file. A developer shows you a correct managed-settings.json and says the policy is not applying. Write the two things you check in /status, in order. ✅ You pass when your first check distinguishes "no managed source at all" from "a higher source won," and your second names the overriding source.
  1. Predict the winner. A machine has an MDM plist, a managed-settings.json, and an HKCU value. Which supplies the policy under the default, and what changes under "merge"? ✅ You pass when you name the MDM plist for both, and add that HKCU stays out of the merge.
  1. Rehearse without admin rights. Simulate a policy for one session using --settings, then explain why that is not managed settings. ✅ You pass when you can say which layer --settings occupies and which source would beat it.
  1. Avoid a merge accident. Plan a policy split across three managed-settings.d/ files where two files set the same list key. Predict the merged list. ✅ You pass when your prediction matches the combined, de-duplicated list and you name the file order that produced it.
  1. Prove enforcement. Deploy allowManagedPermissionRulesOnly: true and try to add an allow rule in a project settings file. ✅ You pass when the project's allow rule has no effect and you can say which layer dropped it.

Key Terms

TermWhat people sayWhat it actually means
managed settings"admin settings.json"A policy that outranks user, project, local, and --settings. Its own sources also outrank each other
policy key"any setting"Any key other than the two control keys. A file with none is not a source
first-wins"the default"The top-ranked source with a policy key supplies the policy; the rest are skipped and named
merge"combine them"An opt-in where every admin source contributes, combined by kind of key
fail closed"a bug"A restrictive key that is present but invalid reads as its restrictive value, on purpose
refuses to start"it broke"What happens when a managed source is present but not parseable — a deliberate hard stop
/status line"a status readout"The field that tells you which source won and which were skipped
policyHelper"a script"An executable that computes the managed settings at startup
scoped key"a normal setting"A key read only from a managed source; putting it in your own file does nothing

What this lesson skipped

Server-managed settings and gateways. The claude.ai console path and the self-hosted gateway deliver the same keys through different infrastructure. See server-managed settings and gateways.

MDM tooling. Deployment templates for Jamf, Intune, and Group Policy live in the MDM examples repository; this lesson covered the ranking, not the packaging.

The full key list. There are hundreds of keys with per-source scopes. Read all settings when you need a specific one.

Compliance configurations. HIPAA and zero-data-retention setups have their own documents; they are organisation policy, not the mechanism this lesson teaches.

Check yourself

3 questions. Answer before you reveal — recognising the right option is not the same as being able to produce it.

  1. A developer's managed-settings.json is at the correct path and is valid JSON, yet the policy is not applying. /status shows no Enterprise managed settings line. What are the two likely causes?

    1. The file sets no policy key, or a higher-ranked source such as an MDM profile is present and won
    2. The file is invalid JSON, or the developer lacks admin rights
    3. The developer edited a project settings file instead, or removed the file
    4. Claude Code needs a restart, or the model alias is wrong
    Show answer

    A. The file sets no policy key, or a higher-ranked source such as an MDM profile is present and won

    Under first-wins, a managed file counts only if it delivers a policy key — any key other than the two control keys. A file of control keys alone is not a source, so the line is absent. The line is also absent when a higher-ranked source (server-managed, or MDM/OS policy) supplies the policy; /status then names the selected source, and a Skipped sources line names the file. B is tempting because invalid JSON is a real failure mode — but it makes Claude Code refuse to start, not run without a policy, so it contradicts the symptom. Admin rights matter for writing the file, not for whether it is read. C and D guess at causes the stated facts already rule out.

  2. A machine has an MDM/OS policy, a managed-settings.json, and an HKCU registry value, each with policy keys. Under the default behaviour, which supplies the policy?

    1. The managed-settings.json, because files are the canonical source
    2. The MDM/OS policy, because it outranks the file; and under merge the HKCU value still stays out
    3. The HKCU value, because it is closest to the user
    4. All three merge automatically, so the question is moot
    Show answer

    B. The MDM/OS policy, because it outranks the file; and under merge the HKCU value still stays out

    The ranking, highest first, is: remote (server-managed), MDM/OS policy, managed files, then the user-writable HKCU registry. Under the default first-wins, the highest-ranked source that carries a policy key wins, so the MDM policy supplies the policy and the file is skipped (and named under Skipped sources). If you opt into merge, every admin source contributes — but the HKCU registry is user-writable and is excluded from merging, so it still does not join. A is tempting because a file feels authoritative, yet files are ranked below device policy. C reverses the ranking. D is the exact misconception: merging is opt-in, and never automatic.

  3. A manager sets allowManagedPermissionRulesOnly in a managed source, but mistypes the value so it cannot be read. What should you expect when the policy is next applied?

    1. The key is dropped, so permission rules from user and project files apply again
    2. The key reads as its restrictive value — permission rules come only from managed settings — until the value is fixed
    3. Claude Code refuses to start until the value is fixed
    4. The whole managed source is ignored and the next-ranked source is used
    Show answer

    B. The key reads as its restrictive value — permission rules come only from managed settings — until the value is fixed

    Restrictive single-value keys like allowManagedPermissionRulesOnly fail closed: when present but invalid, they read as the restrictive value, so the policy cannot silently loosen. This is deliberate — a broken restriction should not become an open gate. A is the tempting 'fail open' assumption, and it is wrong for exactly these keys. C is a real behaviour for a managed source that cannot be parsed at all (malformed JSON), but a single invalid value inside a valid source is repaired, not fatal. D misapplies the source ranking: a source that delivers keys is still the selected source.