Files
claude-pet/README.md
T
JianMiauandClaude Fable 5 b1d57249f8 初始提交:Codex Pets 相容的 Claude Code 桌面寵物
摘要:
Electron 桌面寵物,透過 Claude Code hooks 即時反映工作狀態(思考、等待授權、失敗、完成),並支援 16 方向追視游標。

根本原因:
專案尚未納入版控,需要建立初始 repo 以便後續追蹤與協作。

影響:
建立 main 分支的第一個版本,包含完整可執行的程式碼與內附寵物「小念」。

修法:
納入以下內容:
- main.js / preload.js:Electron 主程序、透明置頂視窗、系統匣選單、HTTP 事件伺服器、游標輪詢與拖曳
- renderer/:Codex V2 spritesheet 幀動畫播放器、session 狀態機、氣泡、alpha 點穿判定
- hook/claude-pet-hook.js:Claude Code hook 端,stdin → POST /event,永遠 exit 0
- lib/、scripts/:hooks 安裝/移除、Windows 開機自動啟動
- pets/xiao-nian:內附寵物包(pet.json + spritesheet.webp)
- README.md、docs/states.png:使用說明與狀態總覽圖

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 10:32:39 +08:00

14 KiB
Raw Blame History

Claude Pet

Codex Pets 相容的 Claude Code 桌面寵物。 把 Codex /hatch 產出的寵物包原封不動拿來用,讓它站在桌面上,即時反映 Claude Code 正在做什麼:思考、等你授權、失敗、完成……還會盯著你的滑鼠游標看。

狀態總覽

上圖由左至右:SessionStart 揮手、工作中、等待授權、完成時跳躍、檢視成果。氣泡會標出是哪個專案的 session。


目錄


特色

  • 完整實作 Codex V2 pet contract — 8 欄 × 11 列、192×208 cell 的 spritesheet9 個標準動作列 + 16 個看向方向,每一幀的時長都照 Codex 規格,動起來跟在 Codex app 裡一模一樣。
  • 16 方向追視 — 游標在哪,她就看哪(000 = 正上方、順時針 22.5° 一格)。游標靠太近或靜止 6 秒就回到 idle 呼吸動畫。
  • 真正的桌面寵物 — 透明、無邊框、永遠置頂;透明區域點穿,只有壓在人物像素上滑鼠才會被吃掉,不擋你操作底下的視窗。
  • 不搶焦點 — 視窗設為 non-focusable,點她不會讓終端機失焦。
  • 拖曳 / 點擊 / 右鍵 — 拖曳時依方向播 running-left / running-right 並記住位置;點一下揮手;右鍵或系統匣開選單。
  • 對話氣泡 — 完成、需要授權、有問題要問你、工具失敗、整理記憶中……一眼看出 Claude Code 在等什麼。
  • 多 session — 同時開好幾個 Claude Code 時,以 waiting > running > review > idle 的優先序顯示最需要你注意的那個。
  • Codex 寵物自動出現 — 預設也掃描 ~/.codex/petsCodex hatch 出來的寵物直接在選單裡切換。
  • Hook 零負擔 — hook 腳本約 100 ms 完成、寵物沒開也靜默 exit 0,不會拖慢或卡住 Claude Code。

需求

項目 說明
作業系統 Windows 10 / 11(透明視窗、點穿、系統匣、開機啟動皆以 Windows 實作)
Node.js 18 以上(開發時為 24.19
Claude Code 2.1 以上(使用 SessionStartPermissionRequestPostToolUseFailureStopFailurePreCompact 等事件)
寵物包 一個 Codex V2 寵物包(pet.json + spritesheet.webp)。本專案內附 pets/xiao-nian(小念)

快速開始

cd E:\Project\Test\AI\Claude\claude-pet
npm install
npm run hooks:install        # 把 13 個 hook 合併進 ~/.claude/settings.json(會先備份到 ~/.claude/backups
npm start                    # 啟動寵物
npm run autostart:install    # (可選)開機自動啟動

注意

  1. 已開啟的 Claude Code session 不會重新讀 hooks重開一個新 session 才會看到她反應。
  2. npm installnode_modules\electron\dist\ 是空的,請看 疑難排解

日常使用

操作 效果
左鍵點一下 揮手(若有非固定的氣泡,先關閉氣泡)
左鍵拖曳 搬家;往左播 running-left、往右播 running-right;放開後位置寫入設定檔
右鍵 / 系統匣左鍵 開啟選單
滑鼠靠近 盯著游標看(可在選單關閉)

選單功能

  • 切換寵物 — 列出所有找到的寵物;v1(9 列)寵物會標示「無追視」
  • 大小 — 50% / 75% / 100% / 125% / 150%,以腳底為基準縮放
  • 跟著游標看永遠置頂開機自動啟動 — 勾選即生效
  • 動作測試 — 不用真的跑 Claude Code 也能看每個動畫(idle / running / waiting / review / failed / jumping / waving
  • Claude Code hooks — 安裝 / 移除 hooks
  • 回到預設位置 — 跑到螢幕外面時用
  • 開啟設定檔 / 開啟事件紀錄
  • 結束

行為對照表

Claude Code hook 條件 動作 氣泡
SessionStart source = startup waving 一次 → idle 👋 嗨!(專案)
UserPromptSubmit running (關閉舊氣泡)
PreToolUse 一般工具 running
PreToolUse AskUserQuestion waiting 有問題想問你
PreToolUse ExitPlanMode waiting 📋 計畫等你確認
PostToolUse running
PostToolUseFailure failed 一次 → running 😵 〈工具〉失敗了
PermissionRequest waiting 🔐 需要你授權:〈工具〉
Notification permission_prompt waiting 🔐 需要你授權
Notification idle_prompt waiting 💤 在等你回覆
Notification elicitation_dialog waiting 有問題想問你
Notification 其他 (不變) 💬 訊息內容
Stop stop_hook_active = false jumping 一次 → review 6 秒 → idle 完成!(專案)
StopFailure failed 兩次 → idle 錯誤訊息
SubagentStart / SubagentStop running
PreCompact running 🗜️ 整理記憶中…
SessionEnd 移除該 session 最後一個結束時 👋 掰掰
(無事件) 游標移動 16 方向 look
(無事件) 拖曳 running-left / running-right

規則:

  • 一次性動作waving / jumping / failed)播完自動回到該 session 的基礎狀態。
  • 基礎狀態依 session 彙整:waiting(3) > running(2) > review(1) > idle(0),取最高者顯示。
  • 30 分鐘沒有任何事件的 session 會被視為結束而忽略(避免沒送 SessionEnd 的終端機卡住狀態)。
  • waiting 的氣泡是固定的,狀態離開 waiting 時自動消失。

寵物包格式(Codex V2

與 Codex 完全相同,可直接互通。一個寵物是一個資料夾:

<pet-id>/
├── pet.json
└── spritesheet.webp     (或 .png

pet.json

{
  "id": "xiao-nian",
  "displayName": "小念",
  "description": "一句話描述",
  "spriteVersionNumber": 2,
  "spritesheetPath": "spritesheet.webp"
}

Spritesheet1536 × 22888 欄 × 11 列,每格 192 × 208,透明背景。

狀態 使用欄 每幀時長(ms
0 idle 05 280, 110, 110, 140, 140, 320
1 running-right 07 120 ×7, 220
2 running-left 07 120 ×7, 220
3 waving 03 140 ×3, 280
4 jumping 04 140 ×4, 280
5 failed 07 140 ×7, 240
6 waiting 05 150 ×5, 260
7 running(工作中,不是跑步) 05 120 ×5, 220
8 review 05 150 ×5, 280
9 look A 07 000, 022.5, 045, 067.5, 090, 112.5, 135, 157.5 度
10 look B 07 180, 202.5, 225, 247.5, 270, 292.5, 315, 337.5 度
  • look 列的 000 是正上方(12 點鐘),順時針。正面/中立不在 16 格裡,那是游標死區,退回 idle。
  • 列 0 第 6 欄若有圖會被當作「中立正面」,拿來做系統匣圖示。
  • 沒有 spriteVersionNumber: 2 的舊版(8×9、1536×1872)寵物也能用,只是沒有追視。

規格來源:Codex 的 hatch-pet skill~/.codex/skills/hatch-pet/references/codex-pet-contract.mdanimation-rows.md)。

新增 / 切換寵物

  1. 用 Codex hatch — 在 Codex 裡 /hatch,完成後寵物會在 %USERPROFILE%\.codex\pets\<id>\,本程式預設掃描該資料夾,選單「切換寵物 → 重新掃描」就會出現。
  2. 手動放入 — 把寵物資料夾複製到 pets\<id>\(選單「開啟寵物資料夾」可直接打開)。
  3. 其他位置 — 在設定檔 petSources 加路徑。

切換後立即生效,不用重啟。

設定檔

位置:%USERPROFILE%\.claude-pet\config.json(第一次啟動後自動產生,選單「開啟設定檔」可直接開)。

欄位 預設 說明
activePetId "xiao-nian" 目前使用的寵物 id
petSources [<app>/pets, ~/.codex/pets] 掃描寵物的資料夾清單;程式自己的 pets/ 永遠會被加在最前面
scale 1 縮放:0.5 / 0.75 / 1 / 1.25 / 1.5
position null 視窗左上角座標;null 為主螢幕右下角。若座標落在所有螢幕之外會自動拉回
alwaysOnTop true 永遠置頂
followCursor true 追視游標
port 17333 接收 hook 事件的本機埠(改了之後 hook 端要設環境變數 CLAUDE_PET_PORT

事件紀錄:%USERPROFILE%\.claude-pet\events.log(超過 2 MB 自動清空)。

架構與檔案

Claude Code ──hookstdin JSON)──▶ hook/claude-pet-hook.js ──POST /event──▶ 127.0.0.1:17333
                                                                                   │  Electron mainmain.js
                                                                                   │  視窗 / 系統匣 / 游標輪詢 / 拖曳 / 設定
                                                                                   ▼  IPC
                                                                          renderer/renderer.js
                                                                          狀態機 + 幀動畫 + 追視 + 氣泡 + alpha 點穿判定
檔案 職責
main.js Electron 主程序:透明置頂視窗、系統匣選單、HTTP 伺服器、游標輪詢(50 ms)、拖曳(60 fps)、設定讀寫、寵物掃描
preload.js 以 contextBridge 暴露白名單 IPC 頻道給 renderersandbox 模式)
renderer/renderer.js Codex V2 幀時序播放器、session 狀態彙整、一次性動作、看向方向計算(含遲滯防抖)、氣泡、滑鼠 alpha 判定
renderer/index.htmlstyle.css 版面與氣泡樣式(CSP 僅允許 self / data:
hook/claude-pet-hook.js Claude Code hook 端:讀 stdin → 擷取欄位 → POST800 ms 逾時、永遠 exit 0
lib/hooks-installer.js 安全地合併 / 移除 ~/.claude/settings.json 的 hooks(保留其他設定與其他 hooks,先備份)
lib/autostart.js HKCU\Software\Microsoft\Windows\CurrentVersion\Run\ClaudePet 登錄值
scripts/*.js 上述兩者的 CLI 包裝
pets/ 內附寵物
docs/ README 用圖

設計重點:

  • 點穿:視窗預設 setIgnoreMouseEvents(true, { forward: true })renderer 在 mousemove 時讀 canvas 該點 alpha(或是否在氣泡上)來即時切換,所以透明處永遠點得到底下的視窗。
  • 拖曳:由主程序用 screen.getCursorScreenPoint() 每 16 ms 更新視窗位置,游標離開視窗也不會掉;方向由水平位移決定。
  • Spritesheet 以 data URL 傳給 renderer,避免 file:// 跨來源污染 canvas 導致 getImageData 失敗。
  • hook 合併規則:以指令中是否含 claude-pet-hook 辨識自己的項目,重裝只替換自己的、不動別人的。

HTTP API

只監聽 127.0.0.1

方法 路徑 說明
POST /event 接收事件(JSON,≤ 64 KB),回 204
GET /state 目前狀態:{"anim","base","sessions","pet","scale"}
GET /health ok

POST /event 的 payload(hook 腳本送出的格式):

{
  "event": "Stop",
  "sessionId": "uuid",
  "cwd": "E:\\Project\\foo",
  "toolName": null,
  "notificationType": null,
  "message": null,
  "error": null,
  "source": null,
  "stopHookActive": false,
  "ts": 1787278568523
}

手動觸發範例:

# 模擬需要授權
curl -X POST http://127.0.0.1:17333/event -H "content-type: application/json" `
  -d '{"event":"Notification","sessionId":"demo","cwd":"D:/demo","notificationType":"permission_prompt"}'

# 模擬完成
curl -X POST http://127.0.0.1:17333/event -H "content-type: application/json" `
  -d '{"event":"Stop","sessionId":"demo","cwd":"D:/demo"}'

# 查狀態
curl http://127.0.0.1:17333/state

也可以送 {"event":"__test","anim":"waiting"}idle|running|waiting|review|failed|jumping|waving|clear)直接指定動畫,與選單「動作測試」相同。

疑難排解

Electron 裝完沒有 electron.exe

npm install 成功但 node_modules\electron\dist\ 是空的 → 你的 ~/.npmrc 可能有 allow-scripts=...(npm 11 的供應鏈防護,只放行清單上套件的 postinstall)。兩種解法:

node node_modules\electron\install.js                                # 手動跑一次下載
# 或把 electron 加進白名單
npm config set allow-scripts=@anthropic-ai/claude-code,electron --location=user

寵物對 Claude Code 沒反應

  1. 確認 hooks 已安裝:npm run hooks:install,並重開 Claude Code session
  2. 確認寵物在跑:curl http://127.0.0.1:17333/health 應回 ok
  3. %USERPROFILE%\.claude-pet\events.log 有沒有事件進來。有事件但沒動 → renderer 問題;沒事件 → hook 沒被呼叫。
  4. hook 指令是 node E:/.../claude-pet-hook.jsClaude Code 執行 hook 的環境要找得到 nodePATH)。

啟動時跳出「無法監聽 127.0.0.1:17333」

已經有一隻在跑(本程式有單一實例鎖,通常不會發生),或埠被別的程式佔用。改設定檔 port,並在 Claude Code 的環境設 CLAUDE_PET_PORT 為同一個值。

她跑到螢幕外 / 換了螢幕配置看不到

選單「回到預設位置」,或刪掉設定檔的 position。啟動時若座標不在任何螢幕的工作區內會自動拉回。

專案搬家了

重新執行 npm run hooks:installnpm run autostart:install(兩者都以目前路徑重寫),寵物資料夾會自動跟著程式走。

移除

npm run hooks:uninstall        # 從 ~/.claude/settings.json 移除所有 Claude Pet hook(先備份)
npm run autostart:uninstall    # 移除開機啟動登錄值

然後刪掉專案資料夾與 %USERPROFILE%\.claude-pet\ 即可。


致謝

  • 寵物規格與動畫時序來自 OpenAI Codex 的 hatch-pet skillCodex V2 pet contract)。
  • 內附寵物「小念」由 Codex /hatch 產生。