# peon-ping
**Repository Path**: pingtouai/peon-ping
## Basic Information
- **Project Name**: peon-ping
- **Description**: 镜像自 https://github.com/PeonPing/peon-ping(仅镜像,版权与许可证归上游作者)
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-07-30
- **Last Updated**: 2026-07-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# peon-ping
[English](README.md) | [한국어](README_ko.md) | **中文** | [日本語](README_ja.md)
     

                    
**当你的 AI 编程助手需要关注时,播放游戏角色语音 + 显示视觉覆盖通知 — 或通过 MCP 让 AI 自行选择音效。**
AI 编程助手完成任务或需要权限时不会通知你。你切换标签页、失去焦点,然后浪费 15 分钟重新进入状态。peon-ping 通过魔兽争霸、星际争霸、传送门、塞尔达等游戏的角色语音和醒目的屏幕横幅来解决这个问题 — 支持 **Claude Code**、**Amp**、**Gemini CLI**、**GitHub Copilot**、**Codex**、**Cursor**、**OpenCode**、**Kilo CLI**、**Kiro**、**Kimi Code**、**Windsurf**、**Google Antigravity**、**Rovo Dev CLI**、**DeepAgents**、**Qwen Code**、**iFlow CLI**、**Trae**、**Kiro IDE**、**ECA** 及任何 MCP 客户端.
**查看演示** → [peonping.com](https://peonping.com/)
---
- [安装](#安装)
- [你会听到什么](#你会听到什么)
- [快捷控制](#快捷控制)
- [配置](#配置)
- [Peon 教练](#peon-教练)
- [MCP 服务器](#mcp-服务器)
- [多 IDE 支持](#多-ide-支持)
- [远程开发](#远程开发ssh--devcontainers--codespaces)
- [手机通知](#手机通知)
- [语音包](#语音包)
- [调试](#调试)
- [卸载](#卸载)
- [系统要求](#系统要求)
- [工作原理](#工作原理)
- [链接](#链接)
---
## 安装
### 方式一:Homebrew(推荐)
```bash
brew install PeonPing/tap/peon-ping
```
然后运行 `peon-ping-setup` 注册钩子并下载语音包。支持 macOS 和 Linux。
### 方式二:安装脚本(macOS、Linux、WSL2)
```bash
curl -fsSL https://raw.githubusercontent.com/PeonPing/peon-ping/main/install.sh | bash
```
⚠️ **WSL2 音频说明。** peon-ping 在 Windows 端播放音频。首次运行时会探测一次 Windows 主机(按 Windows 构建号缓存),自动选择最佳播放方式:
- 在 **Windows 10 / Windows 11 24H2 之前的版本**上,直接使用 WPF MediaPlayer,原生支持 MP3 + WAV,无需额外依赖。
- 在 **Windows 11 24H2+**(构建号 26100+)上,微软已从系统中移除了旧版 Windows Media Player,WPF MediaPlayer 会失败(`MILAVERR_INVALIDWMPVERSION`)。peon-ping 会回退到 `System.Media.SoundPlayer`,它使用 Win32 `PlaySound` API,到处都能工作 — 但仅支持 WAV,因此 MP3 语音包需要安装 **ffmpeg** 进行实时转码:
```sh
sudo apt update; sudo apt install -y ffmpeg
```
可通过 `PEON_WSL_AUDIO_BACKEND=auto|mediaplayer|soundplayer` 覆盖自动检测:
- `auto`(默认)— 如上所述探测并缓存
- `mediaplayer` — 强制通过 WSL UNC 路径使用 WPF MediaPlayer(在 24H2+ 上会静默失败)
- `soundplayer` — 强制复制临时文件并使用 `SoundPlayer`(通用,非 WAV 文件需要 ffmpeg)
### 方式三:Windows 安装
```powershell
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/PeonPing/peon-ping/main/install.ps1" -UseBasicParsing | Invoke-Expression
```
默认安装 5 个精选语音包(魔兽、星际、传送门)。重新运行可更新,同时保留配置和状态。你也可以在 **[peonping.com 交互式选择语音包](https://peonping.com/#picker)** 获取自定义安装命令。
实用安装参数:
- `--all` — 安装所有可用语音包
- `--packs=peon,sc_kerrigan,...` — 仅安装指定语音包
- `--local` — 将语音包、配置和钩子安装到当前项目的 `./.claude/` 目录
- `--global` — 显式全局安装(与默认相同)
- `--init-local-config` — 仅创建 `./.claude/hooks/peon-ping/config.json`
`--local` 不会修改你的 shell rc 文件(不注入全局 `peon` 别名/补全)。钩子注册到项目级 `./.claude/settings.json` 并使用绝对路径,因此在项目内的任何工作目录下都能工作。
示例:
```bash
curl -fsSL https://raw.githubusercontent.com/PeonPing/peon-ping/main/install.sh | bash -s -- --all
curl -fsSL https://raw.githubusercontent.com/PeonPing/peon-ping/main/install.sh | bash -s -- --packs=peon,sc_kerrigan
curl -fsSL https://raw.githubusercontent.com/PeonPing/peon-ping/main/install.sh | bash -s -- --local
```
如果已存在全局安装,你又安装了本地版本(或反之),安装程序会提示你移除现有的以避免冲突。
### 方式四:克隆后检查
```bash
git clone https://github.com/PeonPing/peon-ping.git
cd peon-ping
./install.sh
```
### 方式五:Nix(macOS、Linux)
无需安装即可直接从源码运行:
```bash
nix run github:PeonPing/peon-ping -- status
nix run github:PeonPing/peon-ping -- packs install peon
```
或安装到你的 profile:
```bash
nix profile install github:PeonPing/peon-ping
```
开发 shell(bats、shellcheck、nodejs):
```bash
nix develop # 或使用 direnv
```
#### Home Manager 模块(声明式配置)
如需可复现的设置,使用 Home Manager 模块:
```nix
# 在你的 home.nix 或 flake.nix 中
{ inputs, pkgs, ... }:
let
peonCursorAdapterPath = "${inputs.peon-ping.packages.${pkgs.system}.default}/share/peon-ping/adapters/cursor.sh";
in {
imports = [ inputs.peon-ping.homeManagerModules.default ];
programs.peon-ping = {
enable = true;
package = inputs.peon-ping.packages.${pkgs.system}.default;
claudeCodeIntegration = true;
settings = {
default_pack = "glados";
volume = 0.7;
enabled = true;
desktop_notifications = true;
categories = {
"session.start" = true;
"task.complete" = true;
"task.error" = true;
"input.required" = true;
"resource.limit" = true;
"user.spam" = true;
};
};
# 从 og-packs 安装语音包(简单字符串格式)
# 以及自定义来源(带 name + src 的属性集)
installPacks = [
"peon"
"glados"
"sc_kerrigan"
# 来自 GitHub 的自定义语音包(openpeon.com 注册表)
{
name = "mr_meeseeks";
src = pkgs.fetchFromGitHub {
owner = "kasperhendriks";
repo = "openpeon-mrmeeseeks";
rev = "main"; # 或使用 commit hash 以确保可复现
sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
}
];
enableZshIntegration = true;
};
# 可选的额外 IDE 钩子(如 Cursor)
home.file.".cursor/hooks.json".text = builtins.toJSON {
version = 1;
hooks = {
afterAgentResponse = [{ command = "bash ${peonCursorAdapterPath} afterAgentResponse"; }];
stop = [{ command = "bash ${peonCursorAdapterPath} stop"; }];
};
};
}
```
**语音包安装**:`installPacks` 选项支持两种格式:
- **简单字符串**(如 `"peon"`、`"glados"`)— 从 [og-packs](https://github.com/PeonPing/og-packs) 仓库获取
- **自定义来源** — 带 `name` 和 `src` 字段的属性集,`src` 可以是任何 Nix fetcher 结果(如 `pkgs.fetchFromGitHub`)
在 [openpeon.com](https://openpeon.com/) 上列出的语音包,找到 GitHub 仓库链接并使用 `pkgs.fetchFromGitHub`:
```nix
{
name = "pack_name";
src = pkgs.fetchFromGitHub {
owner = "github-owner";
repo = "repo-name";
rev = "main"; # 或 commit hash/tag
sha256 = ""; # 先留空,Nix 会告诉你正确的 hash
};
}
```
**Claude Code 钩子**:设置 `programs.peon-ping.claudeCodeIntegration = true;` 即可将 Claude Code 钩子脚本安装到 `~/.claude/hooks/peon-ping/`,并把标准的 peon-ping 钩子条目合并进 `~/.claude/settings.json`。
**其他 IDE 钩子**:为避免覆盖与 peon-ping 无关的 IDE 设置,其他 IDE 的钩子仍然是可选的。peon-ping 在 [`adapters/`](https://github.com/PeonPing/peon-ping/tree/main/adapters) 下提供如 `cursor.sh` 之类的适配器脚本,你可以这样接入:
```sh
${inputs.peon-ping.packages.${pkgs.system}.default}/share/peon-ping/adapters/$YOUR_IDE.sh EVENT_NAME
```
参见上方 Cursor 示例。
## 你会听到什么
| 事件 | CESP 分类 | 示例 |
|---|---|---|
| 会话开始 | `session.start` | *"Ready to work!"*, *"Something need doing?"* |
| 任务完成 | `task.complete` | *"Work complete."*, *"Work, work."* |
| 代理确认任务 | `task.acknowledge` | *"I can do that."*, *"Be happy to."*, *"Okie dokie."* *(默认禁用)* |
| 需要权限 | `input.required` | *"Hmm?"*, *"What you want?"*, *"Yes?"* |
| 工具或命令错误 | `task.error` | *"Me not that kind of orc!"*, *"Ugh."* |
| 速率或 token 限制 | `resource.limit` | *"Why not?"* |
| 快速提示(10秒内3次以上)| `user.spam` | *"Whaaat?"*, *"Me busy, leave me alone!"*, *"No time for play."* |
此外,还会在每个屏幕上显示**大型覆盖横幅**(macOS/WSL/MSYS2)和终端标签页标题(`● 项目: 完成`)——即使你在其他应用中,也能立即知道任务完成。
peon-ping 实现了 [编码事件语音包规范(CESP)](https://github.com/PeonPing/openpeon) — 这是一个任何代理式 IDE 都可以采用的编码事件声音开放标准。
## 快捷控制
开会或结对编程时需要静音?两种方式:
| 方式 | 命令 | 适用场景 |
|---|---|---|
| **斜杠命令** | `/peon-ping-toggle` | 在 Claude Code 中工作时 |
| **CLI** | `peon toggle` | 从任意终端标签页 |
希望它自动生效?设置 [`focus_detect`](#configuration),让 peon-ping 遵循 macOS 的**专注模式 / 勿扰模式**。专注模式开启时声音和通知自动静音,关闭后恢复。另见 `headphones_only` 和 `meeting_detect`。
其他 CLI 命令:
```bash
peon pause # 静音
peon mute # 'pause' 的别名
peon volume # 查看当前音量
peon volume 0.7 # 设置音量(0.0–1.0)
peon rotation # 查看当前轮换模式
peon rotation random # 设置轮换模式(random|round-robin|session_override)
peon resume # 取消静音
peon unmute # 'resume' 的别名
peon status # 查看暂停或活动状态(简洁模式)
peon status --verbose # 显示完整详情(通知、耳机、IDE 等)
peon packs list # 列出已安装的语音包
peon packs list --registry # 浏览注册表中所有可用语音包
peon packs community # 按信任等级列出所有注册表语音包(Windows)
peon packs search # 按名称搜索注册表语音包(Windows)
peon packs install # 从注册表安装语音包
peon packs install --all # 从注册表安装所有语音包
peon packs install-local # 从本地目录安装语音包
peon packs use # 切换到指定语音包(Windows 上自动从注册表安装)
peon packs use --install # 切换到语音包,如需则从注册表安装
peon packs next # 切换到下一个语音包
peon packs remove # 移除指定语音包
peon packs bind # 将语音包绑定到当前目录
peon packs bind --pattern # 将语音包绑定到目录模式,例如 "*/services"
peon packs unbind # 移除当前目录的绑定
peon packs bindings # 列出所有已分配的绑定
peon packs ide-bind # 将语音包绑定到 IDE 标识,例如 codex
peon packs ide-unbind # 移除 IDE 绑定
peon packs ide-bindings # 列出所有 IDE 绑定
peon packs exclude add # 为 glob 或目录跳过 path_rules
peon packs exclude remove # 移除排除路径
peon packs exclude list # 列出排除路径
peon sounds list [pack] # 列出语音包中的所有声音,并标记已禁用项
peon sounds disable [--pack=] # 禁用语音包中的单个声音
peon sounds enable [--pack=] # 重新启用之前禁用的声音
peon notifications on # 启用桌面通知
peon notifications off # 禁用桌面通知
peon notifications overlay # 使用大型覆盖横幅(默认)
peon notifications standard # 使用标准系统通知
peon notifications test # 发送测试通知
peon notifications position [pos] # 获取/设置通知位置(top-left、top-center、top-right、bottom-left、bottom-center、bottom-right)
peon notifications dismiss [N] # 获取/设置自动关闭时间(秒,0 = 持续显示)
peon notifications label [text|reset] # 获取/设置项目标签覆盖
peon notifications template [key] [fmt] # 获取/设置/重置消息模板(键:stop、permission、error、idle、question)
peon preview # 播放 session.start 的所有声音
peon preview # 播放指定分类的所有声音
peon preview --list # 列出活动语音包的所有分类
peon mobile ntfy # 设置手机通知(免费)
peon mobile off # 禁用手机通知
peon mobile test # 发送测试通知
peon debug on # 启用调试日志
peon debug off # 禁用调试日志
peon debug status # 显示调试状态、日志目录、文件数和总大小
peon logs # 显示今天日志的最后 50 行
peon logs --last N # 显示所有日志文件的最后 N 行
peon logs --session ID # 按会话 ID 过滤今天的日志
peon logs --session ID --all # 搜索所有日志文件中的会话 ID
peon logs --clear # 删除所有日志文件(需确认)
peon relay --daemon # 启动音频中继(用于 SSH/devcontainer)
peon relay --stop # 停止后台中继
```
`peon preview` 支持的 CESP 分类:`session.start`、`task.acknowledge`、`task.complete`、`task.error`、`input.required`、`resource.limit`、`user.spam`。(扩展分类 `session.end` 和 `task.progress` 已在 CESP 规范中定义,语音包可以实现,但目前未由内置钩子事件触发。)
支持 Tab 补全 — 输入 `peon packs use ` 查看可用语音包名称。
暂停会立即静音声音和桌面通知。暂停状态会跨会话保持,直到你恢复。暂停时标签页标题仍会更新。
## 配置
peon-ping 在 Claude Code 中安装以下斜杠命令:
- `/peon-ping-toggle` — 静音/取消静音
- `/peon-ping-config` — 更改任意设置(音量、语音包、分类等)
- `/peon-ping-rename <名称>` — 为当前会话设置自定义名称,显示在通知标题和终端标签标题中(零 token 消耗,由钩子拦截处理);不带参数则重置为自动检测
你也可以直接让 Claude 帮你修改设置 — 例如"启用轮换语音包"、"将音量设为 0.3"或"添加 glados 到我的语音包轮换"。无需手动编辑配置文件。
配置位置取决于安装模式:
- 全局安装:`$CLAUDE_CONFIG_DIR/hooks/peon-ping/config.json`(默认 `~/.claude/hooks/peon-ping/config.json`)
- 本地安装:`./.claude/hooks/peon-ping/config.json`
```json
{
"volume": 0.5,
"categories": {
"session.start": true,
"task.acknowledge": true,
"task.complete": true,
"task.error": true,
"input.required": true,
"resource.limit": true,
"user.spam": true
}
}
```
### 独立控制
peon-ping 有三个独立的控制开关,可以混合使用:
| 配置键 | 控制项 | 影响声音 | 影响桌面弹窗 | 影响手机推送 |
|--------|--------|----------|--------------|--------------|
| `enabled` | 主音频开关 | ✅ 是 | ❌ 否 | ❌ 否 |
| `desktop_notifications` | 桌面弹窗横幅 | ❌ 否 | ✅ 是 | ❌ 否 |
| `mobile_notify.enabled` | 手机推送通知 | ❌ 否 | ❌ 否 | ✅ 是 |
这意味着您可以:
- 保留声音但禁用桌面弹窗:`peon notifications off`
- 保留桌面弹窗但禁用声音:`peon pause`
- 启用手机推送但不显示桌面弹窗:设置 `desktop_notifications: false` 和 `mobile_notify.enabled: true`
- **volume**:0.0–1.0(适合办公室使用的音量)
- **desktop_notifications**:`true`/`false` — 独立于声音控制桌面通知弹窗(默认:`true`)。禁用时,声音继续播放但视觉弹窗被抑制。手机通知不受影响。
- **notification_style**:`"overlay"` 或 `"standard"` — 控制桌面通知显示方式(默认:`"overlay"`)
- **overlay**:大型醒目横幅 — macOS 上使用 JXA Cocoa 覆盖,WSL/MSYS2 上使用 Windows Forms 弹窗。点击覆盖层可聚焦终端(支持 Ghostty、Warp、iTerm2、Zed、Terminal.app)。在 iTerm2 上,点击可聚焦到正确的标签页/窗格/窗口。
- **standard**:系统通知 — macOS 上使用 [`terminal-notifier`](https://github.com/julienXX/terminal-notifier) / `osascript`,WSL/MSYS2 上使用 Windows toast。安装 `terminal-notifier`(`brew install terminal-notifier`)后,点击通知可自动聚焦终端。在原生 Windows 上,点击 toast 通知可聚焦 IDE 或终端窗口(支持 VS Code、Cursor、Windsurf、Windows Terminal、PowerShell)。当打开多个窗口时,通知会通过基于 PID 的进程树匹配精确定位到触发事件的窗口。
- **overlay_theme**:`"jarvis"`、`"glass"`、`"sakura"`,或留空使用默认覆盖层 — 仅 macOS(默认:无)
- **jarvis**:圆形 HUD,带旋转弧线、刻度和进度环
- **glass**:毛玻璃风格面板,带强调色条、进度线和时间戳
- **sakura**:禅意花园,带盆景树和动态樱花花瓣
- **wsl_toast**:`true`/`false` — 在 WSL 上使用原生 Windows toast 通知代替 Windows Forms 弹窗。Toast 不会抢占焦点并出现在操作中心。(默认:`true`)
- **categories**:单独开关 CESP 声音分类(例如 `"session.start": false` 禁用问候声音)
- **annoyed_threshold / annoyed_window_seconds**:在 N 秒内多少次提示触发 `user.spam` 彩蛋
- **silent_window_seconds**:对于短于 N 秒的任务,抑制 `task.complete` 声音和通知。(例如 `10` 表示只播放超过 10 秒的任务声音)
- **session_start_cooldown_seconds**(数字,默认:`30`):当多个工作区同时启动时(例如用 OpenCode 或 Cursor 打开多个文件夹),对问候声音进行去重。只有第一个会话启动会播放问候声;在此窗口期内的后续会话保持静默。设为 `0` 可禁用去重,始终播放问候声。
- **suppress_idle_prompt_repeats**(布尔值,默认:`true`):当终端未聚焦时,Claude Code 会每 ~60 秒重复触发 `idle_prompt` 通知。peon-ping 把 `idle_prompt` 路由到 `task.complete`,让你仍能在需要输入时听到提示——但若不去重,同一个声音会随每次提醒重复播放。当为 `true` 时,如果同一会话已在 `idle_prompt_suppress_window_seconds` 窗口内触发过 `task.complete`,则抑制此次 `idle_prompt`。设为 `false` 可恢复周期性提醒。
- **idle_prompt_suppress_window_seconds**(数字,默认:`3600`):`suppress_idle_prompt_repeats` 使用的窗口长度。在某会话播放过 `task.complete` 之后的这么多秒内,该会话后续的 `idle_prompt` 通知保持静默。设为 `0` 可禁用窗口(等同于 `suppress_idle_prompt_repeats: false`)。
- **suppress_subagent_complete**(布尔值,默认:`false`):抑制子 Agent 活动产生的声音和通知。当 Claude Code 的 Task 工具并行派发多个子 Agent 时,每个子 Agent 都会触发自己的事件:完成时的提示音、Bash 命令失败时的 `task.error`、权限请求时的 `input.required`。将此选项设为 `true`,则只播放父会话的声音。来自子 Agent 内部的事件通过 Claude Code 在 hook 负载中添加的 `agent_id` 字段识别;独立会话的子 Agent(旧版客户端、其他 IDE)仍通过 SubagentStart 时间窗口启发式识别。
- **default_pack**:当没有更具体的规则时使用的备选语音包(默认:`"peon"`)。取代旧的 `active_pack` 键——现有配置在 `peon update` 时自动迁移。
- **path_rules**:`{ "pattern": "...", "pack": "..." }` 对象数组。根据工作目录使用通配符匹配(`*`、`?`)为会话分配语音包。第一个匹配规则生效,优先级高于 `pack_rotation` 和 `default_pack`,但低于 `session_override` 分配。
- **exclude_dirs**:glob 或目录模式数组。如果当前工作目录匹配其中一项,**所有声音和通知都会被静音**(钩子日志记录 `suppressed=True reason=excluded_dir pattern=<匹配项>`)。纯目录路径也会匹配其所有子目录,所以 `"~/conductor/workspaces"` 会让整棵目录树都保持静默。适用于后台代理(如 `CodexBar/ClaudeProbe`)、临时目录或不希望发出声音的工作区。
- **ide_rules**:`{ "ide": "...", "pack": "..." }` 对象数组。在 `path_rules` 之后、轮换与默认包之前按 IDE/source 指定语音包。第一个匹配规则生效。常见 id:`claude`、`codex`、`cursor`、`opencode`、`kilo`、`kiro`、`gemini`、`copilot`、`windsurf`、`kimi`、`antigravity`、`amp`、`deepagents`、`openclaw`、`rovodev`。
- **pack_rotation**:语音包名称数组(例如 `["peon", "sc_kerrigan", "peasant"]`)。用于 `pack_rotation_mode` 为 `random` 或 `round-robin` 时。留空 `[]` 则仅使用 `default_pack`(或 `path_rules` / `ide_rules`)。
- **pack_rotation_mode**:`"random"`(默认)、`"round-robin"` 或 `"session_override"`。使用 `random`/`round-robin` 时,每个会话从 `pack_rotation` 中选择一个语音包。使用 `session_override` 时,`/peon-ping-use ` 命令为每个会话分配语音包。无效或缺失的语音包会按层级回退。(`"agentskill"` 作为 `"session_override"` 的旧别名仍被接受。)
- **session_ttl_days**(数字,默认:7):使超过 N 天的陈旧每会话语音包分配过期。防止使用 `session_override` 模式时 `.state.json` 无限增长。
- **headphones_only**(布尔值,默认:`false`):仅在检测到耳机或外部音频设备时播放声音。启用后,如果内置扬声器是活动输出,声音将被静音 — 适用于开放式办公室。使用 `peon status` 查看状态。支持 macOS(通过 `system_profiler`)和 Linux(通过 PipeWire `wpctl` 或 PulseAudio `pactl`)。
- **suppress_sound_when_tab_focused**(布尔值,默认:`false`):当生成钩子事件的终端标签页处于当前活动/聚焦状态时,跳过声音播放。声音仍会在后台标签页中播放,提醒您其他地方发生了事件。桌面和移动通知不受影响。适用于只想在未查看的标签页中听到音频提示的用户。仅支持 macOS(使用 `osascript` 检查最前端应用和 iTerm2 标签页焦点)。
- **tmux_passthrough**(布尔值,默认:`false`):将标签页标题和 iTerm2 标签页颜色转义序列通过 tmux 的 DCS 透传发送到宿主终端(需要 tmux 3.3a+ 并设置 `set -g allow-passthrough on`)。默认关闭,因为 tmux 客户端会将多个窗格/窗口复用到单个宿主终端标签页上,且没有按窗格寻址的能力:当多个 agent 会话同时运行时,每个钩子(包括来自后台窗格的)都会以"最后写入者获胜"的方式重绘那个共享标签页,使其不再反映任何单个会话。建议保持关闭,让 tmux 自身的窗口/状态栏承载每个会话的状态;仅当您每个终端标签页只运行一个 tmux 窗口(即 1 个标签页 = 1 个会话)时才启用。在 tmux 之外无效,此时转义序列始终发送。
- **meeting_detect**:检测麦克风是否正在使用中,并在麦克风使用期间临时抑制音频播放。通知仍会正常显示。
- **focus_detect**(布尔值,默认:`false`):遵循 macOS 的**专注模式 / 勿扰模式**。peon-ping 通过 `afplay` 播放声音并在自定义窗口中绘制覆盖通知,两者都绕过通知中心,因此系统的专注模式开关默认对它们没有影响。启用后,peon-ping 会直接读取专注模式状态,并在**任意**专注模式(勿扰、工作、睡眠等)激活时抑制输出,关闭专注模式后自动恢复。移动推送(如已配置)不受影响,因为手机会遵循其自身的专注模式。仅支持 macOS,采用失败放行策略(若无法读取专注模式状态,则照常播放声音)。
- **focus_detect_mode**(字符串,默认:`"all"`):专注模式激活时 `focus_detect` 抑制的内容。`"all"` 同时静音声音和覆盖/桌面通知。`"sound"` 仅静音声音(通知仍会显示)。`"notifications"` 仅静音通知(声音仍会播放)。当 `focus_detect` 为 `false` 时忽略此设置。
- **notification_position**(字符串,默认:`"top-center"`):覆盖通知在屏幕上的显示位置。选项:`"top-left"`、`"top-center"`、`"top-right"`、`"bottom-left"`、`"bottom-center"`、`"bottom-right"`。
- **notification_dismiss_seconds**(数字,默认:`4`):覆盖通知在 N 秒后自动消失。设为 `0` 则通知持续显示,需点击关闭。
- **`CLAUDE_SESSION_NAME` 环境变量**:在启动 `claude` 前设置,为会话指定自定义名称。同时显示在桌面通知标题和终端标签标题中,优先级高于所有配置项。示例:`CLAUDE_SESSION_NAME="Auth Refactor" claude` 或先 `export CLAUDE_SESSION_NAME="功能: Auth"` 再 `claude`。
- **notification_title_override**(字符串,默认:`""`):覆盖通知标题中显示的项目名称。为空时自动检测:`/peon-ping-rename` > `CLAUDE_SESSION_NAME` > `.peon-label` > `notification_title_script` > `project_name_map` > git 仓库名 > 文件夹名。
- **notification_title_marker**(字符串,默认:`"●"`):通知标题和终端标签标题前显示的字符。设为 `""` 可禁用。例如:`"🔔"`。
- **notification_title_script**(字符串,默认:`""`):在事件触发时运行的 Shell 命令,用于动态计算项目名称。可用环境变量:`PEON_SESSION_ID`、`PEON_CWD`、`PEON_HOOK_EVENT`、`PEON_SESSION_NAME`。使用标准输出(去除首尾空白,最多 50 字符);非零退出码则继续查找下一层级。示例:`"basename $PEON_CWD"`。
- **project_name_map**(对象,默认:`{}`):将目录路径映射为通知中的自定义项目标签。键为路径模式,值为显示名称。
- **notification_templates**(对象,默认:`{}`):自定义通知事件的消息格式。键为事件类型(`stop`、`permission`、`error`、`idle`、`question`),值为支持变量替换的模板字符串。可用变量:`{project}`、`{summary}`、`{tool_name}`、`{status}`、`{event}`。
### 语音包选择层级
peon-ping 通过 6 层层级结构确定使用哪个语音包。第一个产生有效已安装语音包的层级生效:
| 优先级 | 层级 | 来源 | 设置方式 |
|--------|------|------|----------|
| 1(最高) | **session_override** | 每会话分配 | `/peon-ping-use ` 技能或 MCP |
| 2 | **path_rules** | 工作目录的通配符匹配 | `peon packs bind` 或配置中的 `path_rules` |
| 3 | **ide_rules** | IDE/source 匹配 | `peon packs ide-bind` 或配置中的 `ide_rules` |
| 4 | **pack_rotation** | 从列表中随机或轮换 | 配置中的 `pack_rotation` 数组 + `pack_rotation_mode` |
| 5 | **default_pack** | 静态回退 | `peon packs use ` 或配置中的 `default_pack` |
| 6(最低) | **硬编码** | 内置默认 | `"peon"` |
如果某层级引用的语音包未安装,则回退到下一层级。
如果 `exclude_dirs` 命中当前工作目录,则本次调用被完全静音 —— 不播放声音、不发送通知。
### 按项目分配语音包(path_rules)
根据目录路径为不同项目分配不同的语音包。可以使用 CLI 或直接编辑 `config.json`。
**CLI(推荐):**
```bash
peon packs bind glados # 将 glados 绑定到当前目录
peon packs bind sc_kerrigan --pattern "*/services/*" # 绑定到通配符模式
peon packs bind duke_nukem --install # 绑定并在需要时从注册表安装
peon packs unbind # 移除当前目录的绑定
peon packs unbind --pattern "*/services/*" # 移除特定模式的绑定
peon packs bindings # 列出所有绑定
```
**手动配置:**
```json
"path_rules": [
{ "pattern": "*/work/client-a/*", "pack": "glados" },
{ "pattern": "*/personal/*", "pack": "peon" },
{ "pattern": "*/services/*", "pack": "sc_kerrigan" }
]
```
规则使用通配符匹配(`*`、`?`)。第一个匹配规则生效。路径规则优先级高于 `pack_rotation` 和 `default_pack`,但低于 `session_override` 分配。
### 按 IDE 分配语音包(ide_rules)
当某个路径本身很嘈杂、或者多个工具共用同一目录时,可以让语音包跟着 IDE/source 走。
**CLI(推荐):**
```bash
peon packs ide-bind codex glados # 为 Codex 会话使用 glados
peon packs ide-bind claude peon # 为 Claude Code 使用 peon
peon packs ide-unbind codex # 移除一个 IDE 规则
peon packs ide-bindings # 列出 IDE 规则和最近检测到的 IDE
```
**手动配置:**
```json
"ide_rules": [
{ "ide": "codex", "pack": "glados" },
{ "ide": "claude", "pack": "peon" }
]
```
`ide_rules` 在 `path_rules` 之后执行。
## 常见用例
### 保留声音但禁用弹窗
想要语音反馈但不想要视觉干扰?
```bash
peon notifications off
```
这会保持所有声音类别的播放,同时禁用桌面通知横幅。手机通知(如果已配置)继续工作。
您也可以使用别名:
```bash
peon popups off
```
### 静音模式但保留通知
想要视觉提醒但不要音频?
```bash
peon pause # 或在配置中设置 "enabled": false
```
当 `desktop_notifications: true` 时,您将收到弹窗但没有声音。
### 完全静音
禁用所有功能:
```bash
peon pause
peon notifications off
peon mobile off
```
## Peon 教练
你的苦工也是你的私人教练。内置帕维尔风格(Pavel-style)每日锻炼模式 — 那个告诉你"work work"的兽人现在会叫你趴下做二十个俯卧撑。
### 快速开始
```bash
peon trainer on # 启用教练模式
peon trainer goal 200 # 设置每日目标(默认:300/300)
# ... 写一段时间代码,苦工每约 20 分钟唠叨你一次 ...
peon trainer log 25 pushups # 记录你的运动次数
peon trainer log 30 squats
peon trainer status # 查看进度
```
### 工作原理
教练提醒基于你的编程会话运行。当你开始新会话时,苦工会立即鼓励你在写任何代码之前先做俯卧撑。然后在活跃编程期间每约 20 分钟,你会听到苦工喊你做更多次。无需后台守护进程。使用 `peon trainer log` 记录你的次数,进度在午夜自动重置。
### 命令
| 命令 | 描述 |
|---------|-------------|
| `peon trainer on` | 启用教练模式 |
| `peon trainer off` | 禁用教练模式 |
| `peon trainer status` | 显示今日进度 |
| `peon trainer log ` | 记录次数(例如 `log 25 pushups`) |
| `peon trainer goal ` | 设置所有运动的统一每日目标 |
| `peon trainer goal ` | 设置单项运动的统一每日目标 |
| `peon trainer goal ` | 设置特定日期的目标(mon、tue 等) |
| `peon trainer goal ` | 设置某天所有运动的目标 |
### 日程表与统一目标
运动可以设置**统一每日目标**(每天相同)或**按日日程表**(不同日期不同目标)。两者互斥:
- 设置统一目标会移除该运动的所有日程安排
- 设置特定日期目标会移除该运动的统一目标
日期使用缩写:`mon`、`tue`、`wed`、`thu`、`fri`、`sat`、`sun`
```bash
peon trainer goal pushups 300 # 每天 300 俯卧撑(统一目标)
peon trainer goal pushups mon 400 # 覆盖:周一 400(创建日程表)
peon trainer goal squats sun 0 # 周日深蹲休息
peon trainer goal fri 150 # 周五所有运动轻松日
```
在休息日(目标=0),提醒会被跳过,状态显示 `[REST DAY]`。如果你愿意,仍然可以在休息日记录运动次数。
### Claude Code 技能
在 Claude Code 中,你可以不用离开对话就记录次数:
```
/peon-ping-log 25 pushups
/peon-ping-log 30 squats
```
### 自定义语音
将你自己的音频文件放入 `~/.claude/hooks/peon-ping/trainer/sounds/`:
```
trainer/sounds/session_start/ # 会话问候("Pushups first, code second! Zug zug!")
trainer/sounds/remind/ # 提醒语音("Something need doing? YES. PUSHUPS.")
trainer/sounds/log/ # 确认语音("Work work! Muscles getting bigger maybe!")
trainer/sounds/complete/ # 庆祝语音("Zug zug! Human finish all reps!")
trainer/sounds/slacking/ # 失望语音("Peon very disappointed.")
```
更新 `trainer/manifest.json` 来注册你的声音文件。
## MCP 服务器
peon-ping 包含一个 [MCP(模型上下文协议)](https://modelcontextprotocol.io/)服务器,任何兼容 MCP 的 AI 代理都可以通过工具调用直接播放声音,无需钩子。
核心区别:**由代理选择声音**。代理不再在每个事件上自动播放固定声音,而是直接调用 `play_sound` 指定想要的声音——构建失败时用 `duke_nukem/SonOfABitch`,读取文件时用 `sc_kerrigan/IReadYou`。
### 设置
在 MCP 客户端配置中添加(Claude Desktop、Cursor 等):
```json
{
"mcpServers": {
"peon-ping": {
"command": "node",
"args": ["/path/to/peon-ping/mcp/peon-mcp.js"]
}
}
}
```
通过 Homebrew 安装时路径为 `$(brew --prefix peon-ping)/libexec/mcp/peon-mcp.js`。完整设置说明见 [`mcp/README.md`](mcp/README.md)。
### 可用功能
| 功能 | 说明 |
|---|---|
| **`play_sound`** | 按键名播放一个或多个声音(如 `duke_nukem/SonOfABitch`、`peon/PeonReady1`) |
| **`peon-ping://catalog`** | 以 MCP 资源形式获取完整语音包目录——客户端预取一次,无需重复工具调用 |
| **`peon-ping://pack/{name}`** | 获取指定语音包的详细信息和可用声音键名 |
需要 Node.js 18+。由 [@tag-assistant](https://github.com/tag-assistant) 贡献。
## 多 IDE 支持
peon-ping 适用于任何支持钩子的代理式 IDE。适配器将 IDE 特定事件转换为 [CESP 标准](https://github.com/PeonPing/openpeon)。
| IDE | 状态 | 设置 |
|---|---|---|
| **Claude Code** | 内置 | `curl \| bash` 安装会自动处理 |
| **Amp** | 适配器 | `bash adapters/amp.sh` / `powershell adapters/amp.ps1`([设置](#amp-设置)) |
| **Gemini CLI** | 适配器 | 添加指向 `adapters/gemini.sh`(Windows 用 `.ps1`)的钩子([设置](#gemini-cli-设置)) |
| **GitHub Copilot CLI** | 内置(自动检测) | 当 `~/.copilot` 存在时,`install.sh` / `install.ps1` 自动在 `~/.copilot/hooks/peon-ping.json` 注册钩子。也可通过 `adapters/copilot.sh` / `.ps1` 进行逐仓库手动配置([设置](#github-copilot-cli-设置)) |
| **OpenAI Codex** | 内置(自动检测) | 如果 `~/.codex` 存在,`install.sh` / `install.ps1` 会自动在 `~/.codex/config.toml` 注册 stable hooks。也可手动接入适配器([设置](#openai-codex-设置)) |
| **Cursor** | 内置 | `curl \| bash`、`peon-ping-setup` 或 Windows `install.ps1` 自动检测并注册钩子。在 Windows 上,请在 **设置 → 功能 → 第三方技能** 中启用,以便 Cursor 加载 `~/.claude/settings.json` 以播放 SessionStart/Stop 音效。 |
| **OpenCode** | 适配器 | `bash adapters/opencode.sh` / `powershell adapters/opencode.ps1`([设置](#opencode-设置)) |
| **Kilo CLI** | 适配器 | `bash adapters/kilo.sh` / `powershell adapters/kilo.ps1`([设置](#kilo-cli-设置)) |
| **Kiro** | 适配器 | 添加指向 `adapters/kiro.sh`(或 `.ps1`)的钩子条目([设置](#kiro-设置)) |
| **Windsurf** | 适配器 | 添加指向 `adapters/windsurf.sh`(或 `.ps1`)的钩子条目([设置](#windsurf-设置)) |
| **Google Antigravity** | 适配器 | `bash adapters/antigravity.sh` / `powershell adapters/antigravity.ps1`。无头 / macOS LaunchAgent 场景可用 `bash adapters/antigravity-py.sh --install`(基于 Python `watchdog` 的 25 秒空闲阈值守护进程,需要 `pip3 install watchdog`)。Python 守护进程支持旧版 `conversations/*.pb` 状态,以及较新的 `antigravity-cli` / `antigravity-ide` 的 `conversations/*.db` 和 `brain/**/transcript*.jsonl` 布局。 |
| **Kimi Code** | 适配器 | `bash adapters/kimi.sh --install` / `powershell adapters/kimi.ps1 -Install`([设置](#kimi-code-设置)) |
| **OpenClaw** | 适配器 | 调用 `adapters/openclaw.sh `(或 `openclaw.ps1`),支持所有 CESP 分类和原生 Claude Code 事件名 |
| **Rovo Dev CLI** | 适配器 | 如果 `~/.rovodev` 存在,`install.sh` 会自动注册,或手动添加钩子到 `~/.rovodev/config.yml`([设置](#rovo-dev-cli-设置)) |
| **DeepAgents** | 适配器 | `bash adapters/deepagents.sh` / `powershell adapters/deepagents.ps1`([设置](#deepagents-设置)) |
| **oh-my-pi (omp)** | 适配器 | `bash adapters/omp.sh`([设置](#oh-my-pi-omp-设置)) |
| **Qwen Code** | 适配器 | 添加指向 `adapters/qwen.sh`(Windows 用 `.ps1`)的钩子([设置](#qwen-code-设置)) |
| **iFlow CLI** | 适配器 | 添加指向 `adapters/iflow.sh`(或 `.ps1`)的钩子([设置](#iflow-cli-设置)) |
| **Trae** | 适配器 | 文件系统监视器:`bash adapters/trae.sh &` / `powershell adapters/trae.ps1 -Install`([设置](#trae-设置)) |
| **Kiro IDE** | 适配器 | 在 `.kiro/hooks/*.kiro.hook` 中添加调用 `adapters/kiro-ide.sh`(或 `.ps1`)的 Agent 钩子([设置](#kiro-ide-设置)) |
| **ECA** | 适配器 | 添加指向 `adapters/eca.sh`(或 `.ps1`)的 shell 钩子([设置](#eca-设置)) |
> **Windows:** 所有适配器都有原生 PowerShell(`.ps1`)版本。Windows 安装程序(`install.ps1`)会将其复制到 `~/.claude/hooks/peon-ping/adapters/`。文件系统监视器(Amp、Antigravity、Kimi、Trae)使用 .NET `FileSystemWatcher` 而非 fswatch/inotifywait — 无需额外依赖。
### OpenAI Codex 设置
Codex 支持使用 stable Codex hooks API 和 peon-ping 适配器。如果 `~/.codex` 已存在,Unix 和 Windows 安装器会自动向 `~/.codex/config.toml` 写入 peon 管理的配置块。如果你先安装了 peon-ping、之后才安装 Codex,请重新运行 peon-ping 安装器。
默认注册的 Codex 事件包括 `SessionStart`、`UserPromptSubmit`、`PermissionRequest`、`PreCompact`、`SubagentStart`、`SubagentStop` 和 `Stop`。`SessionStart` 只匹配 `startup`、`resume` 和 `clear`;Codex 的上下文压缩由 `PreCompact` 处理,因此会跳过 compact 触发的 `SessionStart`。`PreToolUse`、`PostToolUse` 和 `PostCompact` 会刻意跳过;Codex 适配器会忽略 `PostToolUse`,因为 Codex 没有单独的失败专用 hook,而成功工具调用 hook 对 peon-ping 来说过于频繁。
**设置步骤:**
1. 安装 peon-ping 运行时:
```bash
bash "$(brew --prefix peon-ping)"/libexec/install.sh --no-rc
```
或使用标准安装器:
```bash
curl -fsSL https://raw.githubusercontent.com/PeonPing/peon-ping/main/install.sh | bash -s -- --no-rc
```
2. 如果 Codex 提示,请在 Codex 中运行 `/hooks`。Codex 要求非 managed 命令 hook 在运行前先经过 review 和 trust。
3. 如果安装时 Codex 已经在运行,请重启 Codex。
peon-ping 会把 inline hooks 写入 `~/.codex/config.toml`,而不是创建 `hooks.json`,这符合 [Codex hooks 文档](https://developers.openai.com/codex/hooks) 对同一配置层不要混用两种 hook 表示的建议。旧版 `notify` 接法仍作为回退兼容,但新安装应使用 stable hooks 路径。
### Amp 设置
[Amp](https://ampcode.com)(Sourcegraph)的文件系统监视适配器。Amp 不像 Claude Code 那样提供事件钩子,因此该适配器监视 Amp 的线程文件并检测代理何时完成回合。
**设置步骤:**
1. 确保已安装 peon-ping(`curl -fsSL https://peonping.com/install | bash`)
2. 安装 `fswatch`(macOS)或 `inotify-tools`(Linux):
```bash
brew install fswatch # macOS
sudo apt install inotify-tools # Linux
```
3. 启动监视器:
```bash
bash ~/.claude/hooks/peon-ping/adapters/amp.sh # 前台运行
bash ~/.claude/hooks/peon-ping/adapters/amp.sh & # 后台运行
```
**事件映射:**
- 新线程文件创建 → 问候音效(*"Ready to work?"*、*"Yes?"*)
- 线程文件停止更新 + 代理完成回合 → 完成音效(*"Work, work."*、*"Job's done!"*)
**工作原理:**
适配器监视 `~/.local/share/amp/threads/` 目录的 JSON 文件变化。当线程文件停止更新(1 秒空闲超时)且最后一条消息来自助手的文本内容(非待处理的工具调用)时,发出 `Stop` 事件 — 表示代理已完成,正在等待你的输入。
**环境变量:**
| 变量 | 默认值 | 说明 |
|---|---|---|
| `AMP_DATA_DIR` | `~/.local/share/amp` | Amp 数据目录 |
| `AMP_THREADS_DIR` | `$AMP_DATA_DIR/threads` | 要监视的线程目录 |
| `AMP_IDLE_SECONDS` | `1` | 停止变化后等待多少秒发出 Stop 事件 |
| `AMP_STOP_COOLDOWN` | `10` | 每个线程 Stop 事件之间的最小间隔秒数 |
### GitHub Copilot CLI 设置
[GitHub Copilot CLI](https://github.com/github/copilot-cli) 原生集成,完全符合 [CESP v1.0](https://github.com/PeonPing/openpeon) 规范。
**推荐:用户级(全局)配置 —— 无需逐仓库设置。**
每当 `~/.copilot/` 目录存在时,`install.sh` 和 `install.ps1` 会自动在 `~/.copilot/hooks/peon-ping.json` 注册 Copilot CLI 钩子。如果你在安装 peon-ping 之后才安装了 Copilot CLI,请重新运行安装脚本。该配置使用 **PascalCase 事件名称**,这会让 Copilot CLI 直接发送与 VS Code 兼容的(snake_case)负载,正是 `peon.sh` / `peon.ps1` 原生读取的格式 —— 不需要逐仓库适配器。
全局注册的钩子:
| 事件 | 分类 | 触发条件 |
|---|---|---|
| `SessionStart` | `session.start` | 启动 `copilot`(问候) |
| `SessionEnd` | _(当前静音)_ | 退出 CLI |
| `UserPromptSubmit` | `user.spam`(3+ 次快速提示后) | 每次提交提示 |
| `Stop`(即 `agentStop`) | `task.complete` | Agent 完成一个回合(5 秒去抖) |
| `Notification` | `input.required`(elicitation) | 空闲、elicitation 对话框、权限弹出 |
| `PermissionRequest` | `input.required` | 工具权限请求 |
| `PreToolUse` | `input.required`(仅匹配危险模式时) | 每次工具调用前 |
| `PostToolUseFailure` | `task.error` | 工具失败 |
| `PreCompact` | `resource.limit` | 上下文压缩开始 |
`postToolUse` **未**被注册:peon 没有 `PostToolUse` 处理程序,将其路由到 `Stop` 会淹没去抖窗口,吞掉真正的 `Stop` 事件。
**前置条件(Windows):** Copilot CLI 钩子需要 [PowerShell 7+](https://github.com/PowerShell/PowerShell)(`pwsh` 在 `PATH` 中)以及宽松的执行策略:
```powershell
winget install Microsoft.PowerShell
powershell -NoProfile -Command "Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force"
```
**替代方案:使用适配器进行逐仓库配置。**
如果你想要将 Copilot CLI 钩子提交到特定仓库(例如团队工作流),请使用 `.github/hooks/hooks.json` 配合 `adapters/copilot.sh`(Windows 上为 `.ps1`)转换器:
```json
{
"version": 1,
"hooks": {
"sessionStart": [
{
"type": "command",
"bash": "bash ~/.claude/hooks/peon-ping/adapters/copilot.sh sessionStart",
"powershell": "powershell -NoProfile -File %USERPROFILE%\\.claude\\hooks\\peon-ping\\adapters\\copilot.ps1 sessionStart"
}
],
"agentStop": [
{
"type": "command",
"bash": "bash ~/.claude/hooks/peon-ping/adapters/copilot.sh agentStop",
"powershell": "powershell -NoProfile -File %USERPROFILE%\\.claude\\hooks\\peon-ping\\adapters\\copilot.ps1 agentStop"
}
],
"postToolUseFailure": [
{
"type": "command",
"bash": "bash ~/.claude/hooks/peon-ping/adapters/copilot.sh postToolUseFailure",
"powershell": "powershell -NoProfile -File %USERPROFILE%\\.claude\\hooks\\peon-ping\\adapters\\copilot.ps1 postToolUseFailure"
}
],
"notification": [
{
"type": "command",
"bash": "bash ~/.claude/hooks/peon-ping/adapters/copilot.sh notification",
"powershell": "powershell -NoProfile -File %USERPROFILE%\\.claude\\hooks\\peon-ping\\adapters\\copilot.ps1 notification"
}
]
}
}
```
可按上表添加其他事件。适配器将 Copilot CLI 的 camelCase 负载(`sessionId`、`toolName`、`stopReason` 等)转换为 `peon.sh` / `peon.ps1` 读取的 snake_case 形式(`session_id`、`tool_name`、`stop_reason`)。
**功能:**
- **音频播放** 通过 `afplay`(macOS)、`pw-play`/`paplay`/`ffplay`(Linux)、`MediaPlayer`/`SoundPlayer`(Windows)—— 与 shell 钩子相同的优先级链
- **CESP 事件映射** —— Copilot CLI 钩子映射到标准 CESP 分类(`session.start`、`task.complete`、`task.error`、`input.required`、`user.spam`、`resource.limit`)
- **桌面通知** —— 默认使用大型覆盖横幅,或标准通知
- **垃圾信息检测** —— 检测 10 秒内 3 次以上快速提示,触发 `user.spam` 语音
- **去抖** —— `Stop` 事件在 5 秒窗口内被抑制,防止链式工具调用产生的垃圾消息
### OpenCode 设置
[OpenCode](https://opencode.ai/) 的原生 TypeScript 插件,完全符合 [CESP v1.0](https://github.com/PeonPing/openpeon) 规范。
**快速安装:**
```bash
curl -fsSL https://raw.githubusercontent.com/PeonPing/peon-ping/main/adapters/opencode.sh | bash
```
安装程序将 `peon-ping.ts` 复制到 `~/.config/opencode/plugins/` 并在 `~/.config/opencode/peon-ping/config.json` 创建配置。语音包存储在共享 CESP 路径(`~/.openpeon/packs/`)。
**功能:**
- **声音播放** — 通过 `afplay`(macOS)、`pw-play`/`paplay`/`ffplay`(Linux)— 与 shell 钩子相同的优先级链
- **CESP 事件映射** — `session.created` / `session.idle` / `session.error` / `permission.asked` / 快速提示检测都映射到标准 CESP 分类
- **桌面通知** — 通过 [`terminal-notifier`](https://github.com/julienXX/terminal-notifier) 提供丰富通知(副标题、按项目分组),回退到 `osascript`。仅在终端未获得焦点时触发
- **终端焦点检测** — 通过 AppleScript 检测你的终端应用(Terminal、iTerm2、Warp、Alacritty、kitty、WezTerm、ghostty、Hyper)是否在最前端
- **标签页标题** — 更新终端标签页显示任务状态(`● 项目: 工作中...` / `✓ 项目: 完成` / `✗ 项目: 错误`)
- **语音包切换** — 从配置读取 `default_pack`(旧版配置中回退到 `active_pack`),运行时加载语音包的 `openpeon.json` 清单。`path_rules` 可根据工作目录覆盖语音包。
- **不重复逻辑** — 避免每个分类连续播放相同声音
- **刷屏检测** — 检测 10 秒内 3 次以上快速提示,触发 `user.spam` 语音
🖼️ 截图:带有自定义苦工图标的桌面通知

> **提示:** 安装 `terminal-notifier`(`brew install terminal-notifier`)以获得更丰富的通知(支持副标题和分组)。
🎨 可选:自定义苦工图标用于通知
默认情况下,`terminal-notifier` 显示通用终端图标。包含的脚本使用 macOS 内置工具(`sips` + `iconutil`)将其替换为苦工图标 — 无需额外依赖。
```bash
bash <(curl -fsSL https://raw.githubusercontent.com/PeonPing/peon-ping/main/adapters/opencode/setup-icon.sh)
```
或本地安装(Homebrew / git clone):
```bash
bash ~/.claude/hooks/peon-ping/adapters/opencode/setup-icon.sh
```
脚本会自动查找苦工图标(Homebrew libexec、OpenCode 配置或 Claude 钩子目录),生成正确的 `.icns`,备份原始 `Terminal.icns` 并替换。`brew upgrade terminal-notifier` 后需重新运行。
> **未来:** 当 [jamf/Notifier](https://github.com/jamf/Notifier) 发布到 Homebrew([#32](https://github.com/jamf/Notifier/issues/32))时,插件将迁移到它 — Notifier 内置 `--rebrand` 支持,无需修改图标。
### Kilo CLI 设置
[Kilo CLI](https://github.com/kilocode/cli) 的原生 TypeScript 插件,完全符合 [CESP v1.0](https://github.com/PeonPing/openpeon) 规范。Kilo CLI 是 OpenCode 的分支,使用相同的插件系统 — 此安装程序下载 OpenCode 插件并为 Kilo 打补丁。
**快速安装:**
```bash
curl -fsSL https://raw.githubusercontent.com/PeonPing/peon-ping/main/adapters/kilo.sh | bash
```
安装程序将 `peon-ping.ts` 复制到 `~/.config/kilo/plugins/` 并在 `~/.config/kilo/peon-ping/config.json` 创建配置。语音包存储在共享 CESP 路径(`~/.openpeon/packs/`)。
**功能:** 与 [OpenCode 适配器](#opencode-设置)相同 — 声音播放、CESP 事件映射、桌面通知、终端焦点检测、标签页标题、语音包切换、不重复逻辑和刷屏检测。
### Gemini CLI 设置
[Gemini CLI](https://github.com/google-gemini/gemini-cli) 的 shell 适配器,完全符合 [CESP v1.0](https://github.com/PeonPing/openpeon) 规范。
**设置步骤:**
1. 确保已安装 peon-ping(`curl -fsSL https://peonping.com/install | bash`)
2. 在 `~/.gemini/settings.json` 中添加以下钩子:
```json
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"name": "peon-start",
"type": "command",
"command": "bash ~/.claude/hooks/peon-ping/adapters/gemini.sh SessionStart"
}
]
}
],
"AfterAgent": [
{
"matcher": "*",
"hooks": [
{
"name": "peon-after-agent",
"type": "command",
"command": "bash ~/.claude/hooks/peon-ping/adapters/gemini.sh AfterAgent"
}
]
}
],
"AfterTool": [
{
"matcher": "*",
"hooks": [
{
"name": "peon-after-tool",
"type": "command",
"command": "bash ~/.claude/hooks/peon-ping/adapters/gemini.sh AfterTool"
}
]
}
],
"Notification": [
{
"matcher": "*",
"hooks": [
{
"name": "peon-notification",
"type": "command",
"command": "bash ~/.claude/hooks/peon-ping/adapters/gemini.sh Notification"
}
]
}
]
}
}
```
**事件映射:**
- `SessionStart`(startup)→ 问候音效(*"准备好了吗?"*、*"是的?"*)
- `AfterAgent` → 任务完成音效(*"干活,干活。"*、*"完成了!"*)
- `AfterTool`(成功)→ 任务完成音效;(失败)→ 错误音效(*"我做不到。"*)
- `Notification` → 系统通知
### Windsurf 设置
添加到 `~/.codeium/windsurf/hooks.json`(用户级)或 `.windsurf/hooks.json`(工作区级):
```json
{
"hooks": {
"post_cascade_response": [
{ "command": "bash ~/.claude/hooks/peon-ping/adapters/windsurf.sh post_cascade_response", "show_output": false }
],
"pre_user_prompt": [
{ "command": "bash ~/.claude/hooks/peon-ping/adapters/windsurf.sh pre_user_prompt", "show_output": false }
],
"post_write_code": [
{ "command": "bash ~/.claude/hooks/peon-ping/adapters/windsurf.sh post_write_code", "show_output": false }
],
"post_run_command": [
{ "command": "bash ~/.claude/hooks/peon-ping/adapters/windsurf.sh post_run_command", "show_output": false }
]
}
}
```
### Kiro 设置
创建 `~/.kiro/agents/peon-ping.json`:
```json
{
"hooks": {
"agentSpawn": [
{ "command": "bash ~/.claude/hooks/peon-ping/adapters/kiro.sh" }
],
"userPromptSubmit": [
{ "command": "bash ~/.claude/hooks/peon-ping/adapters/kiro.sh" }
],
"stop": [
{ "command": "bash ~/.claude/hooks/peon-ping/adapters/kiro.sh" }
]
}
}
```
`preToolUse`/`postToolUse` 被有意排除 — 它们会在每次工具调用时触发,会非常嘈杂。
### Rovo Dev CLI 设置
[Rovo Dev CLI](https://developer.atlassian.com/cloud/rovo/)(Atlassian)的 shell 适配器,完全符合 [CESP v1.0](https://github.com/PeonPing/openpeon) 规范。
**自动设置:**
如果运行 `install.sh` 或 `peon-ping-setup` 时 `~/.rovodev/config.yml` 存在,事件钩子会自动注册。
**手动设置:**
1. 确保已安装 peon-ping(`curl -fsSL https://peonping.com/install | bash`)
2. 添加到 `~/.rovodev/config.yml`:
```yaml
eventHooks:
events:
- name: on_complete
commands:
- command: bash ~/.claude/hooks/peon-ping/adapters/rovodev.sh on_complete
- name: on_error
commands:
- command: bash ~/.claude/hooks/peon-ping/adapters/rovodev.sh on_error
- name: on_tool_permission
commands:
- command: bash ~/.claude/hooks/peon-ping/adapters/rovodev.sh on_tool_permission
```
3. 重启 Rovo Dev CLI 以使钩子生效。
**事件映射:**
- `on_complete` → 完成音效(*"Work, work."*、*"Job's done!"*)
- `on_error` → 错误音效(*"I can't do that."*、*"Son of a bitch!"*)
- `on_tool_permission` → 权限提示音效(*"Something need doing?"*、*"Hmm?"*)
**功能:**
- **声音播放** 通过 `afplay`(macOS)、`pw-play`/`paplay`/`ffplay`(Linux)— 与 shell 钩子相同的优先级链
- **CESP 事件映射** — Rovo Dev 事件映射到标准 CESP 分类(`task.complete`、`task.error`、`input.required`)
- **桌面通知** — 默认大型覆盖横幅,或标准通知
- **防抖** — 抑制快速完成产生的重复声音
### Kimi Code 设置
[Kimi Code CLI](https://github.com/MoonshotAI/kimi-cli)(MoonshotAI)的文件系统监视适配器。Kimi Code 将 Wire Mode 事件写入 `~/.kimi/sessions/` — 该适配器作为后台守护进程监视这些文件并将事件转换为 CESP 格式。
```bash
# 安装(启动后台守护进程)
bash ~/.claude/hooks/peon-ping/adapters/kimi.sh --install
# 查看状态 / 停止
bash ~/.claude/hooks/peon-ping/adapters/kimi.sh --status
bash ~/.claude/hooks/peon-ping/adapters/kimi.sh --uninstall
```
macOS 需要 `fswatch`(`brew install fswatch`),Linux 需要 `inotifywait`(`apt install inotify-tools`)。`curl | bash` 安装器会自动检测 Kimi Code 并启动守护进程。
**macOS 上 `--install` 会注册 LaunchAgent**(`~/Library/LaunchAgents/com.peonping.kimi-adapter.plist`),监听器会在登录时自动启动并在崩溃时自动重启 — 重启后无需重新运行 `--install`。设置 `KIMI_NO_LAUNCHD=1` 可回退到 `nohup`+pidfile(例如用于测试)。Linux 始终使用 `nohup`+pidfile。
**仅 Kimi 安装(无需 Claude):**
如果你没有 Claude Code,只想给 Kimi 装 peon-ping,使用 `--kimi`:
```bash
curl -fsSL peonping.com/install | bash -s -- --kimi
```
文件会安装到 `~/.kimi/hooks/peon-ping/` 而不是 `~/.claude/hooks/peon-ping/`,也不会创建 `~/.claude/` 目录。安装器还会自动检测:在仅有 `~/.kimi/` 但没有 `~/.claude/` 的机器上,无参数运行安装器会自动进入 `--kimi` 模式。监视守护进程会在安装时启动,并通过 LaunchAgent 在每次登录时重新启动。
**与 Claude 安装共享语音包:**
如果 `~/.claude/hooks/peon-ping/packs/` 已存在并包含语音包,`--kimi` 安装会将 `~/.kimi/hooks/peon-ping/packs` 软链接到它,而不是重新下载。一次下载即可服务两个 IDE,从任一侧执行 `peon packs install ` 都会更新共享的包集。状态、配置和静音切换在每个安装中保持独立。传递 `--no-shared-packs`(或 `--packs=` / `--all`)以下载独立副本。
**事件映射:**
- 新会话 → 问候音效(*"Ready to work?"*、*"Yes?"*)
- Agent 完成回合 → 完成音效(*"Work, work."*、*"Job's done!"*)
- 上下文压缩 → Token 限制音效
- 子 Agent 启动 → 子 Agent 跟踪
### 工具无关的安装根目录(`--openpeon`)
将全部内容(钩子、语音包、`settings.json`)安装到 `~/.openpeon` 而非 `~/.claude`:
```bash
curl -fsSL peonping.com/install | bash -s -- --openpeon
# Windows:powershell -File install.ps1 -OpenPeon
```
适用于 OpenPeon 品牌化或工具无关的部署:`peon.sh` 会通过其 packs 锚定回退自动发现 `~/.openpeon/packs`,因此指向该根目录的适配器无需 `~/.claude` 即可工作。无需此标志时,也可用 `CLAUDE_CONFIG_DIR=~/.openpeon bash install.sh` 实现相同的重定向。
### oh-my-pi (omp) 设置
[oh-my-pi](https://github.com/can1357/oh-my-pi)(`omp`)的原生 TypeScript 扩展,完全符合 [CESP v1.0](https://github.com/PeonPing/openpeon) 规范。订阅 omp 的 `ExtensionAPI` 生命周期事件,并通过 `peon.sh` 路由,让 omp 用户享受 peon-ping 的所有功能:语音包、桌面通知、训练提醒、移动推送、SSH/devcontainer 中继及标签页标题更新。
**快速安装:**
```bash
curl -fsSL https://raw.githubusercontent.com/PeonPing/peon-ping/main/adapters/omp.sh | bash
```
安装程序将 `peon-ping.ts` 和 `package.json` 复制到 `~/.omp/agent/extensions/peon-ping/`。之后重启 omp。
**事件映射:**
| omp 事件 | peon-ping 事件 |
|----------------------------------------|-----------------------|
| `session_start` | `SessionStart` |
| `turn_start` | `UserPromptSubmit` |
| `turn_end` | `Stop` |
| `tool_result` with `isError: true` | `PostToolUseFailure` |
| `auto_compaction_start` | `PreCompact` |
| `session_shutdown` | `SessionEnd` |
**卸载:**
```bash
curl -fsSL https://raw.githubusercontent.com/PeonPing/peon-ping/main/adapters/omp.sh | bash -s -- --uninstall
```
### Qwen Code 设置
为 [Qwen Code](https://github.com/QwenLM/qwen-code)(阿里巴巴)提供的轻量透传适配器。Qwen Code 采用 Claude Code 风格的钩子系统——事件以 JSON 形式通过 stdin 传入,且事件名使用与 peon-ping 一致的 PascalCase CESP 名称——因此该适配器只是给会话 id 打上 `qwen-` 前缀,并丢弃噪声较大的逐工具调用事件。
添加到 `~/.qwen/settings.json`:
```json
{
"hooks": {
"SessionStart": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/qwen.sh" }] }],
"UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/qwen.sh" }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/qwen.sh" }] }],
"Notification": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/qwen.sh" }] }],
"PostToolUseFailure": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/qwen.sh" }] }],
"SessionEnd": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/qwen.sh" }] }]
}
}
```
在 Windows 上,通过 `powershell -NoProfile -File %USERPROFILE%\.claude\hooks\peon-ping\adapters\qwen.ps1` 指向 `qwen.ps1`。
### iFlow CLI 设置
为 [iFlow CLI](https://cli.iflow.cn)(iflow-ai)提供的透传适配器。iFlow 采用 Claude Code 风格的钩子系统(PascalCase 事件经 stdin 传入);该适配器以 `iflow-` 会话前缀转发有意义的生命周期事件,并将失败的 `PostToolUse` 映射为 `PostToolUseFailure`。
添加到 `~/.iflow/settings.json`(或项目级 `./.iflow/settings.json`):
```json
{
"hooks": {
"SessionStart": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/iflow.sh" }] }],
"UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/iflow.sh" }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/iflow.sh" }] }],
"Notification": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/iflow.sh" }] }],
"PostToolUse": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/iflow.sh" }] }],
"SessionEnd": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/peon-ping/adapters/iflow.sh" }] }]
}
}
```
### Trae 设置
为 [Trae](https://trae.ai)(字节跳动)提供的文件系统监视器适配器。Trae 是基于 VS Code 的 AI IDE,没有同步的 shell 钩子 API,因此 peon-ping 采用与 Amp、Antigravity 相同的监视方式:出现新的会话文件即 `SessionStart`,空闲计时器(会话文件停止更新)触发 `Stop`。
```bash
# 前台运行
bash ~/.claude/hooks/peon-ping/adapters/trae.sh
# 后台运行
bash ~/.claude/hooks/peon-ping/adapters/trae.sh &
```
在 Windows 上:`powershell -File adapters\trae.ps1 -Install` 会注册后台监视器(用 `-Status` / `-Uninstall` 管理)。
Trae 的磁盘会话布局因平台/版本而异且无公开文档,因此被监视的路径可通过环境变量覆盖:
| 变量 | 默认值 |
|---|---|
| `TRAE_DATA_DIR` | `~/.trae` |
| `TRAE_SESSIONS_DIR` | `$TRAE_DATA_DIR/sessions` |
| `TRAE_SESSION_GLOB` | `*.json` |
需要 `fswatch`(macOS:`brew install fswatch`)或 `inotifywait`(Linux:`apt install inotify-tools`)。Windows 使用 .NET `FileSystemWatcher`——无需额外依赖。
### Kiro IDE 设置
为 **Kiro IDE**(Amazon)提供的钩子适配器——与 [Kiro CLI](#kiro-设置)(`adapters/kiro.sh`)不同。IDE 的 Agent Hooks 是 `.kiro/hooks/*.kiro.hook` JSON 文件;其 `then.type: runCommand` 动作运行 shell 命令时**不传 stdin JSON**,而是把触发的事件名作为 argv 参数传给适配器。
为每个事件创建一个钩子文件,例如 `.kiro/hooks/peon-ping-stop.kiro.hook`:
```json
{
"version": "1.0.0",
"enabled": true,
"name": "peon-ping-stop",
"when": { "type": "agentStop" },
"then": {
"type": "runCommand",
"command": "bash ~/.claude/hooks/peon-ping/adapters/kiro-ide.sh agentStop"
}
}
```
用 `when.type` = `promptSubmit`(→ `UserPromptSubmit`)、`preToolUse`(→ 权限提示)或 `sessionStart`(→ `SessionStart`)重复创建,每个都把对应事件名作为命令参数传入。`postToolUse` 及文件/用户触发的钩子不携带 peon 相关信号,将被忽略。在 Windows 上,通过 `powershell -NoProfile -File` 指向 `kiro-ide.ps1`。
### ECA 设置
为 [ECA](https://eca.dev)(Editor Code Assistant,编辑器无关的 LLM Agent 集成)提供的 shell 钩子适配器。ECA 通过 stdin 传入 JSON(顶层键为 snake_case),并将钩子类型同时作为 argv 参数传入;该适配器将 ECA 事件映射为 CESP,并使用从 ECA `db_cache_path` 派生的稳定 `eca-` 会话前缀。最初由社区在 PeonPing/peon-ping#261 贡献,现已第一方内置。
向 ECA 配置添加指向该适配器的 shell 钩子,每个事件一个:
```json
{
"hooks": {
"sessionStart": [{ "actions": [{ "type": "shell", "command": "bash ~/.claude/hooks/peon-ping/adapters/eca.sh sessionStart" }] }],
"preRequest": [{ "actions": [{ "type": "shell", "command": "bash ~/.claude/hooks/peon-ping/adapters/eca.sh preRequest" }] }],
"postRequest": [{ "actions": [{ "type": "shell", "command": "bash ~/.claude/hooks/peon-ping/adapters/eca.sh postRequest" }] }],
"preToolCall": [{ "actions": [{ "type": "shell", "command": "bash ~/.claude/hooks/peon-ping/adapters/eca.sh preToolCall" }] }],
"sessionEnd": [{ "actions": [{ "type": "shell", "command": "bash ~/.claude/hooks/peon-ping/adapters/eca.sh sessionEnd" }] }]
}
}
```
**事件映射:** `sessionStart`/`chatStart` → `SessionStart`,`preRequest` → `UserPromptSubmit`,`postRequest`/`subagentPostRequest`/`postToolCall` → `Stop`,`preToolCall` → 权限提示,`sessionEnd` → `SessionEnd`。
## 远程开发(SSH / Devcontainers / Codespaces)
在远程服务器或容器中编码?peon-ping 自动检测 SSH 会话、devcontainers 和 Codespaces,然后通过本地机器上运行的轻量级中继路由音频和通知。
### SSH 设置
1. **在本地机器上**,启动中继:
```bash
peon relay --daemon
```
2. **带端口转发的 SSH**:
```bash
ssh -R 19998:localhost:19998 your-server
```
3. **在远程安装 peon-ping** — 它会自动检测 SSH 会话并通过转发端口将音频请求发送回本地中继。
就这样。声音在你的笔记本电脑上播放,而不是远程服务器。
### Devcontainers / Codespaces
无需端口转发 — peon-ping 自动检测 `REMOTE_CONTAINERS` 和 `CODESPACES` 环境变量并将音频路由到 `host.docker.internal:19998`。只需在主机上运行 `peon relay --daemon`。
### 中继命令
```bash
peon relay # 前台启动中继
peon relay --daemon # 后台启动
peon relay --stop # 停止后台中继
peon relay --status # 检查中继是否运行
peon relay --port=12345 # 自定义端口(默认:19998)
peon relay --bind=0.0.0.0 # 监听所有接口(安全性较低)
```
环境变量:`PEON_RELAY_PORT`、`PEON_RELAY_HOST`、`PEON_RELAY_BIND`。
如果 peon-ping 检测到 SSH 或容器会话但无法连接中继,它会在 `SessionStart` 时打印设置说明。
### 基于分类的 API(用于轻量级远程钩子)
中继支持在服务器端处理声音选择的基于分类的端点。这对于未安装 peon-ping 的远程机器很有用 — 远程钩子只需发送分类名称,中继从活动语音包中随机选择声音。
**端点:**
| 端点 | 描述 |
|---|---|
| `GET /health` | 健康检查(返回 "OK") |
| `GET /play?file=` | 播放指定声音文件(旧版) |
| `GET /play?category=` | 播放分类中的随机声音(推荐) |
| `POST /notify` | 发送桌面通知 |
**远程钩子示例(`scripts/remote-hook.sh`):**
```bash
#!/bin/bash
RELAY_URL="${PEON_RELAY_URL:-http://127.0.0.1:19998}"
EVENT=$(cat | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('hook_event_name',''))" 2>/dev/null)
case "$EVENT" in
SessionStart) CATEGORY="session.start" ;;
Stop) CATEGORY="task.complete" ;;
PermissionRequest) CATEGORY="input.required" ;;
*) exit 0 ;;
esac
curl -sf "${RELAY_URL}/play?category=${CATEGORY}" >/dev/null 2>&1 &
```
将其复制到远程机器并在 `~/.claude/settings.json` 中注册:
```json
{
"hooks": {
"SessionStart": [{"command": "bash /path/to/remote-hook.sh"}],
"Stop": [{"command": "bash /path/to/remote-hook.sh"}],
"PermissionRequest": [{"command": "bash /path/to/remote-hook.sh"}]
}
}
```
中继从本地机器的 `config.json` 读取活动语音包和音量,加载语音包清单,并选择随机声音(避免重复)。
## 手机通知
当任务完成或需要关注时在手机上收到推送通知 — 当你离开桌面时很有用。
### 快速开始(ntfy.sh — 免费,无需账户)
1. 在手机上安装 [ntfy 应用](https://ntfy.sh)
2. 在应用中订阅一个唯一主题(例如 `my-peon-notifications`)
3. 运行:
```bash
peon mobile ntfy my-peon-notifications
```
也支持 [Pushover](https://pushover.net) 和 [Telegram](https://core.telegram.org/bots):
```bash
peon mobile pushover
peon mobile telegram
```
### 通知优先级(ntfy)
默认情况下,peon-ping 会根据事件类型推断 ntfy 优先级(权限请求为 `high`,常规事件为 `default`/`low`)。在 iOS 上,较低的优先级可能会静默送达(横幅显示但不播放声音)。设置一个明确的优先级可让提醒发出声音:
```bash
peon mobile ntfy my-peon-notifications --priority=max
```
也可以在 `config.json` 的 `mobile_notify` 中添加 `priority` 键:
```json
"mobile_notify": {
"service": "ntfy",
"topic": "my-peon-notifications",
"server": "https://ntfy.sh",
"priority": "max"
}
```
可接受的值为 ntfy 优先级名称(`max`/`urgent`、`high`、`default`、`low`、`min`)或数字 `1` 到 `5`。设置后会应用于每个事件,覆盖按事件类型推断的默认值;保持不设置则维持原有行为。同一个值也会映射到 Pushover 的优先级。
### 手机命令
```bash
peon mobile on # 启用手机通知
peon mobile off # 禁用手机通知
peon mobile status # 显示当前配置
peon mobile test # 发送测试通知
```
手机通知在每个事件时都会触发,无论窗口焦点 — 它们独立于桌面通知和声音。
## 语音包
160 多个语音包,涵盖魔兽争霸、星际争霸、红色警戒、传送门、塞尔达、Dota 2、绝地潜兵2、上古卷轴等。默认安装包含 5 个精选语音包:
| 语音包 | 角色 | 声音 |
|---|---|---|
| `peon`(默认) | 兽人苦工(魔兽争霸 III) | "Ready to work?", "Work, work.", "Okie dokie." |
| `peasant` | 人类农民(魔兽争霸 III) | "Yes, milord?", "Job's done!", "Ready, sir." |
| `sc_kerrigan` | 莎拉·凯瑞甘(星际争霸) | "I gotcha", "What now?", "Easily amused, huh?" |
| `sc_battlecruiser` | 战列巡航舰(星际争霸) | "Battlecruiser operational", "Make it happen", "Engage" |
| `glados` | GLaDOS(传送门) | "Oh, it's you.", "You monster.", "Your entire team is dead." |
**[浏览所有语音包并试听 → openpeon.com/packs](https://openpeon.com/packs)**
使用 `--all` 安装全部,或随时切换语音包:
```bash
peon packs use glados # 切换到指定语音包
peon packs next # 切换到下一个语音包
peon packs list # 列出所有已安装语音包
peon packs list --registry # 浏览所有可用语音包
peon packs install glados,murloc # 安装指定语音包
peon packs install --all # 安装注册表中所有语音包
```
想添加自己的语音包?参见 [openpeon.com/create 完整指南](https://openpeon.com/create) 或 [CONTRIBUTING.md](CONTRIBUTING.md)。
## 调试
当声音不播放或通知未出现时,结构化调试日志可帮助你精确追踪钩子调用期间发生的事情。
### 启用调试日志
```bash
peon debug on # 启用 — 日志写入 ~/.claude/hooks/peon-ping/logs/
peon debug off # 禁用
peon debug status # 显示状态、日志目录、文件数和总大小
```
你也可以通过设置环境变量 `PEON_DEBUG=1` 在单次调用中启用调试日志,而无需更改配置。
### 查看日志
```bash
peon logs # 今天日志的最后 50 行
peon logs --last 100 # 所有日志文件的最后 100 行
peon logs --session # 按会话 ID 过滤今天的日志
peon logs --session --all # 搜索所有日志文件中的会话 ID
peon logs --clear # 删除所有日志文件(需确认)
```
### 日志格式
每行日志是一条结构化的 key=value 记录:
```
2026-03-26T14:32:01.042 [config] inv=a3f1 loaded=/path/to/config.json volume=0.5 pack=peon enabled=True
2026-03-26T14:32:01.045 [event] inv=a3f1 hook_event=Stop cesp=task.complete session=abc123
2026-03-26T14:32:01.048 [sound] inv=a3f1 file=work-work.wav label="Work, work." category=task.complete
2026-03-26T14:32:01.120 [play] inv=a3f1 player=afplay file=work-work.wav
2026-03-26T14:32:01.125 [notify] inv=a3f1 title="peon: done" body="Work, work."
```
- **inv** -- 唯一的 4 字符调用 ID,链接单次钩子调用的所有阶段
- **阶段**:`[config]`、`[event]`、`[sound]`、`[play]`、`[notify]` -- 每个代表钩子管道中的一个阶段
- 包含空格或特殊字符的值会加引号
### 常见故障示例
| 症状 | 在日志中查找 |
|---|---|
| 没有声音播放 | `[event]` 行显示 `exit=early`(分类被禁用、已暂停或去抖动) |
| 错误的语音包 | `[config]` 行显示意外的 `pack=` 值 -- 检查 path_rules 或轮换设置 |
| 缺少声音文件 | `[sound]` 行显示 `error=` 和文件路径 |
| 通知缺失 | `[notify]` 行不存在 -- 检查配置中的 `desktop_notifications` |
### 配置键
| 键 | 默认值 | 说明 |
|---|---|---|
| `debug` | `false` | 启用结构化调试日志 |
| `debug_retention_days` | `7` | 自动清理超过 N 天的日志 |
日志存储在 `~/.claude/hooks/peon-ping/logs/peon-ping-YYYY-MM-DD.log`(每天一个文件)。旧日志会在新一天的日志创建时根据 `debug_retention_days` 自动清理。
## 卸载
**macOS/Linux:**
```bash
bash "${CLAUDE_CONFIG_DIR:-$HOME/.claude}"/hooks/peon-ping/uninstall.sh # 全局
bash .claude/hooks/peon-ping/uninstall.sh # 项目本地
```
**Windows (PowerShell):**
```powershell
# 标准卸载(删除声音前会提示)
powershell -File "$env:USERPROFILE\.claude\hooks\peon-ping\uninstall.ps1"
# 保留语音包(移除其他所有内容)
powershell -File "$env:USERPROFILE\.claude\hooks\peon-ping\uninstall.ps1" -KeepSounds
```
## 系统要求
- **macOS** — `afplay`(内置),AppleScript 用于通知
- **Linux** — 以下之一:`pw-play`、`paplay`、`ffplay`、`mpv`、`play`(SoX)或 `aplay`;`notify-send` 用于通知
- **Windows** — 原生 PowerShell 带 `MediaPlayer` 和 WinForms(无需 WSL),或 WSL2
- **MSYS2 / Git Bash** — `python3`、`cygpath`(内置);音频通过 `ffplay`/`mpv`/`play` 或 PowerShell 回退
- **所有平台** — `python3`(原生 Windows 不需要)
- **SSH/远程** — 远程主机上需要 `curl`
- **IDE** — 支持钩子的 Claude Code(或通过[适配器](#多-ide-支持)的任何支持的 IDE)
## 工作原理
`peon.sh` 是一个为 `SessionStart`、`SessionEnd`、`SubagentStart`、`UserPromptSubmit`、`Stop`、`Notification`、`PermissionRequest`、`PostToolUseFailure` 和 `PreCompact` 事件注册的 Claude Code 钩子。在每个事件:
1. **事件映射** — 嵌入的 Python 块将钩子事件映射到 [CESP](https://github.com/PeonPing/openpeon) 声音分类(`session.start`、`task.complete`、`input.required` 等)
2. **声音选择** — 从活动语音包清单中随机选择一个语音,避免重复
3. **音频播放** — 通过 `afplay`(macOS)、PowerShell `MediaPlayer`(WSL2/MSYS2 回退)或 `pw-play`/`paplay`/`ffplay`/`mpv`/`aplay`(Linux/MSYS2)异步播放声音
4. **通知** — 更新终端标签页标题,如果终端未获得焦点则发送桌面通知
5. **远程路由** — 在 SSH 会话、devcontainers 和 Codespaces 中,音频和通知请求通过 HTTP 转发到本地机器上的[中继服务器](#远程开发ssh--devcontainers--codespaces)
语音包在安装时从 [OpenPeon 注册表](https://github.com/PeonPing/registry)下载。官方语音包托管在 [PeonPing/og-packs](https://github.com/PeonPing/og-packs)。声音文件归各自发行商(Blizzard、Valve、EA 等)所有,根据合理使用原则分发用于个人通知目的。
## 链接
- [@peonping on X](https://x.com/peonping) — 更新和公告
- [peonping.com](https://peonping.com/) — 主页
- [openpeon.com](https://openpeon.com/) — CESP 规范、语音包浏览器、[集成指南](https://openpeon.com/integrate)、创建指南
- [OpenPeon 注册表](https://github.com/PeonPing/registry) — 语音包注册表(GitHub Pages)
- [og-packs](https://github.com/PeonPing/og-packs) — 官方语音包
- [peon-pet](https://github.com/PeonPing/peon-pet) — macOS 桌面宠物(兽人精灵,响应钩子事件)
- [许可证 (MIT)](LICENSE)
## 支持项目
- Venmo: [@garysheng](https://venmo.com/garysheng)
- 社区代币(DYOR / 仅供娱乐):有人在 Base 上创建了 $PEON 代币 — 我们接收交易手续费,帮助资助开发。[`0xf4ba744229afb64e2571eef89aacec2f524e8ba3`](https://dexscreener.com/base/0xf4bA744229aFB64E2571eef89AaceC2F524e8bA3)