One file for the fleet
One file puts the hook on every machine; the required check makes it a gate.
This file is reach. It is not enforcement. A hook that runs on Write and Edit does not see a shell that writes the same bytes, and a managed MCP server is a decision surface. The gate is still the required check, or admission. The steps that make the check required are on install. Where the gate is not is on what each path does.
What was read, and what was not run
Measured 2026-09-27 from code.claude.com/docs/en/managed-settings, admin-setup, and settings-reference. This page did not run Claude Code. No /status line was captured on a machine, including none on 2.1.283 and none on a Max account.
The documentation says a file-based policy shows Enterprise managed settings (file) on the Setting sources line of /status. That sentence is the vendor's check, not a line read back here.
The same pages say the file mechanism is not tied to one billing package. Server-managed delivery from the claude.ai console wants a Teams or Enterprise plan. A Max-account run of this file is not recorded here.
The file, without a deny list
allowManagedHooksOnly: true is documented as: only managed hooks run, plus Agent SDK hooks and hooks from plugins the managed settings force-enable. User, project, and local hooks are blocked. allowManagedMcpServersOnly: true is documented as: only allowedMcpServers from managed settings are respected, and deniedMcpServers still merges from all sources. This example sets neither a deny list nor an allow list. A header is left out: the docs say anyone who can read the file, including the user, can read a header value.
The command below is the package path from the per-repo snippet, written as an absolute path because this file is machine-wide. ${CLAUDE_PROJECT_DIR} is a checkout path, not a fleet path. The matcher here is Write|Edit. The per-repo snippet also names MultiEdit. This command was not executed.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "/usr/local/bin/node",
"args": [
"/absolute/path/node_modules/@coderifts/agent-hooks/claude-code/hook.mjs"
]
}
]
}
]
},
"managedMcpServers": {
"coderifts": {
"type": "http",
"url": "https://app.coderifts.com/mcp"
}
},
"allowManagedHooksOnly": true,
"allowManagedMcpServersOnly": true
}
Where the file goes
File-based, from the managed-settings page, fetched 2026-09-27:
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
Claude Code does not read the legacy Windows path C:\ProgramData\ClaudeCode\managed-settings.json.
The same keys, other shapes. macOS configuration profile: the com.anthropic.claudecode managed preferences domain, nested settings as dictionaries and lists as plist arrays. Windows HKLM: the JSON as a REG_SZ or REG_EXPAND_SZ value named Settings under HKLM\SOFTWARE\Policies\ClaudeCode.
The limit
Under allowManagedHooksOnly, the docs say user hooks do not run. That is a documentation sentence, not a trace from a session. A shell that writes a file does not pass the Write matcher. The admin-setup page says it for the neighbouring control: denying WebFetch blocks Claude's fetch tool, but if Bash is allowed, curl and wget can still reach any URL. The same shape holds for this hook. Whether that bypass is recorded anywhere was not measured. Reach onto the fleet is not a gate. The required check, and admission, are the gates. Install is where those steps are written.