NewsletterBlogLearnCompareTopicsGlossary

What Are Async Hooks in Claude Code? Understanding the Lifecycle

Async hooks in Claude Code are shell commands that fire at lifecycle events like tool calls and prompts. Here's how they work and when to use them.

tools
ShareXLinkedIn

What Are Async Hooks in Claude Code? Understanding the Lifecycle

Hooks in Claude Code are user-configured shell commands that execute automatically in response to specific lifecycle events — tool calls, prompt submissions, and notification triggers. They run outside the AI model's control, giving you a deterministic automation layer on top of Claude Code's agentic behavior. If you've worked with Git hooks or CI/CD pipeline hooks, the concept is identical: event fires, your script runs, the result feeds back into the workflow.

This matters because Claude Code is an autonomous agent. It reads files, runs commands, edits code, and commits changes. Hooks let you inject guardrails, automations, and side effects at precise moments in that lifecycle — without modifying the agent's prompts or behavior directly.

How Claude Code Hooks Work

Hooks are configured in Claude Code's settings.json, not in project code. Each hook definition specifies an event type and a shell command to execute when that event fires. The hook runs as a subprocess — Claude Code waits for it to complete and reads its output before proceeding.

The key lifecycle events where hooks can fire include:

  • Pre-tool-call hooks: Execute before Claude Code runs a tool (like file edits, bash commands, or searches). These act as gates — if the hook exits with a non-zero status, the tool call is blocked.
  • Post-tool-call hooks: Execute after a tool completes. Useful for logging, notifications, or triggering downstream processes.
  • Prompt submission hooks: Fire when a user submits a prompt, before the model processes it. These can transform or validate input.
  • Notification hooks: Fire when Claude Code sends a notification, letting you route alerts to external systems.

The "async" aspect refers to how these hooks interact with Claude Code's event-driven architecture. Each hook runs as a separate shell process, decoupled from the model's inference. The agent pauses at the hook point, your command executes, and control returns to the agent with the hook's output available as context.

For a deeper technical walkthrough, see our guide on Claude Code hooks as a deterministic layer.

Why Hooks Matter for AI Coding Workflows

The fundamental tension with AI coding agents is control. You want the agent to work autonomously — that's the whole point — but you also need predictable behavior at critical moments. Hooks solve this by separating what the AI decides from what your infrastructure enforces.

Consider a few concrete scenarios:

Security scanning before commits. A pre-tool-call hook on the git commit action can run a secrets scanner. If the scan finds an API key or credential in staged files, the hook exits non-zero and blocks the commit. The AI never gets to make a judgment call about whether the secret is "safe" — your deterministic check handles it.

Formatting enforcement. A post-tool-call hook on file edits can run Prettier, ESLint, or gofmt on every file Claude Code touches. The agent writes code in whatever style it prefers, and your hook normalizes it immediately. No prompt engineering required.

Audit logging. Post-tool-call hooks can append every action Claude Code takes to a structured log file — what tool was called, what arguments were passed, what the result was. This gives you a complete audit trail outside the conversation context.

These patterns are covered extensively in our complete guide to automating your AI coding workflow with hooks.

The Hook Lifecycle in Detail

Understanding the exact order of operations matters when you're chaining multiple hooks or debugging unexpected behavior.

Step 1: Event triggers. Claude Code's agent loop decides to use a tool — say, the Edit tool to modify a file. Before executing, it checks settings.json for any hooks registered to the pre-tool-call event.

Step 2: Pre-hook execution. If a matching hook exists, Claude Code spawns a shell subprocess with the hook command. Environment variables and stdin provide context: which tool is being called, what arguments were passed, and metadata about the current session.

Step 3: Gate check. If the hook exits with status 0, the tool call proceeds normally. If it exits non-zero, the tool call is blocked, and the hook's stderr output is fed back to the agent as an error message. The agent can then adjust its approach based on the feedback.

Step 4: Tool execution. The actual tool runs — the file gets edited, the command executes, the search completes.

Step 5: Post-hook execution. After the tool completes, any post-tool-call hooks fire. These receive the tool's result as input. They cannot block the action (it already happened), but they can trigger side effects: logging, notifications, follow-up commands.

Step 6: Agent continues. The agent loop resumes with the tool result and any hook output in context.

This lifecycle is what makes hooks "async" in the Claude Code sense — they're event-driven callbacks that run at defined points in an otherwise autonomous agent loop. The agent doesn't orchestrate the hooks; the Claude Code harness does.

Configuring Your First Hook

Hooks live in Claude Code's settings.json file. The configuration specifies the event matcher and the shell command to execute.

A basic pre-tool-call hook that blocks any attempt to delete files might look like this:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "command": "echo \"$CLAUDE_TOOL_INPUT\" | grep -q 'rm ' && echo 'File deletion blocked by hook' >&2 && exit 1 || exit 0"
      }
    ]
  }
}

This checks whether a Bash tool call contains rm and blocks it if so. The stderr message ("File deletion blocked by hook") gets fed back to the agent, which then knows to try a different approach.

For prompt-level hooks that validate user input before it reaches the model:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "command": "/path/to/your/validation-script.sh"
      }
    ]
  }
}

The validation script receives the prompt text and can transform it, reject it, or pass it through unchanged. This is useful for teams that want to enforce prompt templates or inject standard context.

Hooks vs Skills vs CLAUDE.md

Claude Code has multiple extension points, and choosing the right one matters. Here's how hooks compare to the other mechanisms:

CLAUDE.md provides static project context. It tells the agent what your project is, what conventions to follow, and what constraints exist. The agent reads it and incorporates the instructions into its reasoning. CLAUDE.md is advisory — the model interprets and applies the guidance.

Skills (SKILL.md files) are reusable prompt templates for specific tasks. They shape how the agent approaches a category of work — writing tests, generating content, reviewing code. Like CLAUDE.md, skills influence the model's behavior through prompt engineering.

Hooks are deterministic. They don't influence the model — they run alongside it. A hook doesn't suggest that the agent should run a linter; it runs the linter itself. This distinction is critical for anything where "the model usually gets it right" isn't good enough: security checks, compliance logging, formatting standards.

The full extension stack breakdown explains how these layers compose together.

Common Hook Patterns

Teams using Claude Code hooks in production tend to converge on a few patterns:

The guardian pattern. Pre-tool-call hooks that block dangerous operations. Prevent force pushes, block commits to protected branches, reject changes to critical config files. These are your safety rails.

The normalizer pattern. Post-tool-call hooks that enforce consistency. Auto-format code, sort imports, update lock files, regenerate documentation. The agent focuses on logic; hooks handle style.

The observer pattern. Post-tool-call hooks that log without interfering. Write to audit logs, send Slack notifications, update project dashboards. Zero impact on the agent's workflow, full visibility for the team.

The transformer pattern. Prompt submission hooks that enrich or modify input. Inject team-specific context, expand shorthand commands, or route prompts to different configurations based on content.

For real-world examples and community discussion about these patterns, see the community FAQ on Claude Code hooks.

Debugging Hooks

When a hook isn't behaving as expected, check these common issues:

  1. Path resolution. Hooks run in a shell subprocess. Relative paths resolve from Claude Code's working directory, not from where settings.json lives. Use absolute paths for reliability.

  2. Exit codes. Pre-tool-call hooks only block on non-zero exit. If your validation script has an unhandled error path that exits 0, the tool call proceeds despite the failure.

  3. Stderr vs stdout. Error messages that should reach the agent must go to stderr. Stdout is captured but handled differently depending on the hook type.

  4. Timeouts. Long-running hooks block the agent loop. If your hook calls an external API or runs a slow analysis, consider whether the latency is acceptable or if you should move the logic to a post-tool-call hook instead.

  5. Environment isolation. Hooks don't inherit the agent's conversation context. They receive structured input through environment variables and stdin, but they can't access the model's reasoning or previous tool results directly.

Frequently Asked Questions

Can hooks modify Claude Code's responses directly?

No. Hooks operate at the tool-call and prompt level, not at the model output level. A pre-tool-call hook can block an action, and its error message influences the agent's next step, but hooks cannot rewrite the model's text output.

Do hooks work with Claude Code agent teams?

Hooks configured in settings.json apply to the main agent process. Sub-agents spawned by agent teams inherit the hook configuration from the parent process, so your security and formatting hooks apply consistently across the full agent hierarchy.

Are hooks the same as Git hooks?

Conceptually similar — both are event-driven shell scripts. But Claude Code hooks fire on AI agent lifecycle events (tool calls, prompts), not Git events (commits, pushes). You can use both: Git hooks for repository-level enforcement, Claude Code hooks for agent-level enforcement.


Want more AI insights? Subscribe to LoreAI for daily briefings.