目录
Claude Code 有两种值得关注的停下方式:一是卡住了在等你(权限确认、提问),二是已经做完了。如果你没盯着终端,这两种情况看起来完全一样——什么都不会发生,会话就一直闲置,直到你回来。解决办法是用 hook:在 settings.json 里加几行配置,任何一种情况发生的瞬间,就把 Webhook 发到你的手机。
这篇指南给出可以直接复制的配置,说明不同场景该用哪个 hook 事件,并讲清让它稳定工作的细节:怎么读取 hook 的输入、shell 引号怎么处理、以及如何避免被通知淹没。
什么场景用哪个 hook
Claude Code 会在生命周期事件上运行 hook。其中两个正好覆盖这个需求(hooks 参考文档):
| 你想知道…… | Hook 事件 | Matcher / 过滤 |
|---|---|---|
| Claude 在等你做权限决定 | Notification | permission_prompt |
| Claude 已经闲置、在等你输入 | Notification | idle_prompt |
| Claude 回复完毕 | Stop | 无需设置 |
Notification hook 的 matcher 按通知类型过滤,所以你可以精确选择哪些通知会送到手机。输入以 JSON 形式从 stdin 传入,包含 notification_type、message、cwd 和 session_id。Notification hook 无法阻止或修改任何行为——它们只是观察者,而这正是这里需要的。
Stop 的输入包含 last_assistant_message,也就是 Claude 产出的最后一段文字,正好可以白送一行通知摘要。
你需要什么
- 手机上装好 Echobell(App Store / Google Play)
- 运行 Claude Code 的机器上有
curl和jq - 两分钟
第 1 步 —— 建两个频道
别把所有通知都塞进同一个频道。在 Echobell 里创建:
- Claude Blocked,类型选 时效性通知(Time Sensitive) 或 来电(Calling) —— 用于权限确认:智能体已经停摆,每过一分钟都是在白白浪费算力和时间
- Claude Done,类型选 普通(Normal) —— 一条普通推送,什么时候看都行
复制每个频道的 Webhook URL,形如 https://hook.echobell.one/t/<channel-token>。把它当密码对待:任何拿到它的人都能让你的手机响铃。
把两个 URL 存成环境变量,这样它们就不会进到提交的配置文件里:
export ECHOBELL_CLAUDE_BLOCKED_URL="https://hook.echobell.one/t/<blocked-token>"
export ECHOBELL_CLAUDE_DONE_URL="https://hook.echobell.one/t/<done-token>"
把这两行放进 shell 配置文件,Claude Code 才能继承到它们。
第 2 步 —— 添加 hooks
要对所有项目生效,加到 ~/.claude/settings.json;只对某个仓库生效,加到 .claude/settings.local.json:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"command": "jq -c '{title: \"Claude 需要授权\", body: .message, project: (.cwd | split(\"/\") | last)}' | curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- \"$ECHOBELL_CLAUDE_BLOCKED_URL\""
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "jq -c '{title: \"Claude 已完成\", body: (.last_assistant_message // \"完成\" | .[0:200]), project: (.cwd | split(\"/\") | last)}' | curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- \"$ECHOBELL_CLAUDE_DONE_URL\""
}
]
}
]
}
}
各部分的作用:
jq -c '{...}'从 stdin 读取 hook 的 JSON 并构造一个小载荷,这样 Echobell 收到的正是你想要的字段,而不是整份 hook 文档。.cwd | split("/") | last把/home/me/code/api变成api,通知里就能看出是哪个项目在请求你。.[0:200]截断最后一条消息。Echobell worker 把通知正文限制在 1500 字节以内,而锁屏上能显示的本来就少得多。-m 10给curl设了 10 秒超时,网络出问题时 Claude Code 也不会一直等你的 hook。
Echobell 通过频道模板渲染你发送的键,而新建的频道没有读取这些键的模板——请在频道设置里把标题模板设为 {{title}}、正文模板设为 {{body}}。想显示项目名的话,在其中一个里加上 {{project}},例如 {{title}} ({{project}})。
第 3 步 —— 不等真实提示,直接测试
用一份伪造的 hook 载荷,手动跑一遍同样的管道:
echo '{"message":"Claude needs your permission to use Bash","cwd":"/home/me/code/api","notification_type":"permission_prompt"}' \
| jq -c '{title: "Claude 需要授权", body: .message, project: (.cwd | split("/") | last)}' \
| curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- "$ECHOBELL_CLAUDE_BLOCKED_URL"
如果手机亮了,说明 Echobell 这一侧没问题,剩下的问题都出在 Claude Code 读取配置的方式上。在 Claude Code 里运行 /hooks 确认 hook 已加载;会话运行期间修改的设置,可能需要通过 hooks 菜单或重启才能生效。
第 4 步 —— 让「被阻塞」频道真正响铃
推送通知打不过勿扰模式。来电(Calling) 频道的表现和来电一样,能穿透 iOS 专注模式——当你启动一个长任务、晚上出门时,这一点最重要。如果你只想在部分提示出现时被打扰,不要去改 hook,而是在 Echobell 频道里对你发送的变量设置条件,例如 project == "api"。完整的变量列表见条件参考。
避免通知过载
一个繁忙的会话可能触发大量 Stop 事件——每次回复结束都会有一个。保住有效信号有三个办法:
- 不要把
Stop发到会响铃的频道。 任务完成并不紧急,保持普通推送即可。 - 用
idle_prompt代替Stop,如果你只想在 Claude 停下来等你时才收到通知,而不是每次回复之后都收到。 - 按项目收窄,用条件过滤,这样临时的试验仓库就完全不会通知你。
在远程环境或 CI 中运行 Claude Code
同样的方法在云端或远程环境里也能用,因为 hook 只是一个对外的 HTTPS 请求,不需要任何东西能被公网访问。把这两个环境变量配置到环境的 secrets 里,而不是 shell 配置文件里,无论会话跑在哪里,通知都能送到你的手机。
故障排查
什么都没收到,手动测试也失败。 检查启动 Claude Code 的那个 shell 里是否设置了 URL 变量:echo "$ECHOBELL_CLAUDE_BLOCKED_URL"。变量为空时 curl 会静默失败。
手动测试能通,但 hook 不触发。 确认 matcher:permission_prompt 和 idle_prompt 是不同的,不匹配的 matcher 只是永远不会运行。运行 /hooks 并检查 JSON 是否合法——多一个尾随逗号,就会让整个 settings 文件里的 hook 全部失效。
通知正文是空的。 jq 过滤器引用了该事件中不存在的字段。message 存在于 Notification 的输入中;last_assistant_message 存在于 Stop 的输入中。像上面的配置那样,用 // 提供默认值。
触发太频繁。 参见上一节——把 Stop 换成 idle_prompt,或者加一个条件。
常见问题
Claude Code 需要授权时,怎么收到通知?
添加一个 matcher 为 permission_prompt 的 Notification hook,把 Webhook 发到某个频道。Echobell 会把这个请求变成手机上的推送或来电式提醒。
怎么知道 Claude Code 什么时候完成了任务?
添加一个 Stop hook。它在 Claude 回复完毕时运行,输入里包含 last_assistant_message,可以直接用作通知正文。
通知能突破勿扰模式吗?
可以,前提是接收的频道是来电(Calling)频道。它的表现就像来电,iOS 专注模式会放行;而任何 App 的普通推送都不行。
在网页版 Claude Code 或远程会话里能用吗?
能。hook 只发起一个对外的 HTTPS 请求,所以只要会话能访问互联网就能用。通过环境的 secrets 提供频道 URL 即可。
把 Webhook URL 写进 settings.json 安全吗?
建议像上面那样用环境变量,这样令牌就不会被提交进仓库。如果泄露了,新建一个频道,停用旧的。
小结
两个频道、两个 hook,加一条 jq | curl 管道:permission_prompt 走**来电(Calling)**或时效性频道,Stop 走普通频道。之后你就可以启动一个长时间的智能体任务,离开房间,只在智能体真正需要你的时候被叫回来。
下载 iPhone 版 Echobell,或前往 Google Play 获取,然后先跑一遍上面的手动测试,再放心地把长任务交给它。