[BUG] PermissionRequest hook allow is silently ignored for ExitPlanMode unless updatedInput is provided (2.1.246)
What's Wrong?
A PermissionRequest hook that responds with a plain allow decision is silently ignored for the ExitPlanMode tool. The plan-approval dialog stays open and the session remains blocked, even though the hook exited 0 with a valid decision payload.
This is the same symptom as #15755, which was reported fixed in v2.1.7. It is either a regression, or the fix requires an undocumented extra field (see analysis below).
Environment
- Claude Code 2.1.246 (bundled with the Claude desktop app, macOS; session runs with
--permission-prompt-tool stdio) - Hook registered via a plugin's
hooks/hooks.json:
``json``
"PermissionRequest": [
{ "hooks": [ { "type": "command", "command": "python3 \"${CLAUDE_PLUGIN_ROOT}/run_hook.py\"", "timeout": 900 } ] }
]
Repro
- Enter plan mode, let Claude call
ExitPlanMode. - The
PermissionRequesthook fires (confirmed — our hook posted the request to Slack). - ~11 minutes later the hook prints the documented allow payload to stdout and exits 0:
``json``
{"hookSpecificOutput": {"hookEventName": "PermissionRequest", "decision": {"behavior": "allow"}}}
- Expected (per the hooks guide, "Auto-approve specific permission prompts"): plan mode exits and the previous permission mode is restored.
- Actual: nothing happens. The 3-option plan-approval dialog remains, the turn stays blocked on
ExitPlanMode(in our transcript: 2h41m, until the user came back and answered the dialog manually). The eventual tool_result was the manual rejection.
The same hook's allow works fine for regular tools (e.g. Bash); deny also works for ExitPlanMode.
Analysis
The current behavior appears intentional in the code: for tools with requiresUserInteraction() (ExitPlanMode, AskUserQuestion), a hook allow without updatedInput is discarded and the flow falls through to the normal dialog. An allow that echoes the original input as updatedInput takes a different path ("Hook satisfied user interaction for <tool> via updatedInput") and appears to be the supported way to approve programmatically. We have adopted that as a workaround (echoing tool_input back as updatedInput) but have not yet confirmed it end-to-end.
If the updatedInput requirement is by design, it would be great to have it documented in the hooks guide — the current docs state that a plain allow exits plan mode, which is what #15755's resolution also implied.
What Should Happen?
Either:
- a plain
{"behavior": "allow"}from aPermissionRequesthook approvesExitPlanMode(docs' current promise), or - the docs explicitly state that
requiresUserInteractiontools needupdatedInputin the allow decision.
Refs: #15755 (locked; same symptom, reported fixed in 2.1.7)