Skip to content
Agentmart
Submit a tool

hook

Create, debug, and audit Claude Code hooks in settings.json, plugins, or skill frontmatter.

Skill by nq-rdl

IndexedCC-BY-4.0
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/nq-rdl-hook

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Create, debug, and audit Claude Code hooks in settings.json, plugins, or skill frontmatter. Use for PreToolUse, PostToolUse, PermissionRequest, Stop, SessionStart, or UserPromptSubmit hooks; command blocking, auto-formatting, auto-approval, context injection, or completion checks; or when hook output is ignored or looks like prompt injection. Not for Git hooks such as pre-commit.

Use cases: security, agent-building

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/hook

What's inside

Skill name
hook
Description
Create, debug, and audit Claude Code hooks in settings.json, plugins, or skill frontmatter. Use for PreToolUse, PostToolUse, PermissionRequest, Stop, SessionStart, or UserPromptSubmit hooks; command blocking, auto-formatting, auto-approval, context injection, or completion checks; or when hook output is ignored or looks like prompt injection. Not for Git hooks such as pre-commit.
License
CC-BY-4.0
Compatibility
Claude Code 2.1.x; the hook `if` field requires v2.1.85+. Event contracts checked against the hooks reference with Claude Code 2.1.284 on 2026-09-29; re-check https://code.claude.com/docs/en/hooks when behavior differs.
Metadata
repo: https://github.com/nq-rdl/agent-extensions
Instructions
185 lines in SKILL.md · view on GitHub

Files (16)

  • SKILL.md
  • auto-approve-exit-plan.json · assets/
  • auto-format.json · assets/
  • block-rm-rf.json · assets/
  • prompt-hook-stop.json · assets/
  • protect-env-files.json · assets/
  • safe-context-injection.json · assets/
  • stop-checklist.json · assets/
  • claude-code.rst · references/
  • debugging.rst · references/
  • lifecycle.rst · references/
  • output.rst · references/
  • prompt-and-agent-hooks.rst · references/
  • prompt-injection.rst · references/
  • recipes.rst · references/
  • workflows.rst · references/

SKILL.md (first lines)

## Codex execution

This skill describes another host. Claude Code/OpenCode commands, configuration, and hook examples below are artifacts for that host, not tools available in Codex. Use Codex tools to inspect or author them; launch the target host only when the user requests execution and it is installed. Do not configure Codex as Claude Code.

# Claude Code Hooks

Hooks are **user-defined commands that execute at specific points in Claude Code's
lifecycle**. They give deterministic control over behavior — an action *always*
happens, rather than relying on the model to choose to run it. Use them to enforce
project rules, automate repetitive tasks (formatting, logging), block dangerous
operations, and inject context.

> Summaries of the official docs, with source links, live in `references/`. Read the
> matching reference before writing or debugging a hook — the I/O contract has
> changed across Claude Code versions and getting it wrong is the most common bug.

---

## Decision tree — pick the right hook type

| You want to… | Use | Reference |
|--------------|-----|-----------|
| Run a deterministic check/script (block, format, log) | `type: "command"` | `references/claude-code.rst` |
| Call a web service / shared endpoint | `type: "http"` | `references/claude-code.rst` |
| Call a tool on a connected MCP server | `type: "mcp_tool"` | `references/claude-code.rst` |
| Make a yes/no judgment with a model | `type: "prompt"` | `references/prompt-and-agent-hooks.rst` |
| Verify against real codebase state (run tests, read files) | `type: "agent"` *(experimental)* | `references/prompt-and-agent-hooks.rst` |

> **`prompt` hooks are NOT static text.** A common misconception (and a bug in old
> versions of this skill) is that `type: "prompt"` injects a fixed reminder string.
> It does not. It sends your prompt + the event data to a Claude model that returns
> `{"ok": true|false, "reason": "..."}`. See `references/prompt-and-agent-hooks.rst`.

## Where hooks live

| Location | Scope | Shareable |
|----------|-------|-----------|
| `~/.claude/settings.json` | All your projects | No (your machine) |
| `.claude/settings.json` | One project | Yes — commit it |
| `.claude/settings.local.json` | One project | No — gitignored |
| Managed policy settings | Organization-wide | Admin-controlled |
| Plugin `hooks/hooks.json` | When plugin enabled | Bundled with plugin |
| Skill frontmatter | From invocation to session end | In the skill |
| Subagent frontmatter | While that subagent runs | In the agent |

Run `/hooks` in Claude Code to browse configured hooks (read-only; edit the JSON or
ask Claude to change them). Set `"disableAllHooks": true` to turn them all off.

## Configuration shape

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check.sh",
            "if": "Bash(git *)",
            "timeout": 10
          }
        ]
      }
    ]
  }
}
```

- **matcher** — filters *which* calls fire the hook. Meaning depends on the event
  (tool name for tool events, `startup`/`resume`/… for `SessionStart`, etc.). Omit
  to match everything. See the matcher table in `references/claude-code.rst`.
- **if** (v2.1.85+) — filters by tool name *and arguments* using permission-rule
  syntax (`"Bash(git *)"`, `"Edit(*.ts)"`). Tool events only.
- **type** — `command` (default), `http`, `mcp_tool`, `prompt`, or `agent`.
- **timeout** — seconds. Defaults: command/http/mcp_tool 10 min (30 s under
  `UserPromptSubmit` and the model-switch events), prompt 30 s, agent 60 s.

## The I/O contract (read this before writing output)

A hook reads **event JSON on stdin** and replies through **stdout + exit code**.

**Exit codes** (command hooks):

| Code | Meaning |
|------|---------|
| `0` | No objection. stdout is parsed as JSON for structured control. For `UserPromptSubmit`, `UserPromptExpansion`, `SessionStart`, and `PostModelSwitch`, plain stdout is added to context. |
| `2` | Blocks on events that can block, even if JSON says `allow`. The message is the JSON `reason` if present, else stderr; it goes to Claude for `PreToolUse` but only to the user for `UserPromptSubmit`. `PermissionRequest` ignores exit 2. Per-event effects: `references/lifecycle.rst`. |
| other | Without valid JSON: non-blocking error (even exit 1); the action proceeds. With valid decision JSON, the JSON decides. |

> Pick one channel: **exit 2 + stderr** *or* **exit 0 + JSON**. Mixing is
> legal but confusing: exit 2 always blocks, and a JSON `reason` replaces
> stderr as the message.

**Structured JSON output** — `PreToolUse` permission control (current canonical form):

```json
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Use rg instead of grep"
  }
}
```

`permissionDecision` is one of `allow` / `deny` / `ask` (and `defer` in `-p` mode).
**Other events use different shapes** — `PostToolUse`/`Stop` use top-level
`{"decision": "block", "reason": "..."}`; `PermissionRequest` uses
`hookSpecificOutput.decision.behavior`. The full per-event matrix is in
`references/output.rst`. The legacy `{"decision":"approve"}` form for `PreToolUse`
is superseded by `permissionDecision` — don't use it for new hooks.

## ⚠️ Hook output vs. prompt injection

This is the concern most people hit. Text returned via `additionalContext` (or
plain stdout on `SessionStart`/`UserPromptSubmit`/`UserPromptExpansion`) is injected as a **system
reminder that Claude reads as plain text**. If you phrase it as imperative,

From nq-rdl/agent-extensions, CC-BY-4.0.

More from nq-rdl/agent-extensions

Signals

Stars
0
Forks
1
Open issues
15
Last commit (this folder)
Sep 29, 2026 (1 month ago)
Last release
Oct 16, 2026 (13 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
CC-BY-4.0
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from nq-rdl

Cite this page

hook skill. Agent Mart. https://agentmart.dev/skills/nq-rdl-hook (last updated 2026-10-24)