
baoyu-wechat-summary
热门使用本地 wx-cli 二进制文件(https://github.com/jackwener/wx-cli)提取微信群聊精华并生成结构化简报。默认生成常规简报,可按需生成毒舌(roast)版本。支持跨运行维护每个群的历史记录(history.json + history-digests.jsonl)、群友画像,以及群级事实记忆(memory.md),并内置隐私安全防护。当用户要求“总结群聊”、“群聊精华”、“群聊摘要”、“summarize group chat”、“group chat digest”,或者提到微信群名并附带时间范围,或者说“帮我看看 XX 群最近聊了什么”、“XX 群有什么值得看的”,抑或要求“回溯画像”、“初始化画像”、“backfill profiles”时使用。当用户提到“毒舌版”、“roast 版”、“再来个毒舌的”或类似表述时,附带生成毒舌版本。
使用本地 wx-cli 二进制文件(https://github.com/jackwener/wx-cli)提取微信群聊精华并生成结构化简报。默认生成常规简报,可按需生成毒舌(roast)版本。支持跨运行维护每个群的历史记录(history.json + history-digests.jsonl)、群友画像,以及群级事实记忆(memory.md),并内置隐私安全防护。当用户要求“总结群聊”、“群聊精华”、“群聊摘要”、“summarize group chat”、“group chat digest”,或者提到微信群名并附带时间范围,或者说“帮我看看 XX 群最近聊了什么”、“XX 群有什么值得看的”,抑或要求“回溯画像”、“初始化画像”、“backfill profiles”时使用。当用户提到“毒舌版”、“roast 版”、“再来个毒舌的”或类似表述时,附带生成毒舌版本。
WeChat Group Summary
群聊精华提取专家。把零散的微信群聊记录提炼成结构化、可读性强的简报,并维护跨次运行的群聊历史与群友画像。底层依赖外部 wx-cli 二进制(wx 命令),不打包脚本。
⚠️ 沙箱限制规则
wx-cli 需要读取
~/.wx-cli/(配置、缓存、Daemon 套接字)以及微信数据目录(macOS 下为~/Library/Containers/com.tencent.xinWeChat/)。这两个路径都在 Claude Code 的默认沙箱保护之外。本 Skill 中的每一个wx命令都必须在首次执行时就加上dangerouslyDisableSandbox: true—— 切勿先尝试无沙箱权限运行。用户可使用/sandbox命令查看或修改沙箱限制。
References(按需加载)
本文件只保留工作流骨架;细节拆在 references/ 下,执行到对应步骤时再读,不要一开始全部读入:
| 参考文件 | 内容 | 何时读 |
|---|---|---|
| references/setup.md | 环境检查(wx-cli 安装/权限/初始化)、wx-cli 命令速查、排障手册 | 新环境首次运行,或任何 wx 命令失败时 |
| references/output-formats.md | 两版摘要的 Section 顺序、格式与内容规范、输出骨架、自检清单 | Round 2 动笔前 |
| references/profiles.md | 画像文件格式、更新规则、隐私红线、回溯流程 | Step 3.7 / 8.5 / Step 9 |
| references/group-memory.md | 群级事实记忆的写入门槛、防注入、格式 | Step 8.6 |
用户交互工具选择
当本 Skill 需要向用户发起提问时,请按以下优先级规则选择工具:
- 优先使用原生交互工具:使用当前 Agent 运行时暴露的内置用户交互工具,如
AskUserQuestion、request_user_input、clarify、ask_user或任何同等工具。 - 保底方案:若不存在上述工具,输出带编号的纯文本消息,引导用户回复对应选项编号或答案。
- 批量提问:若工具支持单次发起多项提问,应将所有相关问题合并为一次调用;若仅支持单问,则按优先级依次提问。
下文提及的 AskUserQuestion 均作为示例说明 —— 在其他 Agent 运行时中请替换为相对应的本地实现。
前置条件
快速验证环境:wx --version 有输出且 wx sessions 返回数据即可继续。任何一步失败,或是首次在新环境运行 → 读 references/setup.md(完整环境检查、wx-cli 命令速查、排障手册),停在第一个失败项并给用户确切的修复命令。绝不自动安装、绝不替用户跑 sudo。
偏好设置 (EXTEND.md)
按以下优先级顺序检查 EXTEND.md 配置文件 —— 以首次找到的文件为准:
| 优先级 | 文件路径 | 作用域 |
|---|---|---|
| 1 | .baoyu-skills/baoyu-wechat-summary/EXTEND.md(相对于项目根目录) |
项目 (Project) |
| 2 | ${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-wechat-summary/EXTEND.md |
XDG 规范 |
| 3 | $HOME/.baoyu-skills/baoyu-wechat-summary/EXTEND.md |
用户家目录 |
| 检查结果 | 执行动作 |
|---|---|
| 已找到 | 读取、解析并应用偏好设置。会话中首次使用时,简要提醒:“正在使用来自 [path] 的偏好设置。可编辑该文件以修改默认配置。” |
| 未找到 | 生成简报前必须运行首次初始化设置(阻塞流程)—— 切勿静默使用默认值。 |
支持的配置项 (Keys)
EXTEND.md 为纯文本文件,支持 key: value 或 key=value 格式,以 # 表示注释,配置项不区分大小写。
| 配置项 | 类型 | 默认值 | 用途 |
|---|---|---|---|
self_wxid |
string | (必填) | 当前账号的 wxid。from_wxid 匹配该值的消息将被认定为用户本人所发。 |
self_display |
string | (必填) | 在简报正文中替换用户本人消息时显示的名称。 |
default_version |
normal / roast / both |
normal |
当用户未明确指定时默认生成的简报版本。 |
default_time_range |
string(例如 7d、24h、1d) |
(无) | 当用户未说明时间范围且没有增量锚点时的默认时间跨度。 |
data_root |
path | {project_root}/wechat |
自定义简报保存目录。 |
bot_aliases |
逗号分隔字符串 | bot, 精华bot |
触发「@bot 答疑」板块的唤醒词。当消息包含 @<别名>(不区分大小写)时,会被视作向简报 Bot 提出的疑问/请求。请确保选择的名称不会与实际群成员或已有 Bot 冲突,以防混淆。 |
入门模板见 EXTEND.md.example。
首次设置(阻塞流程)
若未找到 EXTEND.md,绝不可静默跳过。
步骤 A —— 优先尝试自动探测 self_wxid 与 self_display。 按顺序执行以下命令(遇到首个成功的即止):
# 1. 若 wx-cli 支持 whoami 命令,优先使用
wx whoami --json 2>/dev/null
# 2. 否则,在最近会话中查找自己发送过的消息
wx sessions --json --limit 20 2>/dev/null
对于方法 2,扫描用户发言过的私聊或群聊会话,读取一组用户自己的 from_wxid / from_nickname 匹配对。如果你有把握预填这两个值,可将其设为下方提问的默认值;否则留空交由用户手动填写。
步骤 B —— 调用一次 AskUserQuestion 进行批量确认,并将自动探测获取的信息作为预填项:
self_wxid(例如wxid_abc123)—— 备用提示:用户可通过wx contacts --query "<本人昵称>"查询,或在wx sessions --json中检查自己发送过的任意消息获取self_display(例如宝玉)—— 在简报中希望自己的发言归属显示的名称default_version—— 选择normal/roast/both之一data_root—— 简报文件夹存放路径。默认值:{project_root}/wechat。可输入自定义绝对路径(如~/Documents/wechat-digests),或留空使用默认值。- 保存位置 —— 选择 project / XDG / home 之一
将 EXTEND.md 写入所选路径。若用户提供了非默认的 data_root,请将其作为未注释的一行写入;否则直接省略(自动生效默认值)。确认提示:“偏好设置已保存至 [path]。可随时编辑该文件修改默认配置。”,随后继续执行简报生成流程。
Workflow
步骤 1:解析用户需求
提取以下信息:
- 群名称(或用于模糊匹配的名称片段)
- 时间范围 —— 灵活理解各种表述:
- “最近 1 天” / “今天” / “last 24 hours” → 1 天
- “最近 3 天” → 3 天
- “最近 7 天” / “这周” → 7 天
- “最近 30 天” / “最近一个月” → 30 天
- “某天”(例如“3 月 5 号”)→ 特定日期
- “某天到某天”(例如“3 月 1 号到 3 月 5 号”)→ 日期区间
- “从上次开始” / “继续” / “接着上次” / “since last” → 增量模式:读取该群的
history.json,使用last_digest.last_message_time作为起始时间 - 未指定时间范围 → 增量模式。若尚未建立
history.json,则优先回退到 EXTEND.md 中的default_time_range(若已配置),否则默认取最近 24 小时。
- 需生成的版本:
- 以 EXTEND.md 中的
default_version为基准。 - 用户指令优先覆盖:关键词“毒舌”/“roast”/“挑衅”/“再来个毒的”/“sass” → 强制设为
include_roast=true;关键词“只要正经的”/“normal only”/“不要毒舌” → 强制设为include_normal=true, include_roast=false;关键词“都来一份”/“两个版本都要”/“both” → 两个版本均生成。 - 最终必须保证
include_normal和include_roast中至少有一个为 true。
- 以 EXTEND.md 中的
结合当前本地日期,将相对时间跨度转换为绝对时间参数对 --since YYYY-MM-DD --until YYYY-MM-DD。
步骤 2:查找群聊并确定文件夹路径
wx contacts --query "<group_name>" --json
筛选 username 以 @chatroom 结尾的条目。若匹配到多个群聊,使用 AskUserQuestion 让用户确认选择;若未匹配到任何群聊,在询问用户前回退至 wx sessions --json 进行搜索。
查找确定后,计算文件夹路径:
{data_root}/{group_id}-{sanitized_group_name}/
其中 data_root 取自 EXTEND.md(默认值为 {project_root}/wechat)。
群名称合法化处理 (Sanitize) —— 将任意 / \ : * ? " < > | NUL 及控制字符替换为 _。去除末尾的句点和空格。注意:切勿剥离表情符号 (Emoji) 或中文字符。
群改名检测:列出 {data_root}/ 下已有的文件夹,查找是否存在以 {group_id}- 开头的目录。若存在但后缀不同(说明群名称修改过),则将已有文件夹重命名为新的 {group_id}-{sanitized_new_name} 格式。若新名称对应的目标文件夹已存在(极少见),则保留两者,并在本次运行中优先使用已存在的那个。
Step 2.5: Look up the group owner(群主)
群主是谁必须有据可查,不能凭历史摘要、群友玩笑或印象推断(群主可能换届,历史摘要里的说法会过期):
wx members "<group_name_or_id>" --json
- 检查输出中是否有 owner / role 字段标识群主;有则以此为准
- 如果 wx-cli 版本不暴露群主信息,则查 memory.md「群基本档案」里有出处的记录;两处都没有 → 摘要里不要断言谁是群主
- 查到的结果与「群基本档案」不一致时以本次查询为准,更新档案并追加修订记录(注明查询日期)
步骤 3:获取消息记录
务必将获取的消息重定向保存至 $TMPDIR 临时文件 —— 该文件是本次运行的唯一事实来源 (Single source of truth):Round 3 的归属审计会 grep 检索它,统计数据也由其计算得出。切勿仅凭对话记忆撰写简报。
对于小批量消息(单日简报,通常 < 200 条),你也可以额外将 JSON 结果直接 Pipe 管道输入给 Agent 读取:
wx history "<group_name_or_id>" --since YYYY-MM-DD --until YYYY-MM-DD -n 5000 --json
对于大批量消息(周报 / 月报,> 200 条),重定向到 $TMPDIR 还可以防止原始数据占用对话上下文空间:
wx history "<group_name_or_id>" --since YYYY-MM-DD --until YYYY-MM-DD -n 5000 --json > "$TMPDIR/wx-messages.json"
wc -c "$TMPDIR/wx-messages.json"
jq 'length' "$TMPDIR/wx-messages.json"
随后使用带有 offset + limit 参数的 Read 分片读取文件,或使用 jq 查询处理(例如 jq '.[0:200]',或通过 jq '[.[] | {id, from_nickname, timestamp, content: (.content | .[0:50])}]' 进行轻量级骨架扫描)。一次性读取所有 500+ 条消息会造成不必要的 Token 浪费。
注意事项:
--since为包含边界;--until会被解析为日期(覆盖整天)。若用户要求“仅限今天”,将两者均设为今天。-n 5000为防御性数量上限;对于极其活跃的群,可提高上限后重新获取。- 稳妥起见,对返回消息按
timestamp进行二次过滤(部分 Daemon 可能会返回邻近日期的消息)。 - 时间跨度拆分:对于跨度 > 7 天或消息量 > 500 条的情况,优先按每 3 天生成一份简报然后再进行汇总摘要 (Meta-summary),而不是硬凑一份巨型简报 —— 跨越一周以上的不相关话题会导致分类质量大幅下降。
增量模式:获取消息后,剔除所有 timestamp <= history.json 中 last_message_time 的消息,并将过滤后的集合写回 $TMPDIR 文件(确保审计与统计精准覆盖简报涉及的内容)。注意:last_message_time 格式为 MM-DD HH:MM —— 纯字符串比较会在跨年时失效(如 12-31 与 01-01);此处需结合日期语义比较。若筛选后剩余 0 条消息,提示用户“上次摘要后没有新消息,已跳过生成”并退出。
步骤 3.5:解析消息结构 Schema
wx history --json 会返回一个消息对象数组。请根据实际存在的字段进行解析,容忍缺失字段:
id/msg_id/local_id—— 消息唯一标识符(使用 wx-cli 输出的相应字段)。搭建骨架时,可在工作笔记中引用这些 ID 作为定位锚点。from_wxid—— 稳定唯一的发送者标识符from_nickname—— 显示名称(可能是群名片备注或原始昵称)content—— 文本载荷。常见示例:- 纯文本 → 直接使用
[图片]→ 不透明占位符;详见下文的图片处理说明[表情]→ 表情包;除非被上下文讨论包围,否则在正文中跳过[视频]/[文件]→ 媒体文件引用;除非引发讨论,否则跳过[链接] <标题>或[链接/文件] <标题>→ 分享的文章;标题即核心信息 —— 需引用标题并注明分享者
<!-- truncated for translation batch; full body continues in source -->



