Creates Claude Code hooks for static analysis and code quality. Provides pre-built linting, formatting, and type-checking hooks. Use when setting up project quality gates, enforcing code standards, or adding pre-commit style checks.
View on GitHubplugins/ace/skills/writing-hooks/SKILL.md
February 1, 2026
Select agents to install to:
npx add-skill https://github.com/wayne930242/Reflexive-Claude-Code/blob/main/plugins/ace/skills/writing-hooks/SKILL.md -a claude-code --skill writing-hooksInstallation paths:
.claude/skills/writing-hooks/# Hook Creator
Create hooks that enforce code quality through static analysis.
## Core Principles
1. **Exit code 2 blocks** - Use to prevent bad code from being written
2. **Fast checks only** - Hooks run synchronously; keep under 5 seconds
3. **JSON stdin/stdout** - Hooks receive context, can output structured responses
4. **Fail safe** - Non-zero (except 2) continues execution with warning
5. **Use Python** - Wrap shell commands in Python for cross-platform compatibility
## Quick Start
Add a static check hook:
```bash
python3 scripts/add_hook.py <hook-name> --type <lint|format|typecheck|custom>
```
Options:
- `--type`, `-t`: Hook template type (default: `custom`)
- `--path`, `-p`: Output directory (default: `.claude/hooks`)
- `--event`, `-e`: Hook event (default: `PostToolUse`)
## Hook Structure
```
.claude/
├── hooks/
│ ├── eslint_check.py # Linting hook
│ ├── prettier_check.py # Formatting hook
│ └── typecheck.py # Type checking hook
└── settings.json # Hook configuration
```
## Configuration Format
**Important:** Hooks must be configured in `.claude/settings.json` (not `settings.local.json`). The `settings.json` file is shared with the team via version control, ensuring consistent hook behavior across all collaborators.
```json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/eslint_check.py",
"timeout": 30
}]
}
]
}
}
```
## Static Check Patterns
### 1. Linting (ESLint, Ruff, etc.)
```python
#!/usr/bin/env python3
import json, subprocess, sys
data = json.load(sys.stdin)
file_path = data.get('tool_input', {}).get('file_path', '')
if not file_path.endswith(('.js', '.ts', '.tsx')):
sys.exit(0)
result = subprocess.run(
['npx', 'eslint', '--format', 'compact', file_path],
capture_output=True, text=True
)
if result.returncode != 0: