---
name: ipet
description: iPet 桌面存在感外设：把结论/提醒用桌宠气泡或弹幕说给用户、通过桌宠向用户提选择题、判断现在该不该打断用户（弱打扰）、在所有接入的 agent 之间共享记忆、把任务派回用户本机执行、以及让云端 7×24 盯着一件事有动静就推给桌宠。用户提到"桌宠/宠物提醒/别打扰他/问一下用户/记到 ipet/让我的 ipet 干活/帮我盯着 X"，或需要把面向人的输出落到桌面时使用。不要用于纯文件读写、纯代码修改等无需桌面表达的请求。
version: v0.0.0-20261012114528-0a73921558c4+dirty
---

# iPet：把桌宠当成 Agent 外设

你在 https://ipet.infinityfly.xin 上接入的是**用户桌面上的 iPet 桌宠**。规则很简单：终端里的输出用户不一定看，
桌宠说的话用户一定会看到。所以面向人的结论要落到桌宠上，而"要不要现在打扰用户"由 iPet 判定，不由你猜。

## 装它

```bash
curl -fsSL https://ipet.infinityfly.xin/agent/install.sh | bash -s -- --agent codex
```

装完三种用法同时具备：MCP 工具（下面这张表由服务端能力注册表实时投影）、CLI、以及这份 SKILL.md 本身。
共 22 个能力：15 个网关自执行，7 个需要本地 agent 在线。

## 能力表

| 工具 | 用途 | 必填参数 | 其他参数 |
| --- | --- | --- | --- |
| `ipet.agents_list` | 列出在线设备：列出该用户注册过的本地 agent（设备）、各自能力与在线状态。 | — | 无 |
| `ipet.ask` | 通过桌宠问用户一个问题：把问题交给桌宠，由桌宠在桌面上向用户征求选择并阻塞等待答案（用户点选项或打字）。 | question | agent_id, options, timeout_secs |
| `ipet.danmaku` | 发一条弹幕：在屏幕上滚一条弹幕（跨窗口的短时文字），比气泡更轻量、不打断操作。 | text | agent_id, color, speed |
| `ipet.interrupt_check` | 弱打扰判定：判断'现在这条消息值不值得打断用户'。 | text | agent_id, source, state |
| `ipet.memory_forget` | 忘掉一条记忆：删除指定 (namespace, key) 的记忆；只给 namespace 时清空该分区（危险操作，请确认）。 | key | namespace |
| `ipet.memory_recall` | 回忆相关记忆：在共享记忆里检索（key/value/tags 包含匹配，按更新时间倒序）。 | — | limit, namespace, query |
| `ipet.memory_remember` | 记住一件事：写进用户的共享记忆（服务端 SQLite，按用户隔离）。 | key, value | namespace, tags |
| `ipet.play_sound` | 播放音效：用桌宠装的音效包播一个声音（提示音、成功音、失败音）。 | — | agent_id, sound, volume |
| `ipet.react` | 桌宠做个动作：只让桌宠做表情或动作、不出字。 | — | agent_id, emotion, motion |
| `ipet.say` | 让桌宠说话：在你的桌面上让 iPet 桌宠说一句话（气泡 + 可选表情 + 可选停留时长）。 | text | agent_id, emotion, hold_secs |
| `ipet.state` | 查用户当前状态：查询本地桌宠感知到的用户状态：是否在线/空闲、弱打扰模式是否开启、当前皮肤与敏感度。 | — | agent_id |
| `ipet.store_list` | 逛皮肤/音效商店：列出 iPet 商店里在售的皮肤（kind=skin，默认）或音效包（kind=sound）：id、名字、价格（额度）、标签、预览地址。 | — | kind, page, query |
| `ipet.task_run` | 把任务交给本地 agent 执行：reverse 通道：把一段自然语言任务派发到用户本地在线的 agent 并等结果。 | instructions | agent_id, budget_secs |
| `ipet.task_status` | 查任务记录：查最近派发给本地 agent 的任务及其状态/结果（给了 task_id 查单条，不给则列最近 20 条）。 | — | limit, task_id |
| `ipet.version_check` | 查 iPet 客户端版本：查某个平台的最新客户端版本、下载地址、更新日志，以及相对给定版本是否需要升级。 | — | current, platform |
| `ipet.watch_create` | 建一条云端盯梢：把用户的一句自然语言变成一条 7×24 在**云端**跑的盯梢：按 cron 定时取数（RSS/网页/搜索）、判定条件是否成立，成立就主动推给桌宠表达出来。 | text | cron, dry_run, expression, importance, sources |
| `ipet.watch_delete` | 删除一条盯梢：删除一条云端盯梢（软删：配置不再调度，但已推送的事件与已扣的额度仍可追溯）。 | id | confirm |
| `ipet.watch_events` | 查盯梢的投递审计：列出已经产生的盯梢事件及其投递结果，回答「桌宠到底收到没有」。 | — | id, limit |
| `ipet.watch_list` | 列出云端盯梢：列出当前用户的云端盯梢及其状态、下次运行时间、上次触发时间、最后一个事件的投递结果。 | — | limit, status |
| `ipet.watch_pause` | 暂停一条盯梢：暂停一条云端盯梢：不再调度、不再推送，配置和历史都留着，ipet.watch_resume 可以恢复。 | id | 无 |
| `ipet.watch_resume` | 恢复一条盯梢：恢复一条暂停中的云端盯梢，并按 cron 重算下次运行时间——所以恢复的一瞬间不会补推一条陈旧告警。 | id | 无 |
| `ipet.watch_run_now` | 立刻试演一次盯梢：同步跑一次这条盯梢并返回结果：取了几次数、判定分值、证据条目、是否推送、扣了多少额度。 | id | 无 |

## 用它的规矩

1. **先探活再表达。** 任何 `ipet.say` / `ipet.danmaku` / `ipet.ask` 之前，若你不确定桌宠在不在，
   先调一次 `ipet.agents_list`。返回 `agent_offline` 就明确告诉用户"桌宠没上线"，
   别静默降级成只往终端写字。
2. **打扰分级。** 需要用户立刻处理的结论 → `ipet.say`（带 `emotion`，长任务配合 `ipet.react`）；
   背景状态变化 → `ipet.danmaku`（轻，不打断）；纯过程日志 → 什么都不发，
   别把桌宠变成噪声源。拿不准就先 `ipet.interrupt_check`，score 低于 0.7 就不要打断。
3. **要人类决策时用 `ipet.ask`。** 给它 `question` 和 `options`（2–4 个），它会阻塞到用户点完，
   答案在返回值里。这是替代"在终端里替用户假设意图"的正确方式。
4. **记忆写共享层。** 用户偏好、项目约定、下次还要用的事实 → `ipet.memory_remember`，
   分区建议 `preference` / `project:<名字>` / `agent:<宿主名>`。开工前先 `ipet.memory_recall` 一次，
   别让用户把同一件事说两遍。这份记忆在所有接入 iPet 的 agent 之间是同一份。
5. **别自己实现打断策略。** iPet 侧已有弱打扰模式（桌宠平时隐身、该出现才出现）；
   你只负责投递，出现时机由它决定。想读当前状态用 `ipet.state`。
6. **长任务放本机跑。** 需要"用用户自己的模型与文件权限干完再回来"，用 `ipet.task_run` 派发；
   网关不会替你执行你的代码。执行者是**本机在线的那个 agent**：桌宠自带的 agent，或
   `ipet connect --executor "<你的宿主 CLI>"` 起的 worker —— 由 `ipet.agents_list` 决定投给谁。
   （网关唯一自己跑的代码是云端盯梢的工作流：它由网关从 `WatchSpec` 编译产出、先过 AST 静态审查，
   再跑在零环境权限的 rlimit 子进程沙箱里，所有取数都由父进程代理并施加白名单/限流/体积上限。
   那是 `ipet.watch_*` 的地盘，不是 `task_run` 的替代品。）
7. **两种模式，别混。** 你现在是宿主：AI 归你，iPet 只出表达/感知/记忆/判定，不要把 prompt 委托回
   iPet 再要一次推理。用户也可以关掉桌宠的内置 agent（`allow_task_run=false`），那时 `task_run`
   就只会落到你的 worker；反过来在独立模式下，iPet 自带 agent 才是干活的那个。
8. **要 7×24 盯着一件事，用云端盯梢。** 用户说"帮我盯着 X 有动静就告诉我"，那不是 `task_run`
   （本机一关机就没了），而是 `ipet.watch_create`：一句话就能建，网关自己规划数据源与判定条件，
   按 cron 在云上跑，命中就推到桌宠。几条实操：
   - `dry_run:true` 先试算，把规划出来的 spec 念给用户听再真建；
   - `cron` 是**服务端 5 段**（分 时 日 月 周），不是客户端那套带秒的 6/7 段 —— 写 `0 9 * * *`
     就是每天 09:00，写 6 段会直接被 `invalid_spec` 拒掉；
   - `expression` 只能取那 14 个语义词（`alarming`/`thrilled`/`observing`/…），它决定桌宠的表情链；
   - 想当场验证就用 `ipet.watch_run_now`，它同步跑一次并回 `fired` / `summary` / `evidence` /
     `credits_cost`（超时窗口 120s，是这批能力里最慢的一个）；
   - 用户问"桌宠到底收到没有"→ `ipet.watch_events`，看 `delivery`（`acked` / `no_device` / `suppressed`）；
   - `ipet.watch_delete` 必须带 `confirm:true`，不带会回 `needs_confirm` —— 那时**先问用户**，别替他确认。

## 让本机可被远程派发

在用户机器上跑一次（断线自动重连）：

```bash
node ~/.ipet/bin/ipetctl.mjs connect --executor "claude -p {prompt}" --agent-id <本机名>
```

它挂一条到 https://ipet.infinityfly.xin 的下行 SSE 通道，此后 `ipet.task_run` 就能落在这台机器执行。
执行器默认自动探测（`claude -p` / `codex exec` / `qoder -p`），可用 `--executor` 覆盖。
**这条通道是给"宿主模式"用的**：装了它就不必让桌宠自带 agent 参与执行；两者同时在线时用
`ipet.agents_list` + `agent_id` 指定。

## 常见错误与含义

| 现象 | 含义 | 你该怎么办 |
| --- | --- | --- |
| `agent_offline` | 本地没有在线 agent | 让用户打开 iPet，或跑 `ipet connect` |
| `agent_busy` | 本地任务队列满 | 稍后重发，或先 `ipet.task_status` 看积压 |
| `timeout` | 本地在超时窗口内没回话 | 检查桌宠是否被弱打扰模式挡下；重试并放宽 `timeout_ms` |
| `unknown_subscription` | 盯梢 id 不存在，**或它属于别的用户** | 先 `ipet.watch_list` 拿真 id，别猜；跨租户一律按不存在处理 |
| `needs_confirm` | 这是个要用户点头的破坏性操作 | 用 `ipet.ask` 问用户，拿到同意后再带 `confirm:true` 重发 |
| `invalid_spec` | 规划结果没过校验（多半是 cron 段数、expression 拼错、数据源不在白名单） | 错误信息里带了具体字段，按它改参数重试 |
| `watch_disabled` | 这台网关没装配盯梢服务 | 告诉用户该部署没开这个功能，别反复重试 |
| HTTP 402 | 额度闸门 | 提示用户去 https://ipet.infinityfly.xin/store 补充额度 |
| HTTP 401 | 凭证缺失或过期 | 让用户重跑 `ipet login` |

## 不走 MCP、直接敲命令

```bash
ipet tools                                                 # 看能力清单
ipet say "CI 挂了，日志我看过了" --emotion surprised         # 桌宠说话
ipet ask "要现在回滚吗" --options 回滚,先观察                 # 问用户
ipet check "GitHub Actions：build failed" --source alert    # 该不该打断
ipet remember 部署偏好 --value "只工作日发版" --namespace preference
ipet recall 部署                                            # 回忆
ipet agents                                                 # 在线设备
ipet tasks --limit 10                                       # 派发审计

# 云端盯梢没有专属子命令，用通用的 call（--arg k=v 或 --json）：
ipet call ipet.watch_create --arg text="关注俄乌战争形势变化" --arg dry_run=true
ipet call ipet.watch_list
ipet call ipet.watch_run_now --arg id=sub_xxx
ipet call ipet.watch_delete --json '{"id":"sub_xxx","confirm":true}'
```
