Enterprise Integration and Security
Claude Code enterprise integration means enforcing one policy on every developer’s sessions through managed settings: a managed-settings.json file, an MDM profile, or server-managed settings from the claude.ai admin console. Managed settings rank above command-line flags, project, and user settings. Deny rules, the sandbox, telemetry, and a managed CLAUDE.md all ship through that one channel.
This page is for the tech lead or platform engineer who has to make that rollout real, and for the CTO who signs off on it. Security approved Claude Code for 200 developers last week. Now you need every session to block .env reads, refuse --dangerously-skip-permissions, report usage to your OpenTelemetry collector, and prove all of that to an auditor. A wiki page asking people to configure it themselves will not survive the first sprint.
What you’ll walk away with from an enterprise Claude Code rollout
Section titled “What you’ll walk away with from an enterprise Claude Code rollout”- A decision on how policy reaches machines: server-managed, MDM, or a system file
- A baseline
managed-settings.jsonyou can deploy today, with each lock explained - The reason deny rules are not a security boundary, and the sandbox settings that close the gap
- A verification routine (
/status,claude doctor, a canary probe, telemetry checks) that proves the policy is in force without inspecting every laptop - A failure-modes list for the ways a fleet-wide policy goes wrong, with a recovery for each
All keys and paths on this page were checked against the Claude Code settings documentation and the installed CLI, version 2.1.283, on 2026-09-26.
How do managed settings reach developer machines?
Section titled “How do managed settings reach developer machines?”Claude Code reads managed policy from four kinds of source. Pick by how you already manage devices, not by preference:
| Mechanism | Where the policy lives | When Claude Code reads it | Use it when |
|---|---|---|---|
| Server-managed settings | claude.ai Admin Settings > Claude Code > Managed settings (Team and Enterprise; Owner or Primary Owner role) | At startup, then polled hourly | You have no MDM, or developers run cloud sessions |
| MDM or OS policy | macOS profile in the com.anthropic.claudecode domain; Windows Settings value under HKLM\SOFTWARE\Policies\ClaudeCode | At startup, then every 30 minutes | You already run Jamf, Intune, or Group Policy |
| System file | managed-settings.json (plus optional managed-settings.d/*.json drop-ins) in the system directory | At startup, and reloaded when the file changes | Linux hosts, build images, machines without MDM |
| HKCU registry | HKCU\SOFTWARE\Policies\ClaudeCode | At startup, then every 30 minutes | Fallback only; it is user-writable |
The system directories are /Library/Application Support/ClaudeCode/ on macOS, /etc/claude-code/ on Linux and WSL, and C:\Program Files\ClaudeCode\ on Windows. Claude Code does not read the legacy C:\ProgramData\ClaudeCode\ path.
Three trade-offs decide the choice:
- Tamper resistance. Endpoint-managed policy (MDM or a root-owned file) is protected by the operating system. A developer can edit the local cache of server-managed settings, but the edit lasts only until the next successful fetch.
- Cloud sessions. A session in an Anthropic-hosted environment never sees a device’s file or MDM profile. If your developers use cloud sessions, the policy must also exist in server-managed settings.
- Different policies per group. The claude.ai console applies one policy to the whole organization and cannot target a group yet. To give the payments team a stricter policy, ship them a different file or MDM profile.
When several sources exist on one machine, Claude Code uses the highest-ranked one (server-managed, then MDM, then files, then HKCU) and ignores the rest, unless the highest source sets managedSourcesBehavior: "merge". A few locks (for example allowManagedMcpServersOnly, sandbox.network.allowManagedDomainsOnly, forceRemoteSettingsRefresh) and env variables are read from every admin source even then, so a lower MDM profile or file can still set them. merge needs v2.1.242 or later. When a policy seems to be ignored, check this rule first: /status names the source that won.
Inside the settings hierarchy, managed settings sit above everything: managed, then command-line arguments, then .claude/settings.local.json, then .claude/settings.json, then ~/.claude/settings.json. A developer’s --settings file cannot override a managed key. For how the lower layers work, see Claude Code configuration.
Deploy a baseline managed policy
Section titled “Deploy a baseline managed policy”The policy below is a starting point for a security-conscious organization. It blocks the obvious secret files, removes the permission-bypass flag, forces the sandbox on, sets a version floor, and sends telemetry to your collector.
{ "$schema": "https://json.schemastore.org/claude-code-settings.json", "permissions": { "deny": [ "Bash(curl *)", "Bash(wget *)", "Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)", "Read(**/*.pem)", "Edit(./.env)", "Edit(./.env.*)", "Edit(./secrets/**)" ], "disableBypassPermissionsMode": "disable" }, "sandbox": { "enabled": true, "failIfUnavailable": true, "allowUnsandboxedCommands": false, "network": { "allowedDomains": ["github.com", "registry.npmjs.org"], "allowManagedDomainsOnly": true } }, "requiredMinimumVersion": "2.1.274", "env": { "CLAUDE_CODE_ENABLE_TELEMETRY": "1", "OTEL_METRICS_EXPORTER": "otlp", "OTEL_LOGS_EXPORTER": "otlp", "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.internal.example.com:4317" }, "companyAnnouncements": [ "Claude Code runs under the engineering AI policy: go/ai-policy. Secrets belong in Vault, never in .env files." ]}What each block does, and what it costs you:
permissions.denystops Claude’s file tools and the recognized Bash file commands (cat,head,sed,tee) from touching secret paths. File rules must useRead(...)orEdit(...). AWrite(./.env)rule is accepted but never consulted, and Claude Code prints a startup warning about it (v2.1.210 and later).disableBypassPermissionsMode: "disable"makes Claude Code reject--dangerously-skip-permissionsand ignorepermissionMode: bypassPermissionsin subagent definitions. If your policy forbids classifier-approved actions, also setpermissions.disableAutoMode: "disable". Auto mode is the starting mode from v2.1.283 (thelatestchannel); see permissions and sandboxing.sandboxturns on OS-level isolation for Bash commands. It is off by default (sandbox.enableddefaults tofalse).failIfUnavailablemakes Claude Code exit instead of silently running unsandboxed when a dependency is missing.allowUnsandboxedCommands: falseremoves the retry-outside-the-sandbox escape hatch.allowManagedDomainsOnlyignores domains that developers add themselves.requiredMinimumVersionstops older binaries from starting.2.1.274was thestablerelease channel on 2026-09-26; raise it as that channel moves.envconfigures OpenTelemetry. Claude Code has no default OTLP protocol, so setOTEL_EXPORTER_OTLP_PROTOCOLexplicitly. A repository’s.claude/settings.jsoncannot redirect these exporter variables, so the destination stays yours.companyAnnouncementsshows one message at startup. With several entries, Claude Code picks one at random per session.
The sandbox uses Seatbelt on macOS and bubblewrap on Linux and WSL2. Native Windows is not supported. On a Windows fleet, failIfUnavailable: true stops Claude Code from starting at all on native Windows, so either deploy it only to macOS and Linux machines or standardize on WSL2 or dev containers.
-
Keep the policy in a repository. Store
managed-settings.jsonin a platform-team repository with code owners from security. Every change is a reviewed pull request, which is the audit trail an auditor asks for. -
Validate the JSON in CI. A managed file that is not valid JSON makes Claude Code refuse to start on every machine it reaches. Add a check such as
jq empty managed-settings.jsonto the pipeline so a stray comma never reaches the fleet. -
Deploy to one canary machine. Copy the file to the system directory, or paste the JSON into the admin console for a test organization. Then run
/statusin a new session. TheSetting sourcesline must showEnterprise managed settingsfollowed by the source, such as(file),(plist),(HKLM), or(remote). -
Run the probes. Run
claude doctorin a terminal to list any entries Claude Code dropped, then run the canary prompt from the next section. Both must come back clean before you widen the rollout. -
Roll out in rings. Push to the pilot group, wait a full poll cycle (30 minutes for MDM, one hour for server-managed), check telemetry for sessions from those machines, and only then push to the next ring.
Which managed-only keys lock developers out?
Section titled “Which managed-only keys lock developers out?”Most keys can live in any settings file. The keys below take effect only from a managed source. They trade developer flexibility for control, so turn them on deliberately:
| Key | Effect | Turn it on when |
|---|---|---|
allowManagedPermissionRulesOnly | Ignores allow, ask, and deny rules from user, project, local, and --settings files; ignores --allowedTools; hides the “always allow” choice in prompts | Your compliance regime requires one central allowlist. Expect more permission prompts until you ship a good managed allow list |
allowManagedHooksOnly | Runs only managed hooks, Agent SDK hooks, and hooks from plugins your managed settings force-enable | Hooks from repositories are an unacceptable execution risk. It also disables every team’s own hooks, so ship the ones they need centrally |
allowManagedMcpServersOnly | Only managed allowedMcpServers entries count; deniedMcpServers still merges from every source | You maintain an approved MCP server list |
strictKnownMarketplaces | Restricts which plugin marketplaces people can add | You vet plugins. An empty array blocks every marketplace, including the official Anthropic one |
disableSideloadFlags | Rejects --plugin-dir, --plugin-url, --agents, and --mcp-config at startup | You need the plugin and MCP policy to hold even for command-line flags |
forceRemoteSettingsRefresh | Blocks startup until server-managed settings are fetched, and exits if the fetch fails | You use server-managed settings and need fail-closed behavior |
A common misreading: a managed deny rule never needs allowManagedPermissionRulesOnly to hold. Claude Code evaluates deny first, then ask, then allow, across all sources, so a developer’s "allow": ["Bash(curl *)"] cannot re-enable a managed Bash(curl *) deny. allowManagedPermissionRulesOnly exists to stop developers from adding their own allow rules and pre-approvals, not to protect your denies.
Model governance uses the same channel: availableModels and enforceAvailableModels restrict which models people can pick; deniedModels blocks specific models from v2.1.283 (the latest channel), so on the stable channel rely on availableModels. A managed model sets only a default, and --model still overrides it for a session, so use availableModels when you need a restriction. For which model to allow and what each costs, see the models hub.
Why deny rules are not a security boundary
Section titled “Why deny rules are not a security boundary”A Bash deny rule matches the command text Claude writes. Bash(curl *) stops curl https://example.com, but not /usr/bin/curl https://example.com or sh -c 'curl https://example.com'. Read and Edit rules cover Claude’s file tools and the Bash commands Claude Code recognizes. They do not cover a Python or Node script that opens the file itself.
So treat the layers as three different jobs:
- Deny rules stop what Claude usually attempts, cheaply and with a clear message.
- The sandbox enforces filesystem and network limits at the OS level for every process a Bash command starts, whatever the command text says.
- A
PreToolUsehook inspects the full command with your own logic, for rules the first two cannot express.
If exfiltration is in your threat model, the sandbox with allowManagedDomainsOnly is the control that holds. The deny list is the first filter in front of it. For the full threat model, see the agent threat model.
Ship corporate standards with a managed CLAUDE.md
Section titled “Ship corporate standards with a managed CLAUDE.md”A managed CLAUDE.md loads before every user and project CLAUDE.md, and developers cannot exclude it. Put it next to the managed settings file:
- macOS:
/Library/Application Support/ClaudeCode/CLAUDE.md - Linux and WSL:
/etc/claude-code/CLAUDE.md - Windows:
C:\Program Files\ClaudeCode\CLAUDE.md
If you deliver policy through server-managed settings or MDM, use the claudeMd key instead. It holds the same Markdown as a string, with line breaks written as \n.
Keep the file short and limited to rules that apply to every repository. Every line costs context in every session across the company. Repository-specific conventions belong in each repository’s own CLAUDE.md; see the memory system.
# Engineering rules (managed by Platform)
- Never read, print, or write secrets. Credentials come from Vault via `vault kv get`.- Run the repository's lint and test commands before you say a task is done, and report their output.- Database migrations need a reviewer from the owning team. Open a draft PR and stop.- Do not add a dependency without stating its license and weekly downloads in the PR description.CLAUDE.md is guidance, not enforcement. Claude follows it most of the time. Anything that must hold every time belongs in a deny rule, the sandbox, or a hook.
Copy-paste prompts for managing the policy
Section titled “Copy-paste prompts for managing the policy”Run the probe in an interactive session in a throwaway repository that contains a dummy .env file. Steps 1 to 3 must be blocked. Step 3 is the one that proves the sandbox, not the deny list, is doing the work. Step 4 must succeed because github.com is on the allowlist. It is a read-only call that writes nothing to disk, so a filesystem write limit cannot turn it into a false FAIL the way a package-manager cache write can. If Claude Code asks you to approve step 3, approve it: the test is whether the sandbox then blocks the connection. If step 3 succeeds, the sandbox is not running on that machine.
How do you prove the policy is in force?
Section titled “How do you prove the policy is in force?”Nobody can inspect 200 laptops. Verification comes from four signals that scale:
| Signal | What it proves | Who checks it |
|---|---|---|
/status shows Enterprise managed settings (<source>) | The machine selected the managed source you shipped. A Skipped sources line names any source that lost to a higher-ranked one (v2.1.242 and later) | Platform team, on canaries and on any support ticket |
claude doctor | Which entries Claude Code dropped as invalid, and whether server-managed settings were fetched. Its Organization policy line (v2.1.261 and later) shows whether organization-wide admin settings, such as Remote Control and cloud sessions, reached the machine | Platform team |
| The canary probe above | Deny rules and the sandbox block what the policy says they block | Security, after every policy change |
| Telemetry | claude_code.session.count arrives from each machine; a session with no metrics means telemetry, and possibly the whole policy, did not apply | Platform team, weekly |
Telemetry also gives you claude_code.token.usage, claude_code.cost.usage, claude_code.lines_of_code.count, claude_code.commit.count, claude_code.pull_request.count, and claude_code.code_edit_tool.decision. Prompt text, tool arguments, and tool output are not logged unless you set OTEL_LOG_USER_PROMPTS, OTEL_LOG_TOOL_DETAILS, or OTEL_LOG_TOOL_CONTENT. Decide with your privacy officer before you turn any of them on. For dashboards and alerts, see Claude Code monitoring and cost control.
Sign-off splits cleanly: security owns the deny list, sandbox allowlist, and MCP list; the platform team owns delivery, the version floor, and telemetry; engineering leadership owns the managed CLAUDE.md. The operating model page covers who owns what in more depth.
Roll out Claude Code in rings
Section titled “Roll out Claude Code in rings”-
Pilot, 5 to 10 developers. Deploy the baseline policy without
allowManagedPermissionRulesOnlyorallowManagedHooksOnly. Have the pilot write each repository’sCLAUDE.mdand shared skills in.claude/skills/, and log every permission prompt that felt wrong. Design the pilot and its exit criteria with the pilot design guide. -
Team, 20 to 50 developers. Add the managed
allowlist the pilot proved safe, turn on the MCP allowlist, and confirm telemetry arrives from every machine. Set per-team spend alerts onclaude_code.cost.usage. Anthropic’s cost guide puts a typical enterprise deployment at “around $13 per developer per active day and $150-250 per developer per month” (Anthropic, Claude Code costs page, checked 2026-09-26); start your alert thresholds there and replace them with your pilot’s own numbers. -
Organization, 100 or more developers. Turn on the locks your compliance regime needs, raise
requiredMinimumVersionon a schedule, and add Claude Code to onboarding so a new laptop gets the policy on day one. Publish an AI usage policy that matches what the settings enforce.
When enterprise policy breaks
Section titled “When enterprise policy breaks”/status shows no managed source. Claude Code found no source with a policy key. Check the path for the operating system: it is /Library/Application Support/ClaudeCode/, not ~/Library/.... Also check that the file contains a policy key and not only control keys such as managedSourcesBehavior. For server-managed settings, run claude doctor and read the fetch result.
/status names a different source than the one you shipped. A higher-ranked source is present, for example an old MDM profile shadowing your new file. Read Skipped sources, then remove the stale source or set managedSourcesBehavior: "merge" in the highest one.
Claude Code refuses to start on every machine. A managed file, drop-in, plist, or HKLM value is not valid JSON. Roll back the last policy commit through the same tooling, then add the CI JSON check from the deployment steps.
Cloud sessions ignore the policy. Anthropic-hosted sessions never read device files or MDM profiles. Mirror the policy in server-managed settings.
A deny rule is ignored with a startup warning. It is a Write(...), NotebookEdit(...), or MultiEdit(...) path rule. Rewrite it as Edit(...), and use Read(...) in place of Glob(...).
Commands run unsandboxed on Linux. bubblewrap or socat is missing, and without failIfUnavailable Claude Code only warns. Install the packages through your configuration management, and keep failIfUnavailable: true so a missing dependency fails loudly.
Old versions keep running after you raise the floor. requiredMinimumVersion is checked at startup and does not end a running session. Announce the change, and expect long-lived sessions to lag until developers restart.
Telemetry never arrives. Usually a firewall blocks port 4317 to the collector, or OTEL_EXPORTER_OTLP_PROTOCOL is missing. Switch to http/protobuf on port 4318 if gRPC is blocked.
A developer with local admin rights edited the file. Managed settings bind the Claude Code client, not the machine owner. Have MDM redeploy the file or profile on a schedule, and remember that a developer calling the API from another tool is outside this policy entirely.
Where to go next with enterprise Claude Code
Section titled “Where to go next with enterprise Claude Code”- Proxy configuration gets Claude Code working behind a corporate proxy with custom certificates.
- LLM gateway setup routes traffic through an approved gateway or a cloud provider.
- Security audits with Claude Code covers scanning the code the agents write.
- Enforcing one policy across every coding agent covers the same controls for Codex and Cursor.
- For the sibling tools on their own: Codex enterprise governance and Cursor privacy and security.