Claude Code
Installing the Agent Firewall for Claude Code, and what its hooks can and cannot see
Claude Code is the agent the firewall sees the most of. The firewall installs as a set of Claude Code hooks (PreToolUse, PostToolUse, UserPromptSubmit, SessionStart and ConfigChange). Tested with Claude Code 2.1.289; the event formats were captured live from the installed CLI.
Install
launchsafe-firewall install
launchsafe-firewall doctor
launchsafe-firewall doctor --fix # turn on Claude Code's sandbox with a profile from your policy (passphrase)install asks for an approval passphrase, registers the hooks in ~/.claude/settings.json and pins the approver key in the hook command. Use --scope project|local for the project's files. For a machine you administer, use install --managed so no repository can switch the hooks off. See the Quickstart.
When an action needs you
Claude Code can ask. An action that needs a person appears in the agent's permission prompt, with the firewall's reason and rule id. When nobody can answer (claude -p, CI, dontAsk mode), the action is held in the queue with the command that approves it.
How the hooks decide
PreToolUsereturnsallow,denyorask. Across hooks the most restrictive wins, and a hookallownever overrides your owndenyoraskrules, so the firewall can only tighten.- Only exit code 2 or an explicit JSON
denyblocks a tool. Exit 1, a crash, a missing script and a timeout all let the tool run. The firewall therefore catches its own errors and the installed command is wrapped... || exit 2, so even a failure of Node itself fails closed. - Claude Code sends
mcp_server: { name, source }onPreToolUse. A server whose source isproject,dynamicorunknownis untrusted whatever its name, unless your own policy lists it by exact name. - Claude Code can replace tool output, so the firewall can redact secrets and the email guard can keep a withheld message from the model. Codex, Gemini CLI and Cursor cannot do this.
- A change made outside the agent mid-session is blocked by
ConfigChange.
What the hooks cannot do
- Files pulled into a prompt with
@do not pass throughPreToolUse. The firewall cannot see those, so it cannot taint on them. Treat an@-included file as trusted input you chose. - A repository's own
.claude/settings.jsoncan setdisableAllHooks, and in a-prun a repository's settings hooks load without the trust dialog. Only managed settings resist this.doctorchecks for it and can generate a managed-settings install (withallowManagedHooksOnly) so no user or project setting can switch the firewall off. - Hooks are an enforcement point, not a cage. They decide whether a tool runs; they do not contain a process that does run. Run the firewall together with Claude Code's OS sandbox.
doctor --fixwrites a sandbox profile derived from your policy, behind the approval passphrase. - The sandbox sees hosts, not methods. A host admitted for fetching (
registry.npmjs.org,github.com,pypi.org) is reachable for uploads too.doctorlabels such hosts upload-capable. Uploading to them is controlled by the firewall's rules for the commands it can see (git push,npm publish,gh,docker push).
Managed settings
Managed settings files live at /Library/Application Support/ClaudeCode/managed-settings.json (macOS) and /etc/claude-code/managed-settings.json (Linux). A project's disableAllHooks: true turns off user-level hooks; only managed settings resist it, and allowManagedHooksOnly restricts which hooks run at all.
launchsafe-firewall install --managed --print | sudo tee "/Library/Application Support/ClaudeCode/managed-settings.json"The sandbox profile
launchsafe-firewall doctor --fix writes the sandbox key of ~/.claude/settings.json (--scope project|local for the project's files) and, for package managers it finds, a release-age cooldown in their user-level config, each after a backup and a diff you confirm. doctor --fix --dry-run prints every change without asking for anything. From then on an agent change that weakens the sandbox profile is blocked like removing the firewall's hooks (policy sandbox.protectInstalledProfile). See Policy.