Claude Code managed settings for a team: a working file, and what it can't do
A managed-settings.json for a small team: block secrets and force pushes, ask before git push, turn off bypass mode, and log each decision with OpenTelemetry.

Managed settings are the Claude Code settings nobody on the team can override. You put them in one file on each machine, or, on Claude for Teams and Claude for Enterprise, an Owner sets them once in the claude.ai console. Below is a file a team of five can use today, how Claude Code reads it, where it leaks, and the part of the team problem it doesn't touch.
Everything here was checked against Anthropic's Claude Code docs on 6 November 2026. Claude Code ships most days, so read the managed settings docs before you copy anything into production.
Key takeaways
- The file lives at
/Library/Application Support/ClaudeCode/managed-settings.jsonon macOS,/etc/claude-code/managed-settings.jsonon Linux and WSL, andC:\Program Files\ClaudeCode\managed-settings.jsonon Windows. - Managed settings sit above every other level. A tool denied there can't be allowed anywhere else.
- Claude Code checks deny, then ask, then allow. An ask rule still prompts when a narrower allow rule matches.
- Every prompt still goes to the person at that terminal. Managed settings can't ask a lead first.
Where managed settings live
There are two ways to deliver them, and both sit at the top of the settings stack.
A file on each machine. The paths are in the takeaways above. You can also push the same JSON through MDM: the com.anthropic.claudecode preferences domain on macOS, or a Settings value under HKLM\SOFTWARE\Policies\ClaudeCode on Windows. If you deploy MCP servers centrally, managed-mcp.json sits next to the settings file, and Claude Code then stops loading MCP servers people add themselves.
Server-managed settings. On Claude for Teams and Claude for Enterprise, an Owner or Primary Owner sets them under Organization settings, Claude Code, Managed settings in the claude.ai console. Claude Code fetches them at startup and checks for changes every hour. Three things to know before you rely on them:
- They apply the same way to everyone in the organization. Anthropic's docs say per-group settings are not supported yet.
- They need a direct connection to
api.anthropic.com. A session on Bedrock, Google Cloud, Foundry or a custom base URL skips them, and so does a CI job that signs in with a Console API key, because that key belongs to a different organization. managed-mcp.jsoncan't be delivered this way.
The full order, highest first: managed settings, JSON passed with --settings on the command line, .claude/settings.local.json, .claude/settings.json, then ~/.claude/settings.json.
A file a small team can use
{
"permissions": {
"deny": [
"Read(**/.env)",
"Read(**/.env.*)",
"Read(**/secrets/**)",
"Bash(rm -rf *)",
"Bash(git push --force*)",
"Bash(git push -f *)",
"Bash(git push * --force*)"
],
"ask": [
"Bash(git push *)",
"Bash(npm run deploy*)"
],
"disableBypassPermissionsMode": "disable"
},
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
"OTEL_EXPORTER_OTLP_ENDPOINT": "https://otel-collector.example.com:4317"
}
}Every key above checks out against the published settings schema. What each part does:
- deny stops reads of
.envfiles and anything under asecretsfolder,rm -rf, and force pushes.Read(**/.env.*)also blocks.env.example, so drop it if your agents need that file. - ask makes Claude Code prompt before any
git pushand before your deploy script, even when someone has an allow rule for it. Swapnpm run deployfor whatever your team runs. - disableBypassPermissionsMode set to
"disable"makes Claude Code reject--dangerously-skip-permissions. Nobody can switch into bypass mode. - env turns on telemetry and sends it to your own OpenTelemetry collector. More on that below.
Two keys worth adding once the basics work. "allowManagedPermissionRulesOnly": true makes managed settings the only source of permission rules: Claude Code ignores allow, ask and deny rules in everyone's own files and hides the always-allow choice in prompts. And "disableAutoMode": "disable" takes auto mode out of the Shift+Tab cycle, which matters because on Team and Enterprise plans auto mode is available by default.
How Claude Code reads the rules
Rules are checked in a fixed order: deny, then ask, then allow. The first match decides, and a more specific rule doesn't jump the queue. Two consequences people trip on:
- A tool denied at any level can't be allowed at any other level.
- An ask rule prompts even when a more specific allow rule also matches. In the file above,
git push --forcematches a deny rule and thegit push *ask rule, and deny is checked first, so it is refused. A plaingit pushmatches only the ask rule, so it asks.
Where the rules leak
Bash rules match the text of the command, not what it does. Anthropic's own docs give the examples: Bash(rm *) stops rm -rf build/ but not /bin/rm -rf build/ or bash -c 'rm -rf build/', and Bash(git push *) doesn't stop git -C . push origin main. Against the file above, rm -fr and git push origin +main slip past the deny rules too (the push still hits the ask rule). Read deny rules don't cover a command like grep -r pattern . that reads files without naming them.
So treat the file as a seatbelt. For hard limits, turn on Claude Code's sandbox, or check commands in a PreToolUse hook that parses them.
Managed settings are also a client-side control. Anthropic says plainly that a developer who is an administrator on the machine can edit the managed file, and that managed settings bind Claude Code only. Someone calling the API from another tool isn't covered.
Seeing who said yes
With the env block above, Claude Code logs a claude_code.tool_decision event each time a tool call is accepted or rejected. Each event carries:
decision:acceptorrejectsource:config,hook,user_permanent,user_temporary,user_abortoruser_rejecttool_name, plususer.emailwhen the person signed in with OAuth. Anthropic's docs say the email goes only to the endpoint you configure, never to Anthropic.
Three catches. You run the collector and whatever reads it. The command itself isn't in the event unless you also set OTEL_LOG_TOOL_DETAILS=1, which adds each call's parameters, such as the full command and file paths. And an endpoint set from the claude.ai console needs each person to approve it in an interactive session, then takes effect at their next launch.
What managed settings can't do for a team
They decide what Claude Code may run. They don't decide who gets asked.
- Nobody else can be asked. A permission prompt goes to the person at that terminal. There is no setting that sends a
git pushin your infrastructure repository to a lead before it runs. - Everyone gets the same rules. Settings from the claude.ai console apply to the whole organization. You can't give the payments team a stricter file than everyone else from there.
- Only Claude Code is covered. Codex, Cursor and Gemini CLI each read their own configuration. A team that runs all four keeps four sets of rules and four records, or none.
And the telemetry record says who accepted a prompt at their own terminal. It can't say a second person agreed, because no second person was asked.
Where Pushary fits
Pushary for Teams works on the second half. Once a second person joins, each person's agent asks that person, on their phone and in the Pushary dashboard. An owner or admin can write a routing rule that sends a matching step, such as a push to the infrastructure repository, to a lead or a role instead. The team sees one record of whose agent asked and who tapped yes, across Claude Code, Codex and Cursor. How Pushary for Teams decides who an agent asks covers the rules in detail.
Two limits, so nobody is surprised. A routing rule decides who Pushary asks, but it doesn't lock the terminal: the person whose agent asked can still say yes at their own agent's prompt, and that yes carries no name. An answer from a web link carries no name either. Answers in the Pushary phone app, Mac app and dashboard do.
Two settings to watch if you use both. Pushary's setup writes its Claude Code hooks to each person's ~/.claude/settings.json, so with "allowManagedHooksOnly": true those hooks stop running. Setup also adds an allow rule for Pushary's own tools, mcp__pushary__*, to the same file, so with "allowManagedPermissionRulesOnly": true put that rule in managed settings, or Pushary's tools will prompt every time.
Team is $59 a month for 5 people, plus $12 a month for each extra person, and new workspaces get 3 days free. The Team setup guide walks through connecting everyone.
Frequently asked questions
Where is managed-settings.json for Claude Code?
On macOS it is /Library/Application Support/ClaudeCode/managed-settings.json. On Linux and WSL it is /etc/claude-code/managed-settings.json. On Windows it is C:\Program Files\ClaudeCode\managed-settings.json; Claude Code no longer reads the old C:\ProgramData\ClaudeCode path. On Claude for Teams and Claude for Enterprise, an Owner can also set the same keys once in the claude.ai console, under Organization settings, Claude Code, Managed settings.
Can managed settings stop people using --dangerously-skip-permissions?
Yes. Set permissions.disableBypassPermissionsMode to the string "disable" in managed settings. Claude Code then rejects the --dangerously-skip-permissions flag and nobody can switch to bypass permissions mode. It is one key; there is no separate setting for the flag.
Can Claude Code send a permission prompt to a team lead instead of the developer?
Not on its own. A Claude Code permission prompt goes to the person at that terminal, and no managed setting sends it to someone else first. On the Pushary Team plan, an owner or admin can write a routing rule that sends a matching step, such as a push to the infrastructure repository, to a lead or a role instead.
Does Claude Code record who approved a tool call?
Only if you turn on telemetry. With CLAUDE_CODE_ENABLE_TELEMETRY and an OTLP exporter set, Claude Code logs a claude_code.tool_decision event for every accept or reject, with the decision, where it came from and, when the person signed in with OAuth, their email. It goes to the collector you run, not to Anthropic. The command itself is only included when OTEL_LOG_TOOL_DETAILS=1 is set.