home / skills / vasilyu1983 / ai-agents-public / agents-hooks

agents-hooks skill

/frameworks/shared-skills/skills/agents-hooks

This skill automates Claude Code workflows with event-driven hooks, enabling input validation, safe tool use, formatting, auditing, and CI/CD integration.

npx playbooks add skill vasilyu1983/ai-agents-public --skill agents-hooks

Review the files below or copy the command above to add this skill to your agents.

Files (7)
SKILL.md
10.2 KB
---
name: agents-hooks
description: Event-driven hooks for AI coding agents. Use when automating Claude Code or Codex CLI with stdin JSON and decision-control responses.
---

# Claude Code Hooks — Meta Reference

This skill provides the definitive reference for creating Claude Code hooks. Use this when building automation that triggers on Claude Code events.

---

## When to Use This Skill

- Building event-driven automation for Claude Code
- Creating PreToolUse guards to block dangerous commands
- Implementing PostToolUse formatters, linters, or auditors
- Adding Stop hooks for testing or notifications
- Setting up SessionStart/SessionEnd for environment management
- Integrating Claude Code with CI/CD pipelines (headless mode)

---

## Quick Reference

| Event | Trigger | Use Case |
|-------|---------|----------|
| `SessionStart` | Session begins/resumes | Initialize environment |
| `UserPromptSubmit` | User submits prompt | Preprocess/validate input |
| `PreToolUse` | Before tool execution | Validate, block dangerous commands |
| `PermissionRequest` | Permission dialog shown | Auto-allow/deny permissions |
| `PostToolUse` | After tool succeeds | Format, audit, notify |
| `PostToolUseFailure` | After tool fails | Capture failures, add guidance |
| `SubagentStart` | Subagent spawns | Inspect subagent metadata |
| `Stop` | When Claude finishes | Run tests, summarize |
| `SubagentStop` | Subagent finishes | Verify subagent completion |
| `Notification` | On notifications | Alert integrations |
| `PreCompact` | Before context compaction | Preserve critical context |
| `Setup` | `--init`/`--maintenance` | Initialize repo/env |
| `SessionEnd` | Session ends | Cleanup, save state |
## Hook Structure

```text
.claude/hooks/
├── pre-tool-validate.sh
├── post-tool-format.sh
├── post-tool-audit.sh
├── stop-run-tests.sh
└── session-start-init.sh
```
---

## Configuration

### settings.json

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/post-tool-format.sh"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-tool-validate.sh"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/stop-run-tests.sh"
          }
        ]
      }
    ]
  }
}
```

---

## Execution Model (Jan 2026)

- Hooks receive a JSON payload via stdin (treat it as untrusted input) and run with your user permissions (outside the Bash tool sandbox).
- Default timeout is 60s per hook command; all matching hooks run in parallel; identical commands are deduplicated.

### Hook Input (stdin)

```json
{
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "ls -la"
  }
}
```

### Environment Variables (shell)

| Variable | Description |
|----------|-------------|
| `CLAUDE_PROJECT_DIR` | Absolute project root where Claude Code started |
| `CLAUDE_PLUGIN_ROOT` | Plugin root (plugin hooks only) |
| `CLAUDE_CODE_REMOTE` | `"true"` in remote/web environments; empty/local otherwise |
| `CLAUDE_ENV_FILE` | File path to persist `export ...` lines (available in SessionStart; check docs for Setup support) |

---

## Exit Codes

| Code | Meaning | Notes |
|------|---------|------|
| `0` | Success | JSON written to stdout is parsed for structured control |
| `2` | Blocking error | `stderr` becomes the message; JSON in stdout is ignored |
| Other | Non-blocking error | Execution continues; `stderr` is visible in verbose mode |

Stdout injection note: for `UserPromptSubmit`, `SessionStart`, and `Setup`, non-JSON stdout (exit 0) is injected into Claude’s context; most other events show stdout only in verbose mode.

---

## Decision Control + Input Modification (v2.0.10+)

PreToolUse hooks can allow/deny/ask and optionally modify the tool input via `updatedInput`.

### Hook Output Schema

```json
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "Reason shown to user (and to Claude on deny)",
    "updatedInput": { "command": "echo 'modified'" },
    "additionalContext": "Extra context added before tool runs"
  }
}
```

Note: older `decision`/`reason` fields are deprecated; prefer the `hookSpecificOutput.*` fields.

See [hook-templates.md](references/hook-templates.md) for full examples: redirect sensitive file edits to `/dev/null` and strip `.env` files from `git add` commands.

---

## Prompt-Based Hooks

For complex decisions, use LLM-evaluated hooks (`type: "prompt"`) instead of bash scripts. They are most useful for `Stop` and `SubagentStop` decisions.

### Configuration

```json
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Evaluate whether Claude should stop. Context JSON: $ARGUMENTS. Return {\"ok\": true} if all tasks are complete, otherwise {\"ok\": false, \"reason\": \"what remains\"}.",
            "timeout": 30
          }
        ]
      }
    ]
  }
}
```

### Response Schema

- Allow: `{"ok": true}`
- Block: `{"ok": false, "reason": "Explanation shown to Claude"}`

### Combining Command and Prompt Hooks

Use command hooks for fast, deterministic checks. Use prompt hooks for nuanced decisions:

```json
{
  "Stop": [
    {
      "hooks": [
        { "type": "command", "command": ".claude/hooks/quick-check.sh" },
        { "type": "prompt", "prompt": "Verify code quality meets standards" }
      ]
    }
  ]
}
```

---

## Permission Prompt Fatigue Reduction Pattern

Use this when frequent approval dialogs slow down repeated safe workflows.

### Strategy

1. Identify repetitive, low-risk command prefixes (for example: test runners, read-only diagnostics).
2. Approve narrow prefixes instead of full commands.
3. Keep destructive or broad shells (`rm`, `git reset --hard`, generic interpreters with arbitrary input) out of auto-approval rules.
4. Re-check approved prefixes periodically; remove stale ones.

### Practical Guardrails

- Allow only task-scoped prefixes (example: `npm run test:e2e`), not unrestricted executors.
- Keep separate policy for write-outside-workspace actions.
- Pair allow-rules with deny-rules for dangerous patterns.

### Outcome

This reduces repeated permission interruptions while preserving high-safety boundaries.


## Runtime Preflight Hooks (Mandatory for Tool Reliability)

Add a lightweight runtime preflight hook when workflows depend on specific local tool versions (for example Node for JS REPL, test runners, linters).

### Preflight Responsibilities

- Verify required binaries exist.
- Verify minimum version constraints.
- Emit a clear remediation message when requirements are not met.
- Fail fast before expensive task execution starts.

### Recommended Trigger

- `SessionStart` for general runtime checks.
- `Setup` for repository bootstrap checks.

### Minimal Policy

- Keep checks deterministic and fast (<1s target).
- Do not auto-install dependencies silently in hooks.
- Print exact command the operator should run to remediate.

## Hook Templates

Copy-paste templates for the five most common hook scenarios: PreToolUse validation, PostToolUse formatting, PostToolUse security audit, Stop test runner, and SessionStart environment check.

See [references/hook-templates.md](references/hook-templates.md) for all scripts.

---

## Matchers

Matchers filter which tool triggers the hook:

- Exact match: `Write` matches only the Write tool
- Regex: `Edit|Write` or `Notebook.*`
- Match all: `*` (also works with `""` or omitted matcher)

---

## Security Best Practices

Hooks run with full user permissions outside the Bash tool sandbox. Key rules: validate all stdin input, quote every variable (`"$VAR"`), use absolute paths, never `eval` untrusted data, and set `-euo pipefail`.

See [references/hook-security.md](references/hook-security.md) for the full checklist, command injection prevention, path traversal defense, credential protection, and ShellCheck requirements.

---

## Hook Composition

### Multiple Hooks on Same Event

```json
{
  "PostToolUse": [
    {
      "matcher": "Edit|Write",
      "hooks": [
        { "type": "command", "command": ".claude/hooks/format.sh" },
        { "type": "command", "command": ".claude/hooks/audit.sh" },
        { "type": "command", "command": ".claude/hooks/notify.sh" }
      ]
    }
  ]
}
```

All matching hooks run in parallel. If you need strict ordering (format → lint → test), make one wrapper script that runs them sequentially.

---

## Debugging Hooks

```bash
# Test a PostToolUse hook manually (stdin JSON)
export CLAUDE_PROJECT_DIR="$(pwd)"
echo '{"hook_event_name":"PostToolUse","tool_name":"Edit","tool_input":{"file_path":"'"$(pwd)"'/src/app.ts"}}' \
  | bash .claude/hooks/post-tool-format.sh

# Check exit code
echo $?
```

---

## Navigation

### Resources

- [references/hook-templates.md](references/hook-templates.md) — Copy-paste hook scripts
- [references/hook-patterns.md](references/hook-patterns.md) — Common patterns
- [references/hook-security.md](references/hook-security.md) — Security guide
- [references/runtime-preflight-hooks.md](references/runtime-preflight-hooks.md) — Runtime/version preflight patterns for SessionStart and Setup
- [data/sources.json](data/sources.json) — Documentation links
- [assets/template-preflight-runtime-hook.sh](assets/template-preflight-runtime-hook.sh) — Shell hook template for runtime/tool version checks

### Related Skills

- [../agents-subagents/SKILL.md](../agents-subagents/SKILL.md) — Agent creation
- [../agents-skills/SKILL.md](../agents-skills/SKILL.md) — Skill creation
- [../ops-devops-platform/SKILL.md](../ops-devops-platform/SKILL.md) — CI/CD integration

## Fact-Checking

- Use web search/web fetch to verify current external facts, versions, pricing, deadlines, regulations, or platform behavior before final answers.
- Prefer primary sources; report source links and dates for volatile information.
- If web access is unavailable, state the limitation and mark guidance as unverified.

Overview

This skill provides event-driven hooks for AI coding agents, focused on automating Claude Code or Codex CLI workflows using stdin JSON and decision-control responses. It defines hook events, input/output schemas, execution rules, and practical templates to guard, modify, or augment tool runs. Use it to enforce safety, run fast checks, and integrate agent runs into CI/CD pipelines.

How this skill works

Hooks are configured in a settings.json mapping events to command or prompt handlers. Each hook receives a JSON payload via stdin and runs as a normal user process with a 60s default timeout; matching hooks run in parallel and identical commands are deduplicated. PreToolUse hooks can return structured decision-control JSON (allow/deny/ask and updatedInput) and prompt hooks allow LLM-evaluated decisions for nuanced cases.

When to use it

  • Automating event-driven workflows for Claude Code or Codex CLI
  • Blocking or modifying dangerous shell/tool invocations (PreToolUse)
  • Formatting, auditing, or notifying after successful tool runs (PostToolUse)
  • Initializing runtime or repo state at session start or setup
  • Running tests or summaries when the agent stops

Best practices

  • Treat stdin JSON as untrusted input and validate it before use
  • Use absolute paths, quote variables, and avoid eval to prevent injection
  • Keep runtime preflight checks deterministic and fast (<1s target) and fail with clear remediation commands
  • Prefer command hooks for deterministic checks and prompt hooks for nuanced policy decisions
  • If strict ordering is required, wrap multiple steps in a single script rather than relying on parallel execution

Example use cases

  • PreToolUse guard that blocks destructive git or rm commands and suggests safer alternatives
  • PostToolUse formatter plus linter run on edited files before committing changes
  • SessionStart preflight that verifies required binaries and versions and prints remediation steps
  • Stop hook that runs test suite and writes a summary report to stdout for injection into the final context
  • Permission auto-allow rules for repetitive, low-risk command prefixes paired with deny rules for dangerous patterns

FAQ

How do hooks communicate decisions back to Claude?

Hooks exit 0 and write structured JSON to stdout under hookSpecificOutput; PreToolUse can return permissionDecision and updatedInput fields to allow/modify the tool run.

What happens if a hook fails or times out?

Exit code 2 blocks the action and shows stderr as the message; non-zero other than 2 is non-blocking and visible in verbose mode. Default timeout is 60s; handle failures with clear diagnostics.