Claude Skills
CollectionsCompareWorkflowsNominate
Sign inSign up
© 2026 Curated Agent Skills·Learn more about Agent Skills
Back to repository

hooks-development

verified

Claude Code hooks development guide. TRIGGERS - create hook, PostToolUse, PreToolUse, Stop hook, hook lifecycle, decision block.

View on GitHub

Marketplace

cc-skills

terrylica/cc-skills

Plugin

itp-hooks

enforcement

Repository

terrylica/cc-skills
10stars

plugins/itp-hooks/skills/hooks-development/SKILL.md

Last Verified

February 5, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/terrylica/cc-skills/blob/main/plugins/itp-hooks/skills/hooks-development/SKILL.md -a claude-code --skill hooks-development

Installation paths:

Claude
.claude/skills/hooks-development/
Powered by add-skill CLI

Instructions

# Hooks Development

Guide for developing Claude Code hooks with proper output visibility patterns.

## When to Use This Skill

- Creating a new PostToolUse or PreToolUse hook
- Hook output is not visible to Claude (most common issue)
- User asks about `decision: block` pattern
- Debugging why hook messages don't appear
- User mentions "Claude Code hooks" or "hook visibility"

---

## Quick Reference: Visibility Patterns

**Critical insight**: PostToolUse hook stdout is only visible to Claude when JSON contains `"decision": "block"`.

| Output Format                  | Claude Visibility |
| ------------------------------ | ----------------- |
| Plain text                     | Not visible       |
| JSON without `decision: block` | Not visible       |
| JSON with `decision: block`    | Visible           |

**Exit code behavior**:

| Exit Code | stdout Behavior                         | Claude Visibility             |
| --------- | --------------------------------------- | ----------------------------- |
| **0**     | JSON parsed, shown in verbose mode only | Only if `"decision": "block"` |
| **2**     | Ignored, uses stderr instead            | stderr shown to Claude        |
| **Other** | stderr shown in verbose mode            | Not shown to Claude           |

---

## Minimal Working Pattern

```bash
/usr/bin/env bash << 'SKILL_SCRIPT_EOF'
#!/usr/bin/env bash
set -euo pipefail

# Read hook payload from stdin
PAYLOAD=$(cat)
FILE_PATH=$(echo "$PAYLOAD" | jq -r '.tool_input.file_path // empty')

[[ -z "$FILE_PATH" ]] && exit 0

# Your condition here
if [[ condition_met ]]; then
    jq -n \
        --arg reason "[HOOK] Your message to Claude" \
        '{decision: "block", reason: $reason}'
fi

exit 0
SKILL_SCRIPT_EOF
```

**Key points**:

1. Use `jq -n` to generate valid JSON
2. Include `"decision": "block"` for visibility
3. Exit with code 0
4. The "blocking error" label is cosmetic - operation continues

---

## TodoWrite Templates

### Creating a PostToolUse Hook

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
4559 chars