Advanced

Hooks

Hooks let you run custom shell commands automatically in response to Claude Code tool events. They are the mechanism for injecting your own automation into Claude Code's workflow — running formatters on file writes, logging tool calls, or running tests after edits.

What Hooks Are and When They Fire

A hook is a shell command that Claude Code executes automatically when a specific event occurs. The two main hook types:

  • PreToolUse: Fires before Claude Code runs a tool. Can be used to validate, log, or block the tool call. If the hook exits with a non-zero code, the tool call is blocked.
  • PostToolUse: Fires after a tool completes. Used for side effects like auto-formatting, running tests, or logging results. Exit code is informational — it does not block the workflow.

Hooks can be scoped to specific tool names: Bash, Edit, Write, Read, Glob, Grep, and MCP tool names.

Configuring Hooks in settings.json

Hooks are defined in ~/.claude/settings.json (global) or .claude/settings.json in your project directory (project-scoped):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "prettier --write "$CLAUDE_TOOL_INPUT_FILE_PATH""
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo "[HOOK] Bash command: $CLAUDE_TOOL_INPUT_COMMAND" >> /tmp/claude-audit.log"
          }
        ]
      }
    ]
  }
}

The matcher field is a regex matched against the tool name. Hook commands receive context via environment variables set by Claude Code.

Hook Environment Variables

Claude Code sets these environment variables for hooks:

  • CLAUDE_TOOL_NAME — the name of the tool being called (e.g., Edit)
  • CLAUDE_TOOL_INPUT_FILE_PATH — for file tools: the path being read/written
  • CLAUDE_TOOL_INPUT_COMMAND — for Bash tool: the command being run
  • CLAUDE_TOOL_OUTPUT — for PostToolUse: the tool's output (PostToolUse only)

Common Use Cases

Auto-format on write

PostToolUse on Edit/Write → run prettier --write or black on the modified file. Ensures all Claude-generated code matches your project's formatting standards without manual formatting steps.

Run tests after edit

PostToolUse on Edit → run the test file corresponding to the edited source file. Gives Claude immediate feedback on whether its changes break tests, enabling automatic fix-retry loops.

Audit log of shell commands

PreToolUse on Bash → append the command to an audit log file. Provides a record of every shell command Claude Code ran in a session — useful for security review and debugging.

Block dangerous commands

PreToolUse on Bash → check if the command matches a blocklist (e.g., rm -rf, DROP TABLE) and exit non-zero to block it. A last-resort safety net for agentic sessions with broad permissions.

Security Considerations

Hooks run as shell commands with the same permissions as your Claude Code process. This means:

  • Hooks can read and write files, make network requests, and execute arbitrary code
  • A malicious MCP server could theoretically influence hook execution via tool names or outputs — keep hooks simple and explicit
  • Be careful with hooks that pass $CLAUDE_TOOL_INPUT_COMMAND directly to a shell — this creates a command injection risk. Quote variables carefully or avoid passing them to shell interpreters.
  • Test hooks thoroughly before enabling them in agentic sessions — a misconfigured PreToolUse hook that always exits non-zero will block all matching tool calls

Checklist: Do You Understand This?

  • PreToolUse runs before a tool; PostToolUse runs after — PreToolUse can block the call by exiting non-zero
  • Configure in settings.json with a matcher (tool name regex) and a shell command
  • Hook commands receive tool context via environment variables (CLAUDE_TOOL_NAME, CLAUDE_TOOL_INPUT_FILE_PATH, etc.)
  • Common uses: auto-format on write, run tests after edit, audit log, block dangerous patterns
  • Hooks have full shell access — keep them simple, test thoroughly, and quote variables to prevent injection

Page built: 01 Jun 2026