HookStack
All guides

10 Claude Code Hooks Worth Installing (With Examples)

8 min read · Reviewed 2026-06-12

Claude Code hooks are shell or Node scripts that fire on lifecycle events — before a tool runs, after a file is written, when the agent finishes. They turn vague intentions like “don’t touch main” or “always run the tests” into deterministic rules the agent cannot skip. The hard part is not the mechanism; it is knowing which hooks are actually worth the wiring.

This is an opinionated roundup of eight hooks that pay for themselves on the first session, drawn from the HookStack catalogue. Each one names the event it binds to and the concrete outcome it buys you. You can install any of them in a minute with the HookStack CLI, covered at the end.

Why install hooks instead of writing them?

You can write any of these yourself — a hook is just a script wired into .claude/settings.json. The reason to install from a catalogue is that the edge cases are already handled: correct exit-code semantics, the right decision/reason shape on stdout, extension filtering so heavy tools don’t run on every file, and timeouts so a hook never hangs your session.

Installing also keeps the executable script and its settings entry in sync. The CLI writes the script to .claude/hooks/ and patches settings.json for you, so you avoid the most common failure mode: a hook that is on disk but never registered, or registered against the wrong event.

Block a leaked secret before a shell command runs

This PreToolUse hook inspects the command the agent is about to run and blocks it if it contains something that looks like a credential — an API key, a token, an AWS_SECRET value pasted inline. Instead of the secret reaching your shell history or a remote service, the tool call is rejected with an actionable reason.

  • Event: PreToolUse (matcher Bash)
  • Outcome: a command carrying a secret never executes.

Stop a disk-wiping command like rm -rf

The single most expensive mistake an agent can make is a destructive shell command. This PreToolUse hook pattern-matches the proposed Bash command against known-dangerous shapes (rm -rf, git reset --hard on dirty trees, dd to a device, recursive chmod) and returns { decision: 'block' } before anything runs. It earns its place by being the one rule you never want to rely on a prompt to enforce.

Refuse edits on main until you branch

A PreToolUse guard that checks the current git branch before any Write or Edit is applied. If you are on main (or master), it blocks the edit and tells the agent to create a feature branch first. This keeps experimental agent work off your protected branch without you having to remember to branch every session.

  • Event: PreToolUse (matcher Write|Edit)
  • Outcome: no file changes land on main by accident.

Lint and fix every file the moment it is written

This PostToolUse hook runs ESLint with --fix on each file the agent writes or edits, filtered to JavaScript and TypeScript extensions so it stays fast. Style and trivially fixable errors are corrected immediately, which means the agent works against already-clean files instead of accumulating a lint debt you discover at commit time. Being a PostToolUse hook, it is non-blocking: if ESLint is not installed, it stays silent.

Run the test suite when Claude says it is done

A Stop hook fires when the agent finishes a turn. This one runs your test command at that moment, so “I’m done” is verified rather than trusted. If tests fail, the result is surfaced back into the session and the agent keeps working instead of leaving you with a red suite. It is the cheapest way to close the gap between an agent claiming success and the code actually passing.

  • Event: Stop
  • Outcome: every completed turn ends on a green (or visibly red) test run.

Inject your project conventions on every prompt

A UserPromptSubmit hook runs each time you send a message and prepends context to it — your naming conventions, the packages you forbid, the way you structure modules. Rather than repeating house rules in every prompt or hoping they survive in CLAUDE.md, you inject them deterministically at the moment they matter, so the agent reads them on every single turn.

Load git repo state at session start

A SessionStart hook runs once when a session begins and feeds the agent the current git context: the branch, recent commits, and the working-tree status. The agent opens already knowing where it is in history, so it stops re-discovering the repo state with redundant git calls and avoids acting on stale assumptions about what changed.

  • Event: SessionStart
  • Outcome: the agent starts oriented, not blind.

Ping Slack when the agent needs you

A Notification hook fires when Claude Code raises a notification — typically when it is waiting on you for permission or input. This one posts to a Slack webhook so you can step away from a long-running session and get pulled back exactly when the agent is blocked, instead of babysitting the terminal.

How do you install these?

Every hook above is in the HookStack catalogue. The fastest path is the CLI: pick a stack or individual hooks on hookstack.app, copy the generated command, and run it in your project. A minimal install looks like this.

npx hookstack-cli@latest install

The CLI writes each selected script into .claude/hooks/ and patches your .claude/settings.json so the hook is registered against the correct event and matcher. Your existing settings and permissions are preserved — it merges, it does not overwrite. A registered entry looks like the following, pointing at the script the CLI just wrote.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/pre-bash-block-destructive.mjs" }
        ]
      }
    ]
  }
}

After installing, open a new session so the hooks load, and confirm them with a harmless test — for example, ask the agent to run a blocked command and watch the PreToolUse guard reject it.

Frequently asked questions

What are the best Claude Code hooks to start with?
Begin with the safety hooks — secret detection and destructive-command blocking on `PreToolUse` — because they prevent irreversible mistakes. Then add a `Stop` hook that runs your tests and a `PostToolUse` linter so quality is enforced automatically rather than reviewed manually.
Do hooks slow down Claude Code?
Well-written hooks are negligible. `PreToolUse` hooks do cheap pattern matching, and `PostToolUse` tools like ESLint should filter by file extension so they only run on relevant files. Always set an explicit timeout so a hook can never hang the session.
Can a hook actually stop Claude from doing something?
Yes, but only `PreToolUse` hooks. They run before a tool executes and can return `{ decision: 'block', reason: '…' }` on stdout to reject the call. `PostToolUse`, `Stop`, and `SessionStart` hooks react or inject context but cannot retroactively undo a completed action.
Where do installed hooks live?
Scripts go in your project’s `.claude/hooks/` directory and are referenced from `.claude/settings.json` via `$CLAUDE_PROJECT_DIR`. The HookStack CLI writes both, so the script on disk and its registration stay in sync.

Related hooks

Sources

Read next