Support argument patterns in hook matchers (consistent with permissions syntax)
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Hook matchers only support tool names (e.g. "Bash", "Write|Edit"), meaning a hook registered on Bash fires on every Bash tool call. There's no way to narrow a hook to specific commands.
The permissions system already supports argument patterns — Bash(git:*), Bash(npm run test), Edit(.claude). Hook matchers don't, despite sharing the same conceptual role of "match a tool call."
This forces hook authors to handle filtering inside the hook itself. For example, an agent hook that should only run before git commit still spins up on every Bash call, wastes tokens determining the command isn't a commit, and bails out.
Proposed Solution
Extend hook matchers to support the same argument pattern syntax as permissions:
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash(git commit:*)",
"hooks": [{
"type": "agent",
"prompt": "Run /simplify on all changed files before this commit proceeds.",
"timeout": 120
}]
}]
}
}
Pattern syntax (same as permissions):
Bash(git commit:*)— matches any Bash command starting withgit commitBash(npm run test)— exact matchWrite(src/*.ts)— matches writes to TypeScript files in src/Edit(.claude)— matches edits to .claude files
This is already implemented for permissions. Reusing the same matching logic for hook matchers would be a small, consistent change.
Alternative Solutions
- Filter inside the hook — current workaround. Works, but agent/prompt hooks still spin up on every non-matching call, wasting tokens and adding latency.
conditionfield on matchers — a shell command evaluated at session start to gate registration. More complex, and doesn't handle cases where the working directory changes mid-session.- Separate
argumentMatcherfield — more explicit but introduces a new concept when the permissions syntax already exists.
Priority
Medium - Nice to have improvement
Feature Category
Other
Use Case Example
- I want an agent hook that runs
/simplifybefore git commits - Currently:
"matcher": "Bash"— hook fires on every Bash call, agent spins up, checks if it's a commit, bails 99% of the time - With this change:
"matcher": "Bash(git commit:*)"— hook only fires on git commit commands, zero overhead on all other Bash calls
Other useful patterns:
Bash(docker build:*)— lint Dockerfiles before buildsBash(terraform apply:*)— require plan review before applyWrite(*.sql)— validate SQL files after writingEdit(src/api/*:*)— run API tests after editing API files
Additional Context
Related: #35564 proposes matching skill names in hook matchers — a different matcher property but the same underlying idea of making hook matchers more expressive beyond just tool names.
The permissions system's argument matching is already well-understood by users and implemented in the codebase. Extending it to hook matchers creates a consistent experience and avoids the need for more complex gating mechanisms.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗