桌面 · 互动 · 实时响应

Clawd 桌宠

一只住在你桌面上的像素小螃蟹,实时感知 AI 编程助手的每一个动作

项目简介

一款基于 Electron 的桌面互动桌宠,能实时感知 AI 编程助手的运行状态。发起一个长任务后走开,等桌宠告诉你任务完成再回来。

  • 🎬 12 种动画状态 — 待机、思考、打字、建造、耳机律动、杂耍、报错、开心、通知、扫地、搬运、睡觉
  • 👀 眼球追踪 — 待机时跟随鼠标转动视线,身体微倾,影子拉伸
  • 😴 智能睡眠 — 60 秒无活动 → 打哈欠 → 打盹 → 倒下 → 睡觉;惊醒弹起动画
  • 🫧 权限气泡 — AI 工具请求权限时弹出浮动卡片,一键允许/拒绝
  • 📱 手机伴侣 PWA — 手机打开配对链接实时查看各 Agent 会话状态
  • ⬇️ 极简模式 — 拖到屏幕边缘隐藏,悬停探头,完成迷你动画

系统架构

🤖 AI 编程助手
Claude Code / Codex / Cursor 等
⬇ Command Hook / HTTP Hook ⬆
🦀 Clawd 桌宠
Electron 桌面应用
⬇ WebSocket / 日志轮询 ⬆
📱 手机 PWA
局域网实时镜像
AI 工具执行命令 → 通过 Hook 发送状态通知 → Clawd 解析当前状态 → 驱动对应动画 → 可选同步到手机

保姆级安装教程

1 环境准备

Clawd 桌宠需要 Node.js 运行环境。如果你没有安装 Node.js,请按以下步骤操作:

  1. 打开 Node.js 官网
  2. 下载左侧 LTS(长期支持版) 安装包(推荐 20.x 或 22.x)
  3. 双击安装,一路 下一步 即可
  4. 安装完成后,打开终端(命令提示符/PowerShell),输入以下命令验证:
bash验证命令
node --version    # 应显示 v20.x.x 或 v22.x.x
npm --version     # 应显示 10.x.x 或 11.x.x

两条命令都能正常显示版本号,说明环境就绪。

2 下载源码

在本页底部下载桌宠源码压缩包,解压后进入目录:

bash进入项目目录
cd clawd-on-desk

3 安装依赖

进入项目目录后,运行以下命令安装依赖包(包括 Electron 框架):

bash耗时约 2-10 分钟
npm install

📌 提示 安装过程中如果遇到网络慢的问题,可以使用国内镜像:

bash使用淘宝 npm 镜像加速
npm install --registry=https://registry.npmmirror.com

安装完成后,目录下会多出一个 node_modules 文件夹,这是所有依赖包,不要动它。

4 启动桌宠

依赖安装完成后,一行命令启动:

bash启动 Clawd
npm start

启动后你会看到:

  • 桌面出现一只像素小螃蟹 🦀(默认主题)
  • 它会自动检测你电脑上的 Claude CodeCodex CLI
  • 右下角系统托盘中出现螃蟹图标

看到桌宠在桌面上活动,说明安装成功了!

5 配置更多 AI 工具

Clawd 默认自动集成了 Claude Code 和 Codex CLI。如需支持其他 AI 工具:

  1. 右键点击桌宠(或右键系统托盘图标)
  2. 选择 Settings(设置)
  3. 切换到 Agents 标签页
  4. 找到你要集成的工具(如 Cursor、Copilot CLI、Gemini CLI 等)
  5. 点击 Install 安装对应的 Hook

部分工具也可以通过命令行安装:

bash以 Gemini CLI 为例
npm run install:gemini-hooks      # 安装 Gemini CLI 集成
npm run install:cursor-hooks      # 安装 Cursor IDE 集成
npm run install:copilot-hooks     # 安装 Copilot CLI 集成
npm run install:qwen-hooks        # 安装 Qwen Code 集成

6 切换主题

Clawd 内置三套主题,可以随时切换:

  1. 右键桌宠 → Settings
  2. 切换到 Themes(主题)标签页
  3. 选择你喜欢的外观:
    • Clawd 🦀 — 像素小螃蟹(默认)
    • Calico 🐱 — 三花猫
    • Cloudling ☁️ — 云宝
  4. 点击应用,桌宠会立即切换

动画一览

像素小螃蟹 Clawd 的各种动画状态:

待机待机
思考思考
打字打字
建造建造
耳机律动耳机律动
杂耍三球杂耍

三套内置主题

主题风格
🦀 Clawd像素小螃蟹,活泼好动。眼珠咕噜转,爪子跟着鼠标挥舞,默认主题的可爱担当
🐱 Calico Cat三花猫,优雅慵懒。思考时歪头,打字时爪子轻拍键盘,完成时尾巴翘高高
☁️ Cloudling云宝,轻盈梦幻。漂浮状态上下起伏,做动作时云朵会变形,治愈感满满

支持自定义主题,也可导入 Codex Pet 动画包。通过 npm run create-theme my-theme 即可生成主题脚手架。

支持 18+ AI 编程工具

与主流 AI 编程助手深度集成,自动感知工作状态:

Claude Code Codex CLI Copilot CLI Gemini CLI Cursor Agent Antigravity CLI CodeBuddy Kiro CLI Kimi Code CLI Qwen Code CodeWhale opencode Pi Hermes Agent Qoder QoderWork Reasonix CLI

功能特性

功能说明
多 Agent 支持同时追踪多个 AI 编程助手,独立管理各会话状态
子代理感知1 个子代理 → 耳机律动,2 个以上 → 三球杂耍
点击穿透透明区域的点击穿透到下方窗口,只有角色本体可交互
位置记忆重启后回到上次位置(包括极简模式)
多显示器等比缩放,竖屏额外尺寸补偿,跨屏拖动
多语言简中、繁中、英文、韩文、日文 — 右键菜单切换
免打扰静默所有 Hook 事件,直到手动唤醒
自动更新检查 GitHub release,Windows 退出时自动安装更新包
音效系统任务完成和权限请求时播放短提示音,右键菜单可开关
进程守护检测已崩溃/退出的 Agent 进程,10 秒内清理孤儿会话

技术栈

技术用途
Electron跨平台桌面应用框架(~41.x)
Node.js后端逻辑、Hook 管理、进程通信
Canvas / SVG像素动画渲染、眼球追踪
WebSocket (ws)与 AI 工具的状态同步、远程 SSH 转发
PWA手机伴侣 Web 应用(局域网实时镜像)
electron-updater自动更新机制

核心源码解读

以下展示了 Clawd 桌宠的几个核心文件,每个文件都配有代码说明。

launch.js 应用启动入口 — 22 行
#!/usr/bin/env node

const { spawn } = require("child_process");
const electron = require("electron");
const { buildElectronLaunchConfig } = require("./hooks/shared-process");

const forwardedArgs = process.argv.slice(2);
const launchConfig = buildElectronLaunchConfig(__dirname, { forwardedArgs });
const child = spawn(electron, launchConfig.args, {
  stdio: "inherit",
  env: launchConfig.env,
  cwd: launchConfig.cwd,
});

child.on("close", (code) => process.exit(code ?? 0));
📖 代码说明
这是 Clawd 桌宠的启动入口文件。它的核心作用是解决 Electron 的双重运行问题: Claude Code 等 AI 工具设置了 ELECTRON_RUN_AS_NODE=1 环境变量, 会导致 Electron 以 Node.js 模式运行而无法启动窗口。launch.js 会剥离这个环境变量, 然后通过 spawn 重新启动 Electron,确保桌宠窗口正常显示。
src/preload.js 渲染进程与主进程通信桥梁 — 39 行
const { contextBridge, ipcRenderer } = require("electron");

const themeArg = process.argv.find(a => a.startsWith("--theme-config="));
const themeConfig = themeArg ? JSON.parse(themeArg.slice("--theme-config=".length)) : null;

contextBridge.exposeInMainWorld("themeConfig", themeConfig);

contextBridge.exposeInMainWorld("electronAPI", {
  onThemeConfig: (cb) => ipcRenderer.on("theme-config", (_, cfg) => cb(cfg)),
  onViewportOffset: (cb) => ipcRenderer.on("viewport-offset", (_, offsetY) => cb(offsetY)),
  onStateChange: (callback) => ipcRenderer.on("state-change", (_, state, svg) => callback(state, svg)),
  onKimiPermissionPulse: (callback) => ipcRenderer.on("kimi-permission-pulse", () => callback()),
  onEyeMove: (callback) => ipcRenderer.on("eye-move", (_, dx, dy) => callback(dx, dy)),
  onCloudlingPointer: (callback) => ipcRenderer.on("cloudling-pointer", (_, payload) => callback(payload)),
  onRoamHeading: (callback) => ipcRenderer.on("roam-heading", (_, headingLeft) => callback(headingLeft)),
  onWakeFromDoze: (callback) => ipcRenderer.on("wake-from-doze", () => callback()),
  onDndChange: (callback) => ipcRenderer.on("dnd-change", (_, enabled) => callback(enabled)),
  onMiniModeChange: (cb) => ipcRenderer.on("mini-mode-change", (_, enabled, edge, options) => cb(enabled, edge, options)),
  onMiniClip: (cb) => ipcRenderer.on("mini-clip", (_, info) => cb(info)),
  onLowPowerIdleModeChange: (cb) => ipcRenderer.on("low-power-idle-mode-change", (_, enabled) => cb(enabled)),
  onSystemWake: (cb) => ipcRenderer.on("system-wake", (_, payload) => cb(payload)),
  onStartDragReaction: (cb) => ipcRenderer.on("start-drag-reaction", (_, direction) => cb(direction)),
  onEndDragReaction: (cb) => ipcRenderer.on("end-drag-reaction", () => cb()),
  onPlayClickReaction: (cb) => ipcRenderer.on("play-click-reaction", (_, svg, duration) => cb(svg, duration)),
  onPreloadSounds: (cb) => ipcRenderer.on("preload-sounds", (_, payload) => cb(payload)),
  onPlaySound: (cb) => ipcRenderer.on("play-sound", (_, payload) => cb(payload)),
  onInvalidateSoundCache: (cb) => ipcRenderer.on("invalidate-sound-cache", (_, url) => cb(url)),
  reportSoundPlaybackError: (payload) => ipcRenderer.send("sound-playback-error", payload),
  pauseCursorPolling: () => ipcRenderer.send("pause-cursor-polling"),
  resumeFromReaction: () => ipcRenderer.send("resume-from-reaction"),
  setLowPowerIdlePaused: (paused) => ipcRenderer.send("low-power-idle-paused", !!paused),
  reportSystemWakeStatus: (payload) => ipcRenderer.send("system-wake-status", payload),
});
📖 代码说明
这是 Electron 的预加载脚本(preload script),在渲染进程(桌宠窗口)加载前执行。 它通过 contextBridge 安全地将主进程的功能暴露给渲染进程: onStateChange 接收主进程发来的状态变化(如"思考中"、"打字中"), onEyeMove 接收鼠标坐标用于眼球追踪, onMiniModeChange 控制极简模式的切换。 所有通信都通过 Electron 的 IPC(进程间通信)机制完成,保证了安全性。
src/preload-bubble.js 权限气泡窗口通信 — 8 行
const { contextBridge, ipcRenderer } = require("electron");

contextBridge.exposeInMainWorld("bubbleAPI", {
  onPermissionShow: (cb) => ipcRenderer.on("permission-show", (_, data) => cb(data)),
  decide: (behavior) => ipcRenderer.send("permission-decide", behavior),
  onPermissionHide: (cb) => ipcRenderer.on("permission-hide", () => cb()),
  reportHeight: (h) => ipcRenderer.send("bubble-height", h),
});
📖 代码说明
这是权限气泡窗口的预加载脚本,只有 8 行代码但功能关键。 当 AI 工具(如 Claude Code)请求权限时,主进程打开一个浮动气泡窗口, 通过 onPermissionShow 将权限请求信息传给气泡 UI, 用户在气泡上点击"允许"或"拒绝"后,decide 将决定发回主进程, 主进程再转发给 AI 工具。这样用户无需切回终端即可处理权限请求。
src/state-hitbox-resolver.js 角色碰撞检测逻辑 — 27 行
"use strict";

function createHitboxRuntime(theme) {
  return {
    hitBoxes: theme.hitBoxes,
    fileHitBoxes: theme.fileHitBoxes || {},
    wideSvgs: new Set(theme.wideHitboxFiles || []),
    sleepingSvgs: new Set(theme.sleepingHitboxFiles || []),
  };
}

function resolveHitBoxForSvg(svg, runtime) {
  const hitBoxes = runtime.hitBoxes;
  const fileHitBoxes = runtime.fileHitBoxes;
  const wideSvgs = runtime.wideSvgs;
  const sleepingSvgs = runtime.sleepingSvgs;

  if (svg && fileHitBoxes[svg]) return fileHitBoxes[svg];
  if (svg && sleepingSvgs.has(svg)) return hitBoxes.sleeping;
  if (svg && wideSvgs.has(svg)) return hitBoxes.wide;
  return hitBoxes.default;
}

module.exports = {
  createHitboxRuntime,
  resolveHitBoxForSvg,
};
📖 代码说明
这个文件管理桌宠的点击碰撞检测。Clawd 在不同动画状态下的可点击区域不同: 睡觉时区域较小(只点身体),挥爪时区域较宽(包括爪子), 而某些特定动画帧可能有自定义的碰撞区域。 resolveHitBoxForSvg 根据当前播放的 SVG 帧,从主题配置中查找对应的碰撞盒, 实现"指哪打哪"的精准交互体验。
src/taskbar.js 任务栏管理 — 28 行
"use strict";

function shouldKeepOutOfTaskbar(platform = process.platform) {
  return platform === "win32" || platform === "linux";
}

function keepOutOfTaskbarForPlatform(w, platform = process.platform) {
  if (!w || w.isDestroyed()) return;
  if (shouldKeepOutOfTaskbar(platform) && typeof w.setSkipTaskbar === "function") {
    w.setSkipTaskbar(true);
  }
}

function keepOutOfTaskbar(w) {
  keepOutOfTaskbarForPlatform(w);
}

module.exports = {
  keepOutOfTaskbar,
  __test: {
    keepOutOfTaskbarForPlatform,
    shouldKeepOutOfTaskbar,
  },
};
📖 代码说明
桌宠窗口不应该出现在系统任务栏中(它是一个浮动宠物,不是常规应用窗口)。 这个文件在 Windows 和 Linux 上调用 Electron 的 setSkipTaskbar(true) 确保桌宠窗口不会占用任务栏空间。同时暴露了 __test 对象用于单元测试。
package.json 项目配置与依赖 — 全部 188 行
{
  "name": "clawd-on-desk",
  "version": "0.11.0",
  "description": "A desktop pet that reacts to your AI coding sessions in real-time.",
  "main": "src/main.js",
  "scripts": {
    "start": "node scripts/ensure-sidecar-binaries.js && node launch.js",
    "build": "electron-builder --win",
    "build:win:x64": "electron-builder --win nsis:x64",
    "build:win:arm64": "electron-builder --win nsis:arm64",
    "build:win:all": "electron-builder --win nsis:x64 nsis:arm64",
    "build:mac": "electron-builder --mac",
    "build:linux": "electron-builder --linux",
    "build:all": "electron-builder --win --mac --linux",
    "fetch:sidecars": "node scripts/fetch-sidecar-binaries.js",
    "verify:sidecars": "node scripts/verify-sidecar-binaries.js",
    "test": "node test/run-tests.js",
    "create-theme": "node scripts/create-theme.js",
    "install:claude-hooks": "node hooks/install.js",
    "uninstall:claude-hooks": "node hooks/uninstall.js",
    "install:gemini-hooks": "node hooks/gemini-install.js",
    "install:cursor-hooks": "node hooks/cursor-install.js",
    "install:kimi-hooks": "node hooks/kimi-install.js",
    "install:qwen-hooks": "node hooks/qwen-code-install.js",
    "install:codewhale-hooks": "node hooks/codewhale-install.js",
    "install:pi-extension": "node hooks/pi-install.js",
    "install:openclaw-plugin": "node hooks/openclaw-install.js",
    "install:codex-hooks": "node hooks/codex-install.js",
    "install:hermes-plugin": "node hooks/hermes-install.js",
    "install:qoder-hooks": "node hooks/qoder-install.js",
    "install:reasonix-hooks": "node hooks/reasonix-install.js"
  },
  "license": "AGPL-3.0-only",
  "devDependencies": {
    "electron": "^41.0.2",
    "electron-builder": "^26.8.1"
  },
  "dependencies": {
    "@larksuiteoapi/node-sdk": "^1.66.0",
    "electron-updater": "^6.8.3",
    "htmlparser2": "^12.0.0",
    "koffi": "^2.15.2",
    "ws": "^8.21.0"
  }
}
📖 代码说明
package.json 定义了项目的元数据和依赖。关键脚本说明: npm start 先检测 sidecar 二进制文件,然后启动应用; 各种 install:* 脚本用于安装不同 AI 工具的 Hook 集成。 依赖方面,核心依赖只有 5 个:Electron 框架、自动更新、HTML 解析、FFI 调用和 WebSocket, 保持了最小依赖原则。

常见问题

Q 启动后桌面没有看到桌宠?

检查系统托盘区域是否有螃蟹图标。如果没有任何反应,尝试在终端中手动运行 node launch.js 查看错误输出。常见原因:

  • Node.js 版本过低(需 ≥18.x)
  • npm install 未成功(检查 node_modules 是否存在)
  • 端口 23333 被占用(Clawd 使用此端口作为状态服务器)

Q 桌宠不响应 AI 工具的状态变化?

检查 Settings → Agents 中对应的工具是否已启用。Claude Code 和 Codex CLI 默认自动注册 Hook,其他工具需要手动安装集成。

Q 如何完全卸载?

运行 npm run uninstall:claude-hooks 移除 Hook,然后删除整个项目文件夹即可。

下载源码

点击下方按钮下载 Clawd 桌宠完整源码包

下载后解压,按照上方教程 步骤 3 开始安装

下载源码(ZIP)