[DOCS] Hook matcher reference and guide omit comma as a supported alternation separator (added in v2.1.191)

Open 💬 0 comments Opened Jun 25, 2026 by coygeek

Documentation Type

Incorrect/outdated documentation

Documentation Location

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

Section/Topic

The "Matcher patterns" subsection under "Configuration" (and the parallel "Filter hooks with matchers" section in the guide, plus the "Check common causes" table in debug-your-config).

Current Documentation

The hooks reference page says in the "Matcher patterns" table:

The matcher field filters when hooks fire. How a matcher is evaluated depends on the characters it contains: | Matcher value | Evaluated as | Example | | :---------------------------------- | :---------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | "*", "", or omitted | Match all | fires on every occurrence of the event | | Only letters, digits, _, and \| | Exact string, or \|-separated list of exact strings | Bash matches only the Bash tool; Edit\|Write matches either tool exactly | | Contains any other character | JavaScript regular expression | ^Notebook matches any tool starting with Notebook; mcp__memory__.* matches every tool from the memory server |

Under the per-event examples:

| PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied | tool name | Bash, Edit\|Write, mcp__.* |

And in the in-context Edit|Write example block:

``json { "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", ... } ] } } ``

The hooks-guide page mirrors this in "Filter hooks with matchers":

The "Edit|Write" matcher fires only when Claude uses the Edit or Write tool, not when it uses Bash, Read, or any other tool.

And the debug-your-config page lists the matcher symptom:

| Hook never fires | matcher is a JSON array instead of a string | Use a single string with \| to match multiple tools, for example "Edit\|Write". See matcher patterns. |

In all three places the only alternation character documented is |. Nothing in the matcher table, the per-event examples, the troubleshooting table, or the surrounding prose tells a reader that a comma , is also a valid alternation separator.

What's Wrong or Missing?

v2.1.191 fixed hooks with comma-separated matchers (for example "Bash,PowerShell") silently never firing. After the fix, comma is a second supported alternation separator in addition to |, but the documentation still only describes the | form. That leaves three concrete problems:

A. The matcher-evaluator table is incomplete

The "Only letters, digits, _, and \|" row should also list ,, since a matcher like Bash,PowerShell is now treated as alternation rather than as a literal name. As written, the table implies that the only way to target more than one tool from a pure-alphanumeric matcher is Edit|Write, so a reader who writes Bash,PowerShell has no reason to expect it to work (or to know that it works).

B. The "Filter hooks with matchers" guide teaches the wrong recipe

The guide's headline example and follow-up prose only ever show the | form. Anyone following the guide to learn "how do I match multiple tools?" will reach for Edit|Write and never learn that Edit,Write is also valid. The guide should at least mention both separators so users can pick whichever they prefer (and so users who copy/paste from older forum snippets, which historically used commas, are not surprised).

C. The "Hook never fires" troubleshooting row is now misleading

The debug-your-config row points users at Edit|Write as the only multi-tool recipe. After v2.1.191, a user whose config uses Bash,PowerShell will see their hook fire correctly, but the doc still tells them to use | as the only fix. The row also still has no entry for the historical silent-no-fire behaviour around commas — which used to be a real footgun and is now worth a one-line note ("commas are supported as alternation in v2.1.191 and later; on older versions this matcher would silently never fire").

Suggested Improvement

A. Update the matcher pattern table in hooks.md

Add comma to the alternation row and refresh the example:

Before:

| Only letters, digits, _, and \| | Exact string, or \|-separated list of exact strings | Bash matches only the Bash tool; Edit\|Write matches either tool exactly |

After:

| Only letters, digits, _, \|, and , | Exact string, or \|/,-separated list of exact strings | Bash matches only the Bash tool; Edit\|Write and Edit,Write both match either tool exactly |

In the per-event table, the PreToolUse/PostToolUse/etc. example cell should also include a comma-separated form:

| PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied | tool name | Bash, Edit\|Write, Edit,Write, mcp__.* |

B. Mention the second separator in the "Filter hooks with matchers" guide

In hooks-guide.md, after the Edit|Write example, add a one-sentence note such as:

Edit,Write is also accepted as an equivalent comma-separated form. Both separators are valid in v2.1.191 and later; pick whichever you prefer.

C. Add a one-line note in the debug-your-config "Hook never fires" row

Either broaden the existing "Use a single string" row to mention both separators, or add a small follow-up row that calls out the historical comma bug:

| Hook never fires on a comma-separated matcher like Bash,PowerShell on Claude Code v2.1.190 or earlier | This was a pre-v2.1.191 bug — commas are now a valid alternation separator alongside \|. Either upgrade Claude Code or use Bash\|PowerShell on older versions. |

Impact

Medium - Makes feature difficult to understand

Additional Context

Affected Pages:
| Page | Line(s) | Context |
|------|---------|---------|
| https://code.claude.com/docs/en/hooks | 183-187 | "Matcher patterns" evaluator table — alternation row |
| https://code.claude.com/docs/en/hooks | 195 | Per-event example cell for PreToolUse/PostToolUse/etc. |
| https://code.claude.com/docs/en/hooks | 217-232 | In-context Edit\|Write example block |
| https://code.claude.com/docs/en/hooks-guide | 594-613 | "Filter hooks with matchers" section, including the Edit\|Write example |
| https://code.claude.com/docs/en/hooks-guide | 623 | Per-event example cell mirroring the reference |
| https://code.claude.com/docs/en/debug-your-config | 93 | "Hook never fires" troubleshooting row |

Total scope: 3 pages affected, 6 distinct passages to update.

Related precedent: Other Claude Code features that accept both | and , as alternation-style separators (for example, the OTEL_*_EXPORTER environment variables documented in env-vars.md and monitoring-usage.md, and the --allowedTools / --fallback-model CLI flags in cli-reference.md) already document both forms. The hook matcher documentation should follow the same pattern.

Changelog reference: v2.1.191 — "Fixed hooks with comma-separated matchers (e.g. "Bash,PowerShell") silently never firing."

View original on GitHub ↗