baoyu-wechat-summary

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

WeChat Group Summary

微信群聊总结

群聊精华提取专家。把零散的微信群聊记录提炼成结构化、可读性强的简报,并维护跨次运行的群聊历史与群友画像。底层依赖外部 wx-cli 二进制(
wx
命令),不打包脚本。
⚠️ Sandbox restriction
wx-cli reads from
~/.wx-cli/
(config, cache, daemon socket) and from WeChat's data directory (
~/Library/Containers/com.tencent.xinWeChat/
on macOS). Both paths are outside Claude Code's default sandbox. Every
wx
command in this skill needs to run with
dangerouslyDisableSandbox: true
from the start — don't waste a sandbox attempt first. The user can use
/sandbox
to view/edit restrictions.
群聊精华提取专家。把零散的微信群聊记录提炼成结构化、可读性强的简报,并维护跨次运行的群聊历史与群友画像。底层依赖外部 wx-cli 二进制(
wx
命令),不打包脚本。
⚠️ 沙箱限制
wx-cli 读取
~/.wx-cli/
(配置、缓存、守护进程套接字)和微信数据目录(macOS 上为
~/Library/Containers/com.tencent.xinWeChat/
)。这两个路径均在 Claude Code 默认沙箱之外。本技能中的所有
wx
命令从一开始就需要以
dangerouslyDisableSandbox: true
参数运行——不要先尝试默认沙箱,以免浪费机会。用户可使用
/sandbox
命令查看/编辑沙箱限制。

User Input Tools

用户输入工具

When this skill prompts the user, follow this tool-selection rule (priority order):
  1. Prefer built-in user-input tools exposed by the current agent runtime — e.g.,
    AskUserQuestion
    ,
    request_user_input
    ,
    clarify
    ,
    ask_user
    , or any equivalent.
  2. Fallback: if no such tool exists, emit a numbered plain-text message and ask the user to reply with the chosen number/answer for each question.
  3. Batching: if the tool supports multiple questions per call, combine all applicable questions into a single call; if only single-question, ask them one at a time in priority order.
Concrete
AskUserQuestion
references below are examples — substitute the local equivalent in other runtimes.
当本技能需要提示用户时,请遵循以下工具选择规则(优先级从高到低):
  1. 优先使用当前Agent运行时提供的内置用户输入工具——例如
    AskUserQuestion
    request_user_input
    clarify
    ask_user
    或任何等效工具。
  2. 备选方案:如果没有此类工具,则输出带编号的纯文本消息,要求用户回复所选编号/答案以回答每个问题。
  3. 批量处理:如果工具支持单次调用包含多个问题,则将所有适用问题合并为单次调用;如果仅支持单个问题,则按优先级顺序逐个询问。
以下具体的
AskUserQuestion
引用为示例——在其他运行时中请替换为本地等效工具。

Prerequisites

前置条件

Before invoking the workflow, verify the environment. Run these checks in order; stop at the first failure and surface the exact next command the user needs.
  1. wx-cli installed — run
    wx --version
    . If missing, tell the user to install it themselves (
    npm install -g @jackwener/wx-cli
    or use one of the alternatives at https://github.com/jackwener/wx-cli). Do NOT auto-install — this repo forbids piped/silent installs.
  2. ~/.wx-cli
    directory owned by the current user
    sudo wx init
    historically chowned this directory to root, which breaks every subsequent non-sudo
    wx
    call. Check:
    bash
    ls -la ~/.wx-cli/ 2>/dev/null | head -5
    If the directory exists but the owner is
    root
    (or anything other than
    $(whoami)
    ), tell the user to repair it themselves:
    bash
    sudo chown -R $(whoami) ~/.wx-cli
    sudo rm -f ~/.wx-cli/daemon.pid ~/.wx-cli/daemon.sock
    wx daemon start
    The skill should NOT run
    sudo
    on the user's behalf.
  3. wx-cli initialized
    wx sessions
    should return data. If it fails with "no keys" / "init required", instruct the user to run
    wx init
    while WeChat is running (on macOS,
    codesign --force --deep --sign - /Applications/WeChat.app
    first). Prefer non-sudo init; only fall back to
    sudo wx init
    if the user's wx-cli version requires it — and warn them that they'll need step 2's chown after.
  4. WeChat 4.x running and logged in — required for the daemon to find data files.
在调用工作流之前,请验证环境。按顺序执行以下检查;若首次检查失败,则停止并告知用户需要执行的具体下一步命令。
  1. 已安装wx-cli——运行
    wx --version
    。若未安装,请告知用户自行安装(
    npm install -g @jackwener/wx-cli
    或使用 https://github.com/jackwener/wx-cli 提供的其他安装方式)。请勿自动安装——本仓库禁止管道式/静默安装。
  2. ~/.wx-cli
    目录归当前用户所有
    ——历史上使用
    sudo wx init
    会将该目录的所有者设置为root,这会导致后续所有非sudo的
    wx
    调用失败。检查命令:
    bash
    ls -la ~/.wx-cli/ 2>/dev/null | head -5
    如果目录存在但所有者为
    root
    (或非当前用户
    $(whoami)
    ),请告知用户自行修复:
    bash
    sudo chown -R $(whoami) ~/.wx-cli
    sudo rm -f ~/.wx-cli/daemon.pid ~/.wx-cli/daemon.sock
    wx daemon start
    本技能不得代表用户运行
    sudo
    命令。
  3. wx-cli已初始化——
    wx sessions
    应返回数据。若失败并提示“no keys”/“init required”,请指导用户在微信运行时执行
    wx init
    (在macOS上,需先执行
    codesign --force --deep --sign - /Applications/WeChat.app
    )。优先使用非sudo初始化;仅当用户的wx-cli版本要求时,才退而使用
    sudo wx init
    ——并警告用户之后需要执行步骤2的chown命令。
  4. 微信4.x已运行并登录——这是守护进程找到数据文件的必要条件。

Preferences (EXTEND.md)

偏好设置(EXTEND.md)

Check EXTEND.md in priority order — the first one found wins:
PriorityPathScope
1
.baoyu-skills/baoyu-wechat-summary/EXTEND.md
(relative to project root)
Project
2
${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-wechat-summary/EXTEND.md
XDG
3
$HOME/.baoyu-skills/baoyu-wechat-summary/EXTEND.md
User home
ResultAction
FoundRead, parse, apply. On first use in session, briefly remind: "Using preferences from [path]. Edit it to change defaults."
Not foundMUST run first-time setup (BLOCKING) before generating any digest — do NOT silently use defaults.
按优先级顺序检查EXTEND.md——找到的第一个文件生效:
优先级路径作用域
1
.baoyu-skills/baoyu-wechat-summary/EXTEND.md
(相对于项目根目录)
项目级
2
${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-wechat-summary/EXTEND.md
XDG标准
3
$HOME/.baoyu-skills/baoyu-wechat-summary/EXTEND.md
用户主目录
结果操作
找到文件读取、解析并应用配置。在会话中首次使用时,简要提示:“正在使用[路径]中的偏好设置。编辑该文件可修改默认配置。”
未找到文件必须先完成首次设置(阻塞式),再生成任何摘要——不得静默使用默认值。

Supported keys

支持的配置项

EXTEND.md is plain text with
key: value
or
key=value
lines,
#
for comments, case-insensitive keys.
KeyTypeDefaultPurpose
self_wxid
string(required)The owning account's wxid. Messages whose
from_wxid
matches this are attributed to the user.
self_display
string(required)Display name to substitute for the user's own messages in digest text.
default_version
normal
/
roast
/
both
normal
Which version(s) to generate when the user doesn't say otherwise.
default_time_range
string (e.g.
7d
,
24h
,
1d
)
(none)Default range when the user omits time and there's no incremental anchor.
data_root
path
{project_root}/wechat
Override where digest folders live.
A starter template lives at EXTEND.md.example.
EXTEND.md为纯文本文件,采用
key: value
key=value
格式,
#
用于注释,配置项名称不区分大小写。
配置项类型默认值用途
self_wxid
字符串必填当前账号的wxid。
from_wxid
与此值匹配的消息将归属于用户本人。
self_display
字符串必填在摘要文本中替换用户本人消息的显示名称。
default_version
normal
/
roast
/
both
normal
用户未指定时,默认生成的版本类型。
default_time_range
字符串(例如
7d
24h
1d
用户未指定时间范围且无增量锚点时的默认时间范围。
data_root
路径
{project_root}/wechat
覆盖摘要文件的存储目录。
入门模板可参考 EXTEND.md.example

First-Time Setup (BLOCKING)

首次设置(阻塞式)

If no EXTEND.md is found, do NOT silently proceed.
Step A — Try to auto-discover
self_wxid
and
self_display
first.
Run (in order, stop at the first that succeeds):
bash
undefined
若未找到EXTEND.md,不得静默继续执行。
步骤A — 先尝试自动发现
self_wxid
self_display
。按顺序执行命令,首次成功即停止:
bash
undefined

1. If wx-cli exposes a whoami, use it

1. 如果wx-cli提供whoami命令,则使用它

wx whoami --json 2>/dev/null
wx whoami --json 2>/dev/null

2. Otherwise, find self-sent messages in recent sessions

2. 否则,在最近的会话中查找用户发送的消息

wx sessions --json --limit 20 2>/dev/null

For option 2, scan the sessions for any private/group thread the user has sent into and read one of their own `from_wxid` / `from_nickname` pairs. If you can confidently pre-fill both values, use them as defaults in the question below; otherwise leave the fields blank for the user to fill in.

**Step B — Confirm with one `AskUserQuestion` call (batched), pre-filling whatever auto-discovery found:**

- `self_wxid` (e.g., `wxid_abc123`) — fall-back hint: the user can find it with `wx contacts --query "<own nickname>"`, or by inspecting any of their own sent messages in `wx sessions --json`
- `self_display` (e.g., `宝玉`) — how they want their messages attributed
- `default_version` — pick one of `normal` / `roast` / `both`
- `data_root` — where digest folders live. Default: `{project_root}/wechat`. Enter a custom absolute path (e.g. `~/Documents/wechat-digests`) or leave blank for default.
- Save location — pick one of project / XDG / home

Write EXTEND.md to the chosen path. If the user provided a non-default `data_root`, include it as an uncommented line; otherwise omit it (the default applies automatically). Confirm "Preferences saved to [path]. Edit it any time to change defaults.", then continue with the digest workflow.
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`)或留空使用默认值。
- 保存位置——从项目级/XDG标准/用户主目录中选择一个

将EXTEND.md写入所选路径。如果用户提供了非默认的 `data_root`,将其作为未注释的行添加到文件中;否则省略(自动使用默认值)。确认“偏好设置已保存至[路径]。随时编辑该文件可修改默认配置。”,然后继续执行摘要工作流。

Workflow

工作流

Step 1: Parse the user's request

步骤1:解析用户请求

Extract:
  • Group name (or partial name for fuzzy matching)
  • Time range — interpret flexibly:
    • "最近 1 天" / "今天" / "last 24 hours" → 1 day
    • "最近 3 天" → 3 days
    • "最近 7 天" / "这周" → 7 days
    • "最近 30 天" / "最近一个月" → 30 days
    • "某天" (e.g. "3 月 5 号") → that specific date
    • "某天到某天" (e.g. "3 月 1 号到 3 月 5 号") → date range
    • "从上次开始" / "继续" / "接着上次" / "since last" → incremental mode: read
      history.json
      for this group, use
      last_digest.last_message_time
      as the start
    • No time specified → incremental mode. If no
      history.json
      exists yet, fall back to
      default_time_range
      from EXTEND.md if set, else last 24 hours.
  • Version(s) to generate:
    • Start from
      default_version
      in EXTEND.md.
    • User request overrides: keywords "毒舌"/"roast"/"挑衅"/"再来个毒的"/"sass" → force
      include_roast=true
      . Keywords "只要正经的"/"normal only"/"不要毒舌" → force
      include_normal=true, include_roast=false
      . "都来一份"/"两个版本都要"/"both" → both.
    • At least one of
      include_normal
      /
      include_roast
      must end up true.
Convert relative ranges into absolute
--since YYYY-MM-DD --until YYYY-MM-DD
pairs using today's local date.
提取以下信息:
  • 群组名称(或用于模糊匹配的部分名称)
  • 时间范围——灵活解读:
    • "最近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
      中的一个。
使用本地日期将相对时间范围转换为绝对的
--since YYYY-MM-DD --until YYYY-MM-DD
参数对。

Step 2: Find the group + resolve folder path

步骤2:查找群组并解析目录路径

bash
wx contacts --query "<group_name>" --json
Filter for entries whose
username
ends in
@chatroom
. If multiple groups match, use
AskUserQuestion
to disambiguate. If none match, fall back to
wx sessions --json
and search there before asking the user.
Once resolved, compute the folder path:
{data_root}/{group_id}-{sanitized_group_name}/
where
data_root
is from EXTEND.md (default
{project_root}/wechat
).
Sanitize the group name — replace any of
/ \ : * ? " < > | NUL
and control characters with
_
. Trim trailing dots and whitespace. Don't strip emoji or Chinese characters.
Group-rename detection: list existing folders under
{data_root}/
and find any folder whose name starts with
{group_id}-
. If one exists but the suffix differs (group was renamed), rename the existing folder to the new
{group_id}-{sanitized_new_name}
form. If a target with the new name already exists (rare), keep both and prefer the existing one for this run.
bash
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
)。
群组名称清理——将
/ \ : * ? " < > | NUL
及控制字符替换为
_
。删除末尾的点号和空白字符。保留表情符号和中文字符。
群组重命名检测:列出
{data_root}/
下的现有目录,查找任何以
{group_id}-
开头的目录。如果目录存在但后缀不同(群组已重命名),将现有目录重命名为新的
{group_id}-{sanitized_new_name}
格式。如果新名称的目录已存在(罕见情况),则保留两个目录,并在本次运行中优先使用现有目录。

Step 3: Fetch messages

步骤3:获取消息

For small batches (single-day digest, typically < 200 messages), pipe JSON into the agent directly:
bash
wx history "<group_name_or_id>" --since YYYY-MM-DD --until YYYY-MM-DD -n 5000 --json
For large batches (weekly / monthly digests, > 200 messages), redirect to
$TMPDIR
first so the raw payload never sits in conversation context:
bash
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"
Then read the file in slices via
Read
with
offset
+
limit
, or process with
jq
queries (e.g.
jq '.[0:200]'
,
jq '[.[] | {id, from_nickname, timestamp, content: (.content | .[0:50])}]'
for a lightweight skeleton pass). Reading all 500+ messages at once will burn token budget unnecessarily.
Notes:
  • --since
    is inclusive;
    --until
    is interpreted as a date (the whole day). If the user asked for "today only", set both to today.
  • -n 5000
    is a defensive cap; for very active groups, raise it and re-fetch.
  • Filter the returned messages by their
    timestamp
    to be safe (some daemons may return adjacent days).
  • Range splitting: for ranges > 7 days OR > 500 messages, prefer generating per-3-day digests and then a meta-summary over forcing one giant digest — the categorization quality degrades sharply past a week's worth of unrelated topics.
Incremental mode: after the fetch, drop any message whose
timestamp
is
<=
the
last_message_time
from
history.json
. If zero messages remain, tell the user "上次摘要后没有新消息,已跳过生成" and exit.
对于小批量消息(单日摘要,通常少于200条),直接将JSON输出传递给Agent:
bash
wx history "<group_name_or_id>" --since YYYY-MM-DD --until YYYY-MM-DD -n 5000 --json
对于大批量消息(每周/每月摘要,超过200条),先将输出重定向到
$TMPDIR
,避免原始数据占用对话上下文:
bash
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"
然后通过
Read
工具结合
offset
+
limit
分片读取文件,或使用
jq
查询处理(例如
jq '.[0:200]'
jq '[.[] | {id, from_nickname, timestamp, content: (.content | .[0:50])}]'
生成轻量骨架)。一次性读取500条以上消息会不必要地消耗token配额。
注意事项:
  • --since
    为包含性;
    --until
    被解析为日期(全天)。如果用户要求“仅限今天”,则将两者都设置为今天。
  • -n 5000
    是防御性上限;对于非常活跃的群组,可提高该值并重试获取。
  • 为确保安全,根据消息的
    timestamp
    过滤返回的消息(部分守护进程可能返回相邻日期的消息)。
  • 范围拆分:对于超过7天或超过500条消息的时间范围,优先生成每3天的摘要,再生成汇总摘要——超过一周的无关话题会导致分类质量急剧下降。
增量模式:获取消息后,删除所有
timestamp
小于等于
history.json
last_message_time
的消息。如果没有剩余消息,告知用户“上次摘要后没有新消息,已跳过生成”并退出。

Step 3.5: Parse the message schema

步骤3.5:解析消息结构

wx history --json
returns an array of message objects. Use the fields that are present; tolerate missing fields:
  • id
    /
    msg_id
    /
    local_id
    — message identifier (use whichever wx-cli emits). Reference IDs in working notes as anchors when building the skeleton.
  • from_wxid
    — stable sender identifier
  • from_nickname
    — display name (may be the group remark or original nickname)
  • content
    — text payload. Examples:
    • Plain text → use as-is
    • [图片]
      → opaque placeholder; see image handling below
    • [表情]
      → emoji/sticker; skip in body unless surrounded by discussion
    • [视频]
      /
      [文件]
      → media reference; skip unless discussed
    • [链接] <title>
      or
      [链接/文件] <title>
      → shared article; the title IS the information — quote it and credit the sharer
    • [系统] ... revokemsg
      → revoked; exclude from digest and from leaderboard
  • timestamp
    — convert to
    MM-DD HH:MM
    for display (and use full ISO for
    generated_at
    )
  • chat_type
    — sanity-check
    group
  • Quote/reply — try
    quote_id
    ,
    reply_to
    ,
    quoted_msg_id
    , or any nested
    quote
    object. If present, use it as strong attribution. If absent, fall back to context but flag the inferred link as uncertain.
wx history --json
返回消息对象数组。使用存在的字段;容忍缺失的字段:
  • id
    /
    msg_id
    /
    local_id
    ——消息标识符(使用wx-cli输出的任意一个)。构建骨架时,在工作笔记中引用这些ID作为锚点。
  • from_wxid
    ——稳定的发送者标识符
  • from_nickname
    ——显示名称(可能是群备注或原始昵称)
  • content
    ——文本内容。示例:
    • 纯文本 → 直接使用
    • [图片]
      → 不透明占位符;见下文图片处理
    • [表情]
      → 表情/贴纸;除非有相关讨论,否则在正文中跳过
    • [视频]
      /
      [文件]
      → 媒体引用;除非有相关讨论,否则跳过
    • [链接] <title>
      [链接/文件] <title>
      → 分享的文章;标题即为信息——引用标题并注明分享者
    • [系统] ... revokemsg
      → 已撤回消息;从摘要和排行榜中排除
  • timestamp
    ——转换为
    MM-DD HH:MM
    格式显示(
    generated_at
    使用完整ISO格式)
  • chat_type
    ——检查是否为群组聊天
  • 引用/回复——尝试查找
    quote_id
    reply_to
    quoted_msg_id
    或任何嵌套的
    quote
    对象。如果存在,将其作为强归属依据。如果不存在,则依赖上下文,但在工作笔记中标记推断的关联为不确定。

Step 3.6: Resolve self + ambiguous nicknames

步骤3.6:解析本人及模糊昵称

  • Substitute
    self_display
    for every message whose
    from_wxid
    matches
    self_wxid
    (from EXTEND.md). Apply this in the leaderboard, portraits, and body text. The user MUST appear under their real display name and count toward stats — never skip them.
  • Scan all unique senders for ambiguous handles: ≤2 characters, common programming words (
    nil
    ,
    null
    ,
    test
    ,
    admin
    ,
    user
    ,
    undefined
    ), single emoji, or otherwise low-information. For each, run
    wx contacts --query "<nick>" --json --limit 5
    and pick a meaningful name in this priority: remark > nickname > wxid. Apply the substitution everywhere in the digest.
  • 对于所有
    from_wxid
    匹配EXTEND.md中
    self_wxid
    的消息,替换为
    self_display
    。该替换应用于排行榜、画像和正文中。用户必须以其真实显示名称出现并计入统计——不得跳过。
  • 扫描所有唯一发送者的模糊昵称:≤2个字符、常见编程词汇(
    nil
    null
    test
    admin
    user
    undefined
    )、单个表情符号或其他信息量低的昵称。对于每个此类昵称,运行
    wx contacts --query "<nick>" --json --limit 5
    ,并按优先级选择有意义的名称:备注 > 昵称 > wxid。将该替换应用于摘要的所有部分。

Step 3.7: Load user profiles

步骤3.7:加载用户画像

For each unique sender appearing in this batch:
  • Look in
    {folder}/profiles/{wxid}-*.md
    by
    wxid
    prefix match. Read the matched file if found.
  • If
    include_roast
    , also look in
    {folder}/profiles-roast/{wxid}-*.md
    for the roast pass.
Compile a condensed profile context block as internal working memory — do NOT write it into the final digest. Example shape:
== 群友历史画像(来自 profiles/)==
K. H:空中直播员 / 生活百科全书。常见话题:旅行、金融、美食。经典金句:"要不要买moderna"。
可可苏玛:...
Rules:
  • Only load profiles for users active in this batch — never preload everyone.
  • Profile is background, not template. Current messages are still the primary source.
  • Use historical labels for continuity ("又双叒叕化身空中直播员") or contrast ("一向省钱的 XX 今天居然...").
  • Strict separation: normal pass reads only
    profiles/
    , roast pass reads only
    profiles-roast/
    . Never cross-load.
See references/profiles.md for the full file format.
对于本次批次中出现的每个唯一发送者:
  • 通过wxid前缀匹配查找
    {folder}/profiles/{wxid}-*.md
    文件。如果找到,读取该文件。
  • 如果启用
    include_roast
    同时
    {folder}/profiles-roast/{wxid}-*.md
    中查找毒舌版画像。
编译一个浓缩的画像上下文块作为内部工作内存——不要写入最终摘要。示例格式:
== 群友历史画像(来自profiles/)==
K. H:空中直播员 / 生活百科全书。常见话题:旅行、金融、美食。经典金句:"要不要买moderna"。
可可苏玛:...
规则:
  • 仅加载本次批次中活跃用户的画像——不要预加载所有用户。
  • 画像为背景信息,而非模板。当前消息仍是主要信息来源。
  • 使用历史标签体现连续性(“又双叒叕化身空中直播员”)或反差(“一向省钱的XX今天居然...”)。
  • 严格分离:普通版仅读取
    profiles/
    ,毒舌版仅读取
    profiles-roast/
    。不得交叉加载。
完整文件格式请参考 references/profiles.md

Step 3.8: Detect existing in-chat digests (optional)

步骤3.8:检测现有群内摘要(可选)

Some users (e.g., the original 宝玉 workflow) post digests directly into the group as messages. If we don't notice these, the new digest will re-cover the same ground.
Scan the fetched messages for signals of a prior in-chat digest:
  • from_wxid == self_wxid
    AND
  • content
    contains
    群聊精华
    OR
    消息统计:
    OR
    📊 消息统计
    OR a leaderboard pattern (e.g.
    ^\d+\. .+: \d+ 条
    ), AND
  • content
    length > 1500 chars.
If a match is found:
  1. Extract the digest's covered date or range from the title line (e.g.,
    xxx 群聊精华 · 2026-05-12
    or
    ... · 2026-05-10 ~ 2026-05-12
    ).
  2. Surface the finding to the user via
    AskUserQuestion
    :
    • "Detected an in-chat digest by you covering {范围}. Use {范围 end + 1} as the start instead of
      history.json
      ?"
    • Options:
      Yes, skip up to {end of detected range}
      /
      No, use history.json
      /
      No, cover everything in the requested range
      .
  3. Apply the chosen anchor.
This is a heuristic — when uncertain (multiple matches, malformed title), default to
history.json
and tell the user what was skipped.
Generate the digest in three rounds so nothing slips through. The methodology stays here in SKILL.md; the content/style rules live in references/output-formats.md — read that file in Round 2 before drafting.
部分用户(例如原始宝玉工作流)会直接将摘要发布到群聊中作为消息。如果未注意到这些摘要,新生成的摘要会重复覆盖相同内容。
扫描获取的消息,查找群内已有摘要的信号:
  • from_wxid == self_wxid
  • content
    包含「群聊精华」或「消息统计:」或「📊 消息统计」或排行榜模式(例如
    ^\d+\. .+: \d+ 条
    ),且
  • content
    长度超过1500字符。
如果找到匹配项:
  1. 从标题行提取摘要覆盖的日期或范围(例如「xxx群聊精华 · 2026-05-12」或「... · 2026-05-10 ~ 2026-05-12」)。
  2. 通过
    AskUserQuestion
    将发现告知用户:
    • “检测到您发布的群内摘要,覆盖范围为{范围}。是否使用{范围结束日期+1}作为起始时间,而非
      history.json
      ?”
    • 选项:「是,跳过至{检测范围结束日期}」/「否,使用history.json」/「否,覆盖请求范围内的所有内容」。
  3. 应用用户选择的锚点。
这是一种启发式方法——当不确定时(多个匹配项、标题格式错误),默认使用
history.json
并告知用户跳过的内容。
分三轮生成摘要,确保无遗漏。方法论记录在SKILL.md中;内容/风格规则记录在 references/output-formats.md 中——在第二轮起草前请阅读该文件。

Round 1 — Build the skeleton

第一轮 — 构建骨架

Read every message in order. Skip image fetching/decoding in this round. List every distinct discussion topic. Bias toward over-listing — trim in Round 3.
Internal working format (not written to the final file):
== 话题清单(共 N 条消息)==
1. [HH:MM-HH:MM] 话题名称(参与者:A, B, C)— 一句话概括(锚点 id:54052, 54055, 54063)
2. [HH:MM-HH:MM] 话题名称(参与者:D, E)— 一句话概括(锚点 id:54100-54112)
...

== 可能需要图片上下文的话题 ==
- 话题 3:锚点 id=49661(图片是讨论主体)

== 发言统计 ==
1. XXX — N 条  2. YYY — N 条  ...
Topic principles:
  • Topic-switch signals: time gap > 30 min, participant change, content jump.
  • 2+ participants OR substantive content qualifies as a topic; pure emoji-banter does not.
  • Strict attribution: each topic must record "who said what". Don't fuse adjacent messages from different senders just because they're close in time — when minutes apart or interleaved with others, split into separate topics. Prefer two topics over one wrongly-merged topic.
  • Carry anchor IDs: list the key message IDs for each topic. In Round 2, jump back to these IDs in the raw messages and verify content, don't guess from context. If
    quote_id
    /
    reply_to
    is present, use the ID chain — that's the most reliable attribution.
Flag-for-images criteria (any one triggers): an explicit comment on an image (
看发型是X?
,
这是谁?
,
笑死
), multiple people piling onto the same image without saying what it is, an image as the core information (晒单/截图/资料), an explanatory line right after an image (
gpt-image-2
,
太可怕了
), or cross-sender ambiguity (B says "这个看着像 X" but the previous image is from A).
按顺序读取每条消息。本轮跳过图片获取/解码。列出所有不同的讨论话题。倾向于多列话题——在第三轮中再进行删减。
内部工作格式(不写入最终文件):
== 话题清单(共N条消息)==
1. [HH:MM-HH:MM] 话题名称(参与者:A, B, C)— 一句话概括(锚点ID:54052, 54055, 54063)
2. [HH:MM-HH:MM] 话题名称(参与者:D, E)— 一句话概括(锚点ID:54100-54112)
...

== 可能需要图片上下文的话题 ==
- 话题3:锚点ID=49661(图片是讨论主体)

== 发言统计 ==
1. XXX — N条  2. YYY — N条  ...
话题原则:
  • 话题切换信号:时间间隔超过30分钟、参与者变化、内容跳转。
  • 至少2名参与者或实质性内容才算作话题;纯表情互动不算。
  • 严格归属:每个话题必须记录“谁说了什么”。不要仅仅因为时间接近就合并不同发送者的相邻消息——如果间隔数分钟或与其他消息交错,应拆分为不同话题。宁愿分两个话题,也不要合并错误的话题。
  • 携带锚点ID:列出每个话题的关键消息ID。在第二轮中,跳转到原始消息中的这些ID并验证内容,不要仅凭上下文猜测。如果存在
    quote_id
    /
    reply_to
    ,使用ID链——这是最可靠的归属依据。
图片标记标准(满足任意一项即触发):对图片的明确评论(「看发型是X?」「这是谁?」「笑死」)、多人针对同一张图片讨论但未说明内容、图片为核心信息(晒单/截图/资料)、图片后紧跟解释性文字(「gpt-image-2」「太可怕了」)或跨发送者歧义(B说「这个看着像X」但上一张图片来自A)。

Round 2 — Flesh out + write the digest

第二轮 — 填充内容并写入摘要

For each topic in the skeleton, jump back to its anchor IDs and expand into full content with quotes and clear attribution. Then write the digest file.
Image handling (limited — wx-cli does not decode chat images):
For each flagged topic, check whether a description file already exists at
{folder}/imgs/{message_id}.txt
. If yes, read it (one-line plain text) and weave its content into the topic. If no, treat the image as opaque (
[图片]
) and write around it — describe what the surrounding messages tell us, but don't invent visual content.
The
imgs/
directory exists as an extension point: a user (or a future wx-cli capability) can drop
{message_id}.txt
files with one-line descriptions, and the skill will pick them up. The skill itself does NOT generate these files in this version.
Use the profile context block (from Step 3.7):
  • Echo continuity for matching behavior ("又双叒叕直播飞行体验")
  • Highlight contrast for departures ("一向话少的 XX 今天突然爆发")
  • Callback past quotes ("继上次'要不要买 moderna'之后,这次又...")
  • Don't sacrifice current material to force a callback.
Writing order: write the body categories first, then the opening overview based on the finished body (so the hook is accurate).
Detailed structure, voice, formatting rules, and content guidelines are in references/output-formats.md. Load that file now if not already loaded.
针对骨架中的每个话题,跳转到其锚点ID,扩展为包含引用和明确归属的完整内容。然后写入摘要文件。
图片处理(有限支持——wx-cli不解码聊天图片):
对于每个标记的话题,检查
{folder}/imgs/{message_id}.txt
是否存在描述文件。如果存在,读取文件内容(单行纯文本)并将其融入话题内容。如果不存在,则将图片视为不透明的
[图片]
,围绕其进行描述——根据周围消息说明讨论的内容,但不要编造视觉信息。
imgs/
目录是一个扩展点:用户(或未来的wx-cli功能)可将包含单行描述的
{message_id}.txt
文件放入该目录,本技能会自动读取。本版本技能本身不会生成这些文件。
使用画像上下文块(来自步骤3.7):
  • 呼应匹配行为的连续性(「又双叒叕直播飞行体验」)
  • 突出与以往行为的反差(「一向话少的XX今天突然爆发」)
  • 回调过往金句(「继上次'要不要买moderna'之后,这次又...」)
  • 不要为了强行回调而牺牲当前内容。
写作顺序:先写正文分类内容,再根据完成的正文写开头概述(确保引言准确)。
详细的结构、语气、格式规则和内容指南请参考 references/output-formats.md。如果尚未加载,请立即加载该文件。

Round 3 — Audit

第三轮 — 审核

Walk the Round 1 skeleton against the finished digest. Check:
  • Any listed topic missing from the digest?
  • Quotes, names, product/tool names preserved verbatim?
  • Categorization makes sense — is anything in the wrong bucket?
Fix in place. When clean, confirm and proceed.
将第一轮的骨架与完成的摘要进行比对。检查:
  • 是否有列出的话题未包含在摘要中?
  • 引用、名称、产品/工具名称是否保留原文?
  • 分类是否合理——是否有内容放错分类?
就地修复。确认无误后继续执行。

Step 7: Save the digest file(s)

步骤7:保存摘要文件

If
include_normal
:
  • Single date →
    {folder}/YYYY-MM-DD.md
  • Date range →
    {folder}/YYYY-MM-DD_YYYY-MM-DD.md
  • Overwrite if the same date/range already exists.
If
include_roast
:
  • Same naming, but with
    -roast
    suffix:
    YYYY-MM-DD-roast.md
    or
    YYYY-MM-DD_YYYY-MM-DD-roast.md
    .
Both versions share the same statistics (message count, leaderboard) and the same underlying skeleton.
如果启用
include_normal
  • 单日 →
    {folder}/YYYY-MM-DD.md
  • 日期范围 →
    {folder}/YYYY-MM-DD_YYYY-MM-DD.md
  • 如果相同日期/范围的文件已存在,则覆盖。
如果启用
include_roast
  • 命名规则相同,但添加
    -roast
    后缀:
    YYYY-MM-DD-roast.md
    YYYY-MM-DD_YYYY-MM-DD-roast.md
两个版本共享相同的统计信息(消息数量、排行榜)和底层骨架。

Step 8: Save history (two files)

步骤8:保存历史记录(两个文件)

Maintain two files in the group folder:
在群组目录中维护两个文件:

history.json
— single record, fast read

history.json
— 单条记录,快速读取

Always reflects only the most recent normal digest. Overwrite on each run when
include_normal=true
.
json
{
  "group_id": "12345678901@chatroom",
  "group_name": "相亲相爱一家人",
  "folder": "12345678901@chatroom-相亲相爱一家人",
  "last_digest": {
    "file": "2026-03-12.md",
    "date_range": "2026-03-12",
    "generated_at": "2026-03-12T10:30:00+08:00",
    "message_count": 150,
    "last_message_time": "03-12 18:45"
  }
}
  • group_name
    updates on every run (handles renames).
  • folder
    records the current folder basename for cross-reference.
  • last_message_time
    is the timestamp of the most recent message included, in
    MM-DD HH:MM
    — used by incremental mode.
  • Roast-only runs do NOT touch this file.
始终仅反映最新的普通版摘要。当
include_normal=true
时,每次运行都会覆盖该文件。
json
{
  "group_id": "12345678901@chatroom",
  "group_name": "相亲相爱一家人",
  "folder": "12345678901@chatroom-相亲相爱一家人",
  "last_digest": {
    "file": "2026-03-12.md",
    "date_range": "2026-03-12",
    "generated_at": "2026-03-12T10:30:00+08:00",
    "message_count": 150,
    "last_message_time": "03-12 18:45"
  }
}
  • group_name
    在每次运行时更新(处理群组重命名)。
  • folder
    记录当前目录的基名,用于交叉引用。
  • last_message_time
    是包含的最新消息的时间戳,格式为
    MM-DD HH:MM
    ——供增量模式使用。
  • 仅生成毒舌版的运行不会修改此文件。

history-digests.jsonl
— append-only archive

history-digests.jsonl
— 追加式归档

One JSON object per line, same shape as
last_digest
. Every normal-version run appends one line (in chronological order). Used by backfill and historical lookups. Never read for incremental mode (which only needs the latest).
jsonl
{"file":"2026-03-10.md","date_range":"2026-03-10","generated_at":"2026-03-10T09:00:00+08:00","message_count":420,"last_message_time":"03-10 22:30"}
{"file":"2026-03-11.md","date_range":"2026-03-11","generated_at":"2026-03-11T09:05:00+08:00","message_count":312,"last_message_time":"03-11 23:10"}
{"file":"2026-03-12.md","date_range":"2026-03-12","generated_at":"2026-03-12T10:30:00+08:00","message_count":150,"last_message_time":"03-12 18:45"}
If a normal digest with the same
file
name is regenerated, append a new line anyway (the JSONL is a strict log; readers can dedupe by
file
if they need to).
每行一个JSON对象,格式与
last_digest
相同。每次普通版运行都会追加一行(按时间顺序)。供回溯和历史查询使用。增量模式不会读取此文件(仅需最新记录)。
jsonl
{"file":"2026-03-10.md","date_range":"2026-03-10","generated_at":"2026-03-10T09:00:00+08:00","message_count":420,"last_message_time":"03-10 22:30"}
{"file":"2026-03-11.md","date_range":"2026-03-11","generated_at":"2026-03-11T09:05:00+08:00","message_count":312,"last_message_time":"03-11 23:10"}
{"file":"2026-03-12.md","date_range":"2026-03-12","generated_at":"2026-03-12T10:30:00+08:00","message_count":150,"last_message_time":"03-12 18:45"}
如果重新生成了相同文件名的普通版摘要,仍需追加新行(JSONL是严格的日志;读取者可根据
file
去重)。

Step 8.5: Update user profiles

步骤8.5:更新用户画像

For each user with 3+ messages in this batch who appeared in the 群友画像 section:
  • If
    include_normal
    , update
    {folder}/profiles/{wxid}-{nickname}.md
    .
  • If
    include_roast
    , update
    {folder}/profiles-roast/{wxid}-{nickname}.md
    .
Counts, frontmatter updates, append-only rules for quotes and events, and privacy guardrails are detailed in references/profiles.md. Load that file when running this step.
对于本次批次中发言3条以上且出现在群友画像部分的每个用户:
  • 如果启用
    include_normal
    ,更新
    {folder}/profiles/{wxid}-{nickname}.md
  • 如果启用
    include_roast
    ,更新
    {folder}/profiles-roast/{wxid}-{nickname}.md
统计计数、前置更新、金句和事件的追加规则以及隐私防护机制详细记录在 references/profiles.md 中。执行此步骤时请加载该文件。

Completion checklist

完成检查清单

Profile updates are easy to forget once the digest is on disk. Before reporting the run as "done", verify every applicable file:
  • {folder}/YYYY-MM-DD.md
    written (if
    include_normal
    )
  • {folder}/YYYY-MM-DD-roast.md
    written (if
    include_roast
    )
  • {folder}/history.json
    overwritten with the new
    last_digest
    (if
    include_normal
    )
  • {folder}/history-digests.jsonl
    appended one line (if
    include_normal
    )
  • {folder}/profiles/{wxid}-*.md
    updated for every user with 3+ messages (if
    include_normal
    )
  • {folder}/profiles-roast/{wxid}-*.md
    updated for every user with 3+ messages (if
    include_roast
    )
If any item is unchecked, finish it before declaring success. Don't ship a digest with a stale
history.json
— incremental mode depends on it.
摘要写入磁盘后,很容易忘记更新画像。在报告运行“完成”之前,请验证所有适用文件:
  • {folder}/YYYY-MM-DD.md
    已写入(如果启用
    include_normal
  • {folder}/YYYY-MM-DD-roast.md
    已写入(如果启用
    include_roast
  • {folder}/history.json
    已用新的
    last_digest
    覆盖(如果启用
    include_normal
  • {folder}/history-digests.jsonl
    已追加一行(如果启用
    include_normal
  • {folder}/profiles/{wxid}-*.md
    已为所有发言3条以上的用户更新(如果启用
    include_normal
  • {folder}/profiles-roast/{wxid}-*.md
    已为所有发言3条以上的用户更新(如果启用
    include_roast
如果有任何未勾选的项,请完成后再宣告成功。不要交付带有过期
history.json
的摘要——增量模式依赖于此文件。

Step 9: Backfill (user-triggered)

步骤9:回溯画像(用户触发)

When the user says "回溯画像" / "初始化画像" / "backfill profiles":
  1. Confirm the target group (if not specified, ask which one).
  2. List all digest files in
    {folder}/
    and
    history-digests.jsonl
    .
  3. Read existing digests in batches of 10–15 to avoid context blowup.
  4. For users appearing in 3+ digests, seed profile files using their leaderboard counts, portrait paragraphs, and quoted lines from the historical digests.
  5. Write to
    profiles/
    (and
    profiles-roast/
    if any
    -roast.md
    files exist).
  6. Report back: how many profiles were created, how many users covered.
Full procedure in references/profiles.md.
当用户请求「回溯画像」「初始化画像」「backfill profiles」时:
  1. 确认目标群组(如果未指定,询问用户具体是哪个群组)。
  2. 列出
    {folder}/
    中的所有摘要文件和
    history-digests.jsonl
  3. 批量读取现有摘要,每次10-15个,避免上下文过载。
  4. 对于出现在3个以上摘要中的用户,使用其排行榜计数、画像段落和历史摘要中的引用语句生成初始画像文件。
  5. 写入
    profiles/
    (如果存在
    -roast.md
    文件,同时写入
    profiles-roast/
    )。
  6. 反馈结果:创建了多少个画像,覆盖了多少用户。
完整流程请参考 references/profiles.md

Storage layout

存储结构

{data_root}/                                        # default: {project_root}/wechat/
└── {group_id}-{group_name}/                        # e.g. 12345678901@chatroom-相亲相爱一家人/
    ├── history.json                                # last digest pointer (fast)
    ├── history-digests.jsonl                       # append-only archive
    ├── 2026-03-12.md                               # normal digest, single date
    ├── 2026-03-12-roast.md                         # roast digest (only if generated)
    ├── 2026-03-10_2026-03-12.md                    # normal digest, date range
    ├── profiles/                                   # normal user profiles
    │   ├── onlytiancai-胡浩🐸.md
    │   └── ...
    ├── profiles-roast/                             # roast user profiles (only if any roast generated)
    │   ├── onlytiancai-胡浩🐸.md
    │   └── ...
    └── imgs/                                       # optional image-description files
        ├── 49661.txt                               # one-line plain text description
        └── ...
{data_root}/                                        # 默认值:{project_root}/wechat/
└── {group_id}-{group_name}/                        # 示例:12345678901@chatroom-相亲相爱一家人/
    ├── history.json                                # 最新摘要指针(快速读取)
    ├── history-digests.jsonl                       # 追加式归档
    ├── 2026-03-12.md                               # 普通版摘要,单日
    ├── 2026-03-12-roast.md                         # 毒舌版摘要(仅当生成时存在)
    ├── 2026-03-10_2026-03-12.md                    # 普通版摘要,日期范围
    ├── profiles/                                   # 普通版用户画像
    │   ├── onlytiancai-胡浩🐸.md
    │   └── ...
    ├── profiles-roast/                             # 毒舌版用户画像(仅当生成过毒舌版时存在)
    │   ├── onlytiancai-胡浩🐸.md
    │   └── ...
    └── imgs/                                       # 可选图片描述文件
        ├── 49661.txt                               # 单行纯文本描述
        └── ...

wx-cli quick reference

wx-cli快速参考

CommandPurpose
wx --version
Sanity-check that wx-cli is installed
wx sessions --json
List recent sessions; useful for verifying init and finding the user's own wxid
wx contacts --query "<name>" --json
Fuzzy-match contacts/groups by display name, remark, or wxid
wx history "<group>" --since DATE --until DATE -n N --json
Pull a group's messages within a date range as JSON
wx members "<group>" --json
List a group's members (rarely needed; mostly for completeness)
wx stats "<group>" --since DATE
wx-cli's built-in stats; we compute our own from
wx history
JSON so the format matches our digest
wx daemon status
/
wx daemon stop
/
wx daemon logs --follow
Daemon lifecycle (troubleshooting)
All
wx
commands accept
--json
for machine-readable output. Default output is YAML — only use it for human eyeballing during debugging.
命令用途
wx --version
检查wx-cli是否已安装
wx sessions --json
列出最近的会话;用于验证初始化状态和查找用户本人的wxid
wx contacts --query "<name>" --json
根据显示名称、备注或wxid模糊匹配联系人/群组
wx history "<group>" --since DATE --until DATE -n N --json
获取指定日期范围内的群组消息,以JSON格式输出
wx members "<group>" --json
列出群组成员(很少需要;主要用于完整性)
wx stats "<group>" --since DATE
wx-cli内置的统计功能;我们通过
wx history
JSON自行计算统计数据,以匹配摘要格式
wx daemon status
/
wx daemon stop
/
wx daemon logs --follow
守护进程生命周期管理(故障排查)
所有
wx
命令均接受
--json
参数以输出机器可读格式。默认输出为YAML——仅在调试时供人工查看使用。

Troubleshooting

故障排查

When a
wx
command fails, diagnose by the symptom, not by retrying blindly. Common patterns:
SymptomCauseFix (tell the user to run these — do NOT run
sudo
for them)
Operation not permitted
/
Access denied to ~/.wx-cli
Sandbox is onRe-run the command with
dangerouslyDisableSandbox: true
. Persistent fix:
/sandbox
to allow
~/.wx-cli
and the WeChat data dir.
无法写入 /Users/<u>/.wx-cli
/
Permission denied
~/.wx-cli
is owned by root (legacy
sudo wx init
)
sudo chown -R $(whoami) ~/.wx-cli && sudo rm -f ~/.wx-cli/daemon.{pid,sock} && wx daemon start
wx history
hangs / times out / returns nothing
Daemon is stuck
wx daemon stop && rm -f ~/.wx-cli/daemon.{pid,sock} && wx daemon start
, then retry
no keys
/
init required
after the daemon was working
Keys went stale (WeChat restart, version upgrade)Make sure WeChat is running, then
wx init --force
(non-sudo first; only
sudo
if your wx-cli version requires it)
wx contacts
returns zero rows for a group you know exists
Group is folded into 折叠群 or the daemon hasn't indexed it yet
wx sessions --json
and search there; if missing, run
wx daemon stop && wx daemon start
and retry
Messages returned but
--since
/
--until
window looks wrong
Date string not in
YYYY-MM-DD
format, or off-by-one timezone
Confirm the dates are local-time
YYYY-MM-DD
. Re-filter the JSON by
timestamp
locally as a belt-and-suspenders step.
Empty result for a chat that should have activity
-n
cap too low for a noisy group
Raise
-n
(e.g. to 20000) and re-fetch
Recovery order when nothing makes sense:
  1. Is WeChat running?
  2. Is
    ~/.wx-cli
    owned by
    $(whoami)
    ?
  3. Is the daemon healthy? (
    wx daemon status
    )
  4. Restart the daemon (
    wx daemon stop && wx daemon start
    )
  5. Last resort:
    wx init --force
    (while WeChat is running)
Never auto-retry inside the skill — every failure should produce a clear diagnostic plus the exact command the user needs to run.
wx
命令失败时,请根据症状诊断,不要盲目重试。常见模式:
症状原因修复方法(告知用户执行以下命令——不得代表用户运行
sudo
Operation not permitted
/
Access denied to ~/.wx-cli
沙箱已启用使用
dangerouslyDisableSandbox: true
参数重新运行命令。永久修复:使用
/sandbox
命令允许访问
~/.wx-cli
和微信数据目录。
无法写入 /Users/<u>/.wx-cli
/
Permission denied
~/.wx-cli
归root所有(旧版
sudo wx init
导致)
sudo chown -R $(whoami) ~/.wx-cli && sudo rm -f ~/.wx-cli/daemon.{pid,sock} && wx daemon start
wx history
挂起/超时/无返回结果
守护进程卡住
wx daemon stop && rm -f ~/.wx-cli/daemon.{pid,sock} && wx daemon start
,然后重试
守护进程正常工作后提示
no keys
/
init required
密钥失效(微信重启、版本升级)确保微信正在运行,然后执行
wx init --force
(优先使用非sudo;仅当wx-cli版本要求时使用sudo)
wx contacts
对已知存在的群组返回零结果
群组被折叠到「折叠群」中,或守护进程尚未索引
wx sessions --json
中搜索;如果仍未找到,执行
wx daemon stop && wx daemon start
并重试
返回消息但
--since
/
--until
时间范围显示错误
日期字符串格式不是
YYYY-MM-DD
,或时区偏差
确认日期为本地时间的
YYYY-MM-DD
格式。作为额外保障,在本地通过
timestamp
过滤JSON数据。
本应有消息的聊天返回空结果
-n
上限设置过低,无法容纳活跃群组的消息
提高
-n
值(例如设置为20000)并重试获取
当所有方法都无效时的恢复顺序:
  1. 微信是否正在运行?
  2. ~/.wx-cli
    是否归当前用户
    $(whoami)
    所有?
  3. 守护进程是否健康?(
    wx daemon status
  4. 重启守护进程(
    wx daemon stop && wx daemon start
  5. 最后手段:
    wx init --force
    (微信运行时执行)
不得在技能内部自动重试——每次失败都应给出明确的诊断信息和用户需要执行的具体命令。

Notes and limitations

注意事项与限制

  • Image content is opaque. wx-cli does not decode chat images. The skill respects an
    imgs/{message_id}.txt
    extension point but does not auto-populate it. When a topic depends heavily on an image with no description file, the digest should say so honestly rather than invent visual content.
  • Reply attribution is best-effort. If wx-cli's output exposes a quote/reply field, use it. Otherwise fall back to context and flag uncertain inferences in working notes.
  • Local time only. Date parsing uses the agent's local time zone. Cross-time-zone group members may show timestamps that don't match their wall clock. Per the format rules, never use timestamps to infer sleep or location.
  • wx-cli reinit. If
    wx history
    suddenly returns nothing after a WeChat restart, the keys may be stale. Tell the user to run
    sudo wx init --force
    (while WeChat is running) and retry.
  • 图片内容不透明。wx-cli不解码聊天图片。本技能支持
    imgs/{message_id}.txt
    扩展点,但不会自动填充该文件。当某个话题严重依赖无描述文件的图片时,摘要应如实说明,而非编造视觉内容。
  • 回复归属为尽力而为。如果wx-cli的输出提供了引用/回复字段,则使用该字段。否则依赖上下文,并在工作笔记中标记不确定的推断。
  • 仅支持本地时间。日期解析使用Agent的本地时区。跨时区的群成员可能显示与他们本地时间不符的时间戳。根据格式规则,不得使用时间戳推断睡眠状态或位置。
  • wx-cli重新初始化。如果微信重启后
    wx history
    突然无返回结果,可能是密钥失效。告知用户在微信运行时执行
    sudo wx init --force
    并重试。