Claude Code 通知失灵时,原因几乎总是以下四种之一:hook 没有加载;hook 运行了但失败了;你依赖的事件没有在预期的时机触发;或者操作系统把提醒隐藏了。在 Claude Code 里运行 /hooks 查看已加载的内容,用 claude --debug 启动会话查看每个 hook 实际做了什么,然后再检查电脑或手机上的通知设置。如果你用的是 Claude Code Notifier,ccn doctor 和 ccn test 两条命令就能覆盖大部分检查。
下面的清单按原因的常见程度从高到低排列,适用于 Mac、Windows 和 Linux。
011. 确认 Claude Code 已加载该 hook
在 Claude Code 的 prompt 中输入 /hooks。它会以只读方式列出 Claude Code 加载的所有 hook,并标注每个 hook 的来源:用户设置、项目设置、本地设置、插件或当前会话。选中某个 hook 可以看到具体命令以及定义它的文件。
如果你的 hook 不在列表中:
- JSON 无效。设置文件是严格的 JSON。多一个尾逗号或一条
//注释都会让文件失效,Claude Code 会在下次启动时报 Settings Error。运行claude doctor可以看到被 Claude Code 拒绝的条目。 - 文件位置不对。个人 hook 放在
~/.claude/settings.json(Windows 上是%USERPROFILE%\.claude\settings.json)。项目 hook 放在项目内的.claude/settings.json。运行/status,看Setting sources一行就知道加载了哪些文件。 - 事件名写错了。事件名区分大小写:
Notification、Stop、PermissionRequest。未知的事件名会显示为 Settings Warning 并被跳过。 - hook 被关闭了。任一设置文件中有
"disableAllHooks": true都会关闭所有 hook。如果/hooks显示Only hooks from managed settings run here,说明你的组织设置了allowManagedHooksOnly,你自己的 hook 不会运行。 - 修改没有被识别。Claude Code 通常会自动重新加载设置。如果几秒后 hook 仍未出现,重启会话即可。
022. 接受工作区信任
在交互式会话中,只有你在该文件夹的工作区信任对话框中点了接受,Claude Code 才会运行来自任何设置文件的 hook,包括你自己的 ~/.claude/settings.json。如果你关掉了这个对话框,或者当前文件夹从未用 Claude Code 打开过,hook 在这里就不会运行。在该文件夹中启动 claude 并接受对话框。
033. 确认事件在你预期的时机触发
很多“坏掉”的通知其实是时机问题。根据 Anthropic 的 hooks 参考文档:
Notification(permission_prompt)权限提示已等待约六秒且你没有输入。每次按键都会重置计时。Notification 搭配 idle_promptClaude 完成约 60 秒后,前提是你没有输入,且没有仍在运行的后台 agent。Stop每次 Claude 完成回复时触发。中断时不触发。API 出错时触发的是 StopFailure。PermissionRequestClaude Code 即将向你请求权限的那一刻。所以如果你一边在 terminal 里打字一边测试 Notification hook,它可能永远不会触发。切到别的窗口等一会儿。想在一轮结束时立即收到提醒,请用 Stop,详见 Stop hook 指南。
另外检查一下权限模式。较新版本的 Claude Code 会以 auto 模式启动交互式会话,由分类器自动批准大部分操作,不再询问。没有提示,就没有 permission_prompt 通知,也不会触发 PermissionRequest hook。要测试权限提醒,按 Shift+Tab 直到状态栏显示 manual 模式,然后让 Claude 做一件需要批准的事。详情见权限模式详解。
matcher 同样区分大小写。PermissionRequest 的 matcher 写成 bash 是匹配不到 Bash 工具的。
044. 手动运行 hook 命令
从 /hooks 复制命令,在 terminal 中用示例输入运行:
echo '{"hook_event_name":"Stop","cwd":"/tmp","last_assistant_message":"done"}' | ./my-hook.sh
echo $?
常见失败:
command not found:使用脚本的绝对路径,项目内的脚本可用${CLAUDE_PROJECT_DIR}。- 脚本完全没反应:用
chmod +x ./my-hook.sh加上可执行权限。 jq: command not found:安装jq,或者改用 Python 或 Node.js 解析 JSON。
055. 查看 debug 日志
用 claude --debug 启动 Claude Code。terminal 里不会多打印任何东西,日志写入 ~/.claude/debug/<session-id>.txt。想自定义路径,可以用 claude --debug-file /tmp/claude.log,再在另一个 terminal 中运行 tail -f /tmp/claude.log。如果会话已在运行,/debug 会开启日志并告诉你日志位置。
找以 Hooks: 开头的行。每行会列出事件、命令、结束方式(finished with status 0、timed out、failed to start)以及耗时。想看更详细的匹配信息,设置 CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose。
有两个问题只能在这里发现:
- shell 配置文件有输出。如果
~/.bashrc或~/.zshrc里执行了echo,而 shell 又加载了它,这段文字就会出现在 hook 的 JSON 输出前面,Claude Code 会把输出当作纯文本处理。在日志里搜索Hook output does not start with {。把配置文件中的输出包进if [[ $- == *i* ]]; then ... fi,让它只在交互式 shell 中执行。 - 没有可写入的 terminal。在 Mac 和 Linux 上,command hook 运行时没有控制终端。试图响铃或向
/dev/tty写转义码的 hook 会静默失败。请改用桌面通知命令,或使用 Claude Code 自带的preferredNotifChannel设置,详见 terminal 响铃指南。
066. 检查操作系统
如果 debug 日志显示 hook 以状态 0 结束,但你还是什么都没看到,那就是被操作系统隐藏了。检查发出提醒的应用是否有通知权限,并确认专注模式(Mac)、勿扰模式(Windows)或 Linux 桌面的勿扰开关已关闭。在 Linux 上,还必须有通知守护进程在运行。
07如果你在用 Claude Code Notifier
Claude Code Notifier 是一个独立工具(并非 Anthropic 出品),它会把一个小程序 ccn 安装为 Claude Code 的 hook。上面的内容同样适用,因为 ccn 和其他 hook 没什么两样。先用它自带的检查命令:
ccn doctor会检查 hook、凭据、与服务器的连接以及在场检测。先修复它报告的所有问题。ccn test会发送一条测试通知。如果能收到,说明问题出在事件或某项设置上,而不是整条链路。ccn devices会列出与这台电脑配对的手机。如果列表为空,用ccn pair重新配对,具体步骤见配对指南。ccn config show会打印当前生效的设置。确认notify_on_done、notify_on_permission和notify_on_question已开启,且quiet_hours没有覆盖当前时间。在手机上改的设置,需要用ccn sync同步到电脑。
有几种行为看起来像故障,其实是有意为之:
- 你就在电脑前。如果你在过去 30 秒内打过字,就不会等待手机,terminal 照常询问。开启
quiet_when_present(默认开启)时,如果你正在 Claude 运行的 terminal 里,手机什么都不会收到;如果你在其他应用中活跃,手机会收到一张信息卡片。 - Mac 上提醒重复或缺失。不要在同一台 Mac 上同时运行旧版 Mac 菜单栏应用和
ccn。 - 长时间未使用。如果手机或电脑 60 天没有使用,服务器会删除其配对,你需要重新配对。
在手机上,检查是否允许该应用发送通知,并确认专注模式(iPhone)或勿扰模式(Android)没有把它静音。在 Android 上,电池优化可能会延迟某些应用的通知;如果提醒来得晚,在电池设置中允许该应用不受限制地运行。如果你手动编辑过 settings.json,ccn doctor 会告诉你它的 hook 是否还在。ccn upgrade 可以更新到最新版本。
08常见问题
为什么我的 Notification hook 只是偶尔触发?
permission_prompt 和 idle_prompt 这两种类型会在你看起来已离开时才触发。permission_prompt 会等待大约六秒无输入,idle_prompt 则在 Claude 完成后约 60 秒触发。如果你正在打字,它们会被推迟。需要即时信号的话,用 PermissionRequest 或 Stop。
Claude Code 的 debug 日志在哪里?
运行 claude --debug,日志会写入 ~/.claude/debug/<session-id>.txt。可以用 claude --debug-file <path> 指定位置,或在运行中的会话里使用 /debug。
ccn test 正常,但收不到真实通知,为什么?
链路没问题,所以要看设置和时机。用 ccn config show 检查 notify_on_* 和 quiet_hours;记住开启 quiet_when_present 时,你在 terminal 前就不会发送任何通知;再检查一下 Claude Code 的权限模式。