让它跑长任务时主动叫你,而不是你守着屏幕
批量处理四十份文件要跑二十分钟,中间可能停下来等你批准。用通知钩子把「需要你」和「跑完了」推到手机或系统通知上,你可以去干别的。
- 出处
- Hooks reference
- 来自
- Anthropic 官方文档
- 查证日期
- 2026/08/05
让它批量处理四十份访谈稿,要跑二十分钟。中间可能会停下来问你「这个操作要不要批准」,也可能跑到一半卡住。
于是你只能守着屏幕。 而这二十分钟本来是你可以去开会、去吃饭的。
Claude Code 有一套钩子(hooks)机制,能在特定时刻触发你指定的命令。用它把「需要你」和「跑完了」推出来,就不用盯着了。
通知钩子能捕捉哪几种时刻
Notification 事件在 Claude Code 向你发通知时触发。它可以按通知类型过滤,官方支持的类型里,和长任务最相关的是这几个:
| 类型 | 什么时候触发 |
|---|---|
permission_prompt |
需要你批准某个操作 |
agent_needs_input |
代理需要你输入 |
agent_completed |
代理完成了 |
idle_prompt |
空闲等待中 |
前三个正好覆盖「你需要被叫醒」的全部情形。
Notification是非阻塞事件——它只是通知,不会拦下任何操作。
方案一:系统通知(最简单,零依赖)
如果你就在电脑前但在别的窗口工作,系统通知就够了。不需要注册任何服务。
在 ~/.claude/settings.json 里加:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt|agent_needs_input|agent_completed",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/notify.sh"
}
]
}
]
}
}
然后建 ~/.claude/hooks/notify.sh:
#!/bin/bash
# 钩子的输入是一段 JSON,从标准输入进来
INPUT=$(cat)
MSG=$(echo "$INPUT" | jq -r '.message // "Claude Code 需要你"')
# macOS 系统通知
osascript -e "display notification \"$MSG\" with title \"Claude Code\" sound name \"Glass\""
记得给它执行权限:
chmod +x ~/.claude/hooks/notify.sh
Windows 的话把最后那行换成 PowerShell 的气泡通知,或者直接用下面的手机方案。
方案二:推到手机(人不在电脑前)
想出门也能收到,就需要一个推送服务。这类服务(Pushover、Bark、ntfy 等)的原理一样:给你一个专属地址,往那儿发一条 HTTP 请求,你手机上就弹一条通知。
脚本改成这样:
#!/bin/bash
INPUT=$(cat)
MSG=$(echo "$INPUT" | jq -r '.message // "Claude Code 需要你"')
curl -s -X POST "<你的推送服务地址>" \
-d "title=Claude Code" \
-d "message=$MSG" > /dev/null
具体的字段名和认证方式按你选的服务的文档填——各家不同,但都是一条 curl 的事。
⚠️ 别把密钥直接写进提交到版本库的文件里。 放在
~/.claude/下的脚本里(那是本机的),或者读环境变量。
一次性买断 vs 订阅
选服务时注意计费方式。有些是一次性买断(比如 Pushover),有些按月订阅。对这个用途来说,一次性的更划算——你一天可能就用几次。
更进一步:区分「需要你」和「跑完了」
上面的配置把三种情况混成了一条通知。分开处理更有用——「需要批准」是急事,「跑完了」不是。
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt|agent_needs_input",
"hooks": [
{ "type": "command", "command": "~/.claude/hooks/notify-urgent.sh" }
]
},
{
"matcher": "agent_completed",
"hooks": [
{ "type": "command", "command": "~/.claude/hooks/notify-done.sh" }
]
}
]
}
}
两个脚本用不同的提示音,或者推送到不同优先级。手机响一声你就知道是哪一类,不用掏出来看。
配置放在哪
| 位置 | 生效范围 | 能不能共享 |
|---|---|---|
~/.claude/settings.json |
所有项目 | 否,只在本机 |
.claude/settings.json |
单个项目 | 可以提交进版本库共享 |
.claude/settings.local.json |
单个项目 | 否,已被 gitignore |
通知这类偏好是个人的,放 ~/.claude/settings.json 就好。
让 Claude 帮你配
你不用手写这些。直接说:
帮我配一个通知钩子:需要我批准操作、或者任务完成时,发一条 macOS 系统通知。配置写进 ~/.claude/settings.json,脚本放 ~/.claude/hooks/ 下。
它会把 JSON 和脚本都建好。配完让它自己触发一次验证——比如让它请求一个需要批准的操作,看通知有没有弹出来。
顺带一提:钩子还能做别的
通知只是钩子最简单的一个用途。PreToolUse 钩子能在某个操作执行之前拦下来:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(rm *)",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh"
}
]
}
]
}
}
脚本返回一个「拒绝」的判定,这个命令就执行不了。
这一点很重要:钩子是强制执行的,而 CLAUDE.md 里写的规则只是上下文——它会尽量遵守,但不保证。凡是「绝对不能发生」的事(比如删除原始素材目录),写成钩子,别写成规则。
回到那篇检查点能救你什么:
rm删掉的文件回退救不回来。用一个PreToolUse钩子把删除操作拦下来,是比事后补救更靠谱的做法。