Skip to content

Notification hooks (permission_prompt/idle_prompt) never fire in Desktop app #81788

Description

@JBrown0x90

Summary

Notification hooks configured with matcher permission_prompt|idle_prompt in ~/.claude/settings.json never fire in the Claude Desktop app, even though the same hook mechanism works correctly for other events (e.g. Stop) in the same app, and manually invoking the configured hook command directly reproduces the intended behavior without issue.

Setup

"hooks": {
  "Notification": [
    {
      "matcher": "permission_prompt|idle_prompt",
      "hooks": [
        { "type": "command", "command": "osascript -e 'display notification ...'", "timeout": 1 },
        { "type": "command", "command": "~/.claude/hooks/notify-say.sh", "timeout": 2, "async": true }
      ]
    }
  ]
}

notify-say.sh just runs say "Claude needs your input" & in the background — no stdin parsing, so payload shape isn't the issue.

Steps to reproduce

  1. Add the above Notification hook to ~/.claude/settings.json.
  2. Use Claude Desktop (not the CLI terminal) and trigger a real permission-approval dialog (a tool call requiring approval) or leave a session idle waiting on input for an extended period.
  3. Observe: the visual permission dialog / idle state appears normally, but the hook command never executes — no sound, no visible side effect.

What I verified to isolate the cause

  • Manually piping a synthetic payload directly to the hook script (echo '{...}' | ~/.claude/hooks/notify-say.sh) works every time — confirms the script itself, say, and audio output are all fine.
  • The same settings file's Stop hook (used for a separate text-to-speech feature reading Claude's final response) does fire reliably in this same Desktop app session — confirms hooks in general are supported and ~/.claude/settings.json is being read.
  • Ruled out a sandboxed/VM execution context for Desktop sessions (found claude-code-vm under Application Support, but a diagnostic command run inside an affected chat executed directly against the real filesystem and produced audible output, same as a normal terminal session) — so this isn't a lost-in-a-sandbox issue.
  • Checked ~/Library/Logs/Claude/main.log for any trace of the hook being invoked (successfully or with error) — found no reference to the hook script by name, but also found no reference to the known-working Stop hook script either, so the log isn't granular enough to be conclusive either way.
  • /hooks slash command is not available in the Desktop app UI (/hooks isn't available in this environment), so there's no in-app way to confirm hook registration or force a reload.
  • Tested idle_prompt specifically by leaving a Desktop chat idle for extended periods (well beyond any reasonable idle threshold) — never fired.

Expected behavior

Notification hooks with matcher permission_prompt and idle_prompt should fire in Claude Desktop the same way they do in the CLI terminal, since Desktop shows equivalent visual permission-approval dialogs and idle states.

Environment

  • Claude Desktop app on macOS
  • Hooks otherwise functional in the same settings file (Stop hook confirmed working)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions