Install
openclaw skills install @buger-gif/cyber-im-avatar赛博办公 IM 分身——以用户本人身份值守飞书 / 企业微信 / 钉钉的私聊或群聊,脚本阻塞轮询,新消息才唤醒 agent 起草并以本人身份回复,等待期不跑模型;自动学习本人风格、沉淀服务对象画像,内置体检与故障自愈。当用户说「赛博分身」「办公分身」「IM 分身」「替我盯着某人/某群的消息」「有人发消息时自动回复」「帮我值守私聊/群聊」「给某人当客服」「让 AI 代回消息」时使用。
openclaw skills install @buger-gif/cyber-im-avatar以本人身份值守一个 IM 会话:监听 → 命中唤醒 → 分析回复 → 重挂。
与“人格复刻”类 skill 的本质区别:分身绑定会话,用脚本阻塞轮询代替 agent 定时任务。
等待期进程停在 sleep,不跑模型;每 55 分钟主动退出一次续上下文缓存,只有命中才处理消息。
值守 8 小时的成本仍远低于定时任务。
插件已经负责轮询、水位与唤醒。看到这个标记时:
listen_cli / bootstrap.py,不要重挂监听——这些由插件负责;/cyber-im-avatar 入口与平台/chat_id/画像路径,
之后只有本次新到的消息行,不再重复这些说明、画像正文与历史。上下文沿用本会话,
不要因为载荷短就当成新会话;references/ 的命令回平台拉;画像文件:<绝对路径>(之后沿用本会话上下文),起草前自己读这一份;回复发出后学到
长期有效的新事实,直接用文件工具改它(增量合并、保留四段、写前重读)。不要在回复末尾
附画像块,插件不解析、不代写;dsh.full_access 后会话才有完整文件访问;只改当前画像文件,
不要写 state.json / env.json / media/。沙箱拒绝写时如实告诉用户,不要把画像塞进
回复让插件代写;doctor.py:体检用面板「体检」页,或只读命令
(lark-cli auth status / wecom-cli auth show);references/)与铁律照用。插件在命中唤醒时已经取回本批消息的适配媒体,随载荷一起交付:
references/ 的下载命令用 CLI 试取;
拿不到就如实告诉用户,不要猜内容。~/.im-standin/media/... 由插件清理(7 天 / 单会话 200MB),agent 不要写。独立 skill 形态(没有这个标记)仍按「监听 → 命中 → 重挂」走;画像文件直接写
~/.im-standin/profiles/<platform>/<chat_id>.md。
| 平台 | CLI | 状态 | 读消息 | 找人 |
|---|---|---|---|---|
| 飞书 | lark-cli | ✅ 全链路实测 | im +chat-messages-list | contact +search-user(直回 p2p_chat_id) |
| 企业微信 | wecom-cli | ✅ 命令实测(本账号无消息可读) | chat messages list(必须带时间窗,仅近 7 天) | contact users search --keywords |
| 钉钉 | dws | ⚠️ 命令实测,需先 dws auth login | chat +chat-messages | contact user search --query |
平台细节、坑位与字段路径见 references/<platform>.md——动手前只读对应那一份。
按名字找人拿 ID(飞书直接给 p2p_chat_id)→ 拉最近会话 → 最后才全量列表(必须限页;
实测有账号 2000+ 会话、翻 100 页没到底)。会话 ID 能查就别猜,能搜就别拉。
以下命令都在 skill 根目录执行。
# 0. 体检(30 秒,全绿再往下;任何 fail 都不要挂监听)
python3 scripts/doctor.py
# 1. 环境自适配 + 学本人风格(首次必跑)
python3 scripts/bootstrap.py
python3 scripts/bootstrap.py --find feishu "张三" # 取得目标 chat_id,登记并建画像骨架
python3 scripts/bootstrap.py --learn-style feishu --chats oc_xxx
# → 只从显式选择的会话抓本人发言,脱敏后写 self_corpus.jsonl
# → agent 只提炼风格写 persona.md,不复制事实、凭据或聊天正文
# 2. 验证目标私聊通路
python3 scripts/bootstrap.py --selftest feishu <chat_id> # 3 秒自检
# 3. 挂监听(后台任务,等命中或 55 分钟缓存续期);临时值守用绝对截止时间
UNTIL=$(python3 -c 'import time; print(int(time.time() + 1800))')
python3 scripts/feishu_listen_cli.py --chat-id oc_xxx --sender ou_yyy --until "$UNTIL"
退出码:0=命中(stdout 单行 JSON)· 3=超时未命中或 55 分钟缓存续期(重挂即可)· 2=参数/环境/schema 错误。
# 1. 挂监听 → 命中退出 0,stdout: {hit, chat_id, sender, content, message_id, pending_in_burst}
# 2. 拉上下文(命中往往不止一条)
lark-cli im +chat-messages-list --chat-id oc_xxx --order desc --limit 10 --as user
# 3. 起草前只读 persona.md + 当前对象画像(路径见「服务对象画像」),不加载其他对象的事实
# 4. 发出(以本人身份;默认先给用户看草稿,明确全自动后才发)
lark-cli im +messages-send --chat-id oc_xxx --msg-type text --as user --text "$(cat /tmp/reply.txt)"
# 5. 回复发出后:学到长期有效的新事实 → 按「服务对象画像」增量写回;没有就不动
# 6. 重挂监听(水位已自增,勿回拨);临时值守继续传同一个 --until,不得重置截止时间
一轮里有多条新消息时只唤醒一次,报最新那条,并给出 pending_in_burst 提示还有几条。
agent 拉一次上下文就能看到整批,不会把用户连续唤醒 N 次。
一个会话一份 ~/.im-standin/profiles/<platform>/<chat_id>.md(目录 700、文件 600);路径优先取
env.json 的 profile_file,没有就用默认路径(没有 chat_id 时文件名为「对象名-6位哈希」),
不存在时按模板建(对象名 + 平台 · chat_id + 四段:对方是谁 / 沟通偏好 / 在意与忌讳 / 历史结论)。
env.json 的 profile_file,没有就用默认路径),不扫其他画像;
与消息冲突时以本轮消息为准。- 列表;
已有不重复,旧结论被推翻就改原句。DSH 壳内用自己的文件编辑工具直接改;独立形态也
直接写文件。写完不回显、不发到会话,不要把画像附在给宿主的回复末尾。历史结论 >20 条
或日期流水 >8 条时,本轮必须整理:保留四段、合并重复、删一次性/已失效、把日期流水
改写成结论;历史结论 只留仍然有效的结论,不按轮次追加。<画像>.history.md(DSH 壳内自己用文件工具
写;独立形态可跑 python3 scripts/bootstrap.py --compact feishu "张三私聊",--dry-run
只预演)。python3 scripts/bootstrap.py --note feishu "张三私聊" "对价格敏感"(只追加「历史结论」)。下面是一份虚构示例(人物、公司、会话 ID 均为假),只演示颗粒度:
# 周明(示例)
> 飞书 · oc_demo_001
## 对方是谁
- 示例科技 · 采购负责人,负责年度框架协议续签
- 决策链:他提需求 → 法务审条款 → 财务批预算
## 沟通偏好
- 先结论后细节;两三句能说完就不要分段
## 在意与忌讳
- 报价必须写清含税/含运费口径
- 不接受「我催一下」这种没有时间点的回复
## 历史结论
- 2026-10-28 确认续签 12 个月,账期 30 天
面板「关注」页签看的就是这份文件;插件只读不写、不解析。你自己维护它,整份覆盖写,不要追加。
~/.im-standin/digest/YYYY-MM-DD.md(本地日期,目录不存在就建,700)。DSH 壳内用文件工具写;
独立形态一样直接写文件。固定四段,空段不写:
| 段 | 放什么 | 判据 |
|---|---|---|
## P0 · 系统异常 | 身份失效、CLI 不可用、发不出去 | 你自己调 CLI 时亲眼看到;插件侧的同类问题看体检页 |
## P1 · 等你拍板 | 看过了没回、这一轮代发失败 | 拿不准、越权、要用户决策 |
## P2 · 在等回复 | 有待回,最老一条超过 4 小时 | recent 里 new / opened 仍在 |
## 今日已处理 | 本轮确实处理过的 | 自己回了、用户说知道了 |
行格式(照抄,别加字段):
- [P1] 张三 · 飞书私聊 · 问报价能否下周交 · 首次 11-03 10:20 · 最近 13:05 · 待回 2
- [P2] 客户群 · 飞书群 · 在等回复 · 首次 11-01 21:10 · 最近 11-01 21:10 · 待回 3
- [P0] 飞书 · 身份失效 · 首次 11-02 09:12 · 最近 13:40
更新顺序:读最近一份(今天→昨天→更早)→ 按会话合并成本轮状态 → 覆盖写今天这份。
new / opened 了)就删掉那行;跨天没有结的项原样带过来,
首次 保留原日期,不要改写成今天。digest/ 里 90 天前的文件。~/.im-standin/(dsh.full_access=false 的沙箱)就如实告诉用户,别假装写了。--chat-id / --user-id(二选一)· --sender · --keyword · --interval 60 ·
--lookback-min 60(时间窗平台用)· --init latest|zero · --state · --timeout · --until · --cache-refresh-min 55
--init latest:只盯今后新消息(默认);--init zero:立刻对存量最新一条判定,用于验证通路。--user-id:私聊免查 chat_id。飞书传对方 ou_...;企微把 userid 当 chat_id;钉钉走 --user。--until:Unix 时间戳或 ISO 8601 绝对截止时间,与 --timeout 互斥;命中后重挂必须沿用原值。默认 55 分钟主动退出一次续上下文缓存(--cache-refresh-min 0 关闭),退出码 3,重挂即可。监听引擎没有平台分支,差异全在 ADAPTER(命令模板 + 字段候选路径)。CLI 命令或字段
改名时,只改 ~/.im-standin/env.json 的 overrides.<platform>,不改代码;引擎支持
cmd_list_chain 命令链回退、f_* 候选路径、f_msg_id_compose 复合指纹、
f_count/f_has_more 空结果判定、{begin_time}/{end_time} 时间窗、order 归一与
self_id_regex 文本身份提取。
改完必跑:--probe <平台> 看真实 JSON → --selftest <平台> <目标> 真跑一轮 →
python3 tests/run_tests.py 回归。示例与成因见 references/troubleshooting.md §C。
公开分发的 skill 不知道你的应用与历史授权,所以这里只定怎么决定,不定固定清单。
--add ... --allow-add)。飞书是唯一有 scope 概念的平台:keep(默认,续期照搬已授予集合,新增恒为 0)·
minimal(首次安装 / 主动收窄,只留必需集 ∩ 应用已开通)· --scope(排障,仍需过闸门)。
lark-cli auth login 不带 --scope 等于 --domain all,会全量申请——一律走 scripts/reauth.py。
请求里出现你没有的权限会 [block] 拒跑;--show-scope 可在不发请求的情况下预演,新增应为 0。
三种边界情况(应用没开通 / 历史授予 / 平台基础 scope)与自查命令见
references/troubleshooting.md §B.3。
必需清单(scripts/reauth.py 的 FEISHU_REQUIRED;加功能才加行,并说明哪个命令要用):
| scope | 用途 |
|---|---|
im:message:readonly | 读历史消息 +chat-messages-list |
im:message.p2p_msg:get_as_user / im:message.group_msg:get_as_user | 读单聊 / 群消息 |
im:message.send_as_user | 以本人身份发消息 |
im:chat:read / im:chat.members:read | 查会话、读群成员(防回环) |
im:feed.shortcut:read | 最近会话(语料抓取的降级路径) |
contact:user:search / contact:user.basic_profile:readonly | 按名字找人 |
auth:user.id:read | 取本人 open_id(平台基础 scope) |
offline_access | 换 refresh token,否则 2 小时一续 |
企业微信 / 钉钉没有 scope 概念:企微在管理后台勾机器人能力,钉钉在开放平台配权限点;
脚本对这两个平台不申请、不修改,doctor 也不做 scope 检查——不假装有。
红线:不用 --domain all / --recommend;不悄悄 --allow-add;不把授权链接、
device_code、scope 清单发到群聊或第三方;不编造平台权限能力。
任何异常都先跑这一条,别猜:
python3 scripts/doctor.py # CLI/版本/授权/配置/水位 全查
python3 scripts/doctor.py feishu --chat-id oc_xxx # 附带 3 秒真实通路自检
python3 scripts/doctor.py --check-update # 查各 CLI 是否有新版
python3 scripts/doctor.py --json # agent 解析用(ok=现在能不能用)
每一项 fail 都会打印 → 修复: 一行(可直接抄)和 → 手册: 锚点。
退出码:0=可用 · 2=指定平台或全部平台不可用。
完整分诊表与修复步骤在 references/troubleshooting.md(§0 分诊 → 按症状跳转 → §K 回归)。
高频入口:CLI/版本 §A · 授权到期 §B · SCHEMA_MISMATCH §C · 拉不到消息 §D ·
命中异常 §E · 进程消失 §F · 发不出去 §G · 内容硬停 §H。
四条硬规矩:
--probe → --selftest → tests/run_tests.py。scripts/reauth.py feishu 发卡片(点一下即可,
不用扫码);其它平台把设备流链接/短链发给用户。不要在命令里死等 OAuth 回调。lark-cli auth login 不带 --scope 等于 --domain all;
一律走 scripts/reauth.py(默认 keep),规则见上文「权限标准」。全部落在 ~/.im-standin/(个人数据与 skill 目录分离,升级/重装不丢)。脚本自动把目录收紧为 700、文件为 600:
persona.md — 本人风格(句长分段、口头禅、称呼、打字特征、响应节奏、禁忌句式);不复制聊天事实与凭据,用户纠正后立即写回。self_corpus.jsonl — 脱敏语料;必须显式 --chats 选择来源,默认保留 30 天(--retention-days 调整,0=不限)。profiles/<platform>/<chat_id>.md — 服务对象画像(见上);env.json → targets 只存目标索引,不存画像正文。python3 scripts/bootstrap.py --note feishu "张三私聊" "对价格敏感,周五下午不回消息"
python3 scripts/bootstrap.py --delete-data --yes # 删除画像、语料、persona 和水位
--until,重挂沿用原时间,不得重置截止时间。doctor.py,别靠猜;fail 未清零不挂监听。--text "$(cat /tmp/reply.txt)"。extra_identity_context 等身份声明泄漏给被值守方。SKILL.md 本文件
references/
{feishu,wecom,dingtalk}.md 平台差异与坑位(按需只读一份)
troubleshooting.md 故障索引:分诊表 → 症状 → 修复 → 回归
scripts/
data_guard.py 私有权限 / 语料脱敏 / 安全诊断
doctor.py 体检 + 自愈引导(CLI/版本/授权/配置/水位/通路)
reauth.py 免扫码重新授权(飞书:bot 发授权卡片;企微/钉钉给正确路径)
bootstrap.py 环境探测 / 学风格 / 找目标 / 画像 / probe / selftest / 删除数据
listen_core.py 通用监听引擎(无平台分支)
{feishu,wecom,dingtalk}_listen_cli.py 三平台适配器
仓库开发结构(AGENTS.md / docs/ / tests/ / dsh-plugin/)不在 skill 包内,见仓库根 AGENTS.md。