Hook Matchers: Precision Targeting
Day 36 · Week 8 · Hooks — Guardrails
Slack Message — copy & paste
🤖 Tip #36 — Hook matchers give you precision targeting — match only `git push --force`, not every Bash call. Glob-style wildcards, no regex.
#36 Claude Code
Matcher Syntax
- Tool name plus optional argument pattern in parentheses
- › `"Bash"` — matches ALL Bash tool calls (too broad for most uses)
- › `"Bash(git commit*)"` — matches Bash calls starting with "git commit" (perfect for branch protection)
- › `"Bash(git push --force*)"` — matches only force pushes (precise, no false positives)
- MCP and other tool matchers
- › `"mcp__*figma*"` — matches any MCP tool with "figma" in the name
- › `"Edit"` — matches all Edit tool calls (good for file validation)
- › `"Write(*.env*)"` — catches secret file creation
- Wildcard rules
- › `*` matches anything (including nothing)
- › Pattern matches tool name and optionally arguments in parentheses
- › No regex — just glob-style wildcards
- The `if` field — fine-grained filtering inside a hook
- › `matcher` selects which tool events to listen for; `if` adds a second filter using permission rule syntax
- › Evaluated BEFORE spawning the hook process — avoids unnecessary shell invocations
- › Example: `"matcher": "Bash"` + `"if": "Bash(git commit*)"` — the hook entry fires on all Bash events, but only spawns the script for git commits
- › Example: `"matcher": "Edit"` + `"if": "Edit(**/.claude-plugin/**)"` — only validate plugin file edits, skip all other edits
- › Use `if` when your matcher is broad but your script only applies to a subset
Matchers Wildcards Patterns
#36 Hooks — Guardrails
Matchers for Every Risk
- 1 A matcher for every risk level
- › `Bash(rm -rf*)` — catch destructive deletions
- › `Bash(git reset --hard*)` — catch history destruction
- › `Write(*.env*)` — catch secret file creation
- › `Bash(curl*|*wget*)` — catch network calls
- 2 List the 3 most dangerous commands for your project — write a matcher for each and you have a safety net
- 3 Start specific, not broad — `Bash(git commit*)` is better than `Bash` because it avoids false positives on harmless commands
- 4 Test matchers by asking the AI to run the matched command — verify the hook fires and the error message is clear
Matchers Wildcards Patterns
Your screenshot here Optional — add a screenshot from your own workflow