尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

利用Claude Code的Stop Hook实现任务结束自动提示音

利用Claude Code的Stop Hook实现任务结束自动提示音 1. 项目缘起从“默默结束”到“主动通知”不知道你有没有过这样的经历在终端里跑一个耗时比较长的脚本比如编译一个大项目、处理一批数据或者像我一样用 Claude Code 执行一个复杂的代码生成任务。然后你就切到浏览器去查资料或者打开另一个编辑器写点别的。过一会儿你突然想起来“诶刚才那个任务跑完了吗”切回终端一看哦早就结束了进度条停在 100% 那里安安静静的仿佛什么都没发生过。这种“静默结束”在很多时候其实挺耽误事的。尤其是当任务结果是你下一步工作的输入时你可能会白白等上几分钟甚至更久。对于 Claude Code 这种 AI 编程助手来说更是如此它处理一个复杂请求可能需要几十秒这段时间足够你走个神、回个消息然后就把这事儿给忘了。所以我就想能不能让 Claude Code 在任务结束时像老朋友一样“喊”我一声不是那种弹个对话框需要我去点的干扰而是一个简单的、非侵入式的提示音告诉我“嘿伙计你交代的事儿办妥了可以回来验收了。”这个需求听起来简单但实现起来却让我把 Claude Code 的 Hooks 机制、操作系统的进程间通信以及不同 Shell 环境下的脚本编写都摸了一遍。最终我找到了一个既优雅又通用的解决方案利用 Claude Code 的Stop Hook配合系统原生的音频播放能力实现任务结束自动播报。整个过程不依赖任何第三方播放器软件几行脚本就搞定而且跨平台Windows/macOS/Linux的思路是相通的。下面我就把这套“让 Claude Code 会说话”的配置方法以及背后的原理和踩过的坑详细分享给你。2. 理解 Claude Code 的 Hooks 机制事件驱动的扩展点要实现自动提示音首先得明白 Claude Code 在哪里给我们留了“后门”。这个后门就是Hooks钩子。简单来说Hooks 是 Claude Code 在自身生命周期的关键节点比如启动、收到消息、结束任务等向外抛出的“事件”。我们可以为这些事件编写自定义脚本当事件发生时Claude Code 就会自动执行我们的脚本。这有点像我们熟悉的 Git Hooks比如pre-commit或者一些 CI/CD 工具如 Jenkins的构建后步骤。Claude Code 的 Hooks 让我们能够深度定制它的行为而不需要去修改其核心代码。Claude Code 主要支持以下几种类型的 HooksStart Hook: 在 Claude Code 启动时执行。Message Hook: 在 Claude Code 发送或接收消息时执行。这通常用于消息的格式化、日志记录或触发外部工作流。Stop Hook:这是我们本次关注的重点。在 Claude Code 结束一个任务例如完成一次代码生成、执行完一个命令时执行。Error Hook: 在 Claude Code 运行过程中发生错误时执行。我们的目标很明确在Stop Hook被触发时执行一个播放提示音的脚本。这样每当 Claude Code 完成你交给它的任何一项工作你都能立刻得到听觉反馈。注意Hooks 脚本的执行是同步的或者说会阻塞 Claude Code 的主线程直到脚本执行完毕。因此你的 Hook 脚本应该尽可能轻量和快速避免长时间的操作否则会影响 Claude Code 本身的响应速度。播放一个短促的提示音是完美符合这个要求的。3. 方案选型为什么不用“轮询”而用“事件”在动手之前我们不妨先想想有没有其他“土办法”。比如写个脚本轮询检查 Claude Code 的进程状态或者在运行命令时手动在后面加个 echo -e \a发送系统蜂鸣这些方法都有明显的缺陷轮询Polling效率低下且不精确你需要启动一个额外的后台进程每隔几秒去检查一次浪费系统资源。更重要的是你很难精准定义“任务结束”的时刻。是 Claude Code 进程退出还是某个特定会话结束轮询很难把握这个粒度。手动附加命令不通用你需要在每次执行命令时都记得加上播放声音的指令这违背了我们“自动化”的初衷。而且对于 Claude Code 内部触发的复杂任务链你根本无法手动干预。因此基于Stop Hook的事件驱动方案是唯一正确、优雅的选择。它精准地在“任务结束”这个业务定义明确的事件点上触发我们的动作无需轮询无需手动干预与 Claude Code 的生命周期完美绑定。4. 核心实现编写跨平台的提示音播放脚本确定了使用 Stop Hook 后接下来要解决的核心问题是如何在 Hook 脚本里播放一个提示音我们追求的是零依赖、系统原生。好消息是主流操作系统都提供了命令行播放音频的基础能力。4.1 Windows 平台基于 PowerShell 的System.Media.SoundPlayer在 Windows 上最原生的方式是使用 .NET Framework 或 .NET Core 中的System.Media.SoundPlayer类。我们可以通过 PowerShell 直接调用它无需安装任何额外软件。首先我们需要一个提示音文件。系统自带的“叮”声是一个好选择它的路径通常是C:\Windows\Media\notify.wav。你也可以使用任何其他.wav格式的简短音频文件。下面是一个完整的 PowerShell 脚本 (play_notify.ps1)# play_notify.ps1 # 使用 .NET 的 SoundPlayer 播放系统提示音 # 定义音频文件路径这里使用系统自带的提示音 $soundPath “C:\Windows\Media\notify.wav” # 检查文件是否存在 if (Test-Path $soundPath) { # 加载 .NET 程序集如果尚未加载 Add-Type -AssemblyName System.Windows.Forms # 创建 SoundPlayer 对象并播放 $player New-Object System.Media.SoundPlayer $soundPath $player.PlaySync() # PlaySync 会同步播放即等待播放完毕脚本才结束。对于短提示音没问题。 # 如果想要异步播放不阻塞可以使用 $player.Play() } else { Write-Warning “提示音文件未找到: $soundPath” # 备选方案使用控制台蜂鸣符不一定所有终端都支持 # Write-Host “a” -NoNewline }脚本要点解析Add-Type -AssemblyName System.Windows.Forms这行代码确保了包含System.Media.SoundPlayer的程序集被加载到当前的 PowerShell 会话中。这是关键一步。PlaySync()方法同步播放脚本会等待声音播放完毕后再退出。对于我们的场景短提示音是合适的能确保声音被完整听到。如果你担心可能存在的极小延迟可以使用Play()进行异步播放但需注意 Hook 脚本可能提前结束。备选蜂鸣方案脚本中注释了Write-Host “a”这是发送 ASCII 码中的 BEL响铃字符。在某些终端如老版 CMD中会触发系统蜂鸣声但在现代终端如 Windows Terminal、VS Code 内置终端或 PowerShell 默认配置下可能无效因此仅作为备选。4.2 macOS 和 Linux 平台使用afplay或paplay、aplay在类 Unix 系统上播放音频的命令行工具很丰富。对于 macOS系统自带afplay命令非常简单。#!/bin/bash # play_notify_mac.sh afplay /System/Library/Sounds/Ping.aiff # 或者使用其他系统声音如 Glass.aiff, Submarine.aiff 等对于 Linux情况稍复杂因为音频系统多样ALSA, PulseAudio, PipeWire。但通常可以尝试以下命令paplay(PulseAudio): 目前大多数桌面 Linux 发行版的首选。#!/bin/bash # play_notify_linux.sh # 尝试播放系统提示音路径可能因发行版而异 SOUND_FILE“/usr/share/sounds/freedesktop/stereo/complete.oga” if [ -f “$SOUND_FILE” ]; then paplay “$SOUND_FILE” elif command -v paplay /dev/null; then # 如果找不到文件但 paplay 命令存在可以播放一个简短的内置提示可能需要生成 echo -e ‘\a’ # 先尝试控制台蜂鸣 # 更可靠的方式用 sox 或生成一个简单波形这里以简单蜂鸣为例 paplay --volume32768 (echo -e ‘#! /usr/bin/env bash\ncat /dev/urandom | head -c 100 | aplay -q 2/dev/null ’) fiaplay(ALSA): 更底层的音频驱动。# 播放一个 WAV 文件 aplay -q /usr/share/sounds/alsa/Noise.wav # 或者播放一个生成的简单声音例如 1kHz 正弦波 0.1秒 # 需要安装 sox 工具包sudo apt install sox (Debian/Ubuntu) # play -q -n synth 0.1 sin 1000控制台蜂鸣echo -e ‘\a’最原始的方法依赖于终端模拟器和系统配置在很多现代桌面环境下可能无声。Linux 下的实操建议 由于 Linux 桌面环境碎片化最稳健的方法是首选检查并安装libcanberra或sound-theme-freedesktop它们提供了标准化的声音主题和播放命令canberra-gtk-play。sudo apt install libcanberra-gtk-module libcanberra-gtk3-module sound-theme-freedesktop # Debian/Ubuntu canberra-gtk-play -i complete将播放命令封装在脚本中并做好失败静默处理因为 Hook 脚本不应该因为播放失败而报错导致 Claude Code 本身异常。#!/bin/bash play_sound() { # 尝试多种方法直到一个成功 if command -v canberra-gtk-play /dev/null; then canberra-gtk-play -i complete 2/dev/null return 0 fi if command -v paplay /dev/null; then paplay /usr/share/sounds/freedesktop/stereo/complete.oga 2/dev/null return 0 fi echo -e ‘\a’ 2/dev/null # 最后尝试蜂鸣 return 0 } play_sound5. 配置 Claude Code 的 Stop Hook编写好播放脚本后接下来就是告诉 Claude Code 使用它。Claude Code 的配置通常位于用户目录下的一个配置文件中例如~/.config/claude-code/config.jsonLinux/macOS或%APPDATA%\claude-code\config.jsonWindows。具体路径请参考 Claude Code 的官方文档。我们需要在配置文件中添加hooks字段并指定stop钩子为我们脚本的路径。5.1 配置文件示例假设我们的播放脚本放在C:\Users\YourName\scripts\play_notify.ps1Windows或/home/yourname/scripts/play_notify.shmacOS/Linux。Windows (config.json) 配置{ “model”: “claude-3-5-sonnet”, “api_key”: “your-api-key”, “hooks”: { “stop”: “powershell -ExecutionPolicy Bypass -File C:\\Users\\YourName\\scripts\\play_notify.ps1” } }关键点我们使用powershell -ExecutionPolicy Bypass -File ...来执行 PowerShell 脚本。-ExecutionPolicy Bypass是为了绕过默认可能限制脚本执行的安全策略确保脚本能运行。路径中的反斜杠需要转义所以是C:\\Users\\...。macOS/Linux (config.json) 配置{ “model”: “claude-3-5-sonnet”, “api_key”: “your-api-key”, “hooks”: { “stop”: “/home/yourname/scripts/play_notify.sh” } }关键点确保脚本文件有可执行权限chmod x /home/yourname/scripts/play_notify.sh。在脚本内部我们已经处理了不同播放命令的兼容性。5.2 配置生效与测试保存配置文件后你需要重启 Claude Code如果它正在运行以使新的 Hook 配置生效。测试方法非常简单在 Claude Code 中执行任何一个命令等待其完成。如果配置正确你应该能在任务结束后立刻听到设定的提示音。6. 进阶技巧与避坑指南在实际配置和使用过程中我遇到了几个典型问题这里分享出来帮你避坑。6.1 路径与权限问题脚本无法执行这是最常见的问题。Hook 配置中指定的脚本路径必须是绝对路径并且运行 Claude Code 的用户必须有权限读取和执行该脚本。症状Claude Code 任务结束后没有声音查看 Claude Code 的日志如果有或系统事件查看器可能会发现“文件未找到”或“权限被拒绝”的错误。排查检查路径在终端或文件管理器中手动导航到配置文件里写的路径看看文件是否存在。特别注意 Windows 的路径分隔符和转义。检查权限Linux/macOS在终端执行ls -l /path/to/your/script.sh确认你有执行 (x) 权限。如果没有使用chmod x命令添加。手动测试脚本在对应的 Shell 环境中PowerShell 或 Bash手动运行你的脚本命令看是否能正常播放声音。这是最直接的验证方式。6.2 脚本执行超时或阻塞如前所述Hook 脚本是同步执行的。如果你的脚本执行时间过长比如网络请求、复杂计算会拖慢 Claude Code。症状Claude Code 在任务结束后会“卡住”一会儿才返回提示符。解决确保播放是异步的在 PowerShell 中可以考虑使用$player.Play()而非PlaySync()但要注意脚本可能立即退出导致声音中断。一个更稳妥的方法是启动一个极短的后台作业。# 在 play_notify.ps1 中 $player New-Object System.Media.SoundPlayer “C:\Windows\Media\notify.wav” $player.Play() # 异步播放 Start-Sleep -Milliseconds 100 # 稍作等待确保播放启动 # 脚本结束但声音播放进程独立继续Linux/macOS 使用放入后台在 Bash 脚本中可以在播放命令后加将其放入后台。paplay /usr/share/sounds/freedesktop/stereo/complete.oga 核心原则Hook 脚本的逻辑必须极其轻量播放声音这种 I/O 操作应尽快启动并移交系统处理脚本自身应迅速退出。6.3 环境变量与上下文差异Claude Code 在运行 Hook 脚本时其环境变量如PATH可能与你在交互式终端中看到的不同。这可能导致脚本中使用的命令如afplay,paplay找不到。症状手动运行脚本正常但通过 Claude Code Hook 触发时失败。解决使用绝对路径在脚本中对于关键的系统命令使用其绝对路径例如/usr/bin/afplay而不是afplay。你可以通过which afplay命令来查找绝对路径。在脚本中设置 PATH在脚本开头显式设置PATH环境变量包含必要的目录。#!/bin/bash export PATH“/usr/bin:/bin:/usr/local/bin:$PATH” # ... 其余脚本内容简化依赖这正是为什么我们优先选择系统原生 API如 PowerShell 的 .NET 调用或最普遍存在的工具的原因。6.4 音频输出设备与音量有时脚本执行成功但你就是听不到声音。排查检查系统音量确保系统音量未静音且音量大小合适。检查默认播放设备特别是 Windows 和 Linux有时音频输出可能被定向到了错误的设备如一个未插耳机的端口。测试其他声音播放一个音乐文件或视频确认系统音频输出正常。查看脚本错误输出修改你的脚本将可能出现的错误信息重定向到一个日志文件以便排查。# PowerShell 示例将错误和信息输出到日志 Start-Transcript -Path “C:\Temp\claude_hook.log” -Append # ... 你的播放代码 ... Stop-Transcript7. 扩展思路让提示更智能基本的提示音实现了但我们可以做得更好。Stop Hook 的脚本可以接收 Claude Code 传递的一些上下文信息具体取决于 Claude Code 的实现请查阅其最新文档。理论上你可以根据任务的成功或失败状态播放不同的提示音。例如你可以设想如果任务成功退出退出码为0播放一个清脆的“完成”音。如果任务因错误退出退出码非0播放一个低沉的“错误”音。这需要你的播放脚本能够读取到任务结束的状态码。如果 Claude Code 的 Stop Hook 支持传递退出状态例如通过环境变量或命令行参数你的脚本就可以据此做出判断。#!/bin/bash # 假设 Claude Code 通过环境变量 $CLAUDE_EXIT_CODE 传递退出码 EXIT_CODE${CLAUDE_EXIT_CODE:-0} # 默认为0 if [ “$EXIT_CODE” -eq 0 ]; then paplay /usr/share/sounds/freedesktop/stereo/complete.oga else paplay /usr/share/sounds/freedesktop/stereo/dialog-error.oga fi即使 Claude Code 当前不直接提供你也可以通过包装 Claude Code 的调用命令在外部捕获其退出状态然后触发不同的声音。这需要更深入的集成但思路是可行的。8. 总结与个人体会通过配置一个简单的 Stop Hook我们成功让 Claude Code 从“沉默的劳动者”变成了“会打招呼的伙伴”。这个看似微小的改进在实际开发中带来的体验提升是显著的。它减少了上下文切换的成本让你能更流畅地在多个任务间并行。回顾整个实现过程最关键的是理解“事件驱动”的思想。与其去笨拙地轮询或手动干预不如利用工具本身提供的扩展点。Claude Code 的 Hooks 正是这样一个强大的扩展点。在具体实现上追求“系统原生”和“零依赖”极大地增强了方案的可靠性和可移植性。无论是 Windows 的 PowerShell .NET还是 macOS 的afplay或是 Linux 下对多种音频系统的兼容处理目标都是让脚本在任何一台新机器上都能以最小成本运行起来。最后关于配置细节绝对路径、执行权限和环境上下文这三个点是 Hook 脚本失败的重灾区务必在测试阶段仔细验证。一个良好的习惯是先在独立的 Shell 环境中完整地走一遍你的脚本逻辑确保无误后再集成到 Claude Code 的配置中。我个人现在已经在所有的工作机上配置了这个功能它已经成了我使用 Claude Code 时一个不可或缺的“背景感官”。当那声熟悉的提示音响起我就知道又可以继续下一步了。这种无缝的、自动化的反馈正是高效工作流中那些让人愉悦的细节之一。
返回列表