How to check CLAUDE.md rules on every tool call with a Claude Code prompt hook
Rules in CLAUDE.md are something Claude reads and tries to follow, with no guarantee it will. A Claude Code hook with type: "prompt" has a small model check each matching tool call against your rule and block or allow it. It suits rules that are hard to express in a shell script, such as "commit messages follow Conventional Commits".
- Add a PreToolUse hook to your project's
.claude/settings.json. Theiffilter means the model is only called forgit commit.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "prompt",
"if": "Bash(git commit *)",
"prompt": "This is the command Claude wants to run: $ARGUMENTS\nIf the commit message does not follow Conventional Commits (feat:, fix:, docs: and so on), set ok to false and put what to fix in reason.",
"continueOnBlock": true
}
]
}
]
}
}
- When Claude tries to commit with a message that breaks the format, the model returns
{"ok": false, "reason": "..."}and the call is blocked. WithcontinueOnBlockset totrue, the reason goes back to Claude as the tool error, and Claude fixes the message and commits again. With the default (false), the turn ends and only a warning line appears in the chat.
$ARGUMENTS in prompt is replaced with the hook input JSON (tool name, command and so on); if you leave it out, the input is appended to the prompt. By default the decision is made by the model Claude Code uses for background functionality (the haiku alias, changed with ANTHROPIC_DEFAULT_HAIKU_MODEL), and you can set a model field per hook. The default timeout is 30 seconds.
The hook runs every time, but a model makes the call, so it can be wrong. Keep rules that must never be broken, like no reading .env, in permission deny rules or command hooks. Without if, every Bash call gets an extra model call, which slows things down and adds usage. The same approach on a Stop hook can check that all tasks are done before Claude stops. If the check needs to read files over several turns, use type: "agent" (experimental).
Sources
Get notified when a new tip lands
Tip alerts only go out in the app. Install it and turn notifications on.