[Bug] PermissionRequest hook cannot deny permissions - PermissionRequest hook decision ignored

Resolved 💬 6 comments Opened Jan 19, 2026 by ananas-block Closed Mar 5, 2026

Motivation

Long running sessions get hung up on permission requests.
The goal is to create a hook that automatically denies permission requests after a timeout.

Bug Description
PermissionRequest hook cannot deny permissions

## Summary

The PermissionRequest hook is called but cannot actually deny permission requests. The hook executes and
returns values, but the interactive permission prompt still appears regardless of the hook's output.

## Environment

  • Claude Code version: v2.1.12
  • OS: macOS (Darwin 24.6.0)
  • Shell: zsh

## Expected Behavior

According to documentation and DeepWiki:

  • PermissionRequest hooks run "after initial rule-based filtering and wildcard matching, but before an

interactive permission prompt is displayed"

  • The hook should be able to return allow, deny, or ask decisions
  • Returning deny should deny the permission without showing the interactive prompt

## Actual Behavior

The PermissionRequest hook is called and executes, but:

  • The interactive permission prompt always appears regardless of hook output
  • The hook's decision is ignored
  • The user must still manually respond to the prompt

## Steps to Reproduce

  1. Create hook script at ~/.claude/hooks/permission-timeout.sh:

``bash
#!/bin/bash
INPUT=$(cat)
echo "[$(date)] PermissionRequest: $INPUT" >> /tmp/claude-permissions.log
echo '{"hookSpecificOutput":{"permissionDecision":"deny"}}'
exit 0
``

  1. Make it executable: chmod +x ~/.claude/hooks/permission-timeout.sh
  1. Add to ~/.claude/settings.json:

``json
{
"hooks": {
"PermissionRequest": [
{
"hooks": [
{
"type": "command",
"command": "/path/to/permission-timeout.sh",
"timeout": 65000
}
]
}
]
}
}
``

  1. Start a fresh Claude Code session
  2. Ask Claude to run a command that requires permission (e.g., mkdir /tmp/test)

Expected: Command is denied without showing prompt
Actual: Interactive permission prompt appears

## Formats Tested

All of these were ignored by Claude Code:

| Format | Result |
|--------|--------|
| {"hookSpecificOutput":{"permissionDecision":"deny"}} | Ignored, prompt shown |
| {"decision":"deny"} | Ignored, prompt shown |
| {"deny":true} | Ignored, prompt shown |
| Plain text deny | Ignored, prompt shown |
| Exit code 2 | Ignored, prompt shown |

## Verification

The hook IS being called - log file shows entries:
``
[Mon Jan 19 18:57:41 WET 2026] PermissionRequest:
{"session_id":"...","hook_event_name":"PermissionRequest","tool_name":"Bash","tool_input":{"command":"mkdir
123"...}}
[Mon Jan 19 18:57:41 WET 2026] Immediate deny via hookSpecificOutput
``

## Comparison with PreToolUse

  • PreToolUse hook with exit 2 does work to block tool execution
  • But PreToolUse runs AFTER permission is granted, so it blocks without showing the prompt at all
  • This is different from the desired behavior of "show prompt, auto-deny after timeout"

## Use Case

The intended use case is to implement a permission request timeout:

  1. Show the interactive permission prompt
  2. If user doesn't respond within N seconds, auto-deny
  3. Prevent Claude Code from blocking indefinitely waiting for user input

This is useful for:

  • Automated/CI environments
  • Background agents
  • Preventing hung sessions

## Suggested Fix

Either:

  1. Make PermissionRequest hooks actually respect the returned decision
  2. Add a built-in permissionRequestTimeout setting
  3. Document that PermissionRequest hooks are informational-only (if intentional)

## Related

  • Changelog mentions PermissionRequest hook was added in v2.0.45
  • Changelog mentions "PermissionDecision is exposed to hooks, including ask"

Environment Info

  • Platform: darwin
  • Terminal: zed
  • Version: 2.1.12
  • Feedback ID: 592870b7-0780-4469-ae21-3e2e4640260f

View original on GitHub ↗

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