Skip to content
Development
Skill

/claude-hook-writer

Expert guidance for writing secure, reliable, and performant Claude Code hooks - validates design decisions, enforces best practices, and prevents common pitfalls. Use when creating, reviewing, or debugging Claude Code hooks.

From plugin
secondsky-claude-skills
219183 skills42 agents62 commands2 MCP
Install
$ npx -y skills add secondsky/claude-skills --skill claude-hook-writer --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/claude-hook-writer

Context preview

The summary Claude sees to decide when to auto-load this skill.

Expert guidance for writing secure, reliable, and performant Claude Code hooks - validates design decisions, enforces best practices, and prevents common pitfalls. Use when creating, reviewing, or debugging Claude Code hooks.

SKILL.md

claude-hook-writer.SKILL.md
name: claude-hook-writer
description: Expert guidance for writing secure, reliable, and performant Claude Code hooks - validates design decisions, enforces best practices, and prevents common pitfalls. Use when creating, reviewing, or debugging Claude Code hooks.
metadata:
  version: 2.0.0
  author: Claude Skills Maintainers
  last_verified: 2025-12-17
  optimization_date: 2025-12-17
  token_savings: ~55%
  errors_prevented: 5
license: MIT

Claude Hook Writer

**Status**: Production Ready **Version**: 2.0.0 (Optimized with progressive disclosure) **Last Updated**: 2025-12-17

---

Overview

Expert guidance for writing secure, reliable, and performant Claude Code hooks. This skill validates design decisions, enforces best practices, and prevents common pitfalls.

---

When to Use This Skill

  • Designing a new Claude Code hook
  • Reviewing existing hook code
  • Debugging hook failures
  • Optimizing slow hooks
  • Securing hooks that handle sensitive data
  • Publishing hooks as PRPM packages

---

Core Principles

1. Security is Non-Negotiable

Hooks execute automatically with user permissions and can read, modify, or delete any file the user can access.

**ALWAYS validate and sanitize all input.** Hooks receive JSON via stdin—never trust it blindly.

**For complete security patterns**: Load `references/security-requirements.md` when implementing validation or securing hooks.

2. Reliability Over Features

A hook that works 99% of the time is a broken hook. Edge cases (Unicode filenames, spaces in paths, missing tools) will happen.

**Test with edge cases before deploying.**

**For reliability patterns**: Load `references/reliability-performance.md` when handling errors or edge cases.

3. Performance Matters

Hooks block operations. A 5-second hook means Claude waits 5 seconds before continuing.

**Keep hooks fast. Run heavy operations in background.**

**For performance optimization**: Load `references/reliability-performance.md` when optimizing hook speed.

4. Fail Gracefully

Missing dependencies, malformed input, and disk errors will occur.

**Handle errors explicitly. Log failures. Return meaningful exit codes.**

---

Hook Design Checklist

Before writing code, answer these questions:

What Event Does This Hook Target?

  • `PreToolUse` - Before tool execution (modify input, validate, block)
  • `PostToolUse` - After tool completes (format, log, cleanup)
  • `UserPromptSubmit` - Before user input processes (validate, enhance)
  • `SessionStart` - When Claude Code starts (setup, env check)
  • `SessionEnd` - When Claude Code exits (cleanup, persist state)
  • `Notification` - During alerts (desktop notifications, logging)
  • `Stop` / `SubagentStop` - When responses finish (cleanup, summary)
  • `PreCompact` - Before context compaction (save important context)

**Common mistake:** Using PostToolUse for validation (too late—tool already ran). Use PreToolUse to block operations.

Which Tools Should Trigger This Hook?

Be specific. `matcher: "*"` runs on every tool call.

**Good matchers:**

  • `"Write"` - Only file writes
  • `"Edit|Write"` - File modifications
  • `"Bash"` - Shell commands
  • `"mcp__github__*"` - All GitHub MCP tools

**Bad matchers:**

  • `"*"` - Everything (use only for logging/metrics)

What Input Does This Hook Need?

Different tools provide different input. Check what's available:

# PreToolUse / PostToolUse
{
  "input": {
    "file_path": "/path/to/file.ts",     // Read, Write, Edit
    "command": "npm test",                // Bash
    "old_string": "...",                  // Edit
    "new_string": "..."                   // Edit
  }
}

**Validate fields exist before using them:**

FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty')
if [[ -z "$FILE" ]]; then
  echo "No file path provided" >&2
  exit 1
fi

Should This Be a Command Hook or Prompt Hook?

**Command hooks** (`type: "command"`):

  • Fast (milliseconds)
  • Deterministic
  • Good for: formatting, logging, file checks

**Prompt hooks** (`type: "prompt"`):

  • Slow (2-10 seconds)
  • Context-aware (uses LLM)
  • Good for: complex validation, security analysis, intent detection

**Rule of thumb:** Use command hooks unless you need LLM reasoning.

What Exit Code Communicates Success/Failure?

  • `exit 0` - Success (continue operation)
  • `exit 2` - Block operation (show error to Claude)
  • `exit 1` or other - Non-blocking error (log but continue)

**For PreToolUse hooks:**

  • Exit 2 blocks the tool from running
  • Exit 0 allows it (optionally with modified input)

**For PostToolUse hooks:**

  • Exit codes don't block (tool already ran)
  • Use exit 0 for success, 1 for logging errors

---

Top 5 Pitfalls (Must Know)

Pitfall #1: Not Quoting Variables

**Error**: Hooks break on filenames with spaces or special characters

**Why**: Unquoted variables split on whitespace

**Example**:

# ❌ WRONG - breaks on "my file.txt"
cat $FILE
prettier --write $FILE
rm $FILE

# ✅ RIGHT - handles spaces and special chars
cat "$FILE"
prettier --write "$FILE"
rm "$FILE"

**Why this matters**: Files with spaces (`"my file.txt"`), Unicode (`"文件.txt"`), or special chars (`"file (1).txt"`) are common.

**For quoting best practices**: Load `references/security-requirements.md` for comprehensive input handling patterns.

---

Pitfall #2: Trusting Input Without Validation

**Error**: Hook executes on malicious or malformed input

**Why**: Not validating JSON fields before using them

**Example**:

# ❌ DANGEROUS - no validation
FILE=$(jq -r '.input.file_path')
rm "$FILE"  # Could delete ../../../etc/passwd

# ✅ SAFE - validate first
FILE=$(jq -r '.input.file_path // empty')
[[ -n "$FILE" ]] || exit 1
[[ "$FILE" == "$CLAUDE_PROJECT_DIR"* ]] || exit 2
[[ "$FILE" != *".."* ]] || exit 2
rm "$FILE"

**Why this matters**: Prevents path traversal attacks, protects files outside project, prevents malformed input crashes.

**For complete security patterns**: Load `references/

Read more
Ships withsecondsky-claude-skills

145 production-ready skills for Claude Code CLI 🔌 Platform / Harness Support These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests).

Get the whole plugin

Other skills on secondsky-claude-skills.