Skip to content

Four verified constraints

1. The managed tier is winner-take-all, and managed-settings.d/ is the only thing that merges

Section titled “1. The managed tier is winner-take-all, and managed-settings.d/ is the only thing that merges”

There are five ways managed settings can reach a machine. Only one of them applies per run:

Within the managed tier, apart from the exception keys listed after the ranking, only one source is used and the others are ignored rather than merged.

CC-settings § Settings precedence

The ranking, highest first, is policyHelper output, then remote (server-managed or Claude apps gateway), then MDM/OS-level policies, then file-based (managed-settings.d/*.json and managed-settings.json, merged together), then the Windows HKCU registry (CC-settings § Settings precedence). The narrow exceptions that are read from every admin-controlled source — the sandbox lock keys, allowAllClaudeAiMcps, the sandbox binary paths, forceRemoteSettingsRefresh, and env — are listed in the same section and in CC-server § Per-key exceptions across managed sources. Neither extraKnownMarketplaces nor enabledPlugins is among them.

Inside the file-based source, the drop-in directory is what makes layering possible:

File-based managed settings also support a drop-in directory at managed-settings.d/ in the same system directory alongside managed-settings.json. This lets separate teams deploy independent policy fragments without coordinating edits to a single file.

Following the systemd convention, managed-settings.json is merged first as the base, then all *.json files in the drop-in directory are sorted alphabetically and merged on top. Later files override earlier ones for scalar values, arrays are concatenated and de-duplicated, and objects are deep-merged. Hidden files starting with . are ignored.

Use numeric prefixes to control merge order, for example 10-telemetry.json and 20-security.json.

CC-settings § Settings files

Four consequences follow, and all four shape the files in this repository:

Rule Consequence for Patterson
Sorted alphabetically Organizational precedence has to be encoded in the filename. Hence 10-, 20-, 30-, 40-.
Later files override scalars A team can flip a boolean the enterprise set. This is the override half of 40-team.json.
Arrays concatenate and de-duplicate A later fragment can only widen an array. See the warning below.
Objects deep-merge extraKnownMarketplaces and enabledPlugins are objects, so every layer contributes keys and no layer wipes another’s.

One more property makes the drop-in directory safe to iterate on: managed settings “parse tolerantly”. An entry that fails schema validation is stripped, a warning is recorded, and every remaining valid policy is still enforced, so “a single typo cannot disable the rest of your organization’s policy” (CC-settings § Invalid entries in managed settings, requires Claude Code v2.1.169 or later).

2. Marketplace name is a flat global namespace

Section titled “2. Marketplace name is a flat global namespace”

Each user can register only one marketplace per name: adding a second marketplace with the same name replaces the first.

CC-marketplaces § Marketplace schema > Required fields, the name row

There is no scoping by owner, by org, or by source. patterson-corp is patterson-corp everywhere on the machine, and marketplace state is stored once per user in ~/.claude/plugins/known_marketplaces.json, “not per project” (CC-marketplaces § Require marketplaces for your team).

The operational rule: the name field in a marketplace manifest is a Patterson-wide identifier. patterson-corp, patterson-dental, patterson-vet, and patterson-labs must each be claimed once, org-wide, and never reused for a fork or a mirror.

3. Copilot instruction precedence is inverted, and there is no enterprise tier

Section titled “3. Copilot instruction precedence is inverted, and there is no enterprise tier”

Copilot recognizes exactly three types of custom instruction — personal, repository, and organization (GHC-precedence § Types of custom instructions) — and orders them like this:

Personal instructions take the highest priority. Repository instructions come next, and then organization instructions are prioritized last. However, all sets of relevant instructions are provided to Copilot.

GHC-precedence § Precedence of custom instructions

That is the exact inverse of Claude Code, where the managed tier wins and user settings lose. The enumeration in the same section runs: personal, then repository (path-specific, then repository-wide, then agent instructions such as AGENTS.md), then organization. GHC-support confirms the same three types across every listed environment and names no fourth; no enterprise instruction type appears in either document. Organization instructions are also set in the organization settings UI rather than in a repository file, and require a Copilot Business or Copilot Enterprise subscription (GHC-org-instructions § Adding organization custom instructions; GHC-precedence § About organization custom instructions).

The consequence for Patterson: an enterprise instruction cannot be enforced on Copilot. Anything Patterson needs to be non-negotiable has to be a Copilot policy, not a Copilot instruction — and anything expressed as an instruction can be overridden by any individual developer’s personal instructions. Whether Copilot supports layering more than one organization-level instruction set: [TBD: not specified in GHC-org-instructions].

4. VS Code reads .claude/settings.json with the same keys

Section titled “4. VS Code reads .claude/settings.json with the same keys”

VS Code reads workspace plugin recommendations from .claude/settings.json OR .github/copilot/settings.json, using the SAME field names as Claude Code: extraKnownMarketplaces : { "<name>": { "source": { "source": "github", "repo": "org/repo" } } }, enabledPlugins : { "<plugin>@<marketplace>": true }

VSC-plugins-norm § Convergence point, distilled from https://code.visualstudio.com/raw/docs/agent-customization/agent-plugins.md

The same convergence holds at the enterprise end. VS Code’s Copilot managed settings map policy names onto the identical Claude Code keys (VSC-enterprise § Available managed settings, § Manage agent plugins and marketplaces):

Claude Code key VS Code policy VS Code setting
enabledPlugins ChatEnabledPlugins chat.plugins.enabledPlugins (org-managed)
extraKnownMarketplaces ChatExtraMarketplaces chat.plugins.extraMarketplaces
strictKnownMarketplaces ChatStrictMarketplaces chat.plugins.strictMarketplaces (org-managed)

VS Code also states that it reads these policies “from the same Copilot managed settings that drive enterprise plugin standards for Copilot CLI, so a single definition applies to both clients” (VSC-enterprise § Manage agent plugins and marketplaces). And the marketplace manifest schema is Claude’s: “For the full marketplace plugin schema, see the Claude Code plugin marketplace documentation” (VSC-plugins-norm § Marketplaces).

One settings shape serves both agents. The four files in this repository are therefore not Claude-Code-only artifacts — the same extraKnownMarketplaces and enabledPlugins objects are what a VS Code workspace recommendation and a VS Code enterprise policy carry.

Two limits on that convergence, both worth knowing before anyone plans a single source of truth:

  • VS Code loads only portable skills and MCP configuration from a plugin. Agents, hooks, and slash commands are client-specific, and VS Code ignores client-extension namespaces (VSC-plugins-norm § Portable vs client-specific components). A Patterson plugin’s subagents and hooks do not cross.
  • The Copilot harness supports “only LOCAL MCP servers that require NO authentication” (VSC-harness-norm § Why this matters for Patterson).

Whether VS Code offers any drop-in-directory equivalent for layering org tiers: [TBD: not specified in VSC-enterprise].


Source of truth: docs/architecture/layered-settings.md in the patterson-corp repository.