Skip to content

Claude Code Enterprise Setup: Managed Settings and Policy

Core Concept LearningAugust 18, 202614 min readUpdated October 17, 2026

When a few engineers use Claude Code, each person's ~/.claude/settings.json is enough. When a company rolls it out to hundreds, someone has to make sure every session blocks reads of .env, cannot switch to bypass mode, uses approved models, and reports usage, and that no developer can quietly turn those off. Claude Code's answer is managed settings: a settings layer that sits above every user and project file and that only administrators control.

This guide follows Anthropic's admin documentation. It covers the settings hierarchy, the two ways to deliver a managed policy (from the claude.ai admin console, or onto each device through MDM or a system file), a starter policy, model restrictions, OpenTelemetry, and how to check that a policy actually reached a machine. It ends with the gaps, because a managed policy that silently does not apply is worse than none: you believe a control exists when it does not.

For the permission rules a policy contains, see Claude Code Permissions. For routing traffic through your own proxy, see Claude Code Gateway Routing and Security.

An enterprise Claude Code rollout has three parts: deliver a managed policy, decide what it enforces, and verify it reached each machine
An enterprise Claude Code rollout has three parts: deliver a managed policy, decide what it enforces, and verify it reached each machine

Where managed settings sit

Claude Code reads settings from five levels. When the same key is set in several, the higher level wins:

1. Managed settings: from the claude.ai admin console, an MDM profile, or a managed-settings.json file. Set by your organisation. 2. Command line: claude --settings '<json or file>' for one session. 3. Local project: .claude/settings.local.json, personal and not committed. 4. Shared project: .claude/settings.json, committed to the repository. 5. User: ~/.claude/settings.json, across all of one person's projects.

Managed settings use the same JSON shape as settings.json, so anything you can put in a user file you can usually enforce centrally: permission rules, hooks, environment variables, model choice, sandbox options. A few keys only take effect from managed settings and are ignored anywhere else. They exist to stop lower levels from adding their own exceptions:

  • allowManagedPermissionRulesOnly: ignore permission rules from user, project, and local files and from --allowedTools.
  • allowManagedHooksOnly: run only hooks defined in managed settings.
  • allowManagedMcpServersOnly with allowedMcpServers: limit MCP servers to an approved list.
  • strictKnownMarketplaces: limit which plugin marketplaces users can add.
Settings precedence, highest first: managed settings, command line, local project, shared project, user
Settings precedence, highest first: managed settings, command line, local project, shared project, user

Quick reference

  • Permission rules from different levels combine; with deny-first evaluation, a managed deny cannot be undone by a user allow rule.
  • There are documented exceptions where a stricter value from a lower level still counts, so 'highest wins' is the rule for ordinary keys, not for every security setting.
  • Run /status in a session to see which managed source is active, and /permissions to see the effective rules and where each came from.

Remember this

Managed settings are the top layer. Pair them with the managed-only keys, or users can still add their own allow rules and hooks underneath.

Two ways to deliver the policy

Server-managed settings are JSON you paste into the claude.ai admin console. Clients fetch them from api.anthropic.com when users sign in with an eligible credential, such as a Team or Enterprise login, and cache them at ~/.claude/remote-settings.json. You need no device-management tooling, which makes this the practical choice for unmanaged laptops and the only one that reaches cloud sessions.

Endpoint-managed settings live on the device:

  • macOS: the com.anthropic.claudecode managed-preferences domain (a configuration profile), or /Library/Application Support/ClaudeCode/managed-settings.json.
  • Windows: a Settings value (REG_SZ) under HKLM\SOFTWARE\Policies\ClaudeCode, or C:\Program Files\ClaudeCode\managed-settings.json.
  • Linux and WSL: /etc/claude-code/managed-settings.json.

Next to the file you can add a managed-settings.d/ directory. Claude Code merges managed-settings.json first and then every *.json file in that directory in alphabetical order, so the security team can own 20-security.json while the platform team owns 10-telemetry.json.

If several managed sources exist, Claude Code by default uses the first one that delivers a policy key, checking server-managed settings first, then MDM, then files. It does not merge them, apart from a few documented exceptions such as env, which merges per variable. Setting managedSourcesBehavior: "merge" in the highest source opts into combining them.

Server-managed versus endpoint-managed delivery
Server-managedEndpoint-managed
Configured inclaude.ai: Organization settings > Claude Code > Managed settingsMDM profile, HKLM registry value, or managed-settings.json
RequiresTeams or Enterprise plan, Owner or Primary Owner roleA way to put files or profiles on every device
RefreshAt startup, then hourly during a sessionMDM: startup and every 30 minutes; file: reloaded on change
Cloud sessionsAppliesDoes not reach Anthropic-hosted cloud sessions
Bedrock, Vertex, FoundryFetch skippedApplies
Tamper resistanceClient-side; cached copy is editableOS can block user edits on managed devices
Per-group policyNot supported: one policy for the whole organisationDifferent files or profiles per device group
Server-managed settings come from the claude.ai console; endpoint-managed settings are placed on each device by IT
Server-managed settings come from the claude.ai console; endpoint-managed settings are placed on each device by IT

Quick reference

  • Many organisations use both: server-managed for cloud sessions and unmanaged devices, endpoint-managed on MDM-enrolled laptops for stronger tamper resistance.
  • Because the default is first-source-wins, a server-managed policy with a single key hides your entire MDM policy on that machine. Mirror the important keys, or use the merge opt-in deliberately.
  • Claude Code no longer reads the legacy Windows path C:\ProgramData\ClaudeCode\managed-settings.json. Deploy to C:\Program Files\ClaudeCode\.
  • Only Owners and Primary Owners can edit server-managed settings, and changes apply to everyone in the organisation, so treat edits like a production change.

Remember this

Use server-managed settings to reach every login, including cloud sessions, and endpoint-managed settings where you need the OS to protect the policy.

A starter policy and what each key does

Start small. This policy keeps secrets out of reads, removes bypass mode, makes the managed rules the only rules, and allows two model families:

1{2  "permissions": {3    "deny": [4      "Read(./.env)",5      "Read(./.env.*)",6      "Read(./secrets/**)",7      "Read(~/.aws/**)"8    ],9    "disableBypassPermissionsMode": "disable"10  },11  "allowManagedPermissionRulesOnly": true,12  "availableModels": ["sonnet", "haiku"]13}
  • The deny rules use the normal Tool(specifier) syntax and apply in every permission mode.
  • disableBypassPermissionsMode removes bypassPermissions mode and --dangerously-skip-permissions. permissions.disableAutoMode does the same for auto mode if you are not ready for the classifier.
  • allowManagedPermissionRulesOnly stops users and repositories from adding their own allow rules. This is strict: every command developers want pre-approved must now be in the managed policy, or they will see more prompts.
  • availableModels restricts model selection, covered in the next section.

Expect to add allow rules after a week of feedback, for example Bash(npm test *), Bash(pnpm *), or Bash(git diff *).

Quick reference

  • Bash deny rules match command text. Bash(curl *) does not catch /usr/bin/curl or sh -c 'curl ...'. For network control that does not depend on text, use the sandbox with allowManagedDomainsOnly.
  • Settings that run commands (apiKeyHelper, statusLine, hooks) and many env variables trigger a security approval dialog for users of server-managed settings. A user who rejects it cannot start Claude Code.
  • A managed CLAUDE.md delivered with the claudeMd key needs no approval, because it is instructions rather than a command.
  • Validate a policy change with claude doctor on a test machine before saving it for the whole organisation.

Remember this

Deny the few things that must never happen, remove bypass mode, and expect to add allow rules once people report prompts.

Restricting models: availableModels is not the whole story

availableModels takes model families (sonnet), version prefixes (claude-sonnet-4-5), or full model IDs. It applies wherever a user can choose a model: /model, the --model flag, ANTHROPIC_MODEL, and the model setting. Lower settings levels cannot add to a managed list.

What happens to a blocked choice depends on where it was made. /model rejects the switch with an error. --model, ANTHROPIC_MODEL, or the model setting are replaced at startup with a warning, and the session starts on the default model.

Two details catch administrators out:

1. model is an initial choice, not enforcement. Users can open /model and pick Default, which resolves to the account's runtime default. 2. The Default option is outside availableModels unless you say otherwise. Set enforceAvailableModels: true (Claude Code v2.1.175 or later) to extend the allowlist to Default as well.

1{2  "model": "claude-sonnet-4-5",3  "availableModels": ["claude-sonnet-4-5", "haiku"],4  "enforceAvailableModels": true5}

On Claude Enterprise, admins can also disable models and set an organisation default in the claude.ai admin console. That control travels with the account's entitlements, separately from the availableModels list in settings.

Quick reference

  • deniedModels and availableModelsMatch: "exact" (v2.1.283 or later) block a specific release that a family entry would otherwise allow.
  • On Bedrock, Vertex, or Foundry, server-managed settings do not arrive, so deliver availableModels through MDM or a managed settings file there.
  • maxEffortLevel caps the effort level on any plan and provider, which also bounds cost per request.

Remember this

Use availableModels with enforceAvailableModels, and deliver it on every channel your developers actually use.

Usage and cost reporting with OpenTelemetry

Claude Code exports metrics and events over OpenTelemetry. Turn it on for everyone by putting the variables in the managed env block:

1{2  "env": {3    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",4    "OTEL_METRICS_EXPORTER": "otlp",5    "OTEL_LOGS_EXPORTER": "otlp",6    "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",7    "OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.internal:4317"8  }9}

Metrics include claude_code.session.count, claude_code.token.usage, claude_code.cost.usage (USD), claude_code.lines_of_code.count, claude_code.commit.count, claude_code.pull_request.count, and claude_code.active_time.total. Each carries attributes such as organization.id, user.account_uuid, user.email, and session.id, so you can group usage by person or team in your own backend. Events cover prompts, API requests and errors, tool decisions, and permission-mode changes.

Defaults favour privacy. Prompt text is redacted unless you set OTEL_LOG_USER_PROMPTS=1, and tool arguments are left out unless you set OTEL_LOG_TOOL_DETAILS=1. Decide with your legal and security teams before turning either on: prompts and tool arguments can contain source code, customer data, and secrets.

Quick reference

  • Claude Code has no default OTLP protocol. Set OTEL_EXPORTER_OTLP_PROTOCOL or the signal-specific variable, or the exporter sends nothing.
  • Cost values are estimates calculated by the client, not invoices. Reconcile against billing before using them for chargeback.
  • OpenTelemetry exporter changes apply at the next launch, not to running sessions.
  • A non-empty OTEL_EXPORTER_OTLP_ENDPOINT in server-managed settings shows users the approval dialog, because it redirects data off the machine.

Remember this

Managed env turns telemetry on for everyone; keep prompt and tool-detail logging off unless you have a reason and a retention policy.

Verify the policy reached each machine

A saved policy is not a delivered policy. Check on a real machine, with a real user login, after every change:

1. Ask the user to restart Claude Code. If the policy has hooks or env values that need approval, they should see the security dialog. 2. Run claude doctor and read the Managed settings (remote) line (v2.1.248 or later). It says whether settings loaded, whether the organisation has none, whether the fetch failed and a cached policy applies, or why the fetch was skipped. 3. Run /permissions and confirm the managed deny rules are listed. 4. Try something the policy forbids: read .env, start with --dangerously-skip-permissions, or /model to a blocked model. Each should fail. 5. If delivery fails, run claude --debug-file /tmp/cc.log and search the log for Remote settings.

If a missing policy must stop work rather than allow it, set forceRemoteSettingsRefresh: true. Claude Code then blocks at startup until it has fetched fresh settings and exits if it cannot. That is fail-closed, and it means an outage of api.anthropic.com or a proxy misconfiguration stops every developer, so allow that endpoint through your network first.

Quick reference

  • Without forceRemoteSettingsRefresh, a first launch with no cache waits up to five seconds for the fetch on sign-in; otherwise the session can start before the policy loads.
  • Most settings changes apply to running sessions within the hourly refresh. model, OpenTelemetry exporters, and removing an env variable apply only at the next launch.
  • Audit events for changes to server-managed settings are available through the compliance API or audit log export; ask your Anthropic account team for access.

Remember this

Verify with claude doctor and a blocked action on a real machine, not by reading the admin console.

Where a managed policy does not apply

Anthropic's documentation is direct about this: server-managed settings are a client-side control, not a security boundary. The common gaps:

  • The fetch is skipped. If a user's shell exports CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX, another provider variable, or a non-default ANTHROPIC_BASE_URL, Claude Code does not fetch server-managed settings. Keys from an apiKeyHelper script do not trigger the fetch either. Versions older than the feature never fetch.
  • The wrong organisation. A session gets the policy of the organisation that owns its credential. A Claude Console API key belongs to a Console organisation, separate from your claude.ai Teams or Enterprise organisation, so a CI job using it does not receive your policy. Use claude setup-token for an OAuth token tied to your organisation, or deploy a managed settings file to the CI runner.
  • Local tampering. A user who edits the cached settings file gets the edited version at startup until the next fetch restores it. A user running a modified client can bypass any client-side control.

The stronger options are endpoint-managed settings on MDM-enrolled devices, where the OS stops users from editing the file, and controls outside Claude Code itself: credentials scoped to what the developer may touch, network egress rules, and tenant restrictions that stop logins to personal accounts.

Common ways a server-managed policy does not reach a session
Common ways a server-managed policy does not reach a session

Quick reference

  • claude doctor and /status report a skipped fetch and its cause, which is the quickest way to find a stray provider variable.
  • A server-managed env block cannot clear a provider variable exported in the shell, because the block arrives through the fetch that the export prevents.
  • Server-managed settings apply the same policy to everyone. If teams need different rules, use endpoint-managed files per device group, or the project-level .claude/settings.json for rules that do not need to be tamper-proof.

Remember this

Know which sessions skip the policy. For anything that must hold against a determined user, enforce it outside the client too.

Hands-on: pilot a policy on one machine

Before touching the whole organisation, test the policy where you can see everything.

1. On a test Linux VM or container, write the starter policy from this guide to /etc/claude-code/managed-settings.json. 2. Start claude as a normal user. Run /status and /permissions and confirm the managed source and rules. 3. Try to read .env, start with --dangerously-skip-permissions, and switch to a model outside availableModels. 4. Switch to Manual mode with Shift+Tab, add .claude/settings.json in a project with "allow": ["Bash(curl *)"], and ask Claude to run curl example.com. With allowManagedPermissionRulesOnly, the project rule is ignored and you still get a prompt. 5. Export CLAUDE_CODE_USE_BEDROCK=1 in the shell, run claude doctor, and read what it says about the server-managed fetch.

Pass criterion: every forbidden action in steps 3 and 4 fails or prompts, /permissions shows only managed rules, and you can explain the step 5 output to your security team.

Quick reference

  • If /permissions shows no managed rules, check the file path and JSON validity; trailing commas make the whole file invalid.
  • Repeat steps 2 to 4 with the same policy in the claude.ai admin console and a Team login to compare the two channels.
  • Write down the allow rules your pilot users ask for in the first week; they become version two of the policy.

Remember this

Pilot on one machine with deliberate failures before you save a policy for the whole organisation.

Key takeaway

Enterprise Claude Code setup comes down to one layer: managed settings, which outrank every user, project, and command-line setting. Deliver them from the claude.ai admin console to reach every eligible login and cloud session, or onto devices through MDM and managed-settings.json where you need the OS to protect them. Use the managed-only keys so users cannot add exceptions underneath, restrict models with availableModels plus enforceAvailableModels, and turn on OpenTelemetry through the managed env block.

Then verify with claude doctor and a blocked action, and be clear about the gaps: provider variables and custom base URLs skip the server fetch, Console API keys belong to a different organisation, and any client-side policy can be bypassed by a modified client. For the sandbox and network controls that hold outside the client, see Claude Code Sandboxing and Isolation; for compliance requirements, see Claude Code Enterprise Security and Compliance.

Practice (45 min): run the five-step pilot above, then write the one-page policy proposal you would send to your security team, listing each key and the failure it prevents.

Share:

References

  1. Claude Code docs: Configure server-managed settings — checked Oct 17, 2026
  2. Claude Code docs: Deploy managed settings — checked Oct 17, 2026
  3. Claude Code docs: Model configuration — checked Oct 17, 2026
  4. Claude Code docs: Monitoring usage with OpenTelemetry — checked Oct 17, 2026
SH

Shoaib Hossain

Lead Author & Systems Architect

Software engineer and distributed systems architect specializing in backend scalability, cloud-native infrastructure, databases, and AI engineering workflows. Author and maintainer of Core Concept Learning.

Human-Engineered & Fact-CheckedOriginal Visual DiagramsEditorial Standards →Send Feedback

Related Articles

Many companies already run an LLM gateway, such as LiteLLM, a cloud API gateway, or an in-house proxy, between their dev…

Read

Claude Code can run shell commands, edit files, and fetch URLs. Permission rules decide which of those actions run witho…

Read

Claude Code cloud sessions normally run on Anthropic-managed VMs. A self-hosted environment keeps the same developer exp…

Read

Explore this topic

Keep learning

Follow a structured path or browse all courses to go deeper.