Open source

Guide · Claude Code alerts · 9 min read

How to get notified when Claude Code needs your input or approval.

Claude Code can alert you when it is blocked on you. Pick the right signal, know when it fires, and decide whether you want a banner, a phone push you can answer, or a voice.

Per the Claude Code hooks reference, checked October 2026 · macOS, Linux, Windows

The short answer

Yes: a Notification hook for “waiting on you”, a PermissionRequest hook for “asking right now”.

Claude Code runs a Notification hook when it is blocked on you. The permission_prompt type fires when an approval has waited about six seconds without you typing, and idle_prompt fires about 60 seconds after Claude finishes if you have not replied. Point them at osascript on macOS, notify-send on Linux or PowerShell on Windows in ~/.claude/settings.json. For an alert the instant Claude asks, add a PermissionRequest hook. With no setup at all, Claude Code already sends a desktop notification in Ghostty, Kitty and iTerm2, and "preferredNotifChannel": "terminal_bell" rings the bell in other terminals.

To answer from your phone, Remote Control pushes permission prompts and questions to the Claude app, and the open-source claude-remote-approver sends them to ntfy with Approve and Deny buttons. To hear the question instead of reading it, pipe the hook’s message into say, or use a voice layer like Heard, which tells you which session needs you and why.

Timing

When each signal fires.

Most “my alert is late” reports come down to these delays. From the hooks reference, checked October 7, 2026.

SignalFires whenDelayUse it for
Built-in notificationpreferredNotifChannelA permission prompt is waiting or Claude has finished, and you appear to be awaySame as permission_prompt and idle_promptZero setup in Ghostty, Kitty and iTerm2; a bell elsewhere
permission_promptNotification hookClaude needs you to approve a tool use or a sandboxed network requestAbout 6 s without typing; each keystroke pushes it backApprovals you would otherwise miss
idle_promptNotification hookClaude finished and you have not typed sinceAbout 60 s; not while a background subagent runs“Your turn” reminders
elicitation_dialogNotification hookAn MCP server opens a form that needs your inputAbout 6 s without typingMCP tools that need a value from you
elicitation_url_dialogNotification hookAn MCP server asks you to open a URL in your browserAbout 6 s without typingMCP sign-ins and browser steps
agent_needs_inputNotification hookA background session starts waiting on you while agent view is openAs soon as a background session starts waiting; about 6 s for teammate setup questionsBackground sessions
PermissionRequestHook eventClaude is about to ask you for permission to use a toolNoneInstant approval alerts; not fired for sandboxed network requests
AskUserQuestionPreToolUse hookClaude is about to ask you a multiple-choice questionNoneInstant “Claude has a question” alerts
StopHook eventClaude finishes respondingNoneA “done” sound; see the sound guide

In Claude Desktop and the VS Code extension, permission_prompt fires about six seconds after Claude asks, whether or not you are typing, and does not fire if you or a PermissionRequest hook answer first.

(1)Step 1 · Built-in

Start with the alert Claude Code already sends.

When a permission prompt is waiting or Claude has finished, and you appear to be away from the terminal, Claude Code raises a notification. In Ghostty, Kitty and iTerm2 it becomes a desktop notification with no setup. In other terminals, such as Warp or the VS Code integrated terminal, set preferredNotifChannel to "terminal_bell" to ring the bell instead. The same setting appears in /config as Local notifications.

The built-in notification also reaches your laptop when Claude Code runs over SSH, which a plain hook command cannot do, because hooks run on the remote machine. Ghostty and Kitty forward it with no setup. iTerm2 needs forwarding turned on: Settings → Profiles → Terminal, check Notification Center Alerts, then Filter Alerts and enable Send escape sequence-generated alerts.

~/.claude/settings.json · built-in bell for other terminals
{
  "preferredNotifChannel": "terminal_bell"
}

(2)Step 2 · Notification hook

Get a banner that says which project is asking, and for what.

A Notification hook runs your own command when Claude Code sends a notification, and it still runs if you set preferredNotifChannel to notifications_disabled. Its JSON input includes message (the notification text), notification_type, and cwd, the session’s working directory. The script below turns the folder name into the banner title, so “payments-api: approval needed” and “docs: waiting for you” look different at a glance.

Save it as ~/.claude/hooks/notify.sh, make it executable with chmod +x, and register it for the four types that mean Claude is blocked on you. It needs jq (brew install jq if it is missing). The on run argv form hands the text to osascript as arguments, so quotes inside a message or command cannot break the AppleScript.

~/.claude/hooks/notify.sh · macOS
#!/bin/bash
# Claude Code hook: say which project is asking, and for what.
input=$(cat)
project=$(basename "$(jq -r '.cwd // "Claude Code"' <<<"$input")")

case "$(jq -r '.notification_type // .hook_event_name' <<<"$input")" in
  permission_prompt|PermissionRequest) title="$project: approval needed" ;;
  idle_prompt) title="$project: waiting for you" ;;
  PreToolUse) title="$project: Claude has a question" ;;
  *) title="$project: Claude Code" ;;
esac

body=$(jq -r '.message // .tool_input.command // .tool_input.file_path // .tool_input.questions[0].question // .tool_name // "Needs your attention"' <<<"$input" | head -c 180)

osascript -e 'on run argv' -e 'display notification (item 2 of argv) with title (item 1 of argv)' -e 'end run' "$title" "$body" >/dev/null 2>&1
exit 0
~/.claude/settings.json · Notification hook
{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt|idle_prompt|elicitation_dialog|elicitation_url_dialog",
        "hooks": [
          { "type": "command", "command": "~/.claude/hooks/notify.sh" }
        ]
      }
    ]
  }
}

(3)Step 3 · Instant alerts

Get the alert the moment Claude asks, not six seconds later.

permission_prompt waits until you have not typed for about six seconds, and every keystroke pushes it back. That keeps it quiet while you are at the keyboard, but it can feel late. PermissionRequest runs as soon as Claude is about to ask, and a PreToolUse hook matched to AskUserQuestion runs before Claude shows you a multiple-choice question. Point both at the same script: it reads tool_input and puts the command, file path or question in the banner.

The cost is noise: these fire even while you are looking straight at the prompt. Use them in place of the permission_prompt matcher, not alongside it, or an approval you miss will alert you twice. Keep permission_prompt if you use the sandbox, because PermissionRequest does not fire for a sandboxed command’s network request.

~/.claude/settings.json · instant alerts
{
  "hooks": {
    "PermissionRequest": [
      {
        "hooks": [
          { "type": "command", "command": "~/.claude/hooks/notify.sh", "async": true }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "AskUserQuestion",
        "hooks": [
          { "type": "command", "command": "~/.claude/hooks/notify.sh", "async": true }
        ]
      }
    ]
  }
}

(4)Step 4 · Linux and Windows

The same hooks on Linux and Windows.

On Linux, keep the script and swap its osascript line for notify-send, which ships in libnotify-bin on Debian and Ubuntu. It needs a running notification daemon, so it will not show anything in an SSH session, on a headless server or in most containers.

On Windows, the hooks guide uses a PowerShell message box. It is a dialog, not a corner toast, so it can open behind your terminal. Inside WSL, powershell.exe must be on your PATH through Windows interop. The JSON shape is the same on every platform; only the command changes.

notify.sh · Linux, replace the osascript line
notify-send "$title" "$body"
~/.claude/settings.json · Windows (PowerShell)
{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt|idle_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')\""
          }
        ]
      }
    ]
  }
}

(5)Away from the desk

Answer from your phone, not just notice.

A banner on your Mac does nothing while you are in the kitchen. Remote Control connects a local session to the Claude app on iOS or Android and to claude.ai/code. Start the session with claude --remote-control, then in /config turn on Push when actions required, which covers permission prompts and questions. Permission prompts stay open until you answer, from the terminal or the phone. Remote Control needs a claude.ai login on a Pro, Max, Team or Enterprise plan (on Team and Enterprise an Owner turns it on first), and it is not available with API keys, Amazon Bedrock, Google Cloud’s Agent Platform or Microsoft Foundry.

If Remote Control is not an option, claude-remote-approver installs a PermissionRequest hook that sends each prompt to the ntfy app with Approve, Always Approve and Deny buttons, and falls back to the terminal prompt if you do not answer in time. On the public ntfy.sh server, tool names and commands pass through a third party, so its README suggests self-hosting ntfy for sensitive work. Either way, read the command before you tap Approve.

Remote Control with phone pushes
cd ~/code/payments-api
claude --remote-control

(6)Out loud

Hear the question instead of reading a banner.

A banner only helps if you look at the screen. On macOS, pipe the notification text into say and your Mac reads it aloud with the project name first, which works while your eyes are on another window or you are across the room. On Linux, spd-say does the same. It reads the text exactly as written, which is fine for a short notification.

Heard is a voice layer for coding agents on macOS 14 or later. Its native Claude Code and Codex adapters speak questions, approvals, blockers, failures and results, and name the session each one came from, so with four sessions open you hear which one needs you and why. On Heard Power you can dictate a reply and send it to that session without switching windows, from the Mac or a paired iPhone. The app installs its own hook; see the Claude Code setup docs. New accounts start with a 14-day Power trial, no card required, and the engine is open source under Apache 2.0.

~/.claude/settings.json · speak the question (macOS)
{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt|idle_prompt",
        "hooks": [
          {
            "type": "command",
            "async": true,
            "command": "jq -r '(.cwd | split(\"/\") | last) + \". \" + (.message // \"Claude Code needs you\")' | say"
          }
        ]
      }
    ]
  }
}
Useful

“payments-api. Claude needs your permission.”

Noise

A silent banner that says “Claude Code needs your attention”, under three others just like it.

(7)Fewer interruptions

Only get interrupted when a decision is waiting.

Every alert should mean you have something to decide. These rules keep it that way.

  • Match permission_prompt|idle_prompt|elicitation_dialog|elicitation_url_dialog instead of leaving the matcher empty. An empty matcher also fires on auth_success, elicitation_complete and the usage-limit types.
  • Give “done” its own sound with a Stop hook (setup) so “finished” and “needs you” never sound alike.
  • Cut the prompts themselves. Add an allow rule such as Bash(npm test *) in /permissions for commands you always approve, and that prompt, and its alert, goes away.
  • Using agent view for background sessions? Add agent_needs_input to the matcher.
  • With Remote Control, set CLAUDE_CLIENT_PRESENCE_FILE to a marker file that a screen-lock tool removes when you lock the screen and recreates when you are back. Phone pushes are skipped while the file exists.
  • Running several sessions with Heard? Its Focus mode stays quiet until an agent needs you: questions, approvals, blockers and failures.

(8)Troubleshooting

If the alert never comes, or comes late.

Most missing alerts come down to one of these.

  • No banner from osascript: it posts through Script Editor and fails silently without permission. Run osascript -e 'display notification "test"' once, then turn on Allow Notifications for Script Editor in System Settings → Notifications.
  • Banners vanish during a macOS Focus: add Script Editor, or your terminal for the built-in notification, to the apps that Focus allows.
  • The alert is late: that is the six-second rule for permission_prompt, which restarts on every keystroke, or the 60-second wait for idle_prompt. Use PermissionRequest for an immediate alert.
  • No idle_prompt at all: it does not fire while a background subagent is still running, or while Claude Code waits for a usage limit to reset.
  • The hook is missing: run /hooks. Edits are normally picked up on their own; if the hook still does not appear, restart the session and check the JSON for trailing commas.
  • Over SSH, osascript and notify-send run on the server. Use the built-in notification in Ghostty, Kitty or iTerm2, or have the hook return a terminalSequence so Claude Code sends the notification through your terminal.
  • Inside tmux, the built-in notification needs set -g allow-passthrough on in ~/.tmux.conf, then tmux source-file ~/.tmux.conf.
  • In Claude Desktop or the VS Code extension, permission_prompt arrives about six seconds after the request even while you type. Set CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS=1 to turn it off there.
  • Remote Control pushes not arriving: if /config shows No mobile registered, open the Claude app once. On iOS, check that a Focus or notification summary is not holding Claude’s notifications.
Ready-made

Tools that handle the alert, or the answer, for you.

Each one read from its own README or site on October 7, 2026. Pick by where you want to be when Claude asks.

Remote Control push

Docs

Anthropic’s own way to reach a local session from the Claude app or claude.ai/code. Turn on Push when actions required and permission prompts and questions reach your phone, where you can answer them in the same session.

Best for
Answering from your phone with nothing extra to install
Surface
Claude app (iOS, Android), claude.ai/code
Agent support
Claude Code
Tradeoff
Needs a Pro, Max, Team or Enterprise claude.ai login; no API keys or cloud providers.

claude-remote-approver

GitHub

A PermissionRequest hook that sends each prompt to the ntfy app with Approve, Always Approve and Deny buttons, and sends AskUserQuestion options as buttons too. Falls back to the terminal prompt after a timeout, 120 seconds by default.

Best for
One-tap approvals from your phone
Surface
npm CLI plus the ntfy app
Agent support
Claude Code
Tradeoff
Commands pass through ntfy.sh unless you self-host. Last updated March 2026.

agent-notify

GitHub

An installer that adds a PermissionRequest hook with a desktop notification on macOS, Linux and WSL (a Windows message box under Git Bash), in the CLI and the VS Code extension. A second installer posts permission requests, with the tool name, and session ends to a Slack webhook.

Best for
Slack pings for approvals
Surface
Shell installer
Agent support
Claude Code
Tradeoff
Approvals and Stop only; the desktop text is a fixed line.

code-notify

GitHub

A CLI (cn on) that installs hooks for several agents. It alerts on idle_prompt by default; cn alerts add permission_prompt and cn alerts add ask_user add approvals and questions. Optional sounds, voice announcements on macOS and Windows, and Slack or Discord webhooks.

Best for
One setup across several agent CLIs
Surface
Homebrew, npm or install script
Agent support
Claude Code, Codex, Gemini CLI, Oh My Pi
Tradeoff
For Codex it sees completions only, not approval prompts.

AgentNotch

Site

A Mac menu bar app that shows your agent sessions in one place, in the notch. Approve a request after seeing the command and reason, read a question and jump to its session, and get notified when an agent needs input or finishes. Session monitoring is local.

Best for
Approving at your Mac with several agents open
Surface
macOS app
Agent support
Claude Code, Cursor, Codex, Kimi, OpenCode and more
Tradeoff
A board you look at; a one-time purchase after a 3-day trial.

A voice layer for coding agents. Speaks questions, approvals, blockers, failures and results from each Claude Code and Codex session, so you know which one needs you without looking. On Power, dictate a reply to the right session from your Mac or a paired iPhone.

Best for
Several sessions while your eyes are elsewhere
Surface
macOS app
Agent support
Claude Code, Codex CLI, cloud agents via MCP
Tradeoff
macOS 14 or later; replies need Power (pricing).

Pick one

Which setup fits how you work?

Start with the lightest option that gets you back in time. They combine well.

  1. One session, you are at the Mac in another window

    Notification hook

    The step 2 script with permission_prompt|idle_prompt|elicitation_dialog|elicitation_url_dialog. Quiet while you type, a titled banner when you drift away.

  2. Six seconds feels too long

    PermissionRequest hook

    Same script, "async": true, plus AskUserQuestion under PreToolUse. Instant, at the cost of alerts you did not need.

  3. Linux, Windows or SSH

    Plain hooks or the built-in alert

    notify-send or PowerShell locally; over SSH, use the built-in notification in Ghostty, Kitty or iTerm2, which reaches your laptop.

  4. Away from the desk, want to approve

    Remote Control or claude-remote-approver

    Remote Control on a claude.ai plan; claude-remote-approver if you sign in another way or want ntfy buttons.

  5. Several agents, you want a board to glance at

    AgentNotch

    Approvals and questions for every session in one place on your Mac.

  6. Several agents, eyes on something else

    Heard

    Spoken questions and approvals with the session name, Focus mode for decisions only, replies by voice on Power.

Questions

Frequently asked questions

Is there a way to get notified when Claude Code needs my input or approval?

Yes. Add a Notification hook matched to permission_prompt and idle_prompt in ~/.claude/settings.json and point it at a desktop notification command. For an alert the moment Claude asks, use a PermissionRequest hook. Ghostty, Kitty and iTerm2 also show a built-in desktop notification with no setup.

How do I stop missing Claude Code permission prompts when I’m in another window?

Use a Notification hook with the permission_prompt matcher, which fires once the prompt has waited about six seconds without you typing. If you want it sooner, use a PermissionRequest hook with "async": true; it fires as soon as Claude asks.

Why does my Claude Code notification arrive late?

permission_prompt waits about six seconds and restarts that wait on every keystroke; idle_prompt waits about 60 seconds after Claude finishes and skips while a background subagent runs. Both are by design. PermissionRequest has no delay.

Can a notification hook approve a permission by accident?

Only a PermissionRequest hook that prints a decision object, or a PreToolUse hook that prints a permissionDecision, can allow or deny. A script that prints nothing leaves the prompt alone, and "async": true makes Claude Code ignore decision fields entirely. Notification hooks cannot block or change anything.

Can I approve Claude Code permissions from my phone?

Yes. With Remote Control on a Pro, Max, Team or Enterprise plan, turn on Push when actions required and answer in the Claude app. claude-remote-approver does it through ntfy notifications with Approve and Deny buttons.

Can I hear Claude Code’s questions out loud when it gets stuck waiting for me?

Yes. Pipe the Notification hook’s message into say on macOS or spd-say on Linux. For spoken questions and approvals across several sessions, with the session named, a voice layer such as Heard does it without hooks you maintain yourself.

Are there tools that only interrupt me when a coding agent actually needs a decision?

A hook matched only to permission_prompt, idle_prompt, elicitation_dialog and elicitation_url_dialog is the free version. Remote Control’s Push when actions required covers prompts and questions. Heard’s Focus mode stays quiet until an agent needs you: questions, approvals, blockers and failures.

Ready when your agents are

Hear the work without watching every screen.

Start with the full Heard Power experience for 14 days. No card required. The open source engine remains free.

Download Heard for Mac macOS 14 or later · Claude Code and Codex supported