Roll ACP out to every Claude Code seat
Claude Code has the cleanest rollout of the four harnesses: managed settings can force-enable a plugin from a marketplace, and Claude Code fetches it at startup. Nothing is copied to any machine, and the claude.ai admin console can deliver the whole thing without MDM. Anthropic’s managed settings, admin setup, hooks, managed MCP, and plugin marketplaces pages are the source for every key below. Read the shape all four harnesses share first if you haven’t.
Before you push
- Claim your company domain on the ACP workspace’s Team page so enrollments land in your workspace (why).
- Decide the posture for unenrolled seats. The sample sets
ACP_REQUIRE_ENROLLMENTto1in the managedenv, so a seat with no credential blocks each tool call with the enrollment step. Remove the key for the self-serve posture (run, warn, log). - Note what
allowManagedHooksOnlytakes with it: user, project, local, and plugin hooks other than managed-enabled plugins stop running, and status-line and file-suggestion settings narrow to managed. If teams rely on their own hooks, start without it and add it once you’ve read the audit stream.
The managed settings
{
"extraKnownMarketplaces": {
"acp": {
"source": { "source": "github", "repo": "agentic-control-plane/claude-code-acp-plugin" }
}
},
"enabledPlugins": {
"agentic-control-plane@acp": true
},
"allowManagedHooksOnly": true,
"env": {
"ACP_REQUIRE_ENROLLMENT": "1"
},
"allowedMcpServers": [
{ "serverUrl": "https://api.agenticcontrolplane.com/*" }
],
"permissions": {
"disableBypassPermissionsMode": "disable"
}
}
What each key does:
extraKnownMarketplacesregisters ACP’s marketplace, the same one the self-serve installer adds withclaude plugin marketplace add agentic-control-plane/claude-code-acp-plugin. Pair it withstrictKnownMarketplacesif you want this to be the only marketplace users can add.enabledPluginsforce-enables the plugin. Plugins enabled in managed settings can’t be disabled from user settings, and the plugin’sPreToolUse,PostToolUse, andSessionStarthooks come with it. The plugin runs the samegovern.mjsthe installer writes to~/.acp.allowManagedHooksOnlyblocks hooks from every other source. Hooks from plugins force-enabled in managedenabledPluginsare exempt, which is exactly the ACP case.envapplies to every session and its subprocesses, so the plugin’s hook seesACP_REQUIRE_ENROLLMENTwithout any per-machine wrapper.allowedMcpServerspermits ACP’s endpoint by URL. It doesn’t add the server; see below.disableBypassPermissionsModeremoves--dangerously-skip-permissions. Not an ACP key, but every fleet should set it: ACP’s hook runs regardless, and this closes the harness-side hole next to it.
Deliver it
Four mechanisms, highest priority first. Within the managed tier the first source that supplies a key wins, unless the top source sets managedSourcesBehavior to merge.
| Mechanism | Where | Notes |
|---|---|---|
| Server-managed | claude.ai admin console (or a self-hosted gateway) | No MDM. Polled by clients. Shell-command settings such as hooks in the settings body prompt an approval dialog in interactive sessions; a plugin enabled from a marketplace is how this sample avoids that. |
| OS policy | macOS: com.anthropic.claudecode managed preferences · Windows: HKLM\SOFTWARE\Policies\ClaudeCode, a REG_SZ value named Settings holding the JSON |
Same top-level keys, nested as plist dictionaries on macOS. Managed preferences means a configuration profile from your MDM: the same keys written to a user’s own defaults with defaults import are ignored (checked on 2.1.260, where the debug log shows the MDM load finding nothing). |
| System file | macOS /Library/Application Support/ClaudeCode/managed-settings.json · Linux and WSL /etc/claude-code/managed-settings.json · Windows C:\Program Files\ClaudeCode\managed-settings.json |
Plus a managed-settings.d/ directory merged alphabetically. Claude Code doesn’t read the old C:\ProgramData\ClaudeCode path. |
| Windows user registry | HKCU\SOFTWARE\Policies\ClaudeCode |
Only when nothing above supplies the key. |
Managed settings sit above user, project, local, and --settings values. Array keys such as permissions.deny merge, so developers can add rules but not remove yours.
The MCP endpoint
The allowlist entry above permits ACP’s server; it doesn’t add it. Two ways to get it onto seats:
-
Each user adds it with one command and signs in with MCP OAuth in the browser. Attribution comes with the sign-in.
claude mcp add --transport http acp https://api.agenticcontrolplane.com/mcp -
managed-mcp.jsonat the same system path asmanaged-settings.jsonpushes server definitions to every seat. It makes that list the only servers Claude Code loads and can’t be delivered through server-managed settings, so use it only if you intend to own the whole MCP list:{ "mcpServers": { "acp": { "type": "http", "url": "https://api.agenticcontrolplane.com/mcp" } } }
The hook is what enforces policy on every tool call; the MCP server adds read-only introspection tools and one that drafts a rule for a human to confirm.
Each person enrolls once
The pushed settings identify no one. Each developer opens cloud.agenticcontrolplane.com/plugin/authorize, signs in with their work identity, and pastes the one line it shows:
echo 'gsk_…' > ~/.acp/credentials
Until they do, with ACP_REQUIRE_ENROLLMENT set every tool call is denied with that instruction in the message.
If marketplace access is blocked
Air-gapped or egress-restricted fleets that can’t reach GitHub for the plugin can run the hook directly from managed settings instead. Your MDM drops govern.mjs and a wrapper into a managed directory, as on the Codex and Cursor pages, with ACP_CLIENT=claude-code-plugin in the wrapper, and managed settings declare it:
{
"allowManagedHooksOnly": true,
"hooks": {
"PreToolUse": [{ "matcher": ".*", "hooks": [{ "type": "command", "command": "/etc/acp/claude-hook.sh", "timeout": 5 }] }],
"PostToolUse": [{ "matcher": ".*", "hooks": [{ "type": "command", "command": "/etc/acp/claude-hook.sh", "timeout": 5 }] }]
}
}
Delivered server-managed, hooks in the settings body prompt a one-time approval dialog in interactive sessions; delivered by file or OS policy they don’t.
What you’ll see
/statusinside Claude Code names the setting source that won:(remote),(plist)or(HKLM),(file)or(drop-ins).- Console rows with client
claude-code-plugin, one per person, with subagent chains attributed to their parent session. - On an unenrolled seat:
[ACP] Not enrolled…and the call doesn’t run.
What’s verified and what isn’t
The plugin, its hooks, and the enrollment gate are what every self-serve install runs today. The managed-settings keys above are taken from Anthropic’s published reference as of September 2026, linked at the top. What we have checked on a machine: Claude Code looks for the system file at the macOS path above on every start and loads the macOS preferences domain only as managed (MDM) preferences. What we have not yet done: pushed this file through a claude.ai enterprise admin console or an MDM profile ourselves. The issue tracking that is gatewaystack-connect #943.
Related
- Enterprise rollout: the shape all harnesses share
- Claude Code integration — the self-serve install
- Claude Code native controls
- Anthropic: Managed settings · Admin setup · Managed MCP · Plugin marketplaces
Run agents? ACP lets you see, control, and price every tool call they make — allow/ask/deny policy, per-session cost, and a full audit log for Claude Code, Cursor, Codex, and OpenClaw, in one command:
curl -sf https://agenticcontrolplane.com/install.sh | bash
Getting started → · see your first governed call → · free up to 5 agents · prefer fully on-device? add --local