glimfly
ai updated

What are hooks in Claude Code?

In one sentence:A hook is a command you wire to a specific moment in Claude Code's process (like after a file edit or when it finishes a turn) so it runs automatically without you asking.

What it actually is

A hook is a command you rig to a specific moment in Claude Code’s process, so it runs automatically instead of you having to remember to do it, like a doorbell wired to the front door instead of you checking the peephole every five minutes. You write the trigger once, in a settings file, and Claude Code fires it every time that moment happens, whether or not Claude “decides” to.

Concretely: you add a hooks block to .claude/settings.json (or ~/.claude/settings.json for something that applies across all your projects). Inside it you name an event, say PostToolUse, pick a matcher like Edit|Write so it only fires after file edits, and give it a command, like prettier --write on the file that just got touched. From then on, every time Claude edits a file, your formatter runs. Claude doesn’t have to remember to ask for it, and you don’t have to check.

Why your AI just did this

Claude Code doesn’t invent hooks on its own. They only run because you (or a teammate, or a plugin you installed) configured one ahead of time. What you’re seeing is that configuration doing its job silently. Your agent edits src/App.tsx, and a PostToolUse hook you set up runs a linter against that exact file before the next step happens. Or Claude tries to run a Bash command containing rm -rf, and a PreToolUse hook you wrote checks the command, doesn’t like it, and exits with code 2. Claude gets that rejection back as an error message and has to try something else.

This is also how “Claude just sent me a notification” or “Claude just asked permission for something it normally doesn’t” can happen: a Notification or PreToolUse hook is running behind the scenes, outside the conversation itself.

When you’ll run into it

You’ll first meet hooks by typing /hooks in Claude Code, which opens a browser showing every hook currently configured, grouped by event, with a count next to each. If you’ve never set one up, it’s empty. That’s expected.

The phrase “how do I run something automatically when Claude finishes” points at the Stop event, which fires every time Claude finishes responding to a turn, not just once at the very end of a project, but after each response. If you want a desktop ping specifically when Claude is idle and waiting on you, that’s the Notification event instead.

You’ll also hit hooks when something breaks: a transcript line reading PreToolUse hook error: ... means your hook script exited with an unexpected code, and stderr text appearing as feedback to Claude means a hook deliberately blocked an action and explained why.

What to check

  • Know hooks run with your full user permissions, with no sandbox. A bad hook command can read files, hit the network, or delete things just like you could from your own terminal.
  • Check which settings file you’re editing: .claude/settings.json is project-scoped and safe to commit; ~/.claude/settings.json is personal and stays on your machine only.
  • Never paste a hook script you got from someone else without reading it first. It’s a shell command that runs unattended, every time the event fires.
  • Test a new hook by hand before trusting it: pipe sample JSON into the script and check the exit code (echo $?) rather than assuming it works.
  • Remember a PostToolUse hook runs after the action already happened. It can clean up or flag, but it can’t undo. Use PreToolUse if you actually need to stop something before it runs.

Say it like a dev

Instead of: “make it format my code every time you change something” Say: “Add a PostToolUse hook in .claude/settings.json that runs prettier —write on any file the Edit or Write tool touches.”

Instead of: “tell me when you’re waiting on me” Say: “Set up a Notification hook that fires a desktop notification whenever you’re waiting on my input.”

Instead of: “never touch my .env file” Say: “Add a PreToolUse hook that blocks any Edit or Write to .env or package-lock.json and exits with code 2 so I get a reason in the transcript.”

People actually ask

“What are hooks in Claude Code?”

They're shell commands you register in a settings file that Claude Code runs automatically at specific moments: before a tool runs, after a file edit, when Claude finishes responding, and more. They're enforced by the app itself, not something Claude chooses to do.

“How do I run something automatically when Claude finishes?”

Add a Stop hook to your .claude/settings.json. It fires every time Claude finishes responding to a turn. If you want a ping specifically when Claude is idle and waiting on you rather than after every single response, use a Notification hook instead.

“Are hooks safe to use with scripts I find online?”

Only if you read them first. Hooks run with your full user permissions and no sandbox, so a hook command can touch any file or make any network call you could make yourself. Treat an unread hook script the same way you'd treat an unread shell script someone emailed you.

Related terms

Checked against

Glim can explain your sessions, live.

The app watches your coding agent and narrates it in plain words. Waitlist is open.

Join the waitlist