[DOCS] Hooks docs missing `if` field for permission-rule-based filtering

Resolved 💬 2 comments Opened Mar 27, 2026 by coygeek Closed Mar 28, 2026

Documentation Type

Missing documentation (feature not documented)

Documentation Location

https://code.claude.com/docs/en/hooks

Section/Topic

Hook configuration schema, especially hook filtering (matcher vs the new if field) and the linked plugin/skill/subagent hook-format examples

Current Documentation

The hooks reference currently says:

Hooks are defined in JSON settings files. The configuration has three levels of nesting: 1. Choose a hook event to respond to, like PreToolUse or Stop 2. Add a matcher group to filter when it fires, like "only for the Bash tool" 3. Define one or more hook handlers to run when matched

It then documents filtering only through matcher:

The matcher field is a regex string that filters when hooks fire. Use "*", "", or omit matcher entirely to match all occurrences. | PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest | tool name | Bash, Edit\|Write, mcp__.* |

And the common hook fields table currently lists only:

| type | yes | "command", "http", "prompt", or "agent" | | timeout | no | Seconds before canceling. Defaults: 600 for command, 30 for prompt, 60 for agent | | statusMessage | no | Custom spinner message displayed while the hook runs | | once | no | If true, runs only once per session then is removed. Skills only, not agents. |

Related pages say hook configs share this same format:

Hooks use the same configuration format as settings-based hooks but are scoped to the component's lifetime and cleaned up when it finishes.
Create my-plugin/hooks/hooks.json with your hooks configuration. Copy the hooks object from your .claude/settings.json or settings.local.json, since the format is the same.

What's Wrong or Missing?

Changelog v2.1.85 added a conditional if field for hooks that uses permission rule syntax such as Bash(git *), but the docs never describe this field anywhere.

A. The hooks schema does not list the new if field

The reference still presents hooks as event → matcher group → handlers, and the documented common fields omit if entirely. Users cannot discover that hook execution can now be gated by a conditional field.

B. The docs only describe regex matcher filtering, not permission-rule filtering

The current hooks docs explain matcher as a regex over tool names or other event-specific values. They do not explain that hooks can now use permission rule syntax such as Bash(git *) for finer-grained filtering of actual tool invocations.

C. The docs do not explain why or when to use if

The changelog notes that this reduces process spawning overhead, but the docs do not explain that if lets Claude Code skip launching hook handlers for non-matching calls, or how it complements existing matcher filtering across settings, plugin hooks, skills, and subagents.

Suggested Improvement

Update the hooks reference to document the new if field in the hook configuration schema, including:

  1. Where the field belongs in JSON and YAML hook definitions
  2. That it uses the existing permission rule syntax, with a cross-reference to the permissions/settings docs
  3. How if differs from matcher (matcher = regex over the event's filter field; if = permission-rule-style match over the tool invocation)
  4. Why if is useful: it avoids spawning hook processes for calls that do not match

Also update the guide/examples pages to show a minimal hook example filtered to Git commands with Bash(git *), and make clear that the same field is available in settings, plugin hooks/hooks.json, skill frontmatter, and subagent frontmatter.

Impact

Medium - Makes feature difficult to understand

Additional Context

Affected Pages:

| Page | Context |
|------|---------|
| https://code.claude.com/docs/en/hooks | Primary hook configuration reference; should document the new if field, its schema placement, and its relationship to matcher |
| https://code.claude.com/docs/en/hooks-guide | Usage guide and examples; should show a practical Bash(git *) filtering example and explain why if reduces hook process spawning |
| https://code.claude.com/docs/en/plugins | Plugin migration docs say plugin hooks use the same format as settings hooks; examples should reflect the new field |
| https://code.claude.com/docs/en/plugins-reference | Technical plugin hook reference; should include if anywhere hook schema is described for hooks/hooks.json |
| https://code.claude.com/docs/en/skills | Skill frontmatter points to the shared hooks configuration format; this shared format now has an undocumented field |
| https://code.claude.com/docs/en/sub-agents | Subagent frontmatter hooks use the same shared format and examples currently document only matcher-based filtering |

Total scope: 6 pages affected

Source: Changelog v2.1.85

Changelog entry: Added conditional if field for hooks using permission rule syntax (e.g., Bash(git *)) to filter when they run, reducing process spawning overhead

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗