- Hooks provide deterministic control over Claude Code's lifecycle, ensuring specific commands always execute reliably without exceptions.
- Unlike prompt-based instructions that may sometimes fail, hooks guarantee consistent behavior, such as auto-formatting or logging, after specific events.
- They are primarily used to enforce hard rules, block dangerous operations, or automate routine tasks, making Claude Code behavior predictable and secure.
Hooks in Claude Code
- Hooks are deterministic commands that run automatically at defined points in Claude Code's lifecycle, guaranteeing execution every time.
- Configure hooks in your
settings.jsonfile by selecting an event, optionally defining amatcherfor applicable tools, and providing a command to run. - Common hook events include
User prompt submit,Pre-tool use,Post tool use,Notification, andStop. Post tool usehooks are ideal for tasks like auto-formatting files after edits (e.g., using Prettier for TypeScript) or logging all executed commands for compliance.Pre-tool usehooks can block dangerous operations by receiving tool input viastdin; exiting with code2blocks the action with feedback, while0allows it to proceed.- Use
Pre-tool useto enforce critical rules, such as blocking writes to production directories or preventing specificbashcommands likerm -rf. - Project-level hooks configured in
settings.jsoncan be committed to your repository, ensuring consistent behavior across your entire team. - Reference scripts stored in your project within hook commands using the
claude project durenvironment variable to ensure they work regardless of Claude Code's current working directory.
Hooks — Deterministic commands that run automatically at specific points in Claude Code's lifecycle, guaranteeing execution without fail.
Deterministic — In the context of hooks, meaning they always run without exception, ensuring reliable automation of tasks.
Claude Code (or Claude) — The AI assistant or platform that executes commands and uses tools, whose behavior hooks control.
settings.json — A configuration file where project-level hooks and their parameters are defined.
Matcher — An optional condition or filter used in hook configuration to specify which tools or events a hook applies to (e.g., edit or multi-edit).
Tool call — An instance where Claude Code invokes an external tool or function as part of its operation.
stdin — Standard input; a channel through which a program receives input data, used by hooks to get context like tool name and input.
Exit code — A numerical value returned by a process to its parent upon termination; in Pre-tool use hooks, 0 means proceed, while 2 means block the action.
Lifecycle — The sequence of stages that an application or process goes through from initiation to completion, at different points of which hooks can be triggered.
Hooks let you run commands at different points in Claude Code's life cycle. The key difference between hooks and everything else we covered is that hooks are deterministic. They always run. So, put it this way. You can tell claude in your CLAUDE.md file to run prettier after every file edit. And most of the time it will do that. But sometimes it won't. It's not perfect, but a hook makes it happen every single time with no exceptions. Common use cases could include auto formatting after file edits, logging all executed commands for compliance, blocking dangerous operations like modifying production files, and sending yourself notifications when Claude finishes a task. Hooks are configured in your settings.json file. You pick an event, optionally set a matcher for which tools it applies to, and provide a command to run. User prompt submit runs when you submit a prompt before Claude processes it. Pre-tool use, which runs before a tool call. Post tool use runs after a tool call completes. Notification runs when Claude sends a notification. And stop runs when Claude finishes responding. The most common hook auto formatting after edit. You set a post tool use hook with a matcher of edit or multi-edit, right? So it fires whenever cla modifies a file. The command checks the file extension and runs the appropriate formatter. This could be prettier for TypeScript, go format for Go, rough for Python, whatever your project uses. Pre-tool use hooks can block tool calls before they execute. So your hook receives the tool name and input as JSON on stdin. If it exits with code two, the action is blocked and the std error message gets fed back to cla feedback. So Claude knows why it was blocked and can adjust. Exit code zero means proceed. Exit code 2 means block. This is how you enforce hard rules. Block writes to a production config directory. block bash commands that contain rm-rf block commits domain whatever your team needs to be guaranteed not suggested hooks configured include/ settings.json JSON are project level and can be checked into your repo. This means that your entire team gets the same hooks automatically. Use the claude project dur environment variable in your command set reference scripts stored in your project so they work regardless of claw's current working directory. Hooks gives you deterministic control over Claude Code behavior. Use post tool use for auto formatting and logging. Use pre-tool use to block dangerous operations. Configure them in the /hooks or in settings.json and check them into your repository so your team gets them too. If something needs to happen every time without fail, don't put it in a prompt. Put it in a hook.
TL;DR
- Hooks provide deterministic control over Claude Code's lifecycle, ensuring specific commands always execute reliably without exceptions.
- Unlike prompt-based instructions that may sometimes fail, hooks guarantee consistent behavior, such as auto-formatting or logging, after specific events.
- They are primarily used to enforce hard rules, block dangerous operations, or automate routine tasks, making Claude Code behavior predictable and secure.
Takeaways
- Hooks are deterministic commands that run automatically at defined points in Claude Code's lifecycle, guaranteeing execution every time.
- Configure hooks in your
settings.jsonfile by selecting an event, optionally defining amatcherfor applicable tools, and providing a command to run. - Common hook events include
User prompt submit,Pre-tool use,Post tool use,Notification, andStop. Post tool usehooks are ideal for tasks like auto-formatting files after edits (e.g., using Prettier for TypeScript) or logging all executed commands for compliance.Pre-tool usehooks can block dangerous operations by receiving tool input viastdin; exiting with code2blocks the action with feedback, while0allows it to proceed.- Use
Pre-tool useto enforce critical rules, such as blocking writes to production directories or preventing specificbashcommands likerm -rf. - Project-level hooks configured in
settings.jsoncan be committed to your repository, ensuring consistent behavior across your entire team. - Reference scripts stored in your project within hook commands using the
claude project durenvironment variable to ensure they work regardless of Claude Code's current working directory.
Vocabulary
Hooks — Deterministic commands that run automatically at specific points in Claude Code's lifecycle, guaranteeing execution without fail.
Deterministic — In the context of hooks, meaning they always run without exception, ensuring reliable automation of tasks.
Claude Code (or Claude) — The AI assistant or platform that executes commands and uses tools, whose behavior hooks control.
settings.json — A configuration file where project-level hooks and their parameters are defined.
Matcher — An optional condition or filter used in hook configuration to specify which tools or events a hook applies to (e.g., edit or multi-edit).
Tool call — An instance where Claude Code invokes an external tool or function as part of its operation.
stdin — Standard input; a channel through which a program receives input data, used by hooks to get context like tool name and input.
Exit code — A numerical value returned by a process to its parent upon termination; in Pre-tool use hooks, 0 means proceed, while 2 means block the action.
Lifecycle — The sequence of stages that an application or process goes through from initiation to completion, at different points of which hooks can be triggered.
Transcript
Hooks let you run commands at different points in Claude Code's life cycle. The key difference between hooks and everything else we covered is that hooks are deterministic. They always run. So, put it this way. You can tell claude in your CLAUDE.md file to run prettier after every file edit. And most of the time it will do that. But sometimes it won't. It's not perfect, but a hook makes it happen every single time with no exceptions. Common use cases could include auto formatting after file edits, logging all executed commands for compliance, blocking dangerous operations like modifying production files, and sending yourself notifications when Claude finishes a task. Hooks are configured in your settings.json file. You pick an event, optionally set a matcher for which tools it applies to, and provide a command to run. User prompt submit runs when you submit a prompt before Claude processes it. Pre-tool use, which runs before a tool call. Post tool use runs after a tool call completes. Notification runs when Claude sends a notification. And stop runs when Claude finishes responding. The most common hook auto formatting after edit. You set a post tool use hook with a matcher of edit or multi-edit, right? So it fires whenever cla modifies a file. The command checks the file extension and runs the appropriate formatter. This could be prettier for TypeScript, go format for Go, rough for Python, whatever your project uses. Pre-tool use hooks can block tool calls before they execute. So your hook receives the tool name and input as JSON on stdin. If it exits with code two, the action is blocked and the std error message gets fed back to cla feedback. So Claude knows why it was blocked and can adjust. Exit code zero means proceed. Exit code 2 means block. This is how you enforce hard rules. Block writes to a production config directory. block bash commands that contain rm-rf block commits domain whatever your team needs to be guaranteed not suggested hooks configured include/ settings.json JSON are project level and can be checked into your repo. This means that your entire team gets the same hooks automatically. Use the claude project dur environment variable in your command set reference scripts stored in your project so they work regardless of claw's current working directory. Hooks gives you deterministic control over Claude Code behavior. Use post tool use for auto formatting and logging. Use pre-tool use to block dangerous operations. Configure them in the /hooks or in settings.json and check them into your repository so your team gets them too. If something needs to happen every time without fail, don't put it in a prompt. Put it in a hook.