让Claude Code跑个长任务,切去做别的事,然后忘了回来看——这种事我干过不止一次。或者反过来,一直盯着终端干等,啥也干不了。

Claude Code的Hooks机制可以在任务完成时主动通知你。但原生通知就一句"任务已完成",冷冰冰的,没有温度。

我从Hooks基础开始,一步步做出了一个有性格的通知系统:它知道现在几点、任务跑了多久、成功还是失败,然后用一句有趣的话通知你。

先看看效果

装完之后终端完成消息通知长这样:

飞书消息通知效果图:

Mac电脑系统通知效果图:

有那味儿了吧?接下来说怎么实现的。

开源仓库学习地址:https://github.com/leeandrew94/claude-notify

一、Claude Code Hooks是什么

Hooks是Claude Code提供的事件钩子系统。特定事件发生时(工具执行、会话结束、通知触发等),Claude Code会自动运行你预定义的Shell命令。

前端的同学可以类比Vue的 onMounted,后端的类比@PostConstruct——在关键节点插入自定义逻辑。

1.1 配置位置

Hooks写在 ~/.claude/settings.json"hooks"字段里,结构长这样

{
  "hooks": {
    "<事件名称>": [
      {
        "matcher": "可选的匹配规则",
        "hooks": [
          {
            "type": "command",
            "command": "你的 Shell 命令"
          }
        ]
      }
    ]
  }
}

1.2 事件类型

Claude Code支持多种事件,可以在终端用/hooks命令查看完整列表。

这里截图前半部分,按键盘下键可以继续下拉查看更多

挑几个比较实用的列出来:

类别 事件 触发时机
工具执行 PreToolUse 工具执行前
工具执行 PostToolUse 工具执行后
会话生命周期 SessionStart 会话启动
会话生命周期 SessionEnd 会话结束
会话生命周期 Stop Claude 处理完毕,等待用户输入
通知 Notification 系统通知事件(任务完成、等待输入等)
子代理 SubagentStart / SubagentStop 子代理启动/停止
压缩 PreCompact / PostCompact 压缩前后

我们要实现的功能,关注NotificationStop两个事件就够了。

1.3 数据传递方式

Hook执行时,Claude Code通过Stdin JSON传递上下文:

// Notification 事件的 stdin
{
  "session_id": "abc123",
  "message": "Claude is waiting for your input"
}

// Stop 事件的 stdin
{
  "session_id": "abc123",
  "stop_hook_reason": "end_turn"
}

同时通过环境变量提供元数据:

变量 说明
CLAUDE_HOOK_EVENT 事件名称(Notification / Stop)
CLAUDE_SESSION_ID 会话 ID
CLAUDE_PROJECT_DIR 项目目录

二、最简单的通知Hook

了解了基础,先来一个最小实现。把下面这段复制到~/.claude/settings.json里就能用

{
  "hooks": {
    "Notification": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"任务完成\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

在Claude Code终端随便问个问题,任务完成时macOS侧边栏会弹一条系统通知

但这就是一行固定文案,没有灵魂。

三、设计思路

我这人有点审美洁癖,总觉得看这种干巴巴的通知缺点啥。于是在本子上写写画画,就有了claude-notify的设计想法。

3.1 我想要的通知长什么样

不是一条通知,而是一个通知系统

  1. 有人格 — 不是"任务完成",而是"早安打工人,刚好够去倒杯水,搞定了 ☕"

  2. 有感知 — 知道现在几点、任务跑了多久、成功还是失败

  3. 跨平台 — macOS、Windows、Linux都能用

  4. 可扩展 — 支持企业微信、飞书、ntfy.sh 等webhook推送

  5. 易管理 — CLI 命令行配置,不用手动改 JSON

3.2 架构设计

人格引擎负责平台无关的文案生成,通知发送走平台相关的逻辑,各管各的。

四、让通知有点灵魂

文案不是随机挑选,而是基于四个维度的感知来组合

输入: "Build completed successfully. Took 8m 22s. All 42 tests passed."

感知结果:
  时段 → 下午 (afternoon) ☕
  耗时 → 502 秒(8 分 22 秒)
  类型 → build(构建)
  成败 → success

耗时提取:从message中用正则提取,中英文都支持。

# 中文: "耗时 3 分 22 秒"
cn_min=$(echo "$msg" | grep -oE '耗时[ ]*([0-9]+)[ ]*分')
cn_sec=$(echo "$msg" | grep -oE '([0-9]+)[ ]*秒')

# 英文: "took 3m 22s" / "8 minutes" / "42s"
en_min=$(echo "$msg" | grep -oiE '([0-9]+)\s*(m|min|minutes?)')
en_sec=$(echo "$msg" | grep -oiE '([0-9]+)\s*(s|sec|seconds?)')

任务类型识别:通过关键词匹配。

test    → "test|测试|spec|jest|pytest|pass"
build   → "build|构建|compile|webpack|vite"
deploy  → "deploy|部署|release|publish"
refactor→ "refactor|重构|migrate|迁移"

文案组合:三元组拼接——[时段] + [耗时/场景] + [结果]

"早安打工人" + "刚好够去倒杯水" + "搞定了" → "早安打工人,刚好够去倒杯水,搞定了 🌅"

每个维度从对应文案池里随机选取,组合结果几乎不会重复。

时段文案池(部分)

时段 文案示例
凌晨 (0-6点) 凌晨还在卷 / 修仙成功 / 夜猫子辛苦了
早上 (6-9点) 早安打工人 / 晨间任务完成 / 新的一天从搞定开始
午饭 (12-14点) 饭点任务完成 / 先吃饭再说 / 午休都不放过
深夜 (21-24点) 夜深了 / 夜猫子模式 / 搞完就去睡吧

耗时文案池(部分)

耗时 文案示例
<30s 秒完 / 比你泡咖啡还快 / 手速惊人
1-5min 刚好够去倒杯水 / 完美泡面时间
>5min 等了好久... 你是不是去摸鱼了 / 终于!建议奖励自己一杯奶茶
>15min 等了好久好久... 你确定不来看看 / 这时间够看一集短剧了

结果文案池(部分)

结果 文案示例
成功(测试) 测试全绿 / 全部通过 / 今天可以安心下班了
成功(构建) 构建成功 / 编译通过 / 打包完成
失败 翻车了 / 出了点问题 / 代码它不听话了

五、跨平台通知发送

通过shell脚本检测当前系统

detect_platform() {
    case "$(uname -s)" in
        Darwin*)              PLATFORM="macos" ;;
        Linux*)               PLATFORM="linux" ;;
        MINGW*|MSYS*|CYGWIN*) PLATFORM="windows" ;;
    esac
}

各平台实现命令如下

macOSosascript(侧边栏通知自动适配)

osascript -e "display notification \"$BODY\" with title \"$TITLE\" sound name \"$SOUND\""

Windows — PowerShell Toast 通知

[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("claude-notify").Show($toast)

Linuxnotify-send

notify-send -a "claude-notify" -i dialog-information "$TITLE" "$BODY"

六、Webhook 推送(可选)

之前写过Claude Code接入飞书CLI的文章,那肯定要用起来。支持通过Webhook推送到手机

飞书开源CLI了!保姆级教程,手把手教你接 Claude Code

通道 场景 实现方式
企业微信 团队协作 群机器人 Webhook,POST markdown
飞书 团队协作 自定义机器人 Webhook,POST 卡片消息
ntfy.sh 个人推送 开源免费,手机装 app 订阅 topic
自定义 任意接口 POST JSON {title, body, session_id}

企微的话,一个POST请求就搞定:

curl -X POST "$WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "msgtype": "markdown",
    "markdown": {
      "content": "**早安打工人,搞定了 🌅**\n\n所有测试通过。"
    }
  }'

手动改配置文件太原始了,所以我把claude-notify做成了CLI,通过命令直接配置,对标Claude Code的 CLI玩法。看看怎么操作的

安装执行 ./install.sh,它会自动创建软连接,不污染你的环境

飞书 Webhook 配置流程:群设置 → 群机器人 → 「添加机器人」→ 选择「自定义机器人」→ 复制「webhook」地址

创建机器人 → 选择添加机器人

复制webhook地址

终端执行claude-notify channel feishu填写对应信息就完成了

不想用了?一键卸载

./uninstall.sh # 尽量给 sudo 权限

最后说两句

这个通知功能一开始就是满足自己需求,用着用着就迭代成现在这样了。

写这篇文章主要是分享做工具的思路,顺便学习Claude Code Hooks的用法。做一个工具不是上来就vibe coding,得先构思、确认方案可行性、在本子上画画图和框架,再跟Claude Code对话问它"如果要实现这个功能,我应该如何做、需要为你提供什么",最后确认完整方案再动手,接着就是反复调整验证。

claude-notify这个东西最让我觉得有趣的地方,不是技术多复杂代码多难写,而是每次看到"早安打工人,刚好够去倒杯水,搞定了"这种消息的时候,会觉得这不像一个工具,更像一个搭档。毕竟工作生活都要开心的嘛!!!

好了就到这里啦,大家也可以点点star,还在持续迭代中

我是赛博李同学,大厂写代码的。觉得有用的话,点个赞 + 转发给需要的 TA,感谢支持! 我们下期再见!

 

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐