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
| Requirement | Detail |
|---|---|
| Windows | Native 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 7 | A 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 mode | PowerShell FullLanguage mode. Under a WDAC or AppLocker script policy, allow the DefenseClaw signer, or the run stops with powershell_constrained_language. |
| Privileges | An elevated administrator token, or SYSTEM (for example an MDM agent). |
| Other profiles | No 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.
| Item | Path |
|---|---|
| Binaries | C:\Program Files\Cisco\DefenseClaw\bin (defenseclaw.exe, defenseclaw-gateway.exe, defenseclaw-hook.exe, defenseclaw-acp.exe, defenseclaw-sensor-helper.exe) |
| Lifecycle scripts | C:\Program Files\Cisco\DefenseClaw\libexec (install-enterprise.ps1, DefenseClawEnterprise.psm1) |
| Config | C:\ProgramData\Cisco\DefenseClaw\etc\config.yaml |
| Secrets | C:\ProgramData\Cisco\DefenseClaw\secrets |
| Target manifest | C:\ProgramData\Cisco\DefenseClaw\hook-guardian\targets.yaml (the enumerator writes it) |
| Lifecycle state | C:\ProgramData\Cisco\DefenseClaw\install |
| Gateway data | C:\ProgramData\Cisco\DefenseClaw\runtime |
| Authorization ledger | C:\ProgramData\Cisco\DefenseClaw\hook-guardian-state |
| Service logs | C:\ProgramData\Cisco\DefenseClaw\logs |
| Hook runtime | C:\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:
| Registration | Value |
|---|---|
| Deployment marker | HKLM\SOFTWARE\Cisco\DefenseClaw\Enterprise, with Profile, ProductVersion, InstallRoot, StateRoot, TrustMode, UpdatedAt and DisableSelfUpdate |
| Add/Remove Programs | HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CiscoDefenseClawEnterprise, shown as "Cisco DefenseClaw Enterprise" |
| Event log | The 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 policy | HKLM\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:
| Service | Identity | Role |
|---|---|---|
DefenseClawGateway | NT SERVICE\DefenseClawGateway, with SeChangeNotifyPrivilege only | Runs the policy engine and the hook API on 127.0.0.1:18970 |
DefenseClawSensorHelper | LocalSystem, with SeChangeNotifyPrivilege only | Answers the gateway's fixed AI Discovery requests |
DefenseClawHookGuardian | LocalSystem, with a fixed privilege list | Writes and repairs each enrolled user's hook registrations, using that user's token |
DefenseClawHookEnumerator | LocalSystem, with the same privilege list | Finds eligible profiles (local, domain and Microsoft Entra ID accounts) and writes the target manifest |
The Service Control Manager restarts each service after a failure.
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.txtandchecksums.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_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:
| Code | Meaning |
|---|---|
0 | Success, or nothing to do |
1603 | Failure. 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. |
1618 | Another lifecycle run holds the lock. Retry later. |
1639 | Invalid 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. |
3010 | Reserved. 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.
| Property | Meaning |
|---|---|
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=1 | With /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=1 | Print the result document on standard output |
NOSTART=1 | Install or update with the services stopped and disabled. A later /repair starts them. |
PURGE=1 | With /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:
enterprise:
profile: standalone
inspection:
ai_defense:
enabled: true
credential: ai-defense-api-keyThen 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 --jsonstatus 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:
| Field | Healthy value |
|---|---|
ok | true |
installed, installed_version | true and the version you deployed |
readiness | gateway, guardian, enumerator and sensor_helper all true |
coverage_complete | true: installed, the guardian is ready, and no transaction is pending |
security_complete | true: see below |
enrollment.targets | The number of entries (one per user and connector) in the target manifest. 0 means nobody is protected yet. |
errors | Empty |
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:
-
Install.
security_completeisfalseat this point. -
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.jsonlenterprise policy verify --liveis not available on Windows; see Inspect machine policy. -
Record the attestation from an elevated PowerShell 7 session:
& $Cli enterprise windows repair --profile standalone --attest-claude-effective-policy --jsonThe 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:
& '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 --applicationAn 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:
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' audit export --connector claudecode -o C:\Temp\audit-claudecode.jsonlOn 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:
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise policy show
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise policy verifyshow 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:
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-unsignedcertification 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 action | What happens |
|---|---|
install.ps1 | Refuses when the marker key exists, or when DisableSelfUpdate under HKLM\SOFTWARE\Policies\Cisco\DefenseClaw is nonzero |
defenseclaw upgrade, defenseclaw rollback | Refuse when the marker key exists |
| Per-user gateway | Refuses 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=1Or with the installed CLI:
& 'C:\Program Files\Cisco\DefenseClaw\bin\defenseclaw.exe' enterprise windows uninstall --profile standalone --jsonUninstall 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:
| Mode | How a file is trusted |
|---|---|
authenticode | Every binary and script carries an Authenticode signature that Windows reports as Valid. An allowed-signer list narrows the accepted signer certificates. |
hash_pinned | Every 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 point | Trust used | How to change it |
|---|---|---|
| Standalone Setup | Chosen 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 windows | authenticode | --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' `
--jsonFor 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
| Connector | Route on Windows | Notes |
|---|---|---|
| Codex | Machine policy | Codex requirements file. DefenseClaw always sets allow_managed_hooks_only = true, and an administrator value of false makes the run fail. |
| Claude Code | Machine policy | Managed-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. |
| Cursor | Machine policy | Cursor enterprise hooks |
| GitHub Copilot | Machine policy | %ProgramData%\GitHub\Copilot\policy.d, plus a per-user hook runtime |
| OpenCode | Machine 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, Hermes | Per user | The guardian registers defenseclaw-hook.exe in each user's agent config |
| Amp | Per user | The guardian registers an in-agent plugin that calls the gateway after the listener proves it can derive the user's credential |
| Kiro | ACP | Managed 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, ZeptoClaw | Not managed | The 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.
Enterprise threat model
Who DefenseClaw trusts, where each trust boundary sits on Windows, Linux and macOS, what a standard user can and cannot do, and which risks remain in the standalone enterprise profile.
Linux standalone deployment
Install the standalone DefenseClaw enterprise services on Linux from the deb or rpm package or the payload tarball, check the result, and remove them.