<!--
Hook Creator
Part of the Bles Software agent skills repository:
https://www.bles-software.com/claude-skills

Install for Claude Code:
  mkdir -p ~/.claude/skills/hook-creator
  mv hook-creator.md ~/.claude/skills/hook-creator/SKILL.md

Install for Codex:
  mkdir -p ~/.codex/skills/hook-creator
  mv hook-creator.md ~/.codex/skills/hook-creator/SKILL.md

For Gemini CLI and other agents, drop the body of this file into the
project instruction file the agent already reads.

Note: in production this skill also ships 3 helper file(s) alongside
SKILL.md. The procedure below is complete and self-contained; the helpers are
convenience scripts you can rebuild from the steps described here.
-->

---
name: hook-creator
description: |
  Creates Claude Code hooks for automated responses to tool events.
  Use when user wants to create a hook, automate tool responses, add
  pre/post tool actions, intercept commands, or customize Claude Code behavior.
  Hooks are JSON configs in settings files that trigger on 8 event types.
allowed-tools: Read, Write, Edit, Bash
---

# Creating Claude Code Hooks

Create hooks by editing settings files directly. No external scripts needed.

## Settings File Locations

| Scope | Path | Use Case |
|-------|------|----------|
| User (global) | `~/.claude/settings.json` | All projects |
| Project | `.claude/settings.json` | This project, shared |
| Project local | `.claude/settings.local.json` | This project, not committed |

## Hook JSON Structure

```json
{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "shell command here",
            "timeout": 30
          }
        ]
      }
    ]
  }
}
```

## Hook Events

| Event | Matcher | Description |
|-------|---------|-------------|
| `PreToolUse` | Tool names | Before tool executes |
| `PostToolUse` | Tool names | After tool completes |
| `PermissionRequest` | Tool names | Before permission prompt (return "approve" to auto-approve) |
| `Notification` | Tool names | System notifications |
| `UserPromptSubmit` | None | User sends message |
| `Stop` | None | Agent finishes (supports prompt hooks) |
| `SubagentStop` | None | Subagent finishes (supports prompt hooks) |
| `PreCompact` | `manual`, `auto` | Before context compaction |
| `SessionStart` | `startup`, `resume`, `clear`, `compact` | Session begins |
| `SessionEnd` | None | Session ends |

## Matchers

| Pattern | Matches |
|---------|---------|
| `"Bash"` | Bash tool only |
| `"Write\|Edit"` | Write OR Edit |
| `"Notebook.*"` | Regex match |
| `""` | All tools |
| `"mcp__server__*"` | MCP tools |

## Hook Types

**Command hooks** (all events):
```json
{ "type": "command", "command": "echo 'hello'", "timeout": 30 }
```

**Prompt hooks** (Stop/SubagentStop only) - uses Haiku LLM:
```json
{ "type": "prompt", "prompt": "Your prompt here", "timeout": 30 }
```

### CRITICAL: Prompt Hook Requirements

Prompt hooks use Haiku to evaluate and MUST return valid JSON. **If the prompt is too complex or doesn't explicitly request JSON, you get "JSON validation failed" error.**

**Required response format:**
```json
{"ok": true, "reason": "why complete"}
{"ok": false, "reason": "what's missing"}
```

**Rules for prompt hooks:**
1. **MUST start with:** `You must respond with ONLY valid JSON: {"ok": boolean, "reason": "string"}`
2. **Keep prompts SHORT** - Haiku struggles with complex multi-line prompts
3. **Show example responses** in the prompt
4. **Avoid bullet points and complex formatting** - use simple inline text

**BAD (will fail):**
```json
{
  "type": "prompt",
  "prompt": "Check the following:\n1. Are requirements done?\n2. Are tests passing?\n3. Is code reviewed?\nReturn ok:true if complete."
}
```

**GOOD (will work):**
```json
{
  "type": "prompt",
  "prompt": "You must respond with ONLY valid JSON: {\"ok\": boolean, \"reason\": \"string\"}\n\nIs this task complete? Check: requirements done, tests passing, no errors. Return {\"ok\": false, \"reason\": \"what's missing\"} if incomplete, {\"ok\": true, \"reason\": \"done\"} if complete."
}
```

## Exit Codes

| Code | Effect |
|------|--------|
| 0 | Success |
| 2 | Block - stderr sent to Claude |
| Other | Warning only |

## Common Patterns

### Log Bash Commands
```json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{ "type": "command", "command": "echo \"$(date): $TOOL_INPUT\" >> ~/.claude/commands.log" }]
    }]
  }
}
```

### Auto-Approve Read Operations
```json
{
  "hooks": {
    "PermissionRequest": [{
      "matcher": "Read|Glob|Grep",
      "hooks": [{ "type": "command", "command": "echo 'approve'" }]
    }]
  }
}
```

### Block Dangerous Commands
```json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash(rm -rf*|sudo*)",
      "hooks": [{ "type": "command", "command": "echo 'BLOCKED' >&2; exit 2" }]
    }]
  }
}
```

## Environment Variables in Hooks

- `$CLAUDE_PROJECT_DIR` - Project root path
- `$CLAUDE_ENV_FILE` - Write env vars here (SessionStart only)

## How to Create a Hook

1. Read the target settings file (create if missing)
2. Parse existing JSON (or start with `{}`)
3. Add/merge the `hooks` object with new hook configuration
4. Write back the updated JSON

## Workflow

1. Ask user: What should trigger the hook? (event + matcher)
2. Ask user: What should happen? (command or prompt)
3. Ask user: Where to save? (user/project/local)
4. Read existing settings file
5. Merge new hook into configuration
6. Write updated settings file
7. Inform user to restart Claude Code for hooks to take effect
