Skip to main content

Claude Code Hooks

Claude Code Hooks
Full guide to Claude Code hooks — what hooks are, how to configure them, pre/post-tool hooks for automation, and real examples for solo builder workflows.

Claude Code hooks run deterministic actions around agent events, so teams can add checks that fire at predictable points in a Claude Code workflow.

They are useful for validation, logging, formatting, guardrails, and policy enforcement around tool use, especially when a solo builder wants repeatable automation instead of manual review.

Hooks are best for controlling one Claude Code agent through settings, matchers, scripts, JSON input, exit status, and approval gates.

Verdent fits when the work grows into a coordinated build process: several agents with defined responsibilities, shared context, review loops, and a verified outcome.

What Are Claude Code Hooks and How They Work

Claude Code hooks trigger when a Claude Code event occurs.

A hook can run a command, prompt, or agent at a defined point in the Claude Code lifecycle. Claude Code sends hook input as JSON, so the hook script can inspect details such as the event type, tool name, tool input, session context, or tool result.

Common events include:

  • PreToolUse.
  • PostToolUse.
  • SessionStart.
  • Stop.
  • Notification.

A useful mental model is simple: Claude may decide to call a tool, but the hook runs predictable logic around that event. The model can reason, but the hook executes the rule you wrote.

For example, a PreToolUse hook can inspect a Bash command before it runs. It can block unsafe patterns, require a confirmation path, or allow the command to continue. A PostToolUse hook can inspect the result after a file edit, run a formatter, record a log entry, or return a targeted failure message.

Hooks run with your user permissions. Treat them as executable code. Review hook scripts, keep them small, avoid secrets in the script body, and assume a failing hook can interrupt the developer workflow.

Pre-Tool vs Post-Tool Hooks Explained

PreToolUse runs before a tool.

It can allow, deny, or change a tool request when the hook type supports that behavior. Use it when the risk exists before execution, such as a destructive shell command, a write to a protected file, or a request that violates a project policy.

PostToolUse runs after a successful tool call. It can format, validate, log, or summarize the result. Use it when the useful signal depends on what changed, such as lint output after an edit or a compliance check after a file write.

Use pre-tool hooks for policy. Use post-tool hooks for verification.

A practical split looks like this:

  • Use PreToolUse to block rm -rf, direct edits to generated files, or commands that touch deployment credentials.
  • Use PostToolUse to run a formatter on changed files, check a narrow lint rule, or log completed tool activity.
  • Use SessionStart to prepare context, print reminders, or initialize lightweight local checks.
  • Use Stop to run final validation or summarize local changes before the session ends.
  • Use Notification for external notices when a workflow needs attention.

Keep pre-tool hooks fast because they sit in front of execution. Keep post-tool hooks focused because they can run often during active coding.

Setting Up Hooks in settings.json

Add hooks to .claude/settings.json for a shared project.

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

This configuration attaches a PreToolUse hook to the Bash tool. When Claude Code is about to use Bash, it runs .claude/hooks/check-command.sh and passes hook input to the command.

Keep scripts in version control. Review them like application code.

A clean setup usually follows this pattern:

  1. Create a .claude/hooks/ directory in the project.
  2. Add one small script for one policy, such as check-command.sh.
  3. Make the script executable with the correct file permissions.
  4. Read JSON input from standard input or the mechanism expected by your hook command.
  5. Return a clear success or failure status.
  6. Print a short failure message that tells the developer what to change.
  7. Test the script directly with sample JSON before relying on it in a Claude Code session.

Use relative paths when possible so the project works across machines. If a hook calls an HTTP endpoint, package manager, local daemon, or external CLI, handle timeouts and errors explicitly. A hook that hangs can make the agent appear stuck.

Start with one project-level hook. Add more only when each rule has a clear owner, a clear failure message, and a clear reason to run during the Claude Code workflow.

If lightweight checks are enough for a hook-driven workflow, Claude Haiku can fit quick validation steps without adding much latency.

For source-level validation, Code is worth checking after you understand the Claude Code Hooks workflow described here.

Automating Code Review with Hooks

A post-tool hook can run a formatter or targeted check after an edit.

Use narrow commands:

Format changed files.
Run the relevant linter.
Return only failures.

Do not run the entire test suite after every file write. That creates slow feedback and high cost.

Good review hooks check objective signals first. Useful examples include:

  • Format only files changed in the current working tree.
  • Run a linter only for the package or directory that changed.
  • Run a type check only when TypeScript, Python, or schema files changed.
  • Block edits to generated files, lockfiles, migration files, or protected configuration unless the workflow explicitly allows them.
  • Detect forbidden patterns such as committed secrets, debug-only code, or direct writes to production configuration.
  • Return a compact failure message with the file path, command, and next action.

Hooks work best when the rule is deterministic. They are less useful for judgment-heavy review, such as deciding whether an architecture is appropriate or whether a feature fully satisfies a product requirement.

A strong pattern is to let hooks enforce local rules, then use a separate review step for broader reasoning. The hook catches mechanical issues early. The review step evaluates the change as a whole.

If you are setting up these review hooks from scratch, Claude Code Installation Guide covers the installation steps that come first.

When details such as limits or setup steps matter, Reddit can help confirm the latest implementation surface.

Hooks for Git Commit Automation

Hooks can prepare a commit. They should not silently publish one.

A safer flow is:

  1. Validate the working tree.
  2. Run focused tests.
  3. Generate a proposed message.
  4. Ask for approval.
  5. Commit only after approval.

Never store credentials in the hook. Never auto-push to a protected branch.

A commit-oriented hook should make the final decision visible. It can check that the working tree is clean enough to review, verify that required files changed together, or produce a proposed commit message from the diff. It should not hide a commit or publish code without a human approval policy.

Use guardrails such as:

  • Require an explicit approval phrase before committing.
  • Refuse to commit when tests fail.
  • Refuse to commit when protected files changed without a matching explanation.
  • Keep branch protection, code review, and CI checks outside the hook so the repository still has independent controls.
  • Log what the hook checked and what it skipped.

> The quality signal > > A model can sound certain and still fail the repository. Verdent's 76.1% SWE-bench Verified result is evidence for testing the change, not trusting the tone. > > The point is not more agent activity. It is less Blind AI, less Code Chaos, and a result the team can inspect.

For commit hooks that need repository context from external tools, Claude Code MCP explains how to connect those sources without weakening review controls.

Before you budget a real project around Claude Code Hooks, compare the claims here with Joseparreogarcia.

Debugging Hooks That Aren't Firing

Check:

  • The settings file location.
  • The event name.
  • The matcher.
  • Script permissions.
  • JSON syntax.
  • Command exit status.
  • Input handling.

Run Claude Code with debug logging. Test the script directly with sample JSON.

Remember that a matcher applies to the tool name, not arbitrary prompt text.

A reliable debugging workflow is:

  1. Confirm Claude Code is reading the settings file you edited.
  2. Validate the JSON syntax before starting a new session.
  3. Confirm the event name matches the lifecycle point you expect, such as PreToolUse or PostToolUse.
  4. Confirm the matcher targets the tool name, such as Bash, not the words in your prompt.
  5. Replace the hook command temporarily with a tiny script that writes a timestamp to a local log file.
  6. Run the real hook script manually with sample JSON.
  7. Check whether the script exits successfully or returns the expected failure status.
  8. Add short diagnostic output, then remove noisy logging after the hook works.

Many hook problems come from path assumptions. A script may work from your terminal but fail when Claude Code runs it from a different working directory. Use explicit paths, print the current working directory during debugging, and verify that required tools are available in the environment.

Verdent provides its own verification and controlled execution stages. Use hooks when you need custom local policy around Claude Code.

Frequently Asked Questions

Where are Claude Code hooks configured?

Claude Code hooks are configured in Claude Code settings files. For a shared project, use .claude/settings.json so the hook rules travel with the repository and can be reviewed with the rest of the code.

Can hooks block a command?

Yes. A PreToolUse hook can deny a tool request before it runs. This is useful for blocking destructive Bash commands, protected file edits, or project-specific actions that require approval.

Can hooks change tool input?

Supported pre-tool hooks can return updated input. Use this carefully. Input changes should be predictable, easy to inspect, and limited to safe transformations that match your project policy.

Why is my hook ignored?

Check the event name, matcher, settings file path, script permissions, JSON syntax, command exit status, and input handling. Also confirm that the matcher targets the tool name, such as Bash, rather than text from the prompt.

Should hooks auto-commit code?

Only with an explicit approval policy. A hook can validate changes and propose a commit message, but it should not silently commit or push code, especially to a protected branch.

What Claude Code Hooks Cannot Give You

Claude Code Hooks operate inside one agent run. They can enforce local rules around tool use, but they do not coordinate a full delivery across planning, parallel implementation, review, and verification.

Verdent is built for the task before, the tasks alongside, and the review after.

Hooks control events inside one run. Verdent controls how the whole delivery moves.

Next Step

Extend Hooks with Full Workflow Review

Use Claude Code hooks for deterministic checks inside a run, then add Verdent review to coordinate tasks, validate changes, and keep delivery moving.