Claude Code 的 Notification hook 会在 Claude Code 发送通知时运行,最常见的情况是有权限提示在等待(permission_prompt),或 Claude 已完成而你还没回复(idle_prompt)。它的触发时机针对你不在电脑前的情况:permission_prompt 在提示等待约六秒且无按键后触发,idle_prompt 在 Claude 完成约 60 秒后触发。hook 会以 JSON 形式收到通知文本,无法阻止任何操作,适合用来做桌面提醒或推送到手机之类的副作用。
01通知类型
Notification hook 的 matcher 就是通知类型。留空则匹配所有类型,也可以用 | 列出需要的类型。最常用的几种:
permission_promptClaude 需要你批准一次工具调用(或沙箱命令的网络请求),且提示已等待约六秒idle_promptClaude 约 60 秒前已完成回复,而你之后没有输入elicitation_dialogMCP server 打开了一个表单,而你约六秒没有输入elicitation_url_dialogMCP server 请你打开一个 URL,而你约六秒没有输入auth_success认证完成还有更多类型,比如 agent view 中后台会话用的 agent_needs_input 和 agent_completed,以及用于用量限制等待的一组 quota_auto_resume_* 类型。完整的最新列表见 hooks 参考文档。
02触发时机规则
这一点最容易让人踩坑。Notification hook 和 Claude Code 自带的桌面通知共用同一套触发时机,所以在 terminal 会话里,只有在你离开屏幕时它才会触发:
permission_prompt:prompt 出现时启动一个约 6 秒的计时器,每次按键都会重置。如果你很快就做出回应,它根本不会触发。idle_prompt:在 Claude 完成后约 60 秒触发,前提是你此后没有输入过,且没有后台 agent 仍在运行。Claude Code 等待用量限制重置期间不会触发。- 如果某个请求到达时另一个对话框正开着,它的计时从到达时开始算,所以它还排在已打开的对话框后面时,通知就可能已经发到你这里了。
通过 Agent SDK 处理权限的宿主(比如 Claude Desktop 和 VS Code 扩展)对 permission_prompt 的计时方式不同:请求发出约 6 秒后触发,不会因输入而推迟;如果你或某个 PermissionRequest hook 先做出了回应,则直接跳过。
如果想要没有延迟的提醒,换用其他事件:
03hook 收到的内容
除了通用字段(session_id、transcript_path、cwd、hook_event_name),Notification hook 还会收到通知的 message、可选的 title 以及 notification_type:
{
"session_id": "abc123",
"transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
"cwd": "/Users/...",
"hook_event_name": "Notification",
"message": "Claude needs your permission",
"title": "Permission needed",
"notification_type": "permission_prompt"
}
message 是 Claude Code 自己生成的文案,可以直接原样显示。同时跑多个会话时,cwd 能帮你分辨是哪个项目在请求。
04hook 能做什么、不能做什么
Notification hook 无法阻止、推迟或修改通知。它的退出码和 stderr 都会被忽略,JSON 输出中的 systemMessage 和 continue 也会被 Claude Code 丢弃。它纯粹用来执行副作用。
它唯一能用的输出字段是 terminalSequence。hook 运行时没有 terminal,没法自己写转义序列,但可以把序列交给 Claude Code 来输出。这样 hook 就能在 iTerm2、Ghostty、Kitty、WezTerm、Windows Terminal 等终端中触发原生通知,在 tmux 里也行。不过这只在交互式会话中、且 Claude Code 界面显示在屏幕上时有效。
preferredNotifChannel 设置也不会阻止这个 hook。即使关闭了内置通知,Notification 事件照样会触发。该设置只影响 Claude Code 自身提醒你的方式,详见终端响铃指南。
05示例
按类型使用不同的处理程序
为权限 prompt 和空闲提醒分别运行不同的脚本:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [{ "type": "command", "command": "~/.claude/hooks/permission-alert.sh" }]
},
{
"matcher": "idle_prompt",
"hooks": [{ "type": "command", "command": "~/.claude/hooks/idle-alert.sh" }]
}
]
}
}
用 chmod +x 给每个脚本加上执行权限。Mac、Windows 和 Linux 的桌面通知命令见如何在 Claude Code 完成时收到通知,这里不再重复。
显示真实消息和项目
这个脚本(macOS 和 Linux)会把 Claude Code 的消息和项目文件夹放进通知里,而不是显示固定文本:
#!/bin/bash
# ~/.claude/hooks/notify.sh
input=$(cat)
msg=$(jq -r '.message // "Claude Code needs your attention"' <<<"$input")
project=$(basename "$(jq -r '.cwd // "."' <<<"$input")")
if command -v osascript >/dev/null 2>&1; then
osascript -e 'on run argv' \
-e 'display notification (item 1 of argv) with title (item 2 of argv)' \
-e 'end run' "$msg" "Claude Code: $project"
elif command -v notify-send >/dev/null 2>&1; then
notify-send "Claude Code: $project" "$msg"
fi
exit 0
以参数形式传入文本(on run argv),可以避免消息中含引号时 AppleScript 出错。需要先安装 jq。
终端原生通知
Anthropic 官方示例通过 terminalSequence 使用 OSC 777,Ghostty、Warp 和 urxvt 都支持:
#!/bin/bash
input=$(cat)
title="Claude Code"
body=$(jq -r '.message // "Needs your attention"' <<<"$input")
seq=$(printf '\033]777;notify;%s;%s\007' "$title" "$body")
jq -nc --arg seq "$seq" '{terminalSequence: $seq}'
iTerm2、Windows Terminal 或 WezTerm 请改用 OSC 9,Kitty 则用 OSC 99。不在允许列表内的序列会被忽略。
06Claude Code Notifier 的定位
让 Notification hook 调用 push 服务,就能把提醒发到手机上,对很多人来说这已经够用了。ntfy 指南介绍了这种做法。
缺的是回复。permission_prompt 触发时,Claude 正在等待一个对话框,而 Notification hook 无法回应它。Claude Code Notifier 借助能做到这一点的 hook 来解决:用 PermissionRequest 返回你的决定,用作用于 AskUserQuestion 的 PreToolUse 返回你的回答。它的免费命令行工具 ccn 支持 Mac、Windows 和 Linux,本身就能显示桌面通知。配对 iPhone 或 Android 应用后,你可以在手机上选择允许一次、本次会话内允许或拒绝。如果你在过去 30 秒内有过输入,就不会等待手机,terminal 照常询问。它是独立开发的,并非 Anthropic 出品。安装方法见 ccn 页面。
07常见问题
为什么我的 Notification hook 从来不触发?
最常见的原因是你还在键盘前。每次按键都会推迟 permission_prompt,而 idle_prompt 只有在 Claude 完成后你约一分钟没有输入才会触发。测试方法:触发一个权限 prompt,切到别的窗口,等至少 6 秒。如果还是不触发,确认 /hooks 里列出了它,再参考故障排查清单。
idle_prompt 是什么?
这是 Claude 在约 60 秒前完成回复、且你此后一直没有输入时,Claude Code 发送的通知类型。它是提醒你该你操作了,而不是即时的“已完成”信号。想要即时信号,请用 Stop hook。
Notification hook 能批准权限吗?
不能。Notification hook 没有决策控制能力,无论输出什么都无法回应 prompt。要允许或拒绝,请使用 PermissionRequest hook,详见 PermissionRequest 指南。
如果把 preferredNotifChannel 设为 notifications_disabled,Notification hook 还会运行吗?
会。这个设置只影响 Claude Code 自身的提醒方式,Notification 事件和你的 hook 照常运行。
为什么会收到两条通知?
Claude Code 的内置通知和你的 hook 是同时运行的。在 iTerm2、Ghostty 或 Kitty 中可能两条都会出现。关掉其中一个即可,比如用 preferredNotifChannel,或者只保留 hook。