Security Compliance Auditing with Claude Code Hooks Automation
Claude Code hooks let you automate security compliance auditing by intercepting every shell command before it runs and logging it to an append-only audit file — guaranteed, regardless of what the model decides. Unlike asking Claude to keep a log (which it may or may not do), a PreToolUse hook runs deterministically every single time, making it the right tool for audit trails, policy enforcement, and compliance workflows.
What Are Claude Code Hooks and Why Do They Matter for Security?
Claude Code hooks are user-defined shell commands, HTTP requests, MCP tool calls, or prompt-based evaluations that execute automatically at specific points in Claude Code's lifecycle. The critical distinction for security work is this: hooks guarantee deterministic behavior — they always run regardless of what the model decides.
This is fundamentally different from instructing Claude in a system prompt to "always log commands" or "never touch .env files." Natural language instructions influence Claude probabilistically. Hooks enforce policies with hard guarantees. For compliance auditing, that difference is everything.
Each hook targets a specific lifecycle event:
- PreToolUse — fires before a tool runs; can block the action
- PostToolUse — fires after a tool completes; useful for logging and follow-up
- SessionStart — fires when a session begins
- Notification — fires when Claude needs user input
For security and compliance use cases, PreToolUse is your primary event. It intercepts actions before they happen, giving you the ability to log, inspect, and block — all before any side effects occur.
You can learn more about the full hook system in the official hooks reference.
How Does a Security Audit Hook Actually Work?
When a hook fires, Claude Code passes contextual data to your hook command via standard input as JSON. For a Bash tool invocation, this includes the tool name and its inputs — meaning your hook receives the exact command Claude is about to run.
Your hook command can then:
- Silently allow the action by exiting with code 0
- Block the action with an explanatory message by exiting with code 2
- Inject additional context into Claude's next turn via stdout
For a compliance audit log, the flow is straightforward: the hook receives the command JSON, extracts the command string, appends it to an audit file, and exits with code 0 to allow the command to proceed. The result, as the source material describes it, is "a complete, tamper-resistant record of all shell commands executed during the session, which can be reviewed for security audits or debugging."
How Do You Set Up a Bash Command Audit Log with Hooks?
Here is a step-by-step walkthrough for creating a persistent audit log of every shell command Claude Code executes. This is a beginner-level configuration that provides immediate compliance value.
- Install Claude Code and ensure you are on a supported plan (Pro, Max, Team, or Enterprise).
- Open your terminal and start a Claude Code session.
- Run
/hooksinside Claude Code to open the interactive hooks configuration interface. - Select the
PreToolUseevent — this fires before any tool runs. - Set the matcher to
Bashso the hook only fires for shell commands. - Choose User settings if you want the audit log to apply across all projects, or Project settings for a single repository.
- Enter your handler command — a shell one-liner that reads the incoming JSON from stdin, extracts the command field, and appends it to your audit file.
- Save and restart your Claude Code session. Run a task that uses shell commands, then inspect your audit log file.
Alternatively, you can edit the JSON settings file directly. For user-level hooks, edit ~/.claude/settings.json; for project-level hooks, edit .claude/settings.json in your project root. Add your hook definition under the hooks key. Note that direct file edits require a session restart to take effect — Claude Code does not hot-reload hook configurations during an active session, which is itself a security measure against malicious hook injection.
See the getting started guide for Claude Code hooks for additional configuration examples.
How Do You Block Dangerous Commands Before They Execute?
Logging is reactive. For proactive compliance enforcement, you can configure a PreToolUse hook to block specific commands entirely before they run. The hook inspects the incoming command, applies your policy rules, and exits with code 2 if the command violates policy — returning an explanatory message that Claude Code surfaces to the user.
Common blocking use cases include:
- Preventing writes to sensitive files like
.env,package-lock.json, or anything inside.git/ - Blocking network calls to external hosts in CI/CD pipelines
- Preventing destructive operations in production environments
- Enforcing an allowlist of approved commands for regulated workflows
The key architectural point: use PreToolUse for blocking, never PostToolUse. PostToolUse hooks run after the tool has already executed, so they cannot reverse file writes, command executions, or other side effects. If you need to prevent an action, you must intercept it before it happens.
When Should You Use Hooks vs. Built-In Permission Settings?
| Scenario | Use Hooks | Use Built-In Permission Settings |
|---|---|---|
| Block all Bash commands unconditionally | ✓ Simpler, no hook needed | |
| Block Bash only when command matches a pattern | ✓ Conditional logic on tool inputs | |
| Log every command to an audit file | ✓ Guaranteed execution, append-only log | |
| Broadly deny an entire tool category | ✓ Built-in allow/block lists handle this | |
| Auto-approve safe operations in CI/CD | ✓ Deterministic rules per invocation | |
| Influence Claude's behavior with guidelines | ✓ System prompt instructions (probabilistic) |
The core principle: use hooks when you need guaranteed, deterministic execution based on the content of a tool invocation. Use built-in permission settings when you want to broadly allow or deny entire tool categories without conditional logic.
What Are the Most Important Pitfalls to Avoid?
Mixing exit codes and JSON stdout
Choose exactly one communication strategy per hook: either use exit codes with a plain stderr message, or exit 0 with a valid JSON object on stdout for structured control. When you exit with code 2 to block an action, Claude Code ignores any JSON on stdout entirely. Debug output must always go to stderr — if your hook prints arbitrary text to stdout when Claude Code expects JSON, the parser will fail silently.
Using PostToolUse to undo actions
PostToolUse hooks cannot reverse file writes or command executions. They run after the fact. For any enforcement or blocking logic, always use PreToolUse.
Forgetting to restart after direct file edits
If you edit ~/.claude/settings.json or .claude/settings.json directly, you must restart your Claude Code session for changes to take effect. Changes made via the /hooks interface apply to new sessions automatically.
Long-running hooks blocking the UI
By default, hooks run synchronously and Claude Code waits for them to complete. For hooks that run compilation, test suites, or external API calls, use the async option in your hook definition so the hook runs in the background without freezing the interface.
How Do Hooks Fit into CI/CD and Autonomous Workflows?
One of the most powerful compliance applications is running Claude Code in headless CI/CD pipelines. In non-interactive mode, a PreToolUse hook can evaluate whether a proposed tool invocation is safe to auto-approve based on deterministic rules — for example, allowing read operations while blocking network calls to external hosts. This enables autonomous operation without requiring a human to approve every step, while still maintaining a complete audit trail.
For teams distributing compliance hooks across multiple projects, hooks can now be bundled into Claude Code Plugins — shareable packages that install with a single command. This means your security team can publish a compliance hook bundle that developers install project-wide, ensuring consistent audit logging and policy enforcement without manual configuration on each machine.
Is Hooks-Based Compliance Auditing Worth the Setup Effort?
For any team using Claude Code in environments with security requirements — regulated industries, enterprise deployments, or projects with sensitive data — the answer is yes. The setup is lightweight (a few lines of JSON and a shell command), but the guarantees are strong: every shell command Claude executes is logged, every sensitive file write can be blocked, and every policy violation is caught before it happens.
The alternative — relying on Claude to follow natural language instructions about security — is probabilistic by nature. Hooks are not. That determinism is what makes them the right foundation for compliance automation, not just a convenience feature.
For the complete hook schema, event reference, and advanced configuration options, see the Anthropic hooks documentation.
Frequently asked questions
What is a PreToolUse hook in Claude Code?
A PreToolUse hook is a user-defined command that fires automatically before any tool runs in Claude Code. It receives the tool name and inputs as JSON, and can allow the action (exit code 0), block it with a message (exit code 2), or inject context into Claude's next turn.
Can Claude Code hooks create a tamper-resistant audit log?
Yes. A PreToolUse hook on the Bash tool can intercept every shell command Claude attempts to run and append it to an audit file before the command executes. Because hooks run deterministically regardless of model decisions, the log is complete and cannot be bypassed by Claude.
What plans support Claude Code hooks?
Hooks are available on Pro, Max, Team, and Enterprise plans. You need to install Claude Code and be on one of these supported plans to configure and use hooks.
Can I use a PostToolUse hook to undo a file write?
No. PostToolUse hooks run after the tool has already executed, so they cannot reverse file writes or other side effects. Use PreToolUse hooks to validate and block actions before they happen.
How do I block writes to sensitive files like .env using hooks?
Configure a PreToolUse hook targeting Edit, MultiEdit, and Write tools. In your hook command, inspect the target file path from the incoming JSON. If the path matches sensitive files, exit with code 2 and return an explanatory message to prevent Claude from modifying those files.
Do hook changes take effect immediately after editing the settings file?
No. Direct edits to settings files require a Claude Code session restart to take effect. This is a deliberate security measure. Changes made through the /hooks interactive interface apply to new sessions automatically.
Can hooks be shared across a team?
Yes. Hooks can be bundled into Claude Code Plugins, which are shareable packages that install with a single command. This allows security teams to distribute compliance hooks consistently across projects and team members.
Hooks is one of 85 features in Claude Master — the independent, continuously updated manual with worked examples, the pitfalls, and the workflows that put Claude to work.
Get Claude Master — founding price →Independent product. Not affiliated with or endorsed by Anthropic. "Claude" is a trademark of Anthropic, used here only to describe the subject of this guide.