Clawd 状态映射全解析:从 Agent 生命周期事件到桌面宠物动画状态机
Clawd 状态映射全解析:从 Agent 生命周期事件到桌面宠物动画状态机
Clawd 是一款在桌面上"看着"Claude Code、Codex、Cursor 等 AI 编码代理运行的像素桌面宠物。本指南围绕仓库中的 docs/guides/state-mapping.md 展开,系统梳理 Clawd 如何把各 Agent 的生命周期事件(hook 事件、JSONL 事件、扩展事件)映射为统一的逻辑状态,以及这些状态如何驱动三只内置宠物(Clawd、Calico、Cloudling)的动画资产。读完本文,你将掌握核心状态机的优先级规则、子代理分级动画原理、Kimi 权限模式的完整配置,以及 ZCode、Grok、Pi、OMP 等代理各自的事件映射细节。
核心思想:所有 Agent 事件收敛到同一套状态机
Clawd 的设计哲学很直接:绝大多数代理的生命周期事件(Claude Code hooks、Codex JSONL、Copilot hooks 等)都映射到同一组动画状态。无论是哪家 CLI 发来的事件,最终都会落进这套统一的逻辑状态集合,再由状态机决定宠物的视觉表现。
这套状态集合定义在 src/state-priority.js 中,带有明确的优先级权重:
const STATE_PRIORITY = Object.freeze({
error: 8, // 错误
notification: 7, // 通知/权限提醒
sweeping: 6, // 清扫(PreCompact)
attention: 5, // 完成/注意(Stop / PostCompact)
carrying: 4, // 搬运(WorktreeCreate)
juggling: 4, // 杂耍(子代理运行中)
working: 3, // 工作中(工具调用)
thinking: 2, // 思考(用户提交提示)
idle: 1, // 空闲
roam: 1, // 漫游
sleeping: 0, // 睡眠
});
attention、error、sweeping、notification、carrying 属于一次性(one-shot)状态,播放完成后自动回到由 resolveDisplayState() 解析出的持续状态。多会话并存时,取优先级最高的会话状态作为宠物显示状态——例如一个会话正在报错(error, 8)时,另一个会话即使刚提交提示(thinking, 2)也不会抢走画面。
状态切换的核心实现在 src/state.js 的 setState() / applyState() 中:每个状态受主题 timings.minDisplay 最短展示时间和 timings.autoReturn 自动返回时间约束,新状态如果撞上当前状态的展示保护期,会被排入 pendingTimer 等待切换,且低优先级状态无法抢占高优先级 pending 状态。
主映射表:Agent 事件 → 状态 → 动画资产
下表是整份指南的核心,完整覆盖三只内置宠物在不同事件下的动画表现(动画文件均位于 assets/gif):
| Agent 事件 | 状态 | 动画 | Clawd | Calico | Cloudling |
|---|---|---|---|---|---|
| 空闲(无活动) | idle | 视线跟随 | clawd-idle.gif |
calico-idle.gif |
cloudling-idle.gif |
| 空闲(随机) | idle | 阅读 / 巡逻 | clawd-idle-reading.gif |
— | cloudling-idle-reading.gif |
| UserPromptSubmit | thinking | 思考气泡 + 火花 | clawd-thinking.gif |
calico-thinking.gif |
cloudling-thinking.gif |
| PreToolUse / PostToolUse(1 个会话) | working (typing) | 打字 | clawd-typing.gif |
calico-typing.gif |
cloudling-typing.gif |
| PreToolUse / PostToolUse(2 个会话) | working (2-session tier) | 耳机律动 | clawd-headphones-groove.gif |
calico-juggling.gif |
cloudling-juggling.gif |
| PreToolUse(3+ 个会话) | working (building) | 建造 | clawd-building.gif |
calico-building.gif |
cloudling-building.gif |
| SubagentStart(1 个活动子代理) | juggling | 耳机律动 | clawd-headphones-groove.gif |
calico-juggling.gif |
cloudling-juggling.gif |
| SubagentStart(2+ 个活动子代理) | juggling (2+ tier) | 三球杂耍 | clawd-juggling.gif |
calico-conducting.gif |
cloudling-conducting.gif |
| PostToolUseFailure | error | 错误 | clawd-error.gif |
calico-error.gif |
cloudling-error.gif |
| Stop / PostCompact | attention | 开心 | clawd-happy.gif |
calico-happy.gif |
cloudling-attention.gif |
| PermissionRequest | notification | 提醒 | clawd-notification.gif |
calico-notification.gif |
cloudling-notification.gif |
Codex request_user_input |
notification | 提醒 + 只读问题卡片 | clawd-notification.gif |
calico-notification.gif |
cloudling-notification.gif |
| PreCompact | sweeping | 清扫 | clawd-sweeping.gif |
calico-sweeping.gif |
cloudling-sweeping.gif |
| WorktreeCreate | carrying | 搬运 | clawd-carrying.gif |
calico-carrying.gif |
cloudling-carrying.gif |
| 鼠标空闲 60s | sleeping | 睡眠 | clawd-sleeping.gif |
calico-sleeping.gif |
cloudling-sleeping.gif |
| SessionEnd | 移除会话;无活动会话则回到 idle | 无睡眠过渡 | — | — | — |
子代理分级:juggling 状态如何选择资产
子代理事件仍映射到逻辑 juggling 状态,但 Clawd 现在会按实时子代理数量选择分级资产:1 个子代理使用 clawd-headphones-groove.svg,2 个及以上子代理使用 clawd-working-juggling.svg。旧的 Clawd 指挥(conducting)资产已退役;Calico 和 Cloudling 在 2+ 子代理档位仍使用各自的指挥动画。
分级的关键实现是"按活体子代理数而非会话数计数"。正如 src/state-visual-resolver.js 的注释所述(#862):一个会话可以同时承载多个子代理,如果按处于 juggling 状态的会话数计数,就会永远卡在 1 个子代理的资产上。因此 countLiveSubagents() 遍历每个非 headless、状态为 juggling 的会话,通过会话的 subagentTracker 统计可信子代理 ID 数量(见 src/subagent-lifecycle.js 的 getSubagentVisualCount()),再结合 legacyFloor / recoveredFloor 兜底逻辑得出总活体数,最后交给 selectTieredStateFile() 按主题的 jugglingTiers 配置(minSessions 阈值)选取资产。
空闲视觉:主题默认 vs 用户选择
上表的空闲行描述的是主题的默认行为。你可以在「Settings → Animation & Sound → Animations」中,选择当前主题声明的任意空闲视觉(idle visual)作为宠物持久的静止外观。
这一选择只改变逻辑状态为 idle 时显示的视觉:task、permission、completion、sleep、reaction 和 roam 状态仍然优先,展示完毕后会回到所选外观。选择按主题存储(per theme),若对应文件消失则回退到主题默认。非默认的空闲视觉故意不使用光标视线追踪,也不会触发 spin-to-dizzy(转圈眩晕)。
从源码看,这一逻辑体现在 src/state.js 的 applyState() 中:当状态为 idle 且没有 svgOverride 时,会调用 ctx.getIdleVisualChoice() 获取用户选择的视觉文件;src/state-visual-resolver.js 的 getSvgOverride() 也确认了"用户选择的默认空闲视觉优先于跟随精灵(follow sprite)"(#509)。
Outlaw 空闲彩蛋:西部牛仔装扮
Clawd 还有一个条件触发的 Outlaw 空闲彩蛋:当西部牛仔帽(Western cowboy hat)和香烟(cigarette)两个配饰同时被选中时,一次符合资格的普通空闲滚动有 50% 概率播放 clawd-outlaw-bender.svg,并带有 30 分钟冷却。
隐藏、低功耗、mini、漫游(roaming)、拖拽、菜单打开以及非空闲期间,都不消耗滚动机会或冷却时间。该动画内嵌了自己的帽子和香烟,因此仅对该文件隐藏两个外部配饰图层——即"外部配饰层只对该文件隐藏",其他动画继续正常叠加配饰。
Claude Code 专属行为:设计指令、心心眼与 PostToolBatch
/design 指令与心心眼完成
在 Clawd 主题中,直接向 Claude Code 发送 /design 命令会通过 UserPromptExpansion 选择绘画(painting)视觉;被接受的主会话 Stop 会选择心心眼(heart eyes)——这标记的是"回合完成",而非"发布成功"。
临时工具失败、通知和自动压缩(compaction)会保留设计提示以便恢复工作;而终端失败、会话结束和下一次普通提示会清除它。两种姿态都保留所选头部配饰、临时隐藏嘴部配饰(在支持的普通姿态下恢复)。其他主题使用各自的正常状态视觉。
PostToolBatch(Claude Code 2.1.280+)
Claude Code 2.1.280+ 额外注册了 PostToolBatch 钩子事件:
- 被接受的主会话 batch 会在下一个模型请求前回到
thinking状态,且不标记回合完成。 - 它要求当前的
prompt_id和精确有界的工具身份;早期 batch 会等待每个命名工具的普通关联证据。 - 缺失/模糊身份、待审批、子 batch、headless 会话和延迟的旧回调都不会产生这一相位变化。
- Prompt 身份是**回合关联(turn correlation)**而非消息去重:额外的同 id 消息仍走正常处理;队列中的回合可以在前一回合关闭后、无需再次 Submit 即从已识别工具开始;被否决的 Stop 之后的新工具可以继续该回合。
- 回合打开时出现未见过的 id,会禁用相位推断但不会退休打开的 prompt;
SessionEnd始终权威,与 prompt id 无关。 - 已结算的成功尾部在保留元数据、权限清理和 AskUserQuestion 转录补全回退的同时保留 thinking;当前失败则播放错误提示并在之后恢复已建立的模型相位;活动子代理提示保持其优先级。
- 较旧/未知的 Claude 版本不会注册新的 batch 钩子;该相位事件不会改变持久化的恢复租约或会话历史。
2.1.280 门槛是保守验证的基线,并非声称这是第一个支持该事件的版本。
从状态机源码看,PostToolBatch 被列入 src/state.js 的 COMPLETION_CANCEL_EVENTS——即它属于"代理循环仍在运行"的前进证据,会取消挂起的(防抖)完成动画,从侧面印证了"不标记回合完成"的语义。
Kimi Code CLI(Kimi-CLI)Hook 事件
Kimi Code CLI 现在使用纯 hook 集成(配置文件位于 ~/.kimi/config.toml),并将以下 13 个 hook 事件映射到共享的 Clawd 状态(源码中的映射表见 hooks/kimi-hook.js):
| Kimi Hook 事件 | 状态 |
|---|---|
| SessionStart | idle |
| SessionEnd | 移除会话;无活动会话则回到 idle |
| UserPromptSubmit | thinking |
| PreToolUse | working(详见下方权限模式) |
| PostToolUse | working |
| PostToolUseFailure | error |
| Stop | attention |
| StopFailure | error |
| SubagentStart | juggling |
| SubagentStop | working |
| PreCompact | sweeping |
| PostCompact | attention |
| Notification | notification |
Kimi 权限模式(permission mode)详解
PreToolUse 默认映射 working。显式载荷审批信号(permission_required / requires_approval / waiting_for_approval / is_permission_request)始终立即翻转权限动画。除此之外,持久化模式决定如何处理需要权限的工具:
suspect(安装器默认):武装一个延迟启发式——如果 suspect 窗口内没有PostToolUse到达,就假定 Kimi 阻塞在其审批 TUI 上,触发提示。explicit:只对显式信号响应(当前 kimi-cli 从不发出这些信号——实际效果是完全没有提示)。
安装器(npm run install:kimi-hooks 与启动时的自动同步)会把模式以 --permission-mode=<mode> 标志持久化到 ~/.kimi/config.toml 的 command 字段,并在重新同步时保留先前选择的模式。该 argv 标志的解析实现在 hooks/kimi-hook.js 的 parseHookArgv()。
运行时环境变量可覆盖持久化标志(按优先级):
| 环境变量 | 作用 |
|---|---|
CLAWD_KIMI_PERMISSION_MODE=explicit|suspect |
胜过持久化的 argv 标志(CLAWD_KIMI_DISABLE_PRETOOL_PERMISSION 和 CLAWD_KIMI_PERMISSION_IMMEDIATE 在它之前检查) |
CLAWD_KIMI_PERMISSION_IMMEDIATE=1 |
强制对受门控工具立即重映射(immediate) |
CLAWD_KIMI_PERMISSION_SUSPECT=1 |
旧别名,为当前进程启用 suspect |
CLAWD_KIMI_PERMISSION_SUSPECT_MS=<ms> |
调整 suspect 窗口(默认 800ms,见 src/state.js 的 parseSuspectDelay()) |
CLAWD_KIMI_DISABLE_PRETOOL_PERMISSION=1 |
无论其他开关如何,保持仅显式(explicit-only)行为 |
完整的分类决策链见 hooks/kimi-hook.js 的 classifyPreTool():显式载荷信号 → immediate;CLAWD_KIMI_DISABLE_PRETOOL_PERMISSION=1 → none;CLAWD_KIMI_PERMISSION_IMMEDIATE=1 → immediate;运行时 env 模式 → 按 suspect/explicit 决定;argv 模式 → 同理;最后默认 none。
门控队列台账(gate ledger):被队列化的门控调用会在每会话台账中跟踪(kimiPermissionGateLedgers,见 src/state.js)。legacy kimi-cli 会一次性为一条助手消息中的所有排队工具调用触发 PreToolUse(两次调用间隔约 0.1s),然后逐个阻塞在审批 TUI 上——每答复一次审批,就为下一个待处理调用重新武装提示。台账按 tool_call_id 精确配对关闭,无 id 时按 FIFO 关闭匿名条目。Kimi 持有期间,宠物保持在 notification 状态并周期性脉冲(最小间隔 3s)避免 GIF 反复从第 0 帧重启。
Gemini CLI Hook 专属语义
Gemini CLI 保持纯 hook 集成,但两个 Gemini 原生事件故意不强行套用共享的 Claude/Codex 语义(源码见 hooks/gemini-hook.js):
| Gemini Hook 事件 | Clawd 行为 |
|---|---|
| AfterAgent | 记录为 AfterAgent,会话回到 idle。不重映射为共享 Stop,因此 Gemini 回合不再自动展示 attention/完成动画。 |
| PreCompress | 记录为会话历史中的 PreCompress,但不把宠物切到 sweeping。当前可见状态(通常是 thinking 或 working)保持不变(preserveState: true)。 |
另外注意 Gemini 的钩子输出约定:BeforeTool / AfterTool 应答 {"decision":"allow"},BeforeAgent 应答 {};stdout 应答必须恰好一次,并有 800ms 安全超时保证合法 JSON(见 SAFETY_TIMEOUT_MS)。
ZCode Hook 事件
ZCode 使用 ~/.zcode/cli/config.json 下的配置文件钩子(源码见 hooks/zcode-hook.js):
| ZCode Hook 事件 | 状态 |
|---|---|
| SessionStart | idle |
| UserPromptSubmit | thinking |
| PreToolUse | working |
| PostToolUse | working |
| PostToolUseFailure | error |
| Stop | attention |
| PermissionRequest | notification(仅 fail-closed 路径) |
权限语义值得特别注意:自 Phase 2 起,PermissionRequest 是阻塞式权限审批——钩子等待 Clawd 的本地气泡或远程审批,并通过 stdout 的 hookSpecificOutput 返回人工 allow/deny 决策。权限自动化(permission automation)在 ZCode 的工具面和会话身份被审计之前刻意推迟。
- 上表的
notification映射只在 fail-closed 路径触发(工具名缺失/未知),或当 Clawd 未运行时;真实决策从不发布/state。 - ZCode 在本集成中不提供
SessionEnd钩子,因此完成判定依赖Stop加 Clawd 正常的进程存活与过期会话清理。 - 当 Clawd 不产生决策(超时、断连、DND、气泡关闭)时,钩子打印
{},ZCode 自有的权限流程接管。 - 工具输入有严格的预算护栏(字符串 240 字符、数组 16 项、对象 32 键、深度 6),超限即 fail-closed,避免截断的危险命令尾部(如
...; rm -rf)被渲染成可点击的 Allow。
Grok Build Hook 事件
Grok Build 使用 <GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json 下的配置文件钩子:
| Grok Hook 事件 | 状态 | 备注 |
|---|---|---|
| SessionStart | idle | |
| UserPromptSubmit | thinking | 在 turn fence 中记录最新回合 |
| PreToolUse / PostToolUse | working | |
| PostToolUseFailure / StopFailure | error | |
Stop(reason="end_turn",无活动后台任务/cron,inactive stop hook) |
attention | 仅真正的无阻塞回合结束 |
| Stop(续接信号) | working,event=null |
适配器本地;绝不锁存 terminal |
Stop(channel_closed / shutdown / 缺失 / 未知 reason) |
丢弃 | 绝不合成 Done;由真实 SessionEnd 或 idle_prompt 结算 |
| StopCancelled | idle | 无 Done 结算;纠正同回合的 Stop 尾部 |
Notification(notificationType="idle_prompt") |
notification | 播放一次性动画,然后存储会话 idle;fence 结算回合 |
| 其他 Notification | notification | 仅展示;不结算活动回合 |
| PreCompact | sweeping | |
| PostCompact(手动) | idle | 绝非完成 |
| PostCompact(自动) | thinking | 绝非完成 |
| PermissionDenied | notification(被动) | 无决策;Grok 拥有权限 |
| SessionEnd | 移除会话;无活动会话则回到 idle | 清除 turn fence 记录 |
Grok 从不注册 /permission——适配器始终输出 {}。子代理事件(subagentType)与 SubagentStart / SubagentStop 在 Phase 1 中不属于范围。Stop 的 end_turn 判定在 hooks/grok-hook.js 中是适配器本地的:只有精确的 end_turn 且无活动后台任务/未激活 stop 钩子才算真结束。
Pi 扩展事件
Pi 使用全局扩展(~/.pi/agent/extensions/clawd-on-desk),将交互式会话生命周期事件映射到共享 Clawd 状态:
| Pi 扩展事件 | Clawd 事件 | 状态 |
|---|---|---|
| session_start | SessionStart | idle |
| before_agent_start | UserPromptSubmit | thinking |
| tool_call | PreToolUse | working |
| tool_result (ok) | PostToolUse | working |
| tool_result (isError) | PostToolUseFailure | error |
| agent_end | Stop | attention |
| session_before_compact | PreCompact | sweeping |
| session_compact | PostCompact | attention |
| session_shutdown | SessionEnd | 移除会话;无活动会话则回到 idle |
Pi 在 Clawd 中仅限状态(state-only):Clawd 不拦截权限、不添加确认提示,Pi 保留其默认的 YOLO 执行行为。
OMP 扩展事件
OMP(oh-my-pi)使用每代理扩展目录——默认环境为 ~/.omp/agent/extensions/clawd-on-desk——同样映射交互式会话生命周期事件:
| OMP 扩展事件 | Clawd 事件 | 状态 |
|---|---|---|
| session_start | SessionStart | idle |
| session_switch / session_branch | SessionStart | idle |
| before_agent_start | UserPromptSubmit | thinking |
| tool_call | PreToolUse | working |
| tool_result (ok) | PostToolUse | working |
| tool_result (isError) | PostToolUseFailure | error |
session_stop 候选 + 后续 agent_end(willContinue !== true) |
Stop | attention |
| session_before_compact | PreCompact | sweeping |
| session_compact | PostCompact | attention |
| session_shutdown | SessionEnd | 移除会话;无活动会话则回到 idle |
与 Pi 扩展相比,OMP 有三个刻意不同的行为:
- 完成跨
session_stop与后续agent_end提交。session_stop是预结算聚合钩子:Clawd 处理完后,另一个扩展仍可请求隐藏续接。Clawd 在那里记录主会话候选,仅当后续agent_end不携带willContinue: true时才提交——因此调度暂停、内置重试和扩展续接都不会播放完成铃声。 session_switch/session_branch被上报,且被离开的会话以合成SessionEnd退役。OMP 可以把交互式终端移到另一个对话而不关闭旧会话,否则 HUD 上会残留一行无人再上报的活动行。- 始终发送
session_title。多个交互式 OMP 会话可以合法地共享同一工作目录,仅靠文件夹名回退会让每一行(以及每个跳转目标)看起来完全相同。
OMP 同样是 state-only:Clawd 不拦截权限、不添加确认提示,OMP 保留自己的执行行为。
Mini Mode:贴边小宠物
拖到屏幕右边缘(或右键 → "Mini Mode")即可进入 mini 模式——半身宠物贴屏幕边缘,悬停时探头出来。
| 触发 | Mini 反应 | Clawd | Calico | Cloudling |
|---|---|---|---|---|
| 默认 | 呼吸 + 眨眼 + 视线追踪 | clawd-mini-idle.gif |
calico-mini-idle.gif |
cloudling-mini-idle.gif |
| 悬停 | 探头 + 挥手 | clawd-mini-peek.gif |
calico-mini-peek.gif |
cloudling-mini-peek.gif |
| 通知 | 提醒弹出 | clawd-mini-alert.gif |
calico-mini-alert.gif |
cloudling-mini-alert.gif |
| 任务完成 | 开心庆祝 | clawd-mini-happy.gif |
calico-mini-happy.gif |
cloudling-mini-happy.gif |
Mini 模式的状态重映射逻辑在 src/state.js 的 applyState() 中:notification → mini-alert,attention → mini-happy,working / thinking / juggling → mini-working(若主题声明),其余回到 mini-peek / mini-idle。
点击反应
彩蛋多多——试试双击、快速连点 4 次、或者反复戳 Clawd,去发现隐藏反应。
可选官方主题:Hash Sage(哈希仙人)
Hash Sage 不随 Clawd 捆绑。它是按需从独立仓库 rullerzhou-afk/clawd-themes 下载的可选官方主题(Settings → Theme → Official themes)。安装后作为外部 APNG 主题运行,使用相同的逻辑状态、把已批准的 SVG 特效烘焙进每个 APNG,且无光标视线追踪:
| 状态 | Hash Sage 动画 |
|---|---|
| idle | 空手待机——站立呼吸(已批准样例;完整空闲集尚未最终定稿) |
| idle 随机池(鼠标静止 20s 后) | 小云捉迷藏——小云飞来、带着金色轨迹绕她转圈、在她指尖玩耍后飞走;以 idle 姿态起止 |
| thinking | 掐诀推演——掌中罗盘转动、代码符文升起 |
| working(1 会话) | 执笔制符——书写验证符 |
| working(2 会话)/ juggling(1 子代理) | 御剑 · 哈希符文——双剑带哈希符文 |
| working(3+ 会话)/ juggling(2+ 子代理) | 忙碌协作——两个纸灵帮忙 |
| attention | 完成收功——展开封印卷轴 |
| notification | 小铃轻唤——摇小铃 |
| error | 怎么又炸了——符咒反噬 |
| sweeping / carrying | 拂尘引纸 / 牵云运匣 |
| 打哈欠 → 打盹 → 倒下 → 睡觉 → 醒来 | 哈欠入盹 → 托腮轻盹 → 云来安睡 → 云上代码梦 → 伸懒腰醒来 |
| DND 睡眠过渡 | 直接安睡 |
| roam、mini 螃蟹步 | 乘云而行(朝右绘制,朝左时镜像) |
| 拖拽 / 双击 / 恼火、4 连击 | 张手轻摆 / 小小吃惊 / 有点嫌弃 |
| mini idle / 进入 / 悬停探头 | 贴边探头 / 从右侧走入 / 探出与呼吸 |
| mini 提醒 / 任务完成 / working | 摇铃 / 竖卷收功 / 挥符 |
| mini 进入睡眠 / 睡眠(DND) | 闭眼入场 / 贴墙睡眠呼吸 |
卸载后重新下载是"有损升级":会清除该主题的自定义项和 Clawd 托管的声音覆盖。
可选官方主题:Whale-chan(鲸鱼娘)
Whale-chan 同样不随 Clawd 捆绑,从同一 rullerzhou-afk/clawd-themes 仓库按需下载(Settings → Theme → Official themes),要求 Clawd 1.2.0。安装后作为外部动画图像主题运行(theme 1.0.1 起为动画 WebP),使用相同的逻辑状态、特效烘焙进每个动画,且无光标视线追踪:
| 状态 | Whale-chan 动画 |
|---|---|
| idle | 陪你发一会儿呆——站立呼吸 |
| idle 随机池(鼠标静止 20s 后) | 大家一起来合奏——指挥、音乐光环淡入淡出,再交叉淡回 idle |
| 默认空闲视觉选择(Settings → Default idle visual) | 泡在泳池里偷个懒——通过 idleVisualOptions 提供,绝不随机选中 |
| thinking | 认真想一想 |
| working(1 会话) | 今天也在努力呀 |
| working(2 会话)/ juggling(子代理) | 发现电饭煲啦——魔法电饭煲 |
| working(3+ 会话) | 撑着小伞去踩水——雨中撑伞 |
| attention | 任务完成啦! |
| notification | 有件事要你确认哦 |
| error | 报错也要被接住 |
| sweeping / carrying | 把尾巴擦得亮晶晶 / 泡在泳池里偷个懒 |
| 打哈欠 → 打盹 → 倒下 → 睡觉 → 醒来 | 慢慢钻进纸箱里 → 在纸箱里轻轻呼吸 → 从纸箱飘进云朵 → 睡在软绵绵的云上 → 睡饱啦,回来陪你 |
| DND 睡眠过渡 | 乘着云朵进入深睡 |
| roam、mini 螃蟹步 | 搭上鲸鱼巴士去兜风(朝右绘制,朝左时镜像) |
| 拖拽 / 点击反应 | 被拎起来也要晃一晃 / 戳我干嘛,哼! |
| mini 进入 / idle | 从屏幕边探出头来 / 趴在屏幕边陪着你 |
| mini 悬停探头 | 撑起身子看看你,指针停留时保持该姿态(mini-peek-hold) |
| mini working / 提醒 / 任务完成 | 认真干饭中 / 叮!有事找你 / 砰!做完啦 |
| mini 进入睡眠 / 睡眠(DND)/ 睡眠中悬停 | 闭着眼也来陪你 / 趴在屏幕边睡着了 / 睡着也撑起身子(mini-sleep-peek) |
小结:一张表读懂 Clawd 的状态语义
Clawd 的状态映射体系可以概括为三层:
- 事件层——各代理的 hook/扩展事件(Claude/Codex/Copilot 共享语义,Kimi/Gemini/ZCode/Grok/Pi/OMP 各有专属映射)。
- 状态层——统一逻辑状态(idle / thinking / working / juggling / error / attention / notification / sweeping / carrying / sleeping),由 src/state-priority.js 的优先级决定多会话并存时的显示胜负。
- 视觉层——主题把每个状态绑定到具体动画资产,子代理分级(
jugglingTiers)、working 分级(workingTiers)、显示提示(displayHintMap)与用户自定义空闲视觉共同决定最终画面,最终由 src/state.js 的状态机统一调度。
理解这层映射后,你就能读懂宠物任何一次动画切换背后的原因:为什么 2 个子代理时 Clawd 在抛三球、为什么 Gemini 回合结束不会出现完成动画、为什么 Kimi 卡在审批 TUI 时宠物会进入通知姿态——所有行为都有明确的事件来源和可追溯的源码实现。