AI / GenAI  /  Claude Code

๐Ÿ“„ Claude Code (CLAUDE.md) Guide 4 of 4 16 guides ยท updated 2026

Writing effective CLAUDE.md files โ€” project memory, conventions, permissions, hooks, and the team practices that keep AI coding agents genuinely useful.

Hooks: Automating Behavior Around Claude Code

CLAUDE.md and permissions both shape how Claude Code reasons and what itโ€™s allowed to do. Hooks are a third mechanism entirely โ€” deterministic shell commands that fire automatically in response to specific events during a session, independent of what the model decides to do at all.


Why Hooks Exist

Some things you want to happen every single time a certain event occurs, with zero chance of the agent forgetting or deciding itโ€™s not necessary this time โ€” running a formatter after every file edit, blocking a specific dangerous command pattern outright, or logging every tool call for audit purposes. Asking the agent nicely in CLAUDE.md (โ€œplease run the formatter after editing filesโ€) is advisory; a hook makes it happen unconditionally, enforced by the harness itself rather than by the modelโ€™s judgment.


The Basic Shape

Hooks are configured in .claude/settings.json, tied to specific event types:

{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\""
}
]
}
]
}
}

This runs Prettier automatically on any file the agent edits or writes, every time, without needing the agent to remember to do it or CLAUDE.md to remind it. The formatter runs regardless of whether the current instruction even mentioned formatting.


Common Hook Events

PreToolUse โ€” fires before a tool call executes, and can block it outright (useful for hard-blocking a dangerous command pattern that a permission deny rule doesnโ€™t already cover, or for validation specific to your project).

PostToolUse โ€” fires after a tool call completes, commonly used for auto-formatting, auto-linting, or triggering a follow-up action like re-running affected tests.

Session-level events (start/stop) โ€” useful for one-time setup at the start of a session, or cleanup/notification at the end.

The exact event names and matcher syntax are part of Claude Codeโ€™s hooks configuration reference โ€” the pattern above illustrates the shape, not an exhaustive list of every available event.


Hooks vs CLAUDE.md: A Clear Division

<!-- CLAUDE.md โ€” advisory, the agent decides whether/how to apply it -->
## Conventions
- Run the formatter before committing changes.
<!-- hooks โ€” deterministic, happens regardless of agent judgment -->
"PostToolUse": [{ "matcher": "Edit|Write", "hooks": [{ "type": "command",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\"" }] }]

If an outcome genuinely must happen every time with no exceptions, a hook is the right tool โ€” it doesnโ€™t rely on the instruction being read, remembered, or judged applicable in the moment. If itโ€™s guidance that benefits from judgment (when to apply a convention, how to interpret an edge case), thatโ€™s what CLAUDE.md and the modelโ€™s reasoning are for.


A Practical Example: Blocking a Dangerous Pattern

{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "scripts/check-safe-command.sh"
}
]
}
]
}
}

A small script here can inspect the proposed command and exit non-zero to block it โ€” a hard, scriptable guarantee that goes beyond what a CLAUDE.md warning or even a permission deny pattern can express when the logic needed is more nuanced than a simple pattern match (e.g., โ€œblock force-push only if the target branch is mainโ€).


Common Mistakes

Using CLAUDE.md instructions for things that need hard guarantees. If a formatter run, a specific validation, or a blocked command pattern must happen with zero exceptions, encode it as a hook โ€” relying on the agent to remember and apply a written instruction every time is a weaker guarantee than a hook enforced by the harness.

Overusing hooks for things that benefit from judgment. Not everything should be a rigid, unconditional hook โ€” conventions that genuinely require contextual judgment (when a particular pattern applies, how to handle an edge case) are better served by CLAUDE.md guidance the agent can reason about, not a blunt script that canโ€™t account for nuance.

Writing hooks that are slow or fragile enough to disrupt the workflow theyโ€™re meant to support. A PostToolUse formatter hook that takes many seconds on every single edit, or that fails loudly on files it doesnโ€™t understand, creates more friction than the automation saves โ€” hooks should be fast and robust for the common case.

Frequently Asked Questions

Do hooks run even if the agent doesnโ€™t โ€œwantโ€ to trigger them? Yes โ€” thatโ€™s the point. Hooks are triggered by the harness based on matching tool events, independent of the modelโ€™s own decision-making, which is exactly what makes them suitable for guarantees CLAUDE.md alone canโ€™t provide.

Can hooks reference CLAUDE.md content? Not directly โ€” hooks are shell commands operating on tool-event data (like the file path being edited), not aware of CLAUDE.mdโ€™s prose content; the two systems are complementary but donโ€™t read from each other.

Should every project have hooks configured? Not necessarily โ€” hooks add real value for teams with specific, repeatable, zero-exception automation needs (formatting, validation, blocking specific patterns); a smaller project relying primarily on CLAUDE.md guidance and normal permission prompts is a completely reasonable setup without them.

Summary

Hooks are the deterministic-enforcement layer in Claude Codeโ€™s configuration surface โ€” where CLAUDE.md informs and permissions gate, hooks guarantee. Reach for a hook specifically when an outcome needs to happen every time with no dependency on the agentโ€™s judgment or memory; keep genuinely judgment-dependent guidance in CLAUDE.md, where the modelโ€™s reasoning is actually the right tool for the job.