Learn Claude Code by Building DevPulse · Chapter 13

Hooks that watch for us

You keep glancing at the terminal in case Claude is waiting for you, so how do you stop babysitting it? By the end of this chapter, DevPulse has two hooks: one beeps when Claude needs you, and one checks the tasks file after every edit.

One sitting~7 min read, ~15 min to build along
You start fromchapter 12's DevPulse
You builda beep hook and a tasks.json check
Chapter 13 of 15Claude that tells you
Goes with Episode 13"How do I stop babysitting Claude Code?". The video is being made. This page teaches the same steps, at your own pace.
In a hurry?Jump to the quick reference: every command and key in this chapter, what it does, and when to use it.
Every prompt, ready to copyThis chapter's prompts and commands, each with a Copy button. Type them yourself first; copy if you are stuck or behind.
Where you areDevPulse from chapters 1 to 12, with its tasks in data/tasks.json and 18 tests.

Watching the terminal

Say Claude is working and you switch to your browser. A minute later you look back. It has been waiting for your yes the whole time.

Or worse: an edit broke data/tasks.json, and nobody noticed until the page went blank.

The question for this chapter

How do you stop babysitting Claude Code, and let it tell you when something needs you?

What a hook is

A hook is a command that Claude Code runs by itself when something happens. You don't ask each time. It just runs.

EventWhen it runsOur hook
NotificationClaude needs you, for example to approve a commandBeep
PostToolUseRight after Claude uses a tool, such as EditCheck that data/tasks.json is still valid JSON

Ask Claude to write both hooks

Hooks live in a settings file. The project one is .claude/settings.json, so the whole team gets them.

Windows: type this into Claude Code, as one lineAdd a Notification hook to .claude/settings.json that beeps on Windows when you need me, and a PostToolUse hook that runs python -m json.tool on data/tasks.json after any edit to it, so a broken file is reported at once.
Mac: the same, with two words changedAdd a Notification hook to .claude/settings.json that plays a sound on Mac when you need me, and a PostToolUse hook that runs python3 -m json.tool on data/tasks.json after any edit to it, so a broken file is reported at once.
Claude's summary: the Notification hook runs powershell.exe [console]::Beep(880,300); the PostToolUse hook on Write|Edit checks the edited path and runs python -m json.tool, exiting 2 on failure. It tested both with piped payloads. Left to do: it hasn't seen either hook fire in a real session; open /hooks once or restart.
Written in 40 seconds. It tested both by hand, and is honest: it has not seen them fire in a real session yet. The grey line, commit this, is only a suggestion.

Look at one detail. On a broken file, the check exits 2. Exit code 2 tells Claude Code to send the error back to Claude, so Claude sees it at once.

Restart, then check they are on

The settings file did not exist when this session started. So restart Claude Code: type /exit, then claude.

Type this into Claude Code/hooks
The /hooks menu: 2 hooks on 2 events. This menu is read-only. PostToolUse, after tool execution: a Project python command for Write|Edit. Notification, when notifications are sent: a Project powershell.exe command.
Two hooks on two events, both from the project. The menu only shows them. To change one, edit the file or ask Claude.

Break the file on purpose

A hook you have never seen fire is only a hope. So test it.

Type this into Claude Code, as one lineTo test the hook: use the Edit tool to delete the last closing bracket of data/tasks.json. Then show me what the hook said, and fix the file.
Update(data\tasks.json): removed line 38, the closing ]. PostToolUse:Edit hook returned blocking error: Expecting ',' delimiter: line 38 column 1 (char 901). Claude: the hook fired and reported invalid JSON; that is the missing closing ]. Now I'll restore it.
The moment the edit lands, the hook runs and reports line 38. Claude reads that and knows what to fix.
Added 1 line: the ] back at line 38. Claude: the hook works. I removed the final ], the hook reported a blocking error, I restored it, json.tool now reports the file as valid, and the task data is unchanged.
The bracket is back, and the tasks are unchanged. The grey line, run the tests, is only a suggestion.

Make Claude need you

Now the beep. It plays when Claude waits for you, so we need a command that asks first. Press Shift+Tab until you see manual mode.

Type this into Claude CodeRun node --test.
Bash command: node --test. This command requires approval. Do you want to proceed? 1. Yes 2. Yes, and don't ask again for node 3. Yes, and switch to auto mode 4. No.
Claude waits for your approval. This is when the Notification hook beeps.
Careful here

You won't hear the beep in our video. A screen recording does not catch it. Try it yourself: switch windows before you send the line.

Claude: node --test passed all 18 tests, none failing or skipped, covering current and best streak, the IST day boundary, gaps, duplicate days, month, year and leap days. Manual mode on.
Choose Yes, and all 18 tests pass. Then Shift+Tab back to auto mode. The grey line, run python test_server.py, is only a suggestion.

Now you can look away. You'll hear when Claude needs you, and a broken tasks file is caught at once.

What hooks cost

A hook runs every time its event happens. Our check runs after every edit, so keep it fast. A slow hook slows down every step.

Hooks also run with your permissions. A project you clone can bring its own hooks in .claude/settings.json. Read that file before you trust the folder.

DevPulse now watches itself, but it all stays on your laptop. Next, in chapter 14, DevPulse goes on the internet.

Quick reference

The prompts from this chapter, ready to copy: every prompt, chapter 13.

Command or keyWhat it doesUse it when
Add a Notification hook … that beeps when you need mePlays a sound whenever Claude waits for youYou work in another window while Claude runs
Add a PostToolUse hook that runs … after any edit to …Runs your check every time Claude edits that fileA file must never be left broken
/exit, then claudeRestarts Claude Code so new hooks loadYou just added or changed a hook
/hooksLists your hooks by event (read-only)You want to see which hooks are on
exit 2In a hook command: blocks and sends the error to ClaudeClaude should see the problem and fix it

References

Where each command and file on this page comes from. Every screenshot is from our own recording on 29 Oct 2026, Claude Code 2.1.312.

  1. Anthropic · Get started with Claude Code hooks What hooks are for, with a notification example. https://code.claude.com/docs/en/hooks-guide
  2. Anthropic · Hooks reference The events (Notification, PostToolUse), matchers, the JSON a hook reads, and what exit code 2 does. https://code.claude.com/docs/en/hooks
  3. Anthropic · Claude Code settings The settings files: user, project (.claude/settings.json) and local. https://code.claude.com/docs/en/settings
  4. My own recording · 29 Oct 2026, Windows 11 Both hooks were written in 40 s; the check caught the missing ] at line 38; the beep played but cannot be heard in a screen recording.