DocsWhat may it doClaude Code hooks

Claude Code hooks, and using them to govern every tool call

Claude Code hooks are commands that Claude Code runs at fixed points in a session, such as before a tool call, after one, or when a prompt is submitted. A hook sees what is about to happen and can change the outcome, which makes it the one place a rule can stand in front of the agent without the agent having to cooperate.

This page covers the hooks that matter for keeping an agent safe, how a PreToolUse hook decides a call, and what it takes to turn that into rules that hold. The last part is what Memnox installs for you.

The hook events that matter for safety

Claude Code has many hook events. Four of them decide what an agent does:

EventWhen it firesWhat it is good for
SessionStarta session begins or resumestelling the agent the rules before it plans
UserPromptSubmityou submit a prompt, before Claude reads itadding what the team already decided about the subject
PreToolUsebefore a tool call runsallowing, asking about or denying the call
PostToolUseafter a tool call succeedschecking what a command actually changed

How a hook is configured

Hooks live in settings.json under the event name, with an optional matcher that picks which tools the hook applies to:

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{ "type": "command", "command": "./check-command.sh" }]
      }
    ]
  }
}

The command receives the tool call as JSON on its standard input.

How a PreToolUse hook allows, asks or denies

A PreToolUse hook decides a call in one of two ways.

  • Exit code 2 always blocks the call, and whatever the hook printed to standard error is shown to Claude as the reason.
  • Exit code 0 with JSON decides through hookSpecificOutput, with permissionDecision set to allow, ask or deny, and a permissionDecisionReason that Claude sees on a deny and you see on an ask.
json
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "main is shared. Push a branch and open a PR."
  }
}

A deny from a hook still blocks the call in bypassPermissions mode, which is what --dangerously-skip-permissions starts. Skipping the prompts does not skip the hooks, and that is why a hook is the right place for a rule you never want switched off.

Why a hand-written hook stops short

One script is easy to write. Keeping it right is the hard part.

  • It only covers Claude Code. Codex, Cursor, Gemini CLI and Windsurf each have their own hook format, and a rule in one does nothing in the others.
  • A shell command has to be parsed. git push --force origin main and git push origin feature are both Bash, so the script has to understand every command it cares about, including one hidden inside sh -c.
  • A deny with no way forward stalls the agent. The reason has to say what to do instead, or the agent retries or gives up.
  • Nobody sees what it decided. A script that exits 2 leaves no record of why, or of how often.

Memnox is those hooks, written once

memnox setup installs the hooks for you, in every agent it finds, and they all read one rule file:

bash
npm install -g memnox
memnox setup

In Claude Code it wires the four events above:

  • SessionStart tells the agent where it stands: the mode, what is never run here, what asks first, and the project boundary.
  • UserPromptSubmit adds a decision your team already took when a prompt touches it, with who confirmed it and where.
  • PreToolUse answers every tool call with allow, ask or deny, from rules matched against the action rather than a model's judgement. A deny names what to use instead, so the agent finishes the task.
  • PostToolUse reads what a shell command actually wrote, so an edit made through sed -i is held to the same checks as one made with the edit tool.

The same rules reach Codex, Cursor, Gemini CLI and Windsurf through their own hooks, and every verdict is recorded, so memnox why can say why a call was refused. Memnox in your session shows exactly what the agent is told, and Coding agent permissions compares this with each agent's own permission modes.

Questions people ask

What is a PreToolUse hook in Claude Code?

A command Claude Code runs before every tool call it matches. It can let the call run, ask you about it, or block it with a reason, through its exit code or a JSON permissionDecision.

Do hooks run with --dangerously-skip-permissions?

Yes. Skipping permissions removes the prompts, not the hooks, and a deny from a PreToolUse hook still blocks the call in bypassPermissions mode.

Can a hook ask me instead of blocking?

Yes. Return permissionDecision set to ask, and Claude Code shows its own permission prompt with the hook's reason in it.

Do Cursor, Codex and Gemini CLI have hooks too?

Each has its own hook system in its own format. Memnox installs a hook in each of them from one rule file, so the same call gets the same verdict whichever agent makes it.