Enterprise

Windows standalone deployment

Install the standalone DefenseClaw enterprise services on Windows x64 with the standalone Setup or the lifecycle CLI, check the result, and remove them.

The standalone profile installs DefenseClaw machine-wide on Windows x64 as four Windows services. It does not need Cisco Secure Client. Standard users cannot stop the services or change the config, and the hook guardian restores DefenseClaw's hooks if a user removes them. For the terms used on this page, see Concepts.

Deploying with an MDM?

This page installs on one computer from an administrator shell. To deploy to many computers with Intune, Configuration Manager, Workspace ONE or another MDM, start with Install with an MDM. It uses the same Setup and the same config.

Requirements

RequirementDetail
WindowsNative Windows x64. The lifecycle refuses ARM64, including x64 emulation on ARM64, and refuses to run from a 32-bit process. It does not check the Windows version. The MDM kit's requirement rule uses Windows 10 22H2 or later.
PowerShell 7A stable PowerShell 7 x64, installed from Microsoft's MSI. The lifecycle finds it only through HKLM\SOFTWARE\Microsoft\PowerShellCore\InstalledVersions, requires it under Program Files with a valid Microsoft signature, and ignores PATH. Without it, the run stops with powershell7_required. Install 7.4 or later: the lifecycle accepts any stable 7.x, but the MDM wrapper requires 7.4.
Language modePowerShell FullLanguage mode. Under a WDAC or AppLocker script policy, allow the DefenseClaw signer, or the run stops with powershell_constrained_language.
PrivilegesAn elevated administrator token, or SYSTEM (for example an MDM agent).
Other profilesNo Secure Client DefenseClaw deployment. The two profiles share service names, so the lifecycle refuses with profile_conflict.

Layout

Binaries go under Program Files and state under ProgramData. Standard users cannot change either tree.

ItemPath
BinariesC:\Program Files\Cisco\DefenseClaw\bin (defenseclaw.exe, defenseclaw-gateway.exe, defenseclaw-hook.exe, defenseclaw-acp.exe, defenseclaw-sensor-helper.exe)
Lifecycle scriptsC:\Program Files\Cisco\DefenseClaw\libexec (install-enterprise.ps1, DefenseClawEnterprise.psm1)
ConfigC:\ProgramData\Cisco\DefenseClaw\etc\config.yaml
SecretsC:\ProgramData\Cisco\DefenseClaw\secrets
Target manifestC:\ProgramData\Cisco\DefenseClaw\hook-guardian\targets.yaml (the enumerator writes it)
Lifecycle stateC:\ProgramData\Cisco\DefenseClaw\install
Gateway dataC:\ProgramData\Cisco\DefenseClaw\runtime
Authorization ledgerC:\ProgramData\Cisco\DefenseClaw\hook-guardian-state
Service logsC:\ProgramData\Cisco\DefenseClaw\logs
Hook runtimeC:\ProgramData\Cisco\DefenseClaw-HookRuntime, readable by users. It holds, for each per-user connector, the enrollment list and runtime selector, and machine-policy.json, the public machine-policy summary.
Lifecycle log%WINDIR%\Logs\DefenseClaw: enterprise-lifecycle.log, last-result.json and, for MDM runs, mdm-wrapper.log. Users can read these files.

The lifecycle also registers the deployment with Windows:

RegistrationValue
Deployment markerHKLM\SOFTWARE\Cisco\DefenseClaw\Enterprise, with Profile, ProductVersion, InstallRoot, StateRoot, TrustMode, UpdatedAt and DisableSelfUpdate
Add/Remove ProgramsHKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CiscoDefenseClawEnterprise, shown as "Cisco DefenseClaw Enterprise"
Event logThe DefenseClaw event log, source DefenseClaw Lifecycle, which only LocalSystem and Administrators can write. A legacy copy of each event still goes to the Application log, source DefenseClaw Enterprise
Self-update policyHKLM\SOFTWARE\Policies\Cisco\DefenseClaw\DisableSelfUpdate = 1, written only when the value is absent. The lifecycle records that it wrote the value and removes it on uninstall only in that case, so your own Group Policy value is never changed. Set enterprise.coexistence.disable_self_update: false to opt out.

The four services:

ServiceIdentityRole
DefenseClawGatewayNT SERVICE\DefenseClawGateway, with SeChangeNotifyPrivilege onlyRuns the policy engine and the hook API on 127.0.0.1:18970
DefenseClawSensorHelperLocalSystem, with SeChangeNotifyPrivilege onlyAnswers the gateway's fixed AI Discovery requests
DefenseClawHookGuardianLocalSystem, with a fixed privilege listWrites and repairs each enrolled user's hook registrations, using that user's token
DefenseClawHookEnumeratorLocalSystem, with the same privilege listFinds eligible profiles (local, domain and Microsoft Entra ID accounts) and writes the target manifest

The Service Control Manager restarts each service after a failure.

SCM + DACLs
SCM + DACLs
user config, as user
loopback · SCM PID
fixed requests
TrustedZ0 · Admin and MDM (SYSTEM)
PrivilegedZ1 · Services (LocalSystem)
RestrictedZ2 · Gateway (virtual account)
UntrustedZ4 · User session (user)
OperatorSetup /ensureor enterprise windows
SystemHookGuardian ·HookEnumerator
SystemSensorHelper
Control planeDefenseClawGateway
Agent runtimeAI agent
Connectordefenseclaw-hook.exe
Standalone Windows. Before it sends any bytes, the hook confirms that the process behind its loopback connection is the process the Service Control Manager reports for DefenseClawGateway.

See Threat model for what each zone may do.

Install

Install in four steps: get and check the release, write the config, run Setup, then add the AI Defense key if you use it.

1. Get and check the release

Download these assets from the same GitHub release:

  • DefenseClawSetup-Enterprise-Standalone-x64.exe, the standalone Setup.
  • checksums.txt and checksums.txt.bundle, the signed checksum list.

DefenseClawSetup-Enterprise-x64.exe is the Secure Client Setup. Do not use it for the standalone profile.

Check the checksum list's signature with cosign, then compare the Setup's hash with its line in the list:

cosign verify-blob --bundle checksums.txt.bundle `
  --certificate-identity 'https://github.com/cisco-ai-defense/defenseclaw/.github/workflows/release.yaml@refs/heads/main' `
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' `
  checksums.txt
(Get-FileHash .\DefenseClawSetup-Enterprise-Standalone-x64.exe -Algorithm SHA256).Hash.ToLower()
Select-String -Path .\checksums.txt -Pattern 'DefenseClawSetup-Enterprise-Standalone-x64\.exe$'

The two hashes must match. Keep the hash: MDM recipes pin it.

2. Write the config

The config is an ordinary DefenseClaw config.yaml with the standalone profile. This example protects Codex and Claude Code in observe mode:

config.yaml
config_version: 8
deployment_mode: managed_enterprise
enterprise:
  profile: standalone
gateway:
  api_bind: 127.0.0.1
  api_port: 18970
guardrail:
  enabled: true
  mode: observe
  connectors:
    codex: {}
    claudecode: {}

Each key under guardrail.connectors turns on protection for that agent. A config with no connectors protects nothing. See Choose the agents to protect and the settings reference.

Without guardrail.rule_pack_dir or policy_dir, as here, the gateway uses the rule packs built into it. A rule-pack directory you name must exist and be writable only by administrators. Setup checks the config with the gateway's own compiler, and loads every rule pack the gateway would load, before it changes anything. When the gateway could not load the file, Setup stops with exit code 1639 and names the line and the reason.

Setup accepts the config only from an absolute local path that standard users cannot change. Stage it in a folder that only SYSTEM and Administrators can write:

$Stage = 'C:\ProgramData\DefenseClaw-Staging'
New-Item -ItemType Directory -Path $Stage -Force | Out-Null
icacls $Stage /inheritance:r /grant:r '*S-1-5-18:(OI)(CI)F' '*S-1-5-32-544:(OI)(CI)F' | Out-Null
Copy-Item .\config.yaml "$Stage\config.yaml"

3. Run Setup

From an elevated PowerShell session:

& .\DefenseClawSetup-Enterprise-Standalone-x64.exe /ensure "CONFIG=$Stage\config.yaml" JSON=1
$LASTEXITCODE

/ensure installs when nothing is installed, upgrades an older version, re-applies a changed config, repairs a deployment that fails verification, and otherwise does nothing. Setup unpacks its embedded payload into a protected folder, checks every file against its embedded manifest, and runs the lifecycle from there. See Payload trust for how the lifecycle decides which files to trust. It also generates the target manifest from the profiles on the computer, so you never write targets.yaml.

With JSON=1, Setup prints the lifecycle result document on standard output. The exit code follows Windows Installer conventions:

CodeMeaning
0Success, or nothing to do
1603Failure. A failed install, upgrade or repair is rolled back, and a refusal before any change leaves the computer as it was. When the rollback itself cannot finish, the transaction stays pending (see Recover a pending transaction). For status and verify, 1603 means the deployment is unhealthy.
1618Another lifecycle run holds the lock. Retry later.
1639Invalid arguments: a malformed command line (such as a relative CONFIG= path or an unknown property), or arguments the lifecycle rejected (for example /ensure without CONFIG= on a computer with no deployment, a config the gateway cannot load, or a run that enterprise.trust refuses). Retrying does not help.
3010Reserved. The lifecycle never requests a restart.

Setup properties use NAME=value. Names are case-insensitive and ignore dashes, so ALLOWEDSIGNERS= and allowed-signers= are the same.

PropertyMeaning
CONFIG=<path>The administrator config. Required for the first install. Later runs reuse the installed config when you leave it out.
MANIFEST=<path>A target manifest you publish yourself. Required for /install, and for a first install with enterprise.enrollment.mode: manifest.
ATTESTCLAUDEEFFECTIVEPOLICY=1With /repair: record that Claude Code runs DefenseClaw's managed hooks on this computer. See Verify the install.
ALLOWEDSIGNERS=<sha256>,<sha256>Accept only these Authenticode signer certificates (SHA-256 thumbprints). Applies to a signed Setup.
JSON=1Print the result document on standard output
NOSTART=1Install or update with the services stopped and disabled. A later /repair starts them.
PURGE=1With /uninstall, also remove the state under C:\ProgramData\Cisco\DefenseClaw and each enrolled account's %USERPROFILE%\.defenseclaw
TIMEOUTSECONDS=<n>Lifecycle timeout, from 60 to 7200 seconds. The default is 1800.

The other actions are /install, /upgrade, /repair, /reconcile, /status, /verify and /uninstall. Prefer /ensure: /install also requires MANIFEST=, a target manifest that /ensure generates for you. /quiet and /norestart are accepted and have no effect.

4. Add the AI Defense key

Without a key, the local policy engine decides alone. To add Cisco AI Defense, turn it on in the config. Add these keys before you run Setup, or run /ensure again with the updated config:

config.yaml (excerpt)
enterprise:
  profile: standalone
  inspection:
    ai_defense:
      enabled: true
      credential: ai-defense-api-key

Then store the key. The deployment must be installed first:

& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise secret set `
  --name ai-defense-api-key --from-file 'C:\ProgramData\DefenseClaw-Staging\ai-defense.key' --json
Remove-Item 'C:\ProgramData\DefenseClaw-Staging\ai-defense.key'

The command runs only from an elevated prompt. It writes C:\ProgramData\Cisco\DefenseClaw\secrets\ai-defense-api-key and restarts the gateway. See AI Defense key for the config keys and for rotation.

Verify the install

Run from an elevated PowerShell 7 session:

$Cli = 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe'
& $Cli enterprise windows status --profile standalone --json
& $Cli enterprise windows verify --profile standalone --json

status reports the state. verify also checks every file, permission, service and hook, and returns a nonzero exit code when anything fails. Look for these fields:

FieldHealthy value
oktrue
installed, installed_versiontrue and the version you deployed
readinessgateway, guardian, enumerator and sensor_helper all true
coverage_completetrue: installed, the guardian is ready, and no transaction is pending
security_completetrue: see below
enrollment.targetsThe number of entries (one per user and connector) in the target manifest. 0 means nobody is protected yet.
errorsEmpty

On Windows, security_complete needs at least one of Codex, Claude Code or Cursor enabled, and no agent reported as agent_unprotected or hook_contract_unverified. With Claude Code enabled, it also needs an administrator's attestation that Claude Code runs DefenseClaw's managed hooks on this computer:

  1. Install. security_complete is false at this point.

  2. Confirm that Claude Code runs DefenseClaw's hooks. In an enrolled user's own session, start that user's Claude Code and have it make one tool call, for example listing the current folder. Then, from an elevated prompt, check that the gateway recorded the call:

    & $Cli audit export --connector claudecode -o C:\Temp\audit-claudecode.jsonl

    enterprise policy verify --live is not available on Windows; see Inspect machine policy.

  3. Record the attestation from an elevated PowerShell 7 session:

    & $Cli enterprise windows repair --profile standalone --attest-claude-effective-policy --json

    The Setup form is /repair ATTESTCLAUDEEFFECTIVEPOLICY=1 JSON=1.

DefenseClaw records the attestation as you give it; step 3 does not run Claude Code. The record is bound to the SHA-256 of the installed Claude Code policy file and of the hook binary, not to the computer. Every DefenseClaw upgrade replaces the hook binary, and a change to the Claude Code hook contract the policy is rendered from changes the policy, so either makes the record stale: security_complete returns to false until you repeat steps 2 and 3. Computers that run the same release and Claude Code contract have the same binding, so an MDM can check one reference computer and push the Setup form to the others; the attestation then stands for each of those computers.

The guardian writes a user's hook registrations only while that user has an active (connected) session. It retries until the session is active again.

Each elevated lifecycle run appends its result to the lifecycle log. Every run except a healthy status or verify also writes an event (IDs 100 to 150) to the DefenseClaw event log and a legacy copy of it to the Application log. The marker key and the Add/Remove Programs entry change only after a successful run, and they are for detection only: verify never trusts them. See Detection for the detection rules, Logs and events for the event IDs, and Status and verify for monitoring.

Only LocalSystem and Administrators can write the DefenseClaw log (source DefenseClaw Lifecycle), and the accounts that can read the Application log can read it. Each run that writes an event registers the log and resets its access. A successful uninstall unregisters it, so the uninstall event (110) goes only to the Application log; forward the DefenseClaw log to your SIEM if you need its entries after uninstall. Unregistering does not delete the entries: Windows keeps %WINDIR%\System32\winevt\Logs\DefenseClaw.evtx (the Event Log service holds it open until it restarts), and a later install that registers the log again shows the old entries with the new ones.

Any account can write Application-log entries under any source name, including DefenseClaw Enterprise, so the Application-log copies are legacy, and a later release stops writing them. Point MDM detection rules and SIEM forwarding at the DefenseClaw log (Get-WinEvent -LogName DefenseClaw) instead of the Application log's DefenseClaw Enterprise source.

Each DefenseClaw event ends with record <id>, and the matching line of enterprise-lifecycle.log, which only administrators and LocalSystem can write, holds the same id under event.record with the event ID (event.id), the SHA-256 of the exact message (event.sha256) and the event logs that took the entry (event.logs). Check the entries from any prompt:

Check the DefenseClaw event-log entries
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise windows events
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise windows events --json
# The legacy Application-log copies:
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise windows events --application

An entry is DefenseClaw's only when all of these hold:

  • its message ends with record <id> and the lifecycle log has a line with that record;
  • the entry's event ID and the SHA-256 of its message (the UTF-8 bytes of the event's insertion string, $event.Properties[0].Value) match that line;
  • it was written within two minutes of that line's time;
  • no earlier entry carried the same record. A later entry with the same record is a copy.

events exits 1 and names each entry that fails, and also when the newest lifecycle line whose event went to the checked log has no DefenseClaw entry there. Entries older than the lifecycle log's first event record, such as those an earlier release wrote without records, show as unverifiable. Apply the same rules in a SIEM: matching a record alone is not enough, because anyone can copy a genuine entry.

status and verify also name every agent the enumerator found installed but could not enroll (hook_contract_unverified, agent_unprotected); see Enrollment. Each is one account's agent, so both print it as a warning <code>: <message> line and --json lists it under warnings: security_complete is false, but verify, and so MDM detection, still passes. enterprise policy show lists them as well. Cursor's machine hooks file is published only while a user is enrolled for Cursor; see Machine policy. include_groups and exclude_groups apply on Windows as described there.

Review the audit log

The gateway service owns the local audit database under C:\ProgramData\Cisco\DefenseClaw\runtime. Export it from an elevated Administrator prompt, or as LocalSystem from an MDM script:

Elevated Administrator prompt
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' audit export --connector claudecode -o C:\Temp\audit-claudecode.jsonl

On a standalone host, audit export run this way reads the managed deployment's configuration and audit database read-only beside the running gateway; it needs no environment variables. Standard accounts cannot read the managed audit log, and the command tells them to use an elevated prompt. Omit --connector to export every row. The output file must not exist yet; it takes the permissions of its folder, so write it to a folder only administrators can read. Treat it as sensitive: it can hold prompt and tool content.

Inspect machine policy

Run the policy commands from an elevated Administrator prompt, or as LocalSystem from an MDM script. Like audit export, they read the managed deployment's configuration and need no environment variables:

Elevated Administrator prompt
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise policy show
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise policy verify

show lists each connector's route, lock and coverage; verify exits 1 while coverage is incomplete. With managed_hooks_only: enforce (the default) the Claude Code drop-in C:\Program Files\ClaudeCode\managed-settings.d\90-defenseclaw.json sets allowManagedHooksOnly: true, so user and project Claude Code hooks do not run. Claude Code applies the files in managed-settings.d in name order, so a file that sorts after 90-defenseclaw.json and sets allowManagedHooksOnly to false turns the lock off; enterprise policy verify and enterprise windows verify report that file. Standard accounts are told to use an elevated prompt.

enterprise policy verify --live is not available on Windows: Windows cannot start the client as another account, and a standard account cannot read the managed configuration. Use the static verify above, and to see the hooks run, make a tool call in the client from the user's own session, then read its record from the elevated prompt with audit export, as in Review the audit log.

Recover a pending transaction

A lifecycle that fails normally rolls back. If the rollback itself cannot finish, the transaction stays pending: the result reports transaction_pending: true, the DefenseClaw services stay stopped, and vendor machine policy the transaction had already published can still point at the stopped gateway. status shows the state; verify refuses until the transaction is recovered. The failed result names the command to run next.

Recover by running DefenseClaw Setup as LocalSystem (Intune install behavior System, or another MDM's system context). /ensure recovers the pending transaction and then installs or upgrades; /uninstall recovers it and removes the deployment:

As LocalSystem
DefenseClawSetup-Enterprise-Standalone-x64.exe /ensure CONFIG=C:\ProgramData\DefenseClaw-Staging\config.yaml JSON=1
DefenseClawSetup-Enterprise-Standalone-x64.exe /uninstall JSON=1

/repair also recovers the transaction; after a failed first install it then stops with "run Install", so /ensure is the one-step command. Outside an MDM, a one-time scheduled task that runs as SYSTEM gives the same context. From a payload folder (see Run the lifecycle CLI from a payload folder), "$Payload\defenseclaw.exe" enterprise windows ensure (or repair, uninstall) with the same --profile, trust and --config options, run as LocalSystem, works the same way.

Recovery first uses the gateway the pending transaction staged. When that gateway cannot restore or retire the transaction's managed-hook state, or cannot remove the per-user runtime roots the transaction created (the target-runtime rollback cleanup), for example a release whose defect caused the failure, the standalone lifecycle retries that step once with the defenseclaw-gateway.exe that ships in the running Setup's payload (or beside the staged defenseclaw.exe), and only when all of these hold:

  • the lifecycle runs as LocalSystem;
  • that gateway passes the same checks an install applies to its payload: an administrator-owned source on a local NTFS volume and the deployment's trust mode (a valid Authenticode signature, limited to the allowed signers when any are set, or the SHA-256 the payload manifest pins);
  • it is not the gateway that already failed, and it is not inside the install root;
  • it is the same release as the gateway that failed or a newer one, read from each gateway's version resource (an older Setup never recovers a newer release's transaction);
  • the run is not an --allow-unsigned certification run.

The verified gateway is copied to C:\Program Files\Cisco\DefenseClaw\bin, where the hidden command must run, and the step runs again; the rollback then restores that file to its state before the transaction. The result and enterprise-lifecycle.log record a recovery_gateway_fallback warning with the binary, where it was copied from, its SHA-256, the trust basis, its release and the staged gateway's release, the account, and the staged gateway's failure. When recovery declines the fallback, a recovery_gateway_not_used warning gives the reason (not_local_system, untrusted, same_binary, older_release, version_unknown, no_payload, inside_install_root, unsigned_scope) and the staged gateway's error stands. A failure that concerns file permissions is reported in plain terms; the internal detail is kept in a lifecycle_diagnostic warning for support. Do not edit DefenseClaw files or permissions by hand to recover.

Recovery then restarts the restored release, and its gateway starts only after that release's guardian publishes full coverage. When the restored release is the one that cannot (for example, its guardian cannot republish a user's lost per-user state), every recovery would fail the same way. Under the same conditions as above, the standalone lifecycle instead finishes the recovery with the restored release stopped and disabled and records a recovery_activation_deferred warning (the restored and the Setup's releases, the Setup gateway's SHA-256 and trust basis, and the coverage failure). /ensure then upgrades to the running Setup's release in the same run; its gateway also starts only after full coverage. /repair stops at that point with the next step, because it reapplies the installed release that could not start. With the same release, or from an elevated administrator prompt, recovery keeps the coverage failure and a recovery_gateway_not_used warning gives the reason.

Per-user installs

On a computer with the standalone deployment, the per-user product refuses to run:

Per-user actionWhat happens
install.ps1Refuses when the marker key exists, or when DisableSelfUpdate under HKLM\SOFTWARE\Policies\Cisco\DefenseClaw is nonzero
defenseclaw upgrade, defenseclaw rollbackRefuse when the marker key exists
Per-user gatewayRefuses to start on a managed computer

Nothing migrates a per-user install automatically. Before you deploy, have each user remove their per-user install with defenseclaw uninstall --binaries --yes. Add --all to also delete %USERPROFILE%\.defenseclaw. See Uninstall and preserved state.

Remove

With Setup:

& .\DefenseClawSetup-Enterprise-Standalone-x64.exe /uninstall JSON=1

Or with the installed CLI:

& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise windows uninstall --profile standalone --json

Uninstall removes DefenseClaw's hook registrations and machine-policy entries, the four services and the binaries. It keeps the config, secrets, data and service logs under C:\ProgramData\Cisco\DefenseClaw. To remove those too, add PURGE=1 to Setup or --purge to the CLI. After a successful uninstall, the marker key, the Add/Remove Programs entry and a DisableSelfUpdate value that the lifecycle wrote are gone, and so are their parent keys and C:\Program Files\Cisco when nothing else is left in them. The lifecycle log in %WINDIR%\Logs\DefenseClaw stays. On a computer without DefenseClaw, uninstall succeeds and changes nothing.

Per-user registrations at uninstall

Uninstall revokes every per-user enrollment first. Once it has committed, it removes DefenseClaw's own hook registrations and plugins (Amp, Antigravity, Devin, Hermes, OpenCode, and a DefenseClaw Copilot user hook file) from the agent configuration of every signed-in user, running as that user. Only DefenseClaw's entries are removed; the user's own hooks and settings stay. Cleanups the guardian still owed to revoked users are included.

Acting as a user needs that user's session token, which only LocalSystem can obtain. An MDM uninstall runs as LocalSystem (Intune install behavior System). An uninstall run from an elevated administrator prompt, or from Add/Remove Programs, cannot act as other users, so it removes no per-user registrations. Users who are signed out during the uninstall keep theirs as well: no guardian is left to clean them at their next sign-in. The uninstall result names what stays: the user_registrations_pending warning lists each connector and user SID it could not act as, and user_registrations_failed lists removals that failed, including a registration that a connector's removal left in the user's agent configuration (the message names the file). To clean every user, run the uninstall as LocalSystem while they are signed in.

PURGE=1 also removes each enrolled account's %USERPROFILE%\.defenseclaw folder, including that account's per-user hook tokens, whether or not the account is signed in. Some of its subfolders grant only the account and SYSTEM, not Administrators, so this also needs the uninstall to run as LocalSystem. As on Linux and macOS, two things stay: each DefenseClaw hook script, replaced by a stub that exits without doing anything, because an agent that is still running may call the hook path it loaded; and the account's own hooks that the foreign-hook policy moved aside (foreign-hooks-backup). The per_user_state_remaining warning names each folder the purge could not remove and why: the uninstall did not run as LocalSystem, a file in it could not be removed, or the account's roaming or container profile is not on the computer while it is signed out. Remove what it names as LocalSystem.

What stays is inert. Uninstall has already revoked every enrollment. The OpenCode and Amp plugins stop enforcing once uninstall removes C:\ProgramData\Cisco\DefenseClaw-HookRuntime and the install marker. The Devin, Hermes and Antigravity hooks point at the removed defenseclaw-hook.exe, so each hook call fails to start. None of these agents blocks on that: Devin blocks only on exit code 2 (a missing command exits 127), and Hermes and Antigravity do not enforce a nonzero hook exit. A DefenseClaw Copilot user hook that stays fails open, like every Copilot integration failure.

Payload trust

The lifecycle refuses to run any payload file it cannot trust. There are two trust modes:

ModeHow a file is trusted
authenticodeEvery binary and script carries an Authenticode signature that Windows reports as Valid. An allowed-signer list narrows the accepted signer certificates.
hash_pinnedEvery file that is not validly signed must match a SHA-256 digest in an administrator-owned payload manifest. The CLI checks the installer script and module against it before PowerShell starts.

The default depends on how you start the lifecycle:

Entry pointTrust usedHow to change it
Standalone SetupChosen by the build. An unsigned Setup uses hash_pinned with a payload manifest (payload-trust.json) that Setup writes itself from its embedded, verified manifest. A signed Setup uses authenticode.ALLOWEDSIGNERS= pins the signer of a signed build. You never supply payload-trust.json.
defenseclaw.exe enterprise windowsauthenticode--trust-mode hash_pinned --payload-manifest <file>. --allowed-signer <sha256> (repeatable) pins signers.
MDM wrapper (Invoke-DefenseClawEnterprise.ps1)HashPinned: it checks the Setup file against -Sha256 before running it-TrustMode Authenticode -AllowedSigners <sha256>. See Install with an MDM.

Releases are Authenticode-signed only when the release pipeline has a code-signing certificate. Check the Setup you downloaded:

$sig = Get-AuthenticodeSignature -LiteralPath .\DefenseClawSetup-Enterprise-Standalone-x64.exe
$sig.Status
if ($sig.SignerCertificate) {
  $sha = [Security.Cryptography.SHA256]::Create()
  [BitConverter]::ToString($sha.ComputeHash($sig.SignerCertificate.RawData)).Replace('-', '').ToLowerInvariant()
}

Valid means the Setup is signed, and the last line prints the signer's SHA-256 thumbprint for ALLOWEDSIGNERS=. NotSigned means a hash-pinned build: trust comes from the Setup hash you checked against checksums.txt.

enterprise.trust in the config can only narrow what the entry point accepts. mode: authenticode refuses a hash-pinned run, including the unsigned Setup, with 1639, and also refuses a run over a deployment that was installed hash-pinned, because that deployment keeps admitting its payload by its recorded pins. Leave the mode unset or set hash_pinned while you deploy unsigned builds; a signed Setup is still verified by its signature. enterprise.trust.allowed_signers works like --allowed-signer; when both are given they must list the same thumbprints. See Payload trust.

The deployment marker's TrustMode records how the installed deployment was trusted. The MDM detect.ps1 and uninstall.ps1 scripts check the installed CLI's Authenticode signature only when it is authenticode.

Hash-pinned files have no publisher, so they do not satisfy WDAC or AppLocker rules that require one. Sign or re-sign the payload where those rules apply.

Advanced: run the lifecycle CLI from a payload folder

The lifecycle CLI can run from a folder that holds the seven payload files: defenseclaw.exe, defenseclaw-gateway.exe, defenseclaw-hook.exe, defenseclaw-acp.exe, defenseclaw-sensor-helper.exe, install-enterprise.ps1 and DefenseClawEnterprise.psm1. The CLI uses ..\libexec\install-enterprise.ps1 if that file exists, otherwise the installer script next to itself. ensure takes the binaries from the installer script's folder.

Releases ship these files only inside Setup, and Setup has no extract action. Use this path only when your own build or re-signing pipeline produces the files. Otherwise use Setup.

$Payload = 'C:\ProgramData\DefenseClaw-Staging\payload'
& "$Payload\defenseclaw.exe" enterprise windows ensure `
  --profile standalone `
  --config 'C:\ProgramData\DefenseClaw-Staging\config.yaml' `
  --json

For unsigned files, add --trust-mode hash_pinned --payload-manifest <file>. The manifest is JSON in the form {"schema_version":1,"files":{"<file name>":"<sha256>"}}. It must pin install-enterprise.ps1, DefenseClawEnterprise.psm1 and every other unsigned file. The ...payload-manifest.json release asset uses a different format and cannot be passed here. Later repair, verify and uninstall runs re-trust the installed files from the digests the deployment recorded, so they need no manifest.

Connectors on Windows

ConnectorRoute on WindowsNotes
CodexMachine policyCodex requirements file. DefenseClaw always sets allow_managed_hooks_only = true, and an administrator value of false makes the run fail.
Claude CodeMachine policyManaged-settings drop-in with DefenseClaw's hooks and, under the default managed_hooks_only: enforce, the allowManagedHooksOnly vendor lock. preserve leaves the lock out and turns the foreign-hook guard on for Claude Code. Windows refuses a non-empty HKLM\SOFTWARE\Policies\ClaudeCode\Settings.
CursorMachine policyCursor enterprise hooks
GitHub CopilotMachine policy%ProgramData%\GitHub\Copilot\policy.d, plus a per-user hook runtime
OpenCodeMachine policy%ProgramData%\opencode loads the managed plugin, plus a per-user hook runtime. Falls back to the per-user plugin while the managed plugin is not in force
Antigravity, Devin, HermesPer userThe guardian registers defenseclaw-hook.exe in each user's agent config
AmpPer userThe guardian registers an in-agent plugin that calls the gateway after the listener proves it can derive the user's credential
KiroACPManaged through defenseclaw-gateway enterprise acp. See ACP guard. The guardian does not enroll Kiro on Windows: kiro-cli.exe records its version nowhere DefenseClaw can read without running it.
OpenHands, OmniGent, OpenClaw, ZeptoClawNot managedThe enumerator writes no targets for them, so they are not protected. A target manifest row that names one is refused with a reason.

Windows handles machine policy differently from Linux and macOS. See Machine policy and Foreign-hook guard.

Upgrades and downgrades

Run /ensure with the newer Setup. It upgrades in place and keeps the config and state. /ensure refuses to install an older version (downgrade_refused). See Upgrade and Roll back. For failed runs, see Lifecycle error codes.