Introduction

You've mastered SessionStart hooks for providing context and PreToolUse hooks for preventing dangerous operations. Now we're moving to the third pillar: actions that execute after Claude completes a task.

PostToolUse hooks run after Claude finishes executing tools like writing files or running commands. These hooks enable powerful automatic actions: formatting code, logging operations, and providing feedback that helps Claude make better decisions. By the end, you'll have a complete automation layer that makes your workflow smoother and more consistent.

Understanding PostToolUse Hooks

PostToolUse hooks are like a cleanup crew after an event. After Claude writes a file (the "event"), these hooks automatically tidy things up - formatting the code, logging what happened, checking for issues.

While PreToolUse asks "Should we allow this?", PostToolUse asks "Now that it's done, what housekeeping should we do?"

Real-world analogy: Imagine you're baking. PreToolUse is checking you have all ingredients before you start. PostToolUse is cleaning the kitchen, storing leftovers, and noting what you made in your recipe journal - all automatic cleanup after the baking is done.

Hook scripts receive information as structured data (JSON) containing:

  • What tool just ran (Write, Edit, Bash)
  • What files or commands were involved
  • What the result was

This timing enables intelligent responses. One powerful application is automatic code formatting - ensuring every file Claude touches looks consistent and professional, following your project's style guide without you having to remember to run the formatter.

Building an Auto-Formatter Hook

Let's build a hook that automatically runs Prettier after file write operations:

We check if the tool is a Write operation and extract the file path using Python's JSON parsing. This is the same pattern we used in PreToolUse hooks - reading the structured data Claude sends us.

Formatting Different File Types

Now we apply formatting based on what type of file was created. It's like having specialized cleaning tools: you use different cleaners for windows versus wooden floors.

Breaking this down in human terms:

  • The bash pattern =~ means "match this pattern" - like asking "does this filename end with .ts or .tsx or .js or .jsx?"
  • The backslash-pipe \.(ts|tsx|js|jsx)$ is a regex pattern: \. matches a literal dot, the | means "or", and $ means "at the end of the string"
  • npx prettier --write runs the Prettier formatter to clean up the code style in-place
  • The output goes to stderr using >&2 so you see "✨ Formatting..." in your terminal (but it doesn't go to Claude)
  • || true means "if Prettier has an error, don't break the whole hook" - we'd rather the code stay unformatted than crash the automation
Supporting Additional File Types

The same pattern extends to other formats:

For Markdown, we add --prose-wrap always for consistent text wrapping. Each file type gets appropriate formatting rules. The hook is smart enough to recognize file extensions and apply the right formatter.

Configuring the PostToolUse Hook

Activate the auto-formatter in .claude/settings.json:

The matcher specifies this hook only runs after Write operations. You can add a timeout if needed, though format hooks typically complete quickly (within a second or two).

Building an Audit Log

Beyond automatic actions, PostToolUse hooks excel at recording what happened. An audit log provides a historical record of all file operations - invaluable for debugging ("when did that file change?"), compliance ("who modified this?"), and understanding Claude's work patterns.

Let's create a hook that logs every file write and edit:

This hook triggers for both Write and Edit operations. The mkdir -p .claude/logs ensures the directory exists (the -p flag means "create parent directories as needed, and don't error if it already exists"). The date -u +"%Y-%m-%dT%H:%M:%SZ" command generates ISO 8601 timestamps in UTC (universal time), making logs easy to parse and compare across time zones. Each entry appends to .claude/logs/audit.log using >> (append, not overwrite), creating entries like:

This chronological record helps track changes and identify when issues were introduced. It's like having a security camera recording of everything Claude does to your files.

Running Multiple Hooks in Sequence

Multiple hooks can execute for the same tool event. Since our audit logger tracks both Write and Edit operations while our formatter only needs Write, we configure them separately:

The matcher can use the pipe | character to match multiple tools. The first entry runs the formatter only for Write operations, while the second runs the audit logger for both Write and Edit. Each hook receives the same input data about the tool that just ran, and they execute in parallel - meaning they all start at roughly the same time rather than waiting for each other. If one hook fails (exits with an error), the others continue running independently. This parallel execution lets you compose multiple actions that don't depend on each other, maximizing efficiency.

Teaching Claude About Its Own Work

The most powerful PostToolUse capability is creating a feedback loop - where hooks tell Claude about issues they discovered, and Claude can then fix them.

Imagine you're writing an email and your email client says "Hey, you mentioned attaching a file but I don't see one attached. Want to add it?" That's feedback. Hooks can do the same for Claude.

To send feedback, a hook outputs structured information (JSON) that Claude can read:

The additionalContext is the message that gets added to Claude's understanding of the situation. Here's a hook that checks for TODO comments in newly written files:

How this feedback mechanism works:

  1. The hook uses grep -q to silently search for TODO comments (the -q means "quiet" - just tell me yes/no, don't show matches)
  2. If found, it constructs a JSON message using Python's json.dumps() to ensure proper formatting
  3. The sed command replaces $FILE in the message with the actual filename
  4. This JSON gets printed to stdout, which Claude reads
  5. Claude receives this and might respond: "I noticed the file has TODOs - would you like me to complete them?" or "Should I create issues for these TODOs?"
Conclusion and Next Steps

Excellent progress! You've now mastered SessionStart for initialization, PreToolUse for safety, and PostToolUse for automatic actions. We built auto-formatters that maintain code consistency, audit loggers that track all changes, and feedback hooks that inform Claude about important conditions.

The real power emerges when you combine these patterns. A PreToolUse hook validates an operation is safe, the operation executes, and then PostToolUse hooks format the results, log what happened, and provide feedback. This creates a complete automation layer around Claude's actions - like having a team of assistants handling quality control, record-keeping, and communication automatically.

Now it's time to practice building your own intelligent automation workflows!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal