Claude Code 提示音 Hook 配置迁移指南(Windows)

本文档说明如何把提示音配置从一台 Windows 电脑迁移到另一台 Windows 电脑。内容自包含:只需按步骤操作,无需复制原始文件。

适用环境:Windows 10 / 11,已安装 Claude Code。提示音使用 Windows 系统自带 WAV 文件,不依赖第三方软件。

1. 功能概览

场景 Hook 事件 Matcher 声音
计划中途提问、等待选择方案 PreToolUse AskUserQuestion Windows Notify Calendar.wav
计划完成、等待批准开工 PreToolUse ExitPlanMode Windows Notify Calendar.wav
每轮回复结束 Stop 无 tada.wav

说明:

  • AskUserQuestion 弹出时整轮对话尚未结束,Stop 不会触发,因此必须单独用 PreToolUse 的 matcher 捕获。
  • Stop 在每次回复结束时都触发,纯问答也会响,这是预期行为。

2. 需要准备的文件

%USERPROFILE%\.claude\
├── settings.json          # 合并其中的 hooks 段
└── hooks\
    ├── plan-notify.ps1
    └── auto-done-notify.ps1
  • 两个脚本负责播放声音,需要创建。

  • 音效文件使用系统自带的:

    • C:\Windows\Media\Windows Notify Calendar.wav
    • C:\Windows\Media\tada.wav

    无需复制;文件不存在时脚本会自动退回蜂鸣(Beep)。

  • settings.json 请使用用户级配置(%USERPROFILE%\.claude\settings.json),这样所有项目都会生效。

3. 配置步骤

步骤 1:创建 hooks 目录

打开 PowerShell,执行:

New-Item -ItemType Directory -Force "$env:USERPROFILE\.claude\hooks" | Out-Null

步骤 2:创建两个提示音脚本

在 PowerShell 中执行下面两段命令(使用单引号 here-string,脚本内容不会被变量展开):

@'
try {
    $null = [Console]::In.ReadToEnd()
    $wav = 'C:\Windows\Media\Windows Notify Calendar.wav'
    if (Test-Path -LiteralPath $wav) {
        (New-Object System.Media.SoundPlayer $wav).PlaySync()
    } else {
        [console]::Beep(1200, 300)
    }
} catch { }
exit 0
'@ | Set-Content -Encoding utf8 "$env:USERPROFILE\.claude\hooks\plan-notify.ps1"
@'
try {
    # 读取并丢弃 hook 传入的 JSON,避免 stdin 阻塞
    $null = [Console]::In.ReadToEnd()
    $wav = 'C:\Windows\Media\tada.wav'
    if (Test-Path -LiteralPath $wav) {
        (New-Object System.Media.SoundPlayer $wav).PlaySync()
    } else {
        [console]::Beep(880, 400)
    }
} catch { }
exit 0
'@ | Set-Content -Encoding utf8 "$env:USERPROFILE\.claude\hooks\auto-done-notify.ps1"

也可以手动创建这两个 .ps1 文件并粘贴上面的脚本内容,保存为 UTF-8。

步骤 3:配置 settings.json

把下面的内容合并到 %USERPROFILE%\.claude\settings.json。先把 <用户名> 替换为当前 Windows 用户名(可用 $env:USERNAME 查看):

<!– hooks-json –>

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "AskUserQuestion|ExitPlanMode",
        "hooks": [
          {
            "type": "command",
            "command": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File \"C:\\Users\\<用户名>\\.claude\\hooks\\plan-notify.ps1\"",
            "timeout": 15
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File \"C:\\Users\\<用户名>\\.claude\\hooks\\auto-done-notify.ps1\"",
            "timeout": 15
          }
        ]
      }
    ]
  }
}

合并规则:

  1. 目标文件不存在:直接保存上面的内容(替换用户名后)为 %USERPROFILE%\.claude\settings.json。
  2. 目标文件已存在:保留原有内容,只添加/合并 hooks 键:
    • 已有 hooks.PreToolUse 数组时,把 AskUserQuestion|ExitPlanMode 这一项加入数组;已有同名条目则跳过。
    • 已有 hooks.Stop 数组时,把 Stop 这一项加入数组。
    • 注意 JSON 逗号、引号必须合法,JSON 不支持注释。
  3. JSON 中的 Windows 路径反斜杠必须写成双反斜杠 \\。

安全提醒:settings.json 里可能有 env 段(例如 ANTHROPIC_AUTH_TOKEN、代理或模型配置),这些属于本机专属配置,不要随提示音配置一起复制或分享。本指南只迁移 hooks 段。

步骤 4:重新加载配置

  • 重启 Claude Code;或
  • 在 Claude Code 中打开一次 /hooks 菜单(会重新加载配置)。

之后可用 /hooks 查看已加载的 hooks。

4. 验证

4.1 校验 JSON 语法

python -c "import json,os; json.load(open(os.path.join(os.environ['USERPROFILE'], '.claude', 'settings.json'), encoding='utf-8')); print('JSON OK')"

若没有 Python,可跳过此步,改为在 settings.json 报错时检查逗号和引号。

4.2 模拟触发两个脚本

以下命令在 PowerShell 中执行。使用 cmd /c 管道是为了规避 Windows PowerShell 5.1 给管道文本加 UTF-8 BOM 的问题;脚本本身不解析 stdin,只是读取并丢弃:

cmd /c 'echo {"hook_event_name":"PreToolUse","tool_name":"AskUserQuestion"}| powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "%USERPROFILE%\.claude\hooks\plan-notify.ps1"'

应听到 Windows Notify Calendar.wav 的提示音。

cmd /c 'echo {"hook_event_name":"Stop"}| powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "%USERPROFILE%\.claude\hooks\auto-done-notify.ps1"'

应听到 tada.wav 的提示音。

4.3 实际场景验证

  1. 在计划模式中,Claude 用提问让你选择中间方案时 → 应响提示音。
  2. 计划完成、等待你批准时 → 应响提示音。
  3. 任意一轮回复结束 → 应响 tada.wav。

5. 故障排查

现象 排查方向
完全没有声音 确认 %USERPROFILE%\.claude\hooks\ 下两个 .ps1 存在;确认 settings.json 里的用户名路径正确;运行 4.2 的模拟命令定位问题
模拟命令有声,但 Claude Code 里不响 配置未加载:重启 Claude Code 或打开 /hooks;确认修改的是用户级 %USERPROFILE%\.claude\settings.json,而不是项目里的 .claude\settings.json
settings.json 修改后所有设置失效 JSON 语法错误(最常见是多余/缺失逗号、路径未写 \\、使用了注释);用 4.1 校验
只在部分场景响 检查 matcher 是否为 AskUserQuestion|ExitPlanMode(区分大小写与拼写);Stop 条目不需要 matcher
脚本被 PowerShell 拦截 配置命令已带 -ExecutionPolicy Bypass,一般无需修改系统执行策略;若被安全软件拦截,需放行 powershell.exe
没有系统 WAV 音效 脚本会回退为蜂鸣声;也可以把脚本里的 $wav 改成其他存在的 WAV 路径
声音太小或听不到 检查系统音量、音量合成器以及是否处于静音/专注模式

6. 卸载 / 禁用

  1. 打开 %USERPROFILE%\.claude\settings.json,删除 hooks.PreToolUse 中的 AskUserQuestion|ExitPlanMode 条目、hooks.Stop 中的对应条目;若没有其他 hooks,可删除整个 hooks 键。
  2. 删除文件:
    • %USERPROFILE%\.claude\hooks\plan-notify.ps1
    • %USERPROFILE%\.claude\hooks\auto-done-notify.ps1
  3. 重启 Claude Code 或打开 /hooks 使配置生效。

附:声音与脚本对照

脚本 用途 主要音效 回退
plan-notify.ps1 计划提问 / 计划批准 Windows Notify Calendar.wav Beep(1200, 300)
auto-done-notify.ps1 每轮回复结束 tada.wav Beep(880, 400)