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 alongsidemanaged-settings.json. This lets separate teams deploy independent policy fragments without coordinating edits to a single file.Following the systemd convention,
managed-settings.jsonis merged first as the base, then all*.jsonfiles 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.jsonand20-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, thenamerow
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.jsonOR.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 fromhttps://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.