









在使用 Claude Code 时,经常会同时开启多个终端窗口运行不同的任务。当某个任务需要用户输入或完成时,如果能收到 Windows 系统通知,就能及时切换到对应的终端进行处理。
本文记录了在 Windows 上为 Claude Code 配置通知功能的完整过程,包括遇到的问题和最终解决方案。
配置完成后,当 Claude Code 需要用户输入或任务完成时,会弹出 Windows 原生通知,显示:
通知内容包含:任务名称、具体问题、当前工作目录,方便用户识别是哪个终端的任务。
Install-Module -Name BurntToast -Scope CurrentUser
$PSVersionTable.PSVersion
在 ~/.claude/hooks/ 目录下创建 gsd-burnttoast-notify.js:
#!/usr/bin/env node
// Claude Code Notification Hook
// Sends Windows toast notifications via BurntToast module.
const { spawnSync } = require('child_process');
const path = require('path');
const fs = require('fs');
const STATE_FILE = path.join(process.env.TEMP || process.env.TMP || '/tmp', 'claude-cc-ask-marker.json');
function getState() {
try { return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8')); }
catch { return { askCount: 0, lastCwd: '' }; }
}
function writeState(state) {
try { fs.writeFileSync(STATE_FILE, JSON.stringify(state), 'utf8'); } catch {}
}
function clearState() {
try { fs.unlinkSync(STATE_FILE); } catch {}
}
function psEscape(s) {
return String(s).replace(/'/g, "''");
}
function truncate(s, maxLen) {
if (!s) return '';
return s.length > maxLen ? s.substring(0, maxLen) + '...' : s;
}
function getCwdName() {
try {
return path.basename(process.cwd()) || process.cwd();
} catch {
return 'unknown';
}
}
function sendToast(lines) {
const textParams = lines.filter(l => l).map(l => `'${psEscape(truncate(l, 150))}'`).join(', ');
const script = [
"Import-Module BurntToast -ErrorAction SilentlyContinue;",
`New-BurntToastNotification -Text ${textParams} -Sound Default;`
].join(' ');
spawnSync('powershell', [
'-ExecutionPolicy', 'RemoteSigned',
'-NoProfile',
'-WindowStyle', 'Hidden',
'-Command', script
], { windowsHide: true, encoding: 'utf8' });
}
// --ask: PermissionRequest hook for AskUserQuestion
if (process.argv.includes('--ask')) {
const prompt = process.env.CLAUDE_PERMISSION_PROMPT || '';
const task = process.env.CLAUDE_TASK || '';
const cwd = getCwdName();
const lines = [
'🔴 Claude Code - 需要你的输入',
task ? `任务: ${task}` : '',
prompt ? `问题: ${prompt}` : '',
`目录: ${cwd}`
];
sendToast(lines);
process.exit(0);
}
// --mark-ask: PreToolUse hook for AskUserQuestion
if (process.argv.includes('--mark-ask')) {
const state = getState();
state.askCount += 1;
state.askTime = Date.now();
state.lastCwd = getCwdName();
writeState(state);
process.exit(0);
}
// --stop: Stop hook
if (process.argv.includes('--stop')) {
const state = getState();
const now = Date.now();
const recent = state.askTime && (now - state.askTime) < 60000;
const task = process.env.CLAUDE_TASK || '';
const cwd = getCwdName();
if (recent) {
clearState();
const lines = [
'⏳ Claude Code - 等待输入',
task ? `任务: ${task}` : '',
`目录: ${cwd}`
];
sendToast(lines);
} else {
clearState();
const lines = [
'✅ Claude Code - 任务完成',
task ? `任务: ${task}` : '',
`目录: ${cwd}`
];
sendToast(lines);
}
process.exit(0);
}
// Default
const task = process.env.CLAUDE_TASK || '';
const cwd = getCwdName();
sendToast(['Claude Code', task || 'Notification', `目录: ${cwd}`]);
process.exit(0);
编辑 ~/.claude/settings.json,添加 hooks 配置:
{
"hooks": {
"PermissionRequest": [
{
"matcher": "AskUserQuestion",
"hooks": [
{
"type": "command",
"command": "node \"C:/Users/你的用户名/.claude/hooks/gsd-burnttoast-notify.js\" --ask"
}
]
}
],
"PreToolUse": [
{
"matcher": "AskUserQuestion",
"hooks": [
{
"type": "command",
"command": "node \"C:/Users/你的用户名/.claude/hooks/gsd-burnttoast-notify.js\" --mark-ask"
}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "node \"C:/Users/你的用户名/.claude/hooks/gsd-burnttoast-notify.js\" --stop"
}
]
}
]
},
"permissions": {
"defaultMode": "bypassPermissions"
}
}
注意:将
你的用户名替换为你的 Windows 用户名。
现象:配置了 Notification hook 但不触发。
原因:Claude Code v2.1.50 不支持 Notification hook 类型。
解决:改用 PermissionRequest hook(当 AskUserQuestion 触发时)。
现象:日志显示 Skipping hook execution - workspace trust not accepted。
原因:工作区信任未接受,hooks 被安全策略跳过。
解决:在 settings.json 中添加 "permissions": { "defaultMode": "bypassPermissions" }。
现象:PowerShell 命令中的 $env:CLAUDE_TASK 变成了 :CLAUDE_TASK。
原因:Bash shell 在传递命令时吞掉了 $ 字符。
解决:使用 Node.js spawnSync + 数组参数,绕过 Bash 变量展开。
现象:通知上的按钮点击后没有任何反应。
原因:BurntToast 的按钮需要注册 COM Activator 才能执行命令,PowerShell 没有这个能力。
解决:放弃按钮功能,只使用基础通知。
现象:发送通知时 PowerShell 窗口一闪而过。
原因:spawnSync 创建的进程短暂显示窗口。
解决:添加 -WindowStyle Hidden 和 windowsHide: true 参数。
Claude Code 支持以下 hook 类型:
| Hook | 触发时机 |
|---|---|
PreToolUse |
工具执行前 |
PostToolUse |
工具执行后 |
PermissionRequest |
权限请求时 |
Stop |
Agent 停止时 |
SubagentStop |
子 Agent 停止时 |
UserPromptSubmit |
用户提交输入时 |
Hook 执行时可用的环境变量:
CLAUDE_TASK - 当前任务名称CLAUDE_PERMISSION_PROMPT - 权限/问题提示内容CLAUDE_IDLE_PROMPT - 空闲提示内容由于每次 hook 执行都是独立进程,需要通过临时文件共享状态:
%TEMP%\claude-cc-ask-marker.json{ askCount, askTime, lastCwd }无法聚焦特定终端 Tab:Windows Terminal 没有公开 API 来定位特定 Tab,通知只能提示用户手动切换。
按钮功能不可用:BurntToast 的按钮需要 COM 注册,PowerShell 无法实现。
字符编码:中文路径可能显示乱码,这是 PowerShell 的限制。
通过配置 Claude Code 的 hooks 系统,结合 PowerShell 的 BurntToast 模块,可以实现任务状态的通知功能。虽然有一些 Windows 系统层面的限制(如无法聚焦特定终端 Tab、按钮功能不可用),但基础的通知功能已经能满足日常使用需求。
配置完成后,当你同时运行多个 Claude Code 任务时,就能通过通知的"目录"字段快速识别是哪个任务需要关注了。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。