Machine policy
How the standalone profile protects each AI agent on Windows, Linux and macOS, which machine-wide policy files it writes, which settings each OS honors, and how to inspect, export and verify the result.
Some agents read a machine-wide policy file that standard users cannot change. For those agents, the standalone profile publishes DefenseClaw's hooks in that file instead of in each user's own config, so there is no user-owned file to delete and no repair window. The other agents are protected per user: the guardian writes DefenseClaw's hook into each enrolled user's agent config and repairs it. See Concepts for the terms.
Only agents you select in the config are protected; see Choose the agents to protect.
Routes by connector
| Connector | Linux and macOS | Windows |
|---|---|---|
Codex (codex) | Machine policy, with the vendor lock | Machine policy, with the vendor lock always on |
Claude Code (claudecode) | Machine policy, with the vendor lock | Machine policy, with the vendor lock; see Windows differences |
Cursor (cursor) | Machine policy, with the foreign-hook guard | Same |
GitHub Copilot CLI (copilot) | Machine policy, with the foreign-hook guard | Same |
OpenCode (opencode) | Machine policy through the managed OpenCode plugin, with the foreign-hook guard | Same |
Amp (amp) | Per user, with the foreign-hook guard | Per user (in-agent plugin), with the guard |
Devin (devin) | Per user, with the foreign-hook guard | Per user (hook binary), with the guard |
Hermes (hermes) | Per user, with the foreign-hook guard | Per user (hook binary) |
Antigravity (antigravity) | Per user | Per user (hook binary) |
OpenHands (openhands), OmniGent (omnigent) | Per user | Not managed: the enumerator writes no targets for them, and a manifest row that names one is refused |
Kiro (kiro) | Per user: each user's global ~/.kiro/hooks/defenseclaw.json plus the CLI 2.x defenseclaw agent; ACP stays optional (see Kiro) | ACP, through defenseclaw-gateway enterprise acp; see ACP guard. The Windows guardian does not enroll Kiro |
OpenClaw (openclaw), ZeptoClaw (zeptoclaw) | Not managed: they need the guardrail proxy, which a managed host does not run, so the enumerator skips them (route unsupported) | Not managed, as for OpenHands |
- Vendor lock. A setting in the agent's machine policy that stops user and project hooks from running. Only Codex and Claude Code have one.
- Foreign-hook guard. For agents without a lock, DefenseClaw removes or blocks hooks it has not approved.
- OpenCode. OpenCode stays on the per-user plugin route while the
managed plugin is missing or untrusted, its
ownershipisoff, or OpenCode's managed config does not name the plugin. - Copilot and OpenCode on Windows. The hook registration comes from the machine policy. The guardian writes only each enrolled user's protected DefenseClaw runtime, never the user's Copilot or OpenCode config.
The machine-policy registrations run the administrator-owned hook binary.
On Linux and macOS the command is
'<bin>/defenseclaw-hook' hook --connector <name> --enterprise-managed,
where <bin> is /opt/defenseclaw/bin (Linux) or
/opt/cisco/defenseclaw/bin (macOS). On Windows the binary is
C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw-hook.exe, and Cursor
runs it through a protected PowerShell adapter next to its hooks.json.
The per-user registrations differ by OS:
- Windows. Every per-user registration runs the same hook binary, or an in-agent plugin that calls the gateway (Amp).
- Linux and macOS, Devin. Devin's registration in each user's
~/.config/devin/config.jsonruns the same administrator-owned command, so each Devin hook runs the foreign-hook guard and fails closed; its fail mode is alwaysclosed, whateverhook_fail_modesays for Devin, andstatusand the hook-contract lock report it that way. A registration an earlier release wrote (~/.defenseclaw/hooks/devin-hook.sh) is replaced at the guardian's next repair. - Linux and macOS, other per-user agents. Antigravity, Hermes,
OpenHands and Kiro run a DefenseClaw hook script that the guardian writes
into the user's
~/.defenseclaw/hooks(for examplehermes-hook.sh), and OmniGent a DefenseClaw policy bridge there. The script sends the event to the gateway over the hook socket itself, and the guardian verifies and repairs it. Amp and the per-user OpenCode plugin call the gateway from inside the agent and rundefenseclaw-hookfor the foreign-hook check, and so doeshermes-hook.shbefore each Hermes tool call.
Machine policy files
| Connector | Linux | macOS | Windows |
|---|---|---|---|
| Codex | /etc/codex/requirements.toml | /etc/codex/requirements.toml | %ProgramData%\OpenAI\Codex\requirements.toml |
| Claude Code | /etc/claude-code/managed-settings.d/90-defenseclaw.json | /Library/Application Support/ClaudeCode/managed-settings.d/90-defenseclaw.json | C:\Program Files\ClaudeCode\managed-settings.d\90-defenseclaw.json |
| Cursor | /etc/cursor/hooks.json | /Library/Application Support/Cursor/hooks.json | %ProgramData%\Cursor\hooks.json |
| Copilot | /etc/github-copilot/policy.d/90-defenseclaw.json | /etc/github-copilot/policy.d/90-defenseclaw.json | %ProgramData%\GitHub\Copilot\policy.d\90-defenseclaw.json |
| OpenCode | /etc/opencode/opencode.json | /Library/Application Support/opencode/opencode.json | %ProgramData%\opencode\opencode.json |
For OpenCode, DefenseClaw uses an existing opencode.jsonc instead of
opencode.json, as long as it holds no comments.
Who writes machine policy
| OS | Codex | Claude Code, Cursor | Copilot, OpenCode |
|---|---|---|---|
| Linux and macOS | The lifecycle (ensure, install, upgrade, repair) | The lifecycle | The lifecycle |
| Windows | The lifecycle at install, upgrade and repair; the guardian repairs it | The guardian, with Windows-specific code | The guardian, with the machine-policy engine that Linux and macOS use |
On every OS the guardian keeps each enrolled user's DefenseClaw runtime in
step with the policy, and verify reports any drift. On Linux and macOS the
guardian never writes machine policy itself.
On Windows, the guardian publishes Cursor's hooks.json, and the protected
PowerShell adapter next to it, only while at least one user is enrolled for
Cursor. A user is enrolled when the enumerator finds Cursor Desktop or the
Cursor Agent CLI (%LOCALAPPDATA%\cursor-agent) in their profile at a
version with a verified hook contract. Until then the file does not exist
and Cursor runs without DefenseClaw hooks. enterprise windows status names
each Cursor install it could not enroll (hook_contract_unverified for an
Agent CLI build DefenseClaw has not reviewed), and policy show and
policy verify report the missing file with this reason. Once a user is
enrolled, Cursor refuses the tool calls of every user who is not.
Managed OpenCode plugin
The standalone payload ships a managed OpenCode plugin at
<InstallRoot>/share/opencode/defenseclaw.js
(/opt/defenseclaw/share/opencode/defenseclaw.js on Linux,
/opt/cisco/defenseclaw/share/opencode/defenseclaw.js on macOS,
C:\Program Files\Cisco\DefenseClaw\share\opencode\defenseclaw.js on
Windows). The Linux and macOS lifecycle installs it with the deployment's
files; on Windows the guardian writes it from the payload binaries.
DefenseClaw adds the plugin to the plugin list of OpenCode's managed
config, so it runs in every user's OpenCode and users cannot edit or delete
it. OpenCode itself can still start without it: see
Vendor limits.
- The plugin is the same file on every host and holds no credential. Each
event runs the administrator-owned
defenseclaw-hookbeside it, which reaches the gateway the same way the other machine-policy hooks do (the peer-authorized hook socket on Linux and macOS, the user's protected runtime on Windows) and applies the foreign-plugin guard. - It fails closed: a tool call is blocked when the hook binary cannot run, answers with an error, or the gateway is unreachable. After uninstall it allows calls again.
- OpenCode uses this route only while the file is administrator-owned
(root on Linux and macOS; Administrators, LocalSystem or TrustedInstaller
on Windows), no other user can change it, and OpenCode's managed config
names it. Otherwise DefenseClaw keeps the per-user plugin and
policy showsays why. The payload installs the file even withownership: "off"; that alone does not change the route. verifyandpolicy showreport a plugin whose content differs from the installed release.ensure(Linux and macOS) or the next guardian pass (Windows) restores it.- On Windows, OpenCode's runtime opens every module with the
write-attributes right, so the plugin grants that right to Users. With it a
standard account can set a reparse point on the plugin, which stops every
account's OpenCode from loading it. The guardian watches the plugin's
folder and restores the plugin within about a second of such a change, and
logs it as a tamper in
hook-guardian.log. The same right lets a standard account set the read-only or hidden attribute; OpenCode still loads the plugin then, so the guardian leaves those attributes as they are. After 12 restores in a minute it slows to one restore every 5 seconds, so repeated changes cannot keep the plugin unreadable until the next pass. The right is removed once OpenCode no longer needs it to load a plugin. - A per-user DefenseClaw plugin left from the per-user route counts as a
foreign plugin once the managed plugin is in place; the guardian removes it
with
foreign_hooks: remove(the default). - On Linux and macOS an unenrolled user's OpenCode calls are inspected, as
for the other machine-policy agents (
unenrolled_users: inspect). On Windows each enrolled user gets a protected per-user runtime for OpenCode, as for Copilot, and OpenCode tool calls from a user without an OpenCode enrollment are blocked.
What DefenseClaw writes on Linux and macOS
- Its own entries only.
- Claude Code and Copilot: DefenseClaw owns the whole
90-defenseclaw.jsondrop-in. - Codex: DefenseClaw owns two marked blocks in
requirements.toml, plus single marked lines inside your own tables (for examplehooks = true # defenseclaw-managedin an existing[features]table). The rest of the file, including comments and order, is left byte for byte. - Cursor: DefenseClaw merges one entry per event into
hooks.jsonand keeps every other key, event and entry in order. - OpenCode: DefenseClaw adds one entry, the managed plugin's path, to the
pluginlist and keeps your other entries.
- Claude Code and Copilot: DefenseClaw owns the whole
- Ownership records and preimages in the
machine-policydirectory under the lifecycle directory (/var/lib/defenseclaw-enterpriseon Linux,/opt/cisco/defenseclaw/lifecycleon macOS). Uninstall removes exactly what DefenseClaw added, keeps edits you made later, and does not bring back content you deleted. - Root-owned files that users can read (
0644). Copilot ignores a policy file that is not root-owned or that group or others can write. - Removal of policy it no longer publishes. When you remove a
connector's name from both
guardrail.connectorsandenterprise.machine_policy.connectors, or set itsownershipto"off", the nextensureremoves DefenseClaw's entries for it.enabled: falseis not enough: it stops only per-user enrollment, and the machine policy stays (see Choose the agents to protect).
If a Codex requirements.toml defines features or hooks as dotted keys
or inline tables, DefenseClaw cannot merge without rewriting your content.
It reports a conflict. Rewrite features and hooks as [features] and
[hooks] tables, or set ownership: verify_only and add DefenseClaw's
entries yourself. policy export --connector codex merges with the host's
file, so it also fails while that file uses dotted keys or inline tables.
Windows differences
On Windows, Codex, Claude Code and Cursor policy is written with Windows-specific code, not with the machine-policy engine that Linux and macOS use. That engine writes only the Copilot drop-in, OpenCode's managed config and plugin, and the foreign-hook guard summary. See Who writes machine policy.
- Claude Code. The drop-in
C:\Program Files\ClaudeCode\managed-settings.d\90-defenseclaw.jsoncarries DefenseClaw's hooks and, with the defaultmanaged_hooks_only: enforce, setsallowManagedHooksOnly: true, so user and project Claude Code hooks do not run.preserveleaves the lock out and turns the foreign-hook guard on for Claude Code, as on Linux and macOS. A drop-in that an earlier release wrote without the lock is rewritten with it. Amanaged-settings.dfile that sorts after90-defenseclaw.jsonand setsallowManagedHooksOnlytofalseturns the lock off;enterprise policy verifyandenterprise windows verifyreport that file. - Claude Code registry policy. While
HKLM\SOFTWARE\Policies\ClaudeCode\Settingsholds a non-empty value, DefenseClaw does not publish its Claude Code drop-in and reports an error for each Claude Code target. This release does not merge with that value. Keep it empty on hosts where DefenseClaw manages Claude Code. - Codex. DefenseClaw parses
requirements.tomland writes it back whole, so comments and key order are not kept. It always setsallow_managed_hooks_only = trueand[features] hooks = true. If your file sets either tofalse, the transaction fails. Each Codex hook command names its installer-bound event and hook contract. - Settings.
ownershipandhigher_precedence_sourcesdo not change how Codex, Claude Code or Cursor policy is written, andmanaged_hooks_onlychanges only the Claude Code lock.ownershipapplies to Copilot and OpenCode, andconnectors.claudecode.ownershipalso applies to the Claude Code version floor drop-in, but not to90-defenseclaw.json.managed_hooks_onlyalso turns the foreign-hook guard on or off for Codex and Claude Code, andforeign_hooksandallowed_hooksapply to the guard, as on the other OSes. - Vendor folders under
%ProgramData%. Standard users may create folders in%ProgramData%. A vendor folder a standard user created first gets DefenseClaw's owner and protected DACL. A file, junction, symbolic link or folder a standard user left at a vendor path or at DefenseClaw's drop-in name is removed (a link, never its target) or moved aside to a hidden.<name>.defenseclaw-displaced-<time>-<id>name that DefenseClaw owns, and the folder is created in its place. A*.jsonfile a standard user left in Copilot'spolicy.dis moved aside the same way. Objects Administrators, LocalSystem or TrustedInstaller own are never removed; DefenseClaw reports them instead. policy show. It checks Claude Code with the same rules as on Linux and macOS, including the lock underenforce.
Locks on Linux and macOS
With managed_hooks_only: enforce (the default):
- Codex.
requirements.tomlgetsallow_managed_hooks_only = true. DefenseClaw also always pins[features] hooks = true, so a user's own config cannot turn managed hooks off. - Claude Code. The drop-in sets
allowManagedHooksOnly: true, so user and project hooks do not run. A user'sdisableAllHooksdoes not turn managed hooks off. - Your own values win. If your policy sets a lock to
false, for exampleallow_managed_hooks_only = falseinrequirements.toml, orallowManagedHooksOnly: falsein a Claude Codemanaged-settings.dfile that sorts after90-defenseclaw.json, DefenseClaw does not rewrite it. It reports a conflict and the connector counts as not covered. The same applies to a manageddisableAllHooks: trueor apolicyHelperfor Claude Code, and tohooks.statein Codex requirements.
With the lock on, hooks your developers need run only if you deploy them
through machine policy. Set managed_hooks_only: preserve for a connector
to leave its lock off; the foreign-hook guard then covers it.
Ownership modes
enterprise:
machine_policy:
default:
ownership: merge # write and repair DefenseClaw's entries
connectors:
codex:
ownership: verify_only # your MDM writes the file; DefenseClaw only checks it
cursor:
ownership: "off" # leave this agent's machine policy aloneownership | What DefenseClaw does |
|---|---|
merge (default) | Writes its entries and repairs them |
verify_only | Only checks the file. When its entries are missing, it reports missing_defenseclaw_hooks and the export command to use. |
off | Neither writes nor checks the file. On Linux and macOS, Codex, Claude Code, Cursor and Copilot then get no DefenseClaw hooks at all: the enumerator does not enroll them for per-user hooks, and the guardian removes per-user hooks an earlier release wrote for them. policy show lists them as ownership off: machine policy not managed. OpenCode keeps its per-user plugin |
Quote "off": YAML 1.1 tools read a bare off as the boolean false,
which the config refuses. Use verify_only when an MDM already writes the
file. Export
DefenseClaw's entries (below) and add them to the MDM's template. On
Windows, ownership applies to Copilot and OpenCode, and to the Claude Code
version floor drop-in. The Windows lifecycle
writes the Claude Code hook drop-in, 90-defenseclaw.json, whatever
ownership says.
Claude Code version floor
Claude Code refuses to start when its version is below the managed
requiredMinimumVersion, but only Claude Code 2.1.163 and later read that
setting. Older builds ignore it and start. DefenseClaw sets it to the lowest
Claude Code version it has a verified hook contract for (2.1.154). Every
build below 2.1.154 is older than 2.1.163, so this floor does not stop any
build: 2.1.153, for example, starts with the floor in place. A value of
2.1.163 or later, such as one you set yourself, stops only the builds from
2.1.163 that are below it. To keep older builds off a host, use application
control (see
Vendor limits; tracked in
#920). The
value is in its own drop-in, 00-defenseclaw-version-floor.json, next to
90-defenseclaw.json; the hook drop-in does not change.
enterprise:
machine_policy:
connectors:
claudecode:
version_floor: enforce # enforce (default), report or "off"version_floor is set only under connectors.claudecode; default and
other connectors do not take it. As with any key under
enterprise.machine_policy.connectors, naming claudecode there makes
the Linux and macOS lifecycle publish DefenseClaw's Claude Code machine
policy; see
Choose the agents to protect.
version_floor | What DefenseClaw does |
|---|---|
enforce (default) | Writes the floor drop-in while no other source sets requiredMinimumVersion to a version, and removes it once one does |
report | Writes nothing; policy show reports that older builds can start |
off | Writes nothing and does not manage the setting |
- Your value wins. When
managed-settings.json, another drop-in,HKLM\SOFTWARE\Policies\ClaudeCode\Settingsor the macOS managed preferences setrequiredMinimumVersionto a version, DefenseClaw leaves that file alone and withdraws its own drop-in, even when the value is below 2.1.154.policy shownames the source and says when the value is below 2.1.154. On Windows the guardian withdraws the drop-in on its next cycle. On Linux and macOS the withdrawal happens at the next lifecycle run that applies changes (ensure,reconcileorrepair), not in the background. Until then, a value you add tomanaged-settings.jsonor to a drop-in that sorts before00-defenseclaw-version-floor.jsonis overridden, because DefenseClaw's drop-in merges after it:policy showandpolicy verifyreport the drop-in's value as the one in force and yours as overridden, and underownership: mergeverifyreports drift, so the nextensure(for example your MDM's periodic run) withdraws the drop-in. - A file at the drop-in's name is yours unless DefenseClaw wrote it.
DefenseClaw treats
00-defenseclaw-version-floor.jsonas its own only while its ownership record names the file and the file's hash matches the record. Any other file there is yours: theversion-floorexport you deploy yourself (the same bytes DefenseClaw writes), or a floor DefenseClaw wrote that you or your tools changed. DefenseClaw never rewrites or removes it, under anyversion_floororownershipsetting or at uninstall, andpolicy showreports its value as the administrator's. If that file does not set a version, DefenseClaw cannot write its floor, and underenforcepolicy verifyfails until you add the key to it or remove it. - A value that is not a version does not count. Claude Code ignores
it. When it is in a file that merges before DefenseClaw's drop-in
(
managed-settings.json, or a drop-in whose name sorts before00-defenseclaw-version-floor.json), DefenseClaw keeps its drop-in, whose later value applies, and never edits your file. When it merges after the drop-in (a later drop-in, a higher-precedence source), no floor applies andpolicy verifyfails until you fix or remove the value. - When it applies. The drop-in is written only in the standalone
profile, while
claudecodeis named underguardrail.connectors(even withenabled: false) or underenterprise.machine_policy.connectors, withownership: merge. To stop it, remove the name from both maps or setownership: "off". Windows follows the same name-based rule for the floor, not the enrolled-row rule it uses for90-defenseclaw.json: a Windows config that namesclaudecodewrites the floor even when no Claude Code user is enrolled. Linux and macOS write it at install and at every lifecycle run that applies changes (ensure,repairorreconcile), not in the background; on Windows the guardian writes it every cycle, under the same lock the lifecycle uses for90-defenseclaw.json. Uninstall removes it. - It follows
connectors.claudecode.ownershipon every OS.mergewrites and repairs it.verify_onlyneither writes nor removes it: deploypolicy export --connector claudecode --format version-flooryourself.offremoves DefenseClaw's floor. This is also true on Windows, where the lifecycle writes90-defenseclaw.jsonwhateverownershipsays. - Coverage. With
version_floor: enforceandownership: merge, a floor that is missing or cannot apply (see the next bullet and the ones above) is a conflict:policy showlists Claude Code as not covered, andpolicy verifyexits 1. The hook drop-in stays in place, and Claude Code's hook calls are still inspected. On Linux and macOS, when DefenseClaw's own drop-in is missing,statusandverifyalso warn withclaude_version_floor_missing(verify still passes), and the nextensurewrites it back. - Higher-precedence sources. Claude Code builds older than 2.1.242
ignore
"managedSourcesBehavior": "merge"and read only the higher-precedence source (HKLM\SOFTWARE\Policies\ClaudeCode\Settings, the macOS managed preferences) while one is in force. Every build the floor is meant to stop is older than that, so the floor in the managed settings files does not reach them, with or withoutmerge, even when that source carries DefenseClaw's hooks (for example theclaude-hklm-jsonexport). Add"requiredMinimumVersion": "2.1.154"to that source. Until thenpolicy showmarks the floornot appliedandpolicy verifyfails (a warning withhigher_precedence_sources: warn). - Limits. The check runs when a session starts; running sessions go
on. Builds before 2.1.163 predate the setting and ignore it, and builds
that do not read
managed-settings.dignore the drop-in altogether; see Vendor limits.
Higher-precedence sources
Some policy sources outrank the files DefenseClaw writes.
| Connector | Source | OS | Accepted when |
|---|---|---|---|
| Claude Code | com.anthropic.claudecode managed preferences in /Library/Managed Preferences | macOS | It contains DefenseClaw's hooks, or sets "managedSourcesBehavior": "merge" (Claude Code 2.1.242 or later) |
| Claude Code | Server-managed settings from the claude.ai console | All | Not visible on the machine; prove the result with --live |
| Claude Code | HKLM\SOFTWARE\Policies\ClaudeCode\Settings | Windows | Never; see Windows differences |
| Codex | com.openai.codex managed preferences (requirements_toml_base64) in /Library/Managed Preferences | macOS | It contains DefenseClaw's managed hooks. Export them with --format plist. |
| Codex | Cloud-managed requirements | All | Not visible on the machine; prove the result with --live |
higher_precedence_sources decides what happens when a visible source
does not include DefenseClaw's hooks. Visible sources exist on macOS (Codex
and Claude Code managed preferences) and on Windows (the Claude Code HKLM
Settings value). On Windows the setting changes only what
enterprise policy show and verify report: the lifecycle never publishes
the Claude Code drop-in while that value is set, whatever this setting says.
fail(default). The source is recorded as a conflict and the connector counts as not covered.ensureandstatusreport the warningmachine_policy_incomplete.defenseclaw-gateway enterprise macos verifyturns it into an error, exits 1 and reportssecurity_complete: false. Enrollment continues.warn. The source is reported as a note, and the connector can still count as covered.
Inspect, export and verify
These commands read the managed config and machine policy. They never write
machine policy; the lifecycle and the guardian do. Run them as root (Linux
and macOS) or from an elevated PowerShell 7 session (Windows), and name the
managed config explicitly with DEFENSECLAW_CONFIG.
sudo DEFENSECLAW_CONFIG=/etc/defenseclaw/config.yaml /opt/defenseclaw/bin/defenseclaw-gateway enterprise policy show
sudo DEFENSECLAW_CONFIG=/etc/defenseclaw/config.yaml /opt/defenseclaw/bin/defenseclaw-gateway enterprise policy show --user alice --project /home/alice/repo
sudo DEFENSECLAW_CONFIG=/etc/defenseclaw/config.yaml /opt/defenseclaw/bin/defenseclaw-gateway enterprise policy export --connector codex --format toml
sudo DEFENSECLAW_CONFIG=/etc/defenseclaw/config.yaml /opt/defenseclaw/bin/defenseclaw-gateway enterprise policy verify --json
sudo DEFENSECLAW_CONFIG=/etc/defenseclaw/config.yaml /opt/defenseclaw/bin/defenseclaw-gateway enterprise policy verify --live --user alice --connector codex --agent-binary /usr/local/bin/codexsudo DEFENSECLAW_CONFIG=/opt/cisco/defenseclaw/etc/config.yaml /opt/cisco/defenseclaw/bin/defenseclaw-gateway enterprise policy show
sudo DEFENSECLAW_CONFIG=/opt/cisco/defenseclaw/etc/config.yaml /opt/cisco/defenseclaw/bin/defenseclaw-gateway enterprise policy export --connector codex --format plist
sudo DEFENSECLAW_CONFIG=/opt/cisco/defenseclaw/etc/config.yaml /opt/cisco/defenseclaw/bin/defenseclaw-gateway enterprise policy export --connector claudecode --format plist$env:DEFENSECLAW_CONFIG = 'C:\ProgramData\Cisco\DefenseClaw\etc\config.yaml'
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise policy show
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise policy export --connector copilotshowlists, per connector: the route, whether it is covered, the lock and effective lock, the foreign-hook mode, DefenseClaw-owned and foreign entries, files, conflicts and notes.--connectorlimits it to one connector.--useralso scans that user's own agent config for foreign hooks, and--project(with--user) scans a repository.--jsonprints the report as JSON.exportprints DefenseClaw's entries for one connector, to deploy through your own policy tool.--connectoris required. Without--format, you get the connector's native file.
--connector | --format |
|---|---|
codex | toml (default): the complete merged requirements.toml. plist: a macOS profile payload with requirements_toml_base64. |
claudecode | json (default): the drop-in. claude-hklm-json, reg, intune-settings-catalog: the same content as a HKLM\SOFTWARE\Policies\ClaudeCode Settings value. plist: a macOS managed-preferences payload. version-floor: the version floor drop-in. |
cursor | json: the enterprise hooks.json |
copilot | json: the policy.d drop-in |
opencode | json: a managed OpenCode config that loads <install root>/share/opencode/defenseclaw.js. Deploy it only where that plugin is installed. |
verifychecks coverage and exits 1 when any machine-policy connector is not covered, or when--userfinds a foreign hook that would be blocked.verify --liveruns the real Codex or Claude Code client as a user and proves that it loads DefenseClaw's hooks. It needs--user, exactly one--connector(codexorclaudecode) and--agent-binarywith the client's absolute path.--timeoutdefaults to 90 seconds. For Claude Code, the proof is the gateway'stool.invocation.requestedrecord of a canary tool call in its event history, so the gateway must be running and collecting tool activity;--audit-dbnames the gateway's audit database if it is not in the standard place. On Linux and macOS run it as root or as that user. A managed Windows host refuses--live; see Windows.
Vendor limits
These come from the agents themselves:
- Claude Code.
claude --bareandCLAUDE_CODE_SIMPLE=1skip managedSessionStartandUserPromptSubmithooks.PreToolUseand later tool hooks still run, so tool calls stay inspected; prompt inspection is best effort. - Claude Code before 2.1.163. These builds do not read
requiredMinimumVersion, so no floor stops them, DefenseClaw's or yours. Those that readmanaged-settings.d, such as 2.1.153, still run DefenseClaw's hooks; older ones are the next item. Use application control to allow only the Claude Code versions you support. - Older Claude Code releases (Linux and macOS). Releases that do not
read
managed-settings.dignore both of DefenseClaw's drop-ins, the hooks in90-defenseclaw.jsonand the version floor, so the floor cannot stop them. For example 1.0.128, 2.0.0 and 2.0.77, installed by a standard user under their home (npm install --prefix), run tool calls with no DefenseClaw hook and no audit record, andstatusandverifydo not report them. These releases read onlymanaged-settings.json, which DefenseClaw leaves to you. Use application control to allow only Claude Code at or above 2.1.154. Tracked in #920. - Older Copilot CLI releases. A Copilot CLI below its 1.0.18 floor can
skip machine policy: 1.0.15, installed under a home (
npm install --prefix) and run with--no-auto-update, does not load/etc/github-copilot/policy.d, and its tool calls run with no audit record. Use application control to allow only Copilot CLI at or above the floor. - Copilot. A command hook that times out fails open, including policy
hooks. On Windows, Copilot also loads policy hooks from
HKLM\Software\Policies\GitHub\Copilot; those run beside DefenseClaw's drop-in. - OpenCode. The order in which OpenCode runs plugins is not a
documented contract, so the foreign-hook guard stays on for OpenCode.
OpenCode pure mode (
opencode --pureorOPENCODE_PURE=1) loads no plugins, the managed plugin included, andOPENCODE_TEST_MANAGED_CONFIG_DIR, which release builds honor, replaces the managed config directory. A session started either way never calls DefenseClaw's hooks, on the machine-policy and the per-user route alike, so its tool calls are not inspected.verifyandpolicy showstill report OpenCode covered, because the entry is in place; their details name this limit.OPENCODE_CONFIG_CONTENTandOPENCODE_DISABLE_DEFAULT_PLUGINSdo not remove the managed plugin (observed with OpenCode 1.18.32). - Amp. Amp has no machine-wide plugin location, so it stays per user.
- Cursor. Cursor applies the enterprise
hooks.jsononly on plans that support enterprise hooks. Confirm on a real client.
See Residual risks for the full list.
Enrollment
How the standalone profile finds users on Windows, Linux and macOS, which enrollment settings each OS honors, how directory accounts, new users and deleted users are handled, and how to publish the target list yourself.
Foreign-hook guard
How the standalone profile stops user and project hooks that DefenseClaw has not approved from changing an AI agent's tool call after inspection, which agents and files it covers on each OS, and how to approve or restore a hook.