Skip to content

架构文档

本文档详细说明 @ruan-cat/claude-notifier 的架构设计、技术选型和模块职责。

概述

@ruan-cat/claude-notifier 是一个基于 Node.js 的系统通知工具,专门为 Claude Code 设计。它运行在 Windows 平台上,提供系统通知、定时提醒和自定义配置功能。

技术栈

  • 语言: 纯 TypeScript
  • 构建工具: tsup(基于 esbuild)
  • CLI 框架: commander
  • 通知: node-notifier
  • 日志: consola
  • 运行环境: Node.js 18+

目录结构

plain
packages/claude-notifier/
├── src/                          # 源代码目录
│   ├── cli.ts                    # CLI 主入口(含 shebang)
│   ├── index.ts                  # 导出模块主文件
│   │
│   ├── types/                    # TypeScript 类型定义
│   │   └── index.ts              # 所有类型定义
│   │
│   ├── core/                     # 核心模块
│   │   ├── notifier.ts           # 通知核心逻辑
│   │   └── timer.ts              # 长任务定时器
│   │
│   ├── commands/                 # CLI 子命令
│   │   ├── task-complete.ts      # 任务完成命令
│   │   ├── long-task.ts          # 长任务命令
│   │   ├── timeout.ts            # 超时通知命令
│   │   └── error.ts              # 错误通知命令
│   │
│   ├── config/                   # 配置模块
│   │   ├── sounds.ts             # 音频配置
│   │   ├── icons.ts              # 图标配置
│   │   └── utils.ts              # 配置工具函数(路径查找等)
│   │
│   ├── assets/                   # 静态资源
│   │   ├── sounds/               # 音频(分预设文件夹)
│   │   │   ├── success/
│   │   │   ├── warning/
│   │   │   ├── error/
│   │   │   └── manbo/
│   │   └── icons/                # 图标(分预设文件夹)
│   │       ├── success/
│   │       ├── warning/
│   │       ├── error/
│   │       ├── info/
│   │       └── clock/
│   │
│   └── docs/                     # 架构文档
│       ├── architecture.md       # 本文档
│       ├── how-to-add-assets.md  # 资源添加指南
│       └── use/                  # 使用文档
│           ├── api.md            # API 使用指南
│           ├── cli.md            # CLI 使用指南
│           └── claude-code.md    # Claude Code 配置指南

├── dist/                         # 构建输出目录
│   ├── cli.cjs                   # CLI 可执行文件
│   ├── cli.d.cts                 # CLI 类型定义
│   ├── index.cjs                 # 主模块
│   ├── index.d.cts               # 主模块类型定义
│   └── assets/                   # 复制的静态资源

├── tsup.config.ts                # tsup 构建配置
├── tsconfig.json                 # TypeScript 配置
├── package.json                  # 包配置
└── README.md                     # 主文档

核心模块说明

1. CLI 入口 (src/cli.ts)

职责:CLI 命令行工具的主入口,在 commander 框架上注册所有子命令。

关键代码

typescript
const program = new Command();
program.name("@ruan-cat/claude-notifier").description("Claude Code 的通知工具").version(version);

// 注册子命令
program.addCommand(createTaskCompleteCommand());
program.addCommand(createLongTaskCommand());
program.addCommand(createTimeoutCommand());
program.addCommand(createErrorCommand());

program.parse();

2. 导出模块 (src/index.ts)

职责:对外提供编程式 API 接口。

导出内容

  • 所有 TypeScript 类型定义
  • 核心函数(sendNotification, quickNotify, startLongTaskTimer 等)
  • 配置模块(resolveSoundConfig, resolveIconConfig)
  • 子命令创建函数(供高级用户使用)

3. 通知核心 (src/core/notifier.ts)

职责:封装 node-notifier,提供统一的系统通知接口。

核心函数

typescript
export async function sendNotification(options: NotificationOptions): Promise<void>;
export async function quickNotify(message: string, title?: string): Promise<void>;

特性

  • 默认通知持续 2.5 秒
  • 自动图标配置
  • 处理文件不存在的容错逻辑
  • 仅支持 Windows 平台

4. 长任务定时器 (src/core/timer.ts)

职责:管理后台监控和周期性提醒。

工作机制

  • 在 JSON 文件中保存定时器状态
  • 每 30 秒检查一次时间间隔
  • 所有时间间隔触发后自动停止

状态文件位置os.tmpdir() + ".claude-notifier-timer.json"

5. 资源配置 (src/config/)

配置逻辑:文件夹预设模式

  • 每个预设对应一个文件夹(如 manbo
  • 支持指定具体文件(如 manbo/01.mp3
  • 查找默认文件的优先级(main.mp3 > index.mp3 > default.mp3

5.1 配置工具模块 (src/config/utils.ts)

职责:提供统一的资源路径查找逻辑,解决开发环境和生产环境的路径差异问题。

核心函数

typescript
export function findResourceDir(currentDirname: string, resourceType: string): string;

路径查找策略(按优先级):

  1. dist/{resourceType} - 生产环境(tsup publicDir 直接复制)
  2. dist/config/../{resourceType} - 生产环境备用
  3. src/assets/{resourceType} - 开发环境
  4. src/config/../assets/{resourceType} - 开发环境备用
  5. dist/../../src/assets/{resourceType} - 降级备用

为什么需要多路径查找?

在使用 tsup 打包时遇到的问题:

  • tsup 的 publicDir 配置将 src/assets/ 内容直接复制到 dist/ (不是 dist/assets/
  • tsup 将 ESM 转 CJS 时,所有 import.meta.url 都指向入口文件的 URL
  • 导致所有模块的 __dirname 都指向 dist/ 而不是 dist/config/

通过多路径尝试,确保在各种环境下都能找到正确的资源目录。

设计决策

为什么使用文件夹预设方式?

  • 允许每个预设包含多个可选文件
  • 允许用户自定义预设并指定文件
  • 允许灵活扩展

为什么长任务定时器在后台运行?

  • Claude Code hooks 不支持定时触发
  • hooks 的执行有 60 秒超时限制
  • 需要独立进程长时间监控

为什么默认格式是 MP3?

  • 允许其他格式(如 WAV)
  • 兼容性好
  • 文件体积小
  • 满足 Windows node-notifier 的支持

执行流程

CLI 执行流程

plain
用户执行命令

node dist/cli.cjs task-complete --sound manbo

cli.ts 解析命令行参数

执行 createTaskCompleteCommand()

task-complete.ts 处理参数

执行 sendNotification({...})

notifier.ts 核心逻辑

resolveSoundConfig("manbo") 调用

findResourceDir(__dirname, "sounds") 查找资源目录

解析出 sounds/manbo/main.mp3 的完整路径

node-notifier 发送系统通知

API 执行流程

typescript
import { sendNotification } from "@ruan-cat/claude-notifier";

await sendNotification({
	title: "任务完成",
	message: "构建完成",
	sound: "success",
	icon: "success",
});

扩展性

添加新的通知场景

  1. src/commands/ 创建新命令文件
  2. 导出 createXxxCommand() 函数
  3. src/cli.ts 注册命令
  4. src/index.ts 导出命令

添加新的资源预设

  1. src/assets/sounds/icons/ 创建文件夹
  2. 放入默认文件(main.mp3icon.png
  3. 重新构建:pnpm build
  4. 使用:--sound my-preset--icon my-preset

未来计划

  • [ ] 支持 macOS 和 Linux
  • [ ] 支持更多通知场景(进度条)
  • [ ] 支持通知交互性
  • [ ] 扩展通知模板
  • [ ] 外部配置文件支持(.notifierrc)

贡献者

The avatar of contributor named as ruan-cat ruan-cat

页面历史

最近更新