Claude Code
Claude Code connector wires the documented lifecycle hook set plus native OTel. Thirteen current events can return block decisions, and PreToolUse supports native HITL ask.
The Claude Code connector wires DefenseClaw into Anthropic's documented hook surfaces without inserting a proxy in the data path. Claude Code talks directly to its native upstream; DefenseClaw inspects via hooks + native OTel.
The Claude Code connector is hook-only. There is no LLM-proxy data path — Claude Code talks directly to api.anthropic.com and DefenseClaw observes via hooks + native OTel.
mode=action is supported on Claude Code's declared blocking hook events.
PreToolUse can return deny or native ask before the tool. Post-result events
are advisory: they preserve findings and shadow would_block telemetry without
stopping Claude's next turn. No proxy listener is involved.
Platform support
| Platform | Status | Connector path |
|---|---|---|
| macOS and Linux | Supported | Portable command hooks plus Claude Code's native OTel exporter. |
| Native Windows x64 | Supported | Shell-free native executable hooks using Claude Code's command plus args exec form. Official-client validation metadata remains empty and live=false; support availability is not a certification claim. |
Setup
defenseclaw setup claude-code # observe (default) — record only
defenseclaw setup claude-code --mode action # block on policy hits via PreToolUse denyDefenseClaw installs the portable Claude Code hook and configures the native OTel exporter in the user settings.
defenseclaw setup claude-code # observe (default) — record only
defenseclaw setup claude-code --mode action # block on policy hits via PreToolUse denyInstall and run Claude Code directly from PowerShell or CMD using Anthropic's
native setup. DefenseClaw registers
the protected defenseclaw-hook.exe through Claude Code's shell-free
command plus args exec form. Git for Windows is recommended upstream when
Claude should use its Bash tool, but it is optional; without it Claude uses its
native PowerShell tool. Git for Windows is not part of the DefenseClaw hook
contract. WSL, Git Bash, Cygwin, MSYS, containers, and virtual machines are
outside this native connector path.
setup claude-code is the dedicated Claude Code setup alias. It uses the same
setup backend as setup guardrail, adds or reconfigures claudecode, wires
hooks + native OTel, and can join an existing hook-connector roster when you
choose Add. No proxy listener binds in either mode.
Native OTLP uses managed loopback exporter settings with a Claude-scoped Authorization bearer. Logs and metrics are enabled; traces are explicitly disabled. Prompt and assistant-response content logging are independent vendor opt-ins and DefenseClaw explicitly defaults both off; downstream redaction settings do not silently authorize source capture. The scoped credential cannot authenticate management or another connector and must never be printed or copied.
Redaction is configured through the v8 bucket/profile policy: edit
observability.destinations[].routes[].selector.buckets and
observability.redaction_profiles, then follow
Redaction → Verify policy.
The alias defaults to observe mode and accepts the common hook-connector
options, including --mode, --workspace, --rule-pack,
--human-approval, --hilt-min-severity, --fail-mode, --block-message,
--replace, --with-local-stack, and restart controls. Use the
quick-alias reference for that surface. Use
the full guardrail setup when you also need scanner,
detection-strategy, or judge-provider configuration. Defaults are documented
once on the Defaults page.
Files DefenseClaw will modify
DefenseClaw manages marked hooks and OTLP environment entries in
%CLAUDE_CONFIG_DIR%\settings.json; the default directory is
%USERPROFILE%\.claude. Generated runtime and protected connector credentials
live below %USERPROFILE%\.defenseclaw\hooks. See the
Windows path reference.
DefenseClaw stores a hash-checked backup of settings.json before edits.
Teardown restores it byte-for-byte when the identity still matches; if the file
drifted, only DefenseClaw-owned entries are removed.
Claude Code keeps user/local MCP registration state in ~/.claude.json
(%CLAUDE_CONFIG_DIR%\.claude.json when that override is set) and project MCP
state in <workspace>/.mcp.json; these are inventory surfaces, not hook setup
files. See Anthropic's MCP scope reference.
The current connector inventories those local, project, and user manual scopes.
Plugin-provided MCP and claude.ai connector MCP are not attributed from these
files. Marketplace plugin cache artifacts honor
CLAUDE_CODE_PLUGIN_CACHE_DIR; retained versions are not presented as active
without semantic client evidence. Managed enabledPlugins takes precedence
over user, project, and local preferences; a dynamic policyHelper is reported
as unverified instead of guessed. Skill inventory covers the launch directory,
every parent through the repository root, and existing nested
.claude/skills roots that Claude can lazily activate after file activity.
Nested skills remain discoverable-unverified until session activity proves
activation; true skills take precedence over legacy commands, and documented
skill-directory symlinks are canonicalized and de-duplicated. Recursive
user/project agents use required frontmatter identity and closest-project
precedence. Managed/plugin agents and session --agents remain unverified.
Auto-memory resolves file-based autoMemoryDirectory precedence or the shared
repository/worktree default under ~/.claude/projects/<project>/memory; it is
marked unverified when session --settings, remote settings, or native policy
could change the active path.
Runtime /add-dir roots remain outside persistent passive inventory.
Claude Code 2.1.219+ emits DirectoryAdded, so DefenseClaw records the added
path and source without treating the observation as durable discovery authority.
Enterprise (standalone profile)
In the enterprise standalone profile,
Claude Code gets machine policy instead of the per-user files above. The
managed-settings.d directory (/etc/claude-code on Linux,
/Library/Application Support/ClaudeCode on macOS,
C:\Program Files\ClaudeCode on Windows) holds 90-defenseclaw.json with the
hooks and 00-defenseclaw-version-floor.json, which sets
requiredMinimumVersion to 2.1.154, the lowest Claude Code version with a
verified DefenseClaw hook contract. Claude Code reads that setting only from
2.1.163, so builds older than 2.1.163 ignore it and this floor stops no
build; use application control to keep older builds off a host. Your own
requiredMinimumVersion wins, and a file at that name that DefenseClaw did
not write (for example the version-floor export you deploy) is yours:
DefenseClaw never rewrites or removes it. A higher-precedence source (HKLM Settings,
macOS managed preferences) has to carry the key itself, because Claude Code
builds before 2.1.242 read only that source. See
Claude Code version floor.
Hook capabilities
Block events
- UserPromptSubmit
- UserPromptExpansion
- PreToolUse
- PermissionRequest
- TaskCreated
- TaskCompleted
- TeammateIdle
- Stop
- SubagentStop
- ConfigChange
- PreCompact
- Elicitation
- ElicitationResult
Native ask events
- PreToolUse
Claude Code's post-result surfaces (PostToolUse, PostToolUseFailure,
PermissionDenied, and PostToolBatch) carry returned content rather than a
new typed action request. DefenseClaw still scans that content for trust,
secret, and PII findings, but command, path, cognitive-file, and C2 rules do
not block on literals found in the returned bytes. For example, source text
that explains rm -rf / can produce telemetry without being mistaken for a
request to execute it. If Claude later proposes that command, PreToolUse
evaluates the typed tool arguments and can deny it before execution.
A standalone PostToolUse response may also use physically verified local
source provenance to lower source-code trust findings to detection-only
telemetry. Batch, failure, denial, and mixed outputs remain untrusted content;
they are still advisory because they cannot be attributed to one executable
request safely.
Subagents and the Agent tool
Claude Code runs subagents through its Agent tool. Measured on 2.1.156, with
the hooks outside a sandbox:
- The
Agentcall gets its ownPreToolUse, and aPostToolUseonce the subagent is done. ThatPostToolUsearrives after the subagent's own hooks and itsSubagentStop, and names the subagent it ran intool_response.agentId. A backgrounded call (run_in_background) gets itsPostToolUseat launch, with statusasync_launched. AnAgentcall of an unknown subagent type gets aPostToolUseFailure. - Every hook the subagent fires (
SubagentStart, itsPreToolUse,PermissionRequest,PostToolUse,PostToolUseFailureandPostToolBatch, andSubagentStop) carries itsagent_idandagent_type. The main agent's hooks carry neither. No hook carries the ID of theAgentcall that started the subagent. - A subagent interrupted with Esc sends nothing more: no
PostToolUsefor theAgentcall, noSubagentStop,PostToolBatchorStop. A call the user refuses at Claude Code's permission prompt gets noPostToolUseeither; only thePostToolBatchof its turn lists it.
DefenseClaw records a subagent's calls under the subagent's agent ID and type,
with the main agent as parent at depth 1, also for parallel Agent calls
(Claude Code subagents cannot start subagents). Hooks without an agent_id are
the main agent's, and it keeps one agent identity while subagents run or after
one was interrupted. The correlation ledger records each subagent as caused by
the Agent call that ran it (relationship caused_by, rule
spawned-agent-tool-result). A PostToolBatch names no tool of its own. It is
recorded as a tool_batch tool record that lists its calls by tool_name and
tool_use_id, rather than as a second result of one of them.
Protection for active AGENTS.md and MEMORY.md files is similarly
context-bound. DefenseClaw accepts an active file only from an authenticated
InstructionsLoaded event that names the exact absolute, regular,
non-symlinked file. A later PreToolUse mutation is enforcement-eligible only
in that same Claude Code session and for that exact path. A file mention, a
Read call, a generic payload field, or an event from another session cannot
claim this authority. If an authenticated event names a recognized absolute
AGENTS.md or MEMORY.md path but native file identity cannot be proved,
DefenseClaw records bounded session uncertainty and fails closed only for a
statically proven mutation of the corresponding canonical instruction-file
name. Relative, malformed, and unrelated instruction loads remain ignored.
Distinct lexical same-name mutation aliases remain visible as detection-only
unless cached identity or filename-case proof establishes the exact active path.
Claude Code is one of the few connectors that supports native PreToolUse ask. HITL approvals surface inside the agent UI itself, so the operator never has to leave Claude Code to decide.
Setup is observation-only and is not registered. WorktreeCreate is not
registered because a handler replaces Claude Code's default worktree creation
and must return the new path. The exact version-selected contract registers 28
events for Claude Code >=2.1.154,<2.1.219 and 29 for >=2.1.219.
The added DirectoryAdded hook is synchronous, matcherless, bounded to 30
seconds, and observation-only: it runs after the directory is added and has no
block, ask, or decision authority.
Telemetry channels at boot
In an OpenShell sandbox
defenseclaw sandbox run claude runs Claude Code in an NVIDIA OpenShell
sandbox on Linux, or on a Mac with Apple silicon in a MicroVM of its own that
works on a copy of your folder (macOS): the
agent sees only your project folder, and DefenseClaw hooks gate every tool
call. The sandbox guide
covers setup, the session and every flag. The files below exist only in the
sandbox image; your own Claude Code configuration does not change.
- Managed tier. The hooks are in the root-owned managed policy drop-in
/etc/claude-code/managed-settings.d/50-defenseclaw.json, withallowManagedHooksOnlyset, so user and project settings cannot add hooks or switch DefenseClaw's off. The same drop-in turns off Claude Code's own sandbox (it cannot run inside OpenShell), the auto-updater, the installation checks (the image pins its own Claude Code, so there is nothing to install or update) and non-essential traffic, and sends Claude Code's OTel to DefenseClaw. The hooks fail closed and authenticate with a per-sandbox token, never the host gateway token. - Skip-permissions. On by default (the
openandbalancedpacks): Claude Code starts with--dangerously-skip-permissions.--safe, or thestrictpack, keeps its permission prompts. The sandbox's managed settings then refusebypassPermissionsfrom a flag or any settings file, and--dangerously-skip-permissions,--allow-dangerously-skip-permissionsand--permission-mode bypassPermissionsare dropped from the arguments you pass. - Model sign-in.
--llm auto(the default) sharesANTHROPIC_API_KEY, or elseCLAUDE_CODE_OAUTH_TOKEN(fromclaude setup-token), from your shell. OpenShell holds the secret, and the sandbox gets a placeholder that works only atapi.anthropic.com.--llm bedrock, andautowhen neither is set, shares a short-term Amazon Bedrock API key fromAWS_BEARER_TOKEN_BEDROCKfor the Bedrock Mantle Anthropic endpoint in--bedrock-region(default$AWS_REGION, then$AWS_DEFAULT_REGION, thenus-east-1).openshell.llmsets the choice for runs without--llm, such as theclaudeshell wrapper's. With--llm none, or when no key is found, log in inside the sandbox; that login stays in the sandbox home, where the agent can read it. - Bedrock models. Bedrock Mantle serves Claude models only under
anthropic.*ids, not Claude Code's own model names, so a Bedrock run starts onanthropic.claude-sonnet-5and maps the/modelchoices to Mantle ids: Opus toanthropic.claude-opus-4-8, Sonnet toanthropic.claude-sonnet-5and Haiku (also used for background tasks) toanthropic.claude-haiku-4-5. Pick another model with-- --model MODEL, for exampledefenseclaw sandbox run claude --llm bedrock -- --model anthropic.claude-opus-5, or type/model anthropic.claude-opus-5in the session. The banner'sModelline names the model either way. - Per-sandbox settings. Each sandbox also gets a read-only drop-in,
60-defenseclaw-run.json, that wins over the image's. It pins the model provider the run chose (and on Bedrock its models), so a repository's.claude/settings.jsoncannot send the conversation to another endpoint. It admits only the MCP servers DefenseClaw brought along from your Claude Code setup; a read-only/etc/claude-code/managed-mcp.jsonlists them, so a repository's.mcp.jsonservers never start unless the sandbox pack setsmcp.project_servers: allow.--no-mcpleaves your servers behind. - Image and verification. The image installs Claude Code 2.1.156 by
default and refuses a version without a reviewed Linux hook contract.
Verified end to end: against a mock model every required hook fired and a
blocked tool call did not run, also with hostile user and project settings
such as
disableAllHooks, and a live sandbox run showed a DefenseClaw-blocked command denied and the egress block list holding.
Disable
defenseclaw guardrail disable --connector claudecode --yes