Claude Code
Claude Code hooks: how to stop an action before it runs
A Claude Code hook is a handler that runs automatically at a fixed point in a session, such as a command, an HTTP call or a prompt. The PreToolUse hook runs before Claude uses a tool and can stop the call with exit code 2 or a deny decision, and the reason goes back to Claude.
Updated
What are Claude Code hooks?
Handlers you define that run at session events, for example before and after a tool call or when a prompt is submitted. A handler can be a shell command, an HTTP endpoint, a tool on an MCP server, a prompt evaluated by a model, or a subagent. You configure them in settings.json, by event and matcher.
What does the PreToolUse hook do?
- It runs before the tool call and receives JSON on stdin with tool_name and tool_input.
- Exit code 2 blocks the call, and the text on stderr goes to Claude as the reason.
- It can also return JSON with a permissionDecision of allow, deny, ask or defer.
- A clean exit with no output approves nothing, and the normal permission flow applies.
What does a useful hook look like?
A PreToolUse hook on Bash reads the command and blocks it when it tries to delete a whole folder, with a reason Claude can read. Another hook filters test output so only the failures reach Claude.
Hook or permission rule?
Permission rules are evaluated in the order deny, ask, allow, and the first match wins. A PreToolUse hook does not bypass them: a deny rule blocks even when the hook answered allow. In the other direction, a hook that exits with code 2 stops the call before any rule is checked, even an allow rule.
Where does a hook fall short?
- The if filter on a handler is best-effort. For a hard allow or deny, the docs point to permission rules.
- Read and Edit rules don't catch a script that opens files itself, and Bash rules only match the command text. OS-level isolation comes from the sandbox.
- For high-impact actions, OWASP also recommends human approval.
Frequently asked questions
What does exit code 2 do in a hook?
On events that can block, it stops the action and stderr becomes the reason shown to Claude. The block holds even if the hook also prints JSON.
Why doesn't my hook block when it exits with an error?
Only exit code 2 blocks. Any other error exit is non-blocking, and the action carries on.
Can a hook approve something a deny rule forbids?
No. Claude Code applies deny and ask rules whatever the PreToolUse hook returns.
Where do I configure hooks?
In settings.json at user or project level, in managed settings, in plugins, and in the frontmatter of skills and subagents. Entries from different levels are merged.
Hook or an instruction in CLAUDE.md?
Claude reads CLAUDE.md as context at session start. Anything that must be blocked whatever Claude decides belongs in a PreToolUse hook.
Sources
Further reading
Related articles
Human in the loop: when a person approves what an AI agent does
Human in the loop means a person approves an AI agent's high-impact actions before they happen. Everything else runs on its own with minimal tools and permissions, and authorization lives in the downstream systems, outside the model's judgment. That is how OWASP recommends keeping an agent with too much power in check.ReadClaude Code subagents: what they are and when to use them
A Claude Code subagent is a separate assistant with its own context window, its own system prompt and only the tools you allow it. Claude hands it a task, the subagent works on its own and sends back just a summary, so long logs and search results stay out of your main conversation.Read
Case studies
Related services
Want guardrails on your company's agents?
Tell us which actions your agents take today. We will work out together what should be blocked before it runs.
Write to us