Claude Code guides

FREE GUIDE

Hooks for automation

A hook runs a configured action when Claude Code reaches a particular event.

  • 5 min read
  • Step by step
  • Copy-ready prompt

A hook runs a configured action when Claude Code reaches a particular event. Start with a small, visible example: append a line to a local log after Claude successfully writes or edits a file, then prove that you can turn it off.

Before you start

  • A working, signed-in terminal Claude Code installation on macOS, Linux, or WSL, using Bash or Zsh. The example command is written for these shells.
  • A disposable local project folder with no existing hooks, or a project whose .claude settings you understand and have backed up.
  • An editor that shows hidden folders and a harmless text file named hook-practice.txt in the project root.
  • Permission to configure local hooks. Organization-managed settings may prevent personal or project hooks from running.

Want to do it yourself?

Difficulty
8 out of 10
Estimated completion time
1–2 hours

Skills you’ll need: Edit local configuration and a hook command, inspect logs, and prove both triggering and removal work as expected.

How this helps your brand

A tested local hook can support a consistent development habit around your project files. Knowing exactly which edits trigger it helps you use that automation without confusing it with customer-enquiry or website-form processing.

  1. Step 1: Pick the event and the visible result

    For this exercise, the event is PostToolUse and the matching tool names are Write or Edit. The action adds the sentence “Claude edited a file” to .claude/edit-log.txt. Nothing needs to connect to a service or install an extra library.

    This log demonstrates that the automation ran. It is not a history of every change: edits made through a shell command or another editor do not match Write or Edit. PostToolUse also happens after the successful tool action, so this hook does not prevent or undo an edit.

  2. Step 2: Add one local hook without replacing settings

    Paste the prompt below into Claude Code. It asks Claude to merge a hook into .claude/settings.local.json, leaving any other settings in place. Local settings apply to this project; .claude/settings.json is the separate, shareable project settings file.

    Inspect the resulting JSON in your editor. Under hooks, there should be a PostToolUse array containing an entry with matcher set to Write|Edit. Its hooks array should contain one command hook. The command uses printf to append the fixed sentence to the log under CLAUDE_PROJECT_DIR, the project root where the session started.

    Keep the quotes around the destination path so a project folder with spaces still works. The prompt contains the exact command to compare against the saved value.

    Tip: Hooks execute commands on your computer. For this first exercise, the entire action should be the single log append you inspected.

    Illustrated exampleA local hook adds one safe, visible action
    .claude/settings.local.jsonlocal to this project
    WhenPostToolUseafter a successful tool actionWrite|Edit matcher
    One command
    printf '%s\n' 'Claude edited a file' >> "$CLAUDE_PROJECT_DIR/.claude/edit-log.txt"
    append fixed marker · do not overwrite

    Merge this entry into hooks; preserve every other local setting.

    The event and matcher narrow when it runs; the command appends one fixed line under the project root. Keep the rest of your local settings intact.
  3. Step 3: Confirm that Claude loaded the hook

    Start a fresh Claude Code session from the same project folder. Type /hooks and look for the PostToolUse hook and its Write|Edit matcher.

    If it is missing, check for invalid JSON, including trailing commas, and confirm you edited the settings file in this project. If /hooks reports that only managed hooks run, ask your organization’s administrator about that policy before continuing.

    Do not use the edits that created the settings file as proof of success. The hook was not necessarily active for those earlier actions.

  4. Step 4: Make two deliberate edits and inspect the log

    Ask Claude: Use the Edit tool to replace the text in hook-practice.txt with First hook test. Inspect the tool transcript to confirm it used Edit and the operation succeeded. If it used a shell instead, ask it to repeat a small change using Edit.

    Open .claude/edit-log.txt in your editor. It should contain the marker sentence. Note the number of lines, then ask Claude to use Edit to change First hook test to Second hook test. Reopen the log and confirm it gained one line for that successful matching tool call.

    If one request produces several matching tool calls, several lines are expected. Compare the log with actual tool calls, not the number of chat messages.

    Illustrated exampleCount matching tool calls, then compare the log
    Successful matching tool calls
    1EditReady → First hook test
    2EditFirst → Second hook test

    One chat request can make more than one tool call.

    .claude/edit-log.txt
    01Claude edited a file
    02Claude edited a file
    +2 lines

    Bash editdoes not match Write|Edit

    +0 lines
    Two successful Edit calls add two marker lines, even if they came from one request. A Bash edit is outside this matcher.
  5. Step 5: Investigate a missing log entry

    First check whether the edit succeeded and whether the tool was exactly Write or Edit. The matcher is case-sensitive. An edit made by Bash is a useful comparison: it should not trigger this hook.

    If a successful matching edit produces no marker, recheck /hooks and the quoted command. Start Claude Code with claude --debug to collect hook execution details in its debug log. A missing destination or permission error needs fixing before another test; the website edit may already have happened.

    Stop the exercise if the saved command does more than append the marker. Restore your saved settings, then add only the intended entry again.

    Illustrated exampleTrace a missing marker in a useful order
    START HEREDid the edit succeed with exactly Write or Edit?Check the tool transcript. Shell edits do not match this hook.
    NORepeat a small edit with Edit

    Then compare the log with successful matching calls.

    YESCheck /hooks and the saved command

    Confirm the hook loaded, matcher is Write|Edit, and the quoted path points under $CLAUDE_PROJECT_DIR.

    Still missing? → restart with claude --debug

    If the command does more than append the marker, restore your saved settings before testing again.

    Verify the tool call first, then the loaded hook and command. The file edit may already have succeeded even if the hook failed.
  6. Step 6: Remove the hook and prove it stopped

    Remove only this command hook from .claude/settings.local.json, preserving other entries and valid JSON. Start another session and check /hooks again.

    Note the log’s current length and ask Claude to make one more Edit change to hook-practice.txt. The log should gain no marker from this removed hook. You can now delete the practice file and log yourself.

    Once this cycle is familiar, consider a formatter or another useful local script. Test that script independently before attaching it to an event, and keep its scope equally clear.

You're done when

  • /hooks lists the intended PostToolUse command with the Write|Edit matcher while it is enabled.
  • Two successful matching edits produce corresponding marker lines that you inspected in the log.
  • You can explain why a Bash edit would not be logged by this matcher.
  • After removing the entry and restarting, another matching edit adds no marker from this hook.

Your prompt

Show promptHide prompt

COPY AND PASTE

Help me configure one small Claude Code command hook in this practice project. I use [macOS, Linux, or WSL] with [Bash or Zsh].

Read existing .claude/settings.local.json first and preserve every unrelated setting and hook. If this exact hook already exists, do not duplicate it. Merge an entry under hooks.PostToolUse with matcher "Write|Edit" and one hook with type "command". Use exactly this command as its command value, with the required JSON escaping:

printf '%s\n' 'Claude edited a file' >> "$CLAUDE_PROJECT_DIR/.claude/edit-log.txt"

Do not add other commands or change permission settings. Make sure hook-practice.txt exists with the text Ready for hook test; do not overwrite it if it contains other work. Validate the settings as JSON and show me the saved hook entry. Do not claim it has fired yet. Tell me to restart this project session, inspect /hooks, and test a successful Edit on hook-practice.txt. Explain how to remove only this hook while preserving valid settings.

Paste into terminal Claude Code in your practice project. Replace the operating-system and shell brackets. This shell command example does not cover native Windows PowerShell or CMD.

FREE BY EMAIL

Get the full AI guide

Our complete, step-by-step guide to using AI in your business, sent straight to your inbox.

Keep goingMore Claude Code guidesReturn to Claude Code for more practical guides and launch notes.

Get every new tool guide in your inbox

When a tool drops a new feature, you get the breakdown: what it is, how it works, and how to use it.

By subscribing, you agree to receive the tool guides newsletter. Unsubscribe anytime.