/** * claudeCodeHookCondition — Claude Code's hook `if` field, evaluated. * * A CC hook action may carry `if: "Bash(git push *--force*)"`. The hook command * runs ONLY when the tool call matches; otherwise it is never spawned. The syntax * is CC's permission-rule grammar, which is why this lives in the adapter and not * in core. Reached through `HookProtocol.condition`; the neutral shape and the * event rule live in `src/core/hook-condition.ts`. * * SOURCE OF THE SEMANTICS. Every rule below is transcribed from Claude Code's own * hooks documentation (the `if` row of the common-fields table + its "Bash if * matching" table) and cross-checked against the installed binary, whose bundled * schema carries the string verbatim: "Permission rule syntax to filter when this * hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the * pattern. Avoids spawning hooks for non-matching commands." Measured on * @anthropic-ai/claude-code 2.1.263. * * 🔴 THE MATCHER IS DELIBERATELY CONSERVATIVE IN ONE DIRECTION ONLY, and that is * the whole safety argument. CC itself fails OPEN — where it cannot tell what a * command name expands to, it runs the hook — so mirroring that means every * uncertain input yields `runs: true`. A wrong answer can therefore only ever * make a guardrail report say "this hook ran and did not block", never "this hook * was skipped". The first is a real finding about the hook; the second would be a * false alarm invented by us, and this file must not be able to produce one. * * THE SEVEN DOCUMENTED BASH CASES, all pinned in hook-condition.test.ts: * * | pattern | command | runs | why | * | ------------------ | --------------------------- | ---- | ------------------------------------ | * | `Bash(git *)` | `FOO=bar git push` | yes | leading assignments stripped | * | `Bash(git *)` | `npm test && git push` | yes | each subcommand is checked | * | `Bash(rm *)` | `echo $(rm -rf /)` | yes | commands inside `$()`/`` ` `` too | * | `Bash(rm *)` | `echo $(date)` | no | no subcommand matches | * | `Bash(cat *)` | `echo before $(date) after` | no | full command and `date` both checked | * | `Bash(git *)` | `$TOOL git push` | yes | the command name is unknowable | * | `Bash(git push *)` | `echo $(date)` | yes | argument-bearing pattern + dynamic | * * The last two rows are the fail-open half, and they are why a blanket "contains a * `$` ⇒ run" shortcut is wrong: rows 4 and 5 also contain `$(` and must say NO. * CC resolves command NAMES through substitution (it can see `date`, `rm`) but not * ARGUMENTS, so a command-name-only pattern (`rm *`) is decided precisely while an * argument-bearing one (`git push *`) gives up on any dynamic command. */ import type { HookConditionSupport } from "../../core/hook-condition.js"; export declare const claudeCodeHookCondition: HookConditionSupport; //# sourceMappingURL=hook-condition.d.ts.map