Permission rules should (optionally) evaluate against the original input when a PreToolUse hook returns updatedInput
Use case
A PreToolUse hook that transparently wraps Bash commands in a stall-detection watchdog via hookSpecificOutput.updatedInput — e.g. rewriting npm test into /path/to/stall-guard -c 'npm test'. The wrapper is semantically transparent: same command, same exit codes, plus inactivity detection.
Problem (verified on 2.1.162)
Permission rules are evaluated against the rewritten command, so installing such a hook silently breaks the user's permission configuration:
- Allow rules stop matching. With
"allow": ["Bash(touch:*)"]in.claude/settings.local.json: unwrappedtouch a.txtis auto-allowed; the same command rewritten by the hook gets "This command requires approval". Every allowlist entry the user has accumulated starts prompting again. - Deny rules degrade to ask. A
Bash(rm -rf:*)deny rule doesn't match the wrapped command, so instead of a hard block the user gets a confirmation prompt.
Ask — either would solve it
- An opt-in field on the PreToolUse response, e.g.
"evaluatePermissionsAgainst": "original", so rule evaluation (allow/deny/ask) runs against the pre-rewrite input while the rewritten command is what executes (and is shown in the prompt); or - User-configurable transparent wrappers for Bash rule matching — the docs already strip a fixed list (
timeout,time,nice,nohup,stdbuf); a setting like"permissions": {"transparentWrappers": ["/path/to/stall-guard -c"]}would generalize the existing mechanism.
Current workaround
The hook re-implements the documented rule-matching semantics against the original command and emits permissionDecision: "allow"/"deny" alongside updatedInput (verified working). It's viable but duplicates the permission matcher, with obvious divergence risk — and rule sources the hook can't read (CLI --allowedTools, session-scoped always-allow) stay broken.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗