All Things AI
Daily Stack
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