491a45dd43
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84 lines
3.1 KiB
Markdown
84 lines
3.1 KiB
Markdown
# Hooks
|
|
|
|
Hook scripts are deterministic enforcement — unlike rules (advisory), hooks **guarantee** behavior by blocking or modifying tool calls before/after they execute.
|
|
|
|
Hooks are wired in `settings.json` under the `"hooks"` key. Each hook specifies an event, a matcher, and a command to run.
|
|
|
|
## Available Hooks
|
|
|
|
### protect-files.sh
|
|
**Event**: PreToolUse (Edit|Write)
|
|
|
|
Blocks edits to sensitive and generated files. Fails closed (blocks if `jq` is missing).
|
|
- `.env`, `.env.*` — secrets (by basename and path)
|
|
- `*.pem`, `*.key`, `*.crt`, `*.p12`, `*.pfx` — certificates and keys
|
|
- `id_rsa`, `id_ed25519`, `credentials.json`, `.npmrc`, `.pypirc` — credentials
|
|
- `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml` — lock files
|
|
- `*.gen.ts`, `*.generated.*` — generated code
|
|
- `*.min.js`, `*.min.css` — minified bundles
|
|
- Anything inside `.git/`, `secrets/`, or `.claude/hooks/`
|
|
- Self-protecting: blocks edits to hook scripts and `settings.json`
|
|
|
|
### warn-large-files.sh
|
|
**Event**: PreToolUse (Edit|Write)
|
|
|
|
Blocks writes to build artifacts, dependency directories, and binary files. Fails closed.
|
|
- `node_modules/`, `vendor/`, `dist/`, `build/`, `.next/`, `__pycache__/`, `.venv/`
|
|
- `*.wasm`, `*.so`, `*.dylib`, `*.dll`, `*.exe`, `*.zip`, `*.tar.*`
|
|
- `*.mp4`, `*.mov`, `*.mp3`, `*.pyc`, `*.class`
|
|
|
|
### block-dangerous-commands.sh
|
|
**Event**: PreToolUse (Bash)
|
|
|
|
Blocks dangerous shell commands. Detects patterns even in chained commands (`&&`, `;`). Fails closed.
|
|
- **Git**: `git push origin main/master`, `git push --force` (allows `--force-with-lease`), bare `git push` on main
|
|
- **Filesystem**: `rm -rf /`, `rm -rf ~`, recursive delete on root/home paths
|
|
- **Database**: `DROP TABLE/DATABASE`, `DELETE FROM` without WHERE, `TRUNCATE TABLE`
|
|
- **System**: `chmod 777`, piping `curl`/`wget` to `bash`/`sh`, `mkfs`, `dd if=`, writes to `/dev/`
|
|
|
|
### format-on-save.sh
|
|
**Event**: PostToolUse (Edit|Write)
|
|
|
|
Auto-formats files after Claude edits them. Auto-detects formatters by checking for both the binary and a config file:
|
|
- Biome: `biome.json` + `node_modules/.bin/biome`
|
|
- Prettier: `.prettierrc*` or `package.json` prettier key + `node_modules/.bin/prettier`
|
|
- Ruff: `ruff.toml` or `pyproject.toml [tool.ruff]` + `ruff` binary
|
|
- Black: `pyproject.toml [tool.black]` + `black` binary
|
|
- rustfmt: standard for Rust (no config needed)
|
|
- gofmt: standard for Go (no config needed)
|
|
|
|
### session-start.sh
|
|
**Event**: SessionStart
|
|
|
|
Injects dynamic project context at session start: current branch (or detached HEAD warning), last commit, uncommitted changes count, staged changes indicator, and stash count.
|
|
|
|
## Adding Your Own
|
|
|
|
1. Create a `.sh` script in this directory
|
|
2. Make it executable: `chmod +x your-hook.sh`
|
|
3. Wire it in `settings.json`:
|
|
|
|
```json
|
|
{
|
|
"hooks": {
|
|
"PreToolUse": [
|
|
{
|
|
"matcher": "Bash",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/your-hook.sh"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
- Exit 0 = allow, Exit 2 = block
|
|
- Scripts receive JSON on stdin with `tool_input`
|
|
- Requires `jq` for JSON parsing
|
|
|
|
See [Claude Code docs](https://code.claude.com/docs/en/hooks) for all hook events.
|