diff --git a/apps/cli/SKILL.md b/apps/cli/SKILL.md new file mode 100644 index 00000000..c7416d03 --- /dev/null +++ b/apps/cli/SKILL.md @@ -0,0 +1,60 @@ +--- +name: chatlab-cli +description: Query local chat history (WeChat/QQ/Telegram/WhatsApp and more) through the chatlab CLI. Use when the user asks what a chat group talked about, who said something first, conversation stats, topics, or keyword evidence from imported chat records. +--- + +# ChatLab CLI for AI Agents + +`chatlab` queries locally imported chat history. Read-only for agents: search, list, stats, topics, SQL fallback. Run `chatlab manifest` once to get the full machine-readable command tree (commands, options, exit codes, examples). + +## Contract + +- Always pass `--format` explicitly: `agent` for message bodies (preprocessed, token-friendly text), `json` for structural data (`--no-content`, `--fields`, stats). +- stdout carries exactly one JSON envelope per call; logs go to stderr. +- Success: `{ ok: true, command, data, meta }`. Failure: `{ ok: false, command, error: { code, message, hint, candidates? } }`. +- Exit codes: 0 ok, 2 bad argument/disabled capability, 3 not found, 4 ambiguous (retry with an id from `error.candidates`), 5 SQL error. +- Pagination: when `meta.hasMore` is true, re-run the same query with `--cursor `. +- Time: ISO dates (`2026-06-01`, `"2026-06-01 08:30"`), `today`, `yesterday`, or `--last 30d` (h/d/w). Date-only `--until` includes the whole day; resolved bounds are echoed in `meta.timeRange`. +- Members: pass an id, exact name, or `me` (the data owner). Ambiguity returns candidates with ids. +- Privacy preprocessing (desensitization, blacklist) is always on. Do not use `--raw`; it is disabled unless the user opts in. +- `[#1021]` markers in agent text are message ids; `[#1021*]` marks search hits; `[#1021-1024]` is a merged block. Use these ids as evidence citations. + +## Task recipes + +```bash +# Discover sessions (skip --session everywhere if there is only one) +chatlab sessions list --format json + +# "What did this group talk about today?" +chatlab messages list --session --since today --limit 100 --max-tokens 2000 --format agent + +# "Main topics this month?" (AI summaries; falls back to keywords if empty) +chatlab topics list --session --since 2026-07-01 --format agent +chatlab stats keywords --session --last 30d --top 20 --format json + +# "Who mentioned X first? Give evidence." +chatlab messages search "服务器迁移" --session --sort asc --limit 5 --context 3 --format agent + +# Follow up an evidence id from [#1021*] +chatlab messages context --id 1021 --session --window 10 --format agent + +# "What did I talk about with 小红 last month?" +chatlab messages between --member me --member 小红 --session --last 30d --format agent + +# "Who is most active?" +chatlab stats activity --session --top 10 --format json + +# Scout hit distribution before pulling bodies (json is correct here) +chatlab messages search "旅游" "旅行" --session --since 2026-01-01 --no-content --limit 100 --format json + +# Next page of results +chatlab messages search "报销" --session --cursor --format agent + +# Advanced fallback: read-only SQL (string cells are desensitized) +chatlab schema --session --format json +chatlab sql "SELECT strftime('%Y-%m', ts, 'unixepoch') AS m, COUNT(*) AS n FROM message GROUP BY m" --session --format json +``` + +## Token budget + +`--limit` caps primary hits, `--max-messages` caps context expansion, `--max-tokens` caps agent text (default 4000), `--max-chars` caps per-message length. Prefer narrowing time ranges and paginating over raising limits. diff --git a/apps/cli/package.json b/apps/cli/package.json index 3c01d8c2..d4c9071d 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -12,6 +12,7 @@ "bin/", "dist/", "dist-web/", + "SKILL.md", "LICENSE" ], "engines": { diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 87c2892c..473b6aca 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -10,6 +10,7 @@ const enSidebar: DefaultTheme.SidebarItem[] = [ { text: 'Export Chat Records', link: '/usage/how-to-export' }, { text: 'Import Chat Records', link: '/usage/how-to-import' }, { text: 'Configure AI', link: '/usage/how-to-config-ai' }, + { text: 'External Agent Calls', link: '/usage/cli-query' }, { text: 'Troubleshooting', link: '/usage/troubleshooting' }, ], }, @@ -23,9 +24,7 @@ const enSidebar: DefaultTheme.SidebarItem[] = [ }, { text: 'Contributing', - items: [ - { text: 'Development Guide', link: '/contributing/development' }, - ], + items: [{ text: 'Development Guide', link: '/contributing/development' }], }, { text: 'Acknowledgments', link: '/contributing/acknowledgments' }, ] @@ -39,6 +38,7 @@ const cnSidebar: DefaultTheme.SidebarItem[] = [ { text: '导出聊天记录', link: '/cn/usage/how-to-export' }, { text: '导入聊天记录', link: '/cn/usage/how-to-import' }, { text: '配置 AI', link: '/cn/usage/how-to-config-ai' }, + { text: '外部 Agent 调用', link: '/cn/usage/cli-query' }, { text: '故障排查', link: '/cn/usage/troubleshooting' }, { text: '常见问题', link: '/cn/usage/faq' }, ], @@ -55,9 +55,7 @@ const cnSidebar: DefaultTheme.SidebarItem[] = [ }, { text: '贡献', - items: [ - { text: '开发指南', link: '/cn/contributing/development' }, - ], + items: [{ text: '开发指南', link: '/cn/contributing/development' }], }, { text: '致谢', link: '/cn/contributing/acknowledgments' }, ] diff --git a/docs/cn/usage/cli-query.md b/docs/cn/usage/cli-query.md new file mode 100644 index 00000000..ff30ea38 --- /dev/null +++ b/docs/cn/usage/cli-query.md @@ -0,0 +1,90 @@ +--- +outline: deep +--- + +# 外部 Agent 调用 + +ChatLab 可以作为 Codex、Claude Code、HermesAgent 等外部 Agent 的本地聊天数据工具层。外部 Agent 负责对话、规划和总结,ChatLab 负责受控地读取、搜索、统计和整理本地聊天记录。 + +这种模式不需要打开 ChatLab 网页,也不需要先启动 ChatLab 桌面界面。外部 Agent 会按需调用轻量的 `chatlab` CLI,在本地完成受控查询、搜索和统计,并拿到已经过隐私预处理的文本。 + +## 适合什么场景 + +- 你已经在使用 Codex、Claude Code、HermesAgent 等外部 Agent,并希望复用它们的订阅、token、模型能力和工作流。 +- 你希望外部 Agent 能按需分析 ChatLab 里的聊天记录,但不想把原始数据库或完整聊天导出直接交给 Agent。 +- 你希望先由 ChatLab 完成脱敏、黑名单过滤、清洗、合并和截断,再把适合分析的文本与证据 id 提供给 Agent。 + +`chatlab` CLI 提供一组面向 AI Agent 优化、同时人类可读的查询命令。所有查询命令只读,默认应用你在 ChatLab 中配置的隐私预处理(脱敏、黑名单)。 + +安装:`npm i chatlab-cli -g`(需要 Node.js ≥ 20),并先在 ChatLab 中导入聊天记录。 + +## 命令总览 + +```bash +chatlab sessions list # 列出已导入的会话 +chatlab sessions show # 查看单个会话详情 +chatlab members list # 会话成员列表 +chatlab members history # 成员改名历史 +chatlab messages list # 按时间窗口列消息 +chatlab messages search <关键词...> # 关键词搜索(支持多词、上下文、翻页) +chatlab messages context --id # 查看某条消息前后现场 +chatlab messages between # 两个成员之间的对话 +chatlab stats overview # 会话概览统计 +chatlab stats activity # 成员活跃度排行 +chatlab stats time --by day # 时间分布(hour/weekday/day/month) +chatlab stats keywords # 高频词(已过隐私过滤) +chatlab stats response # 回复速度排行 +chatlab topics list # AI 分段摘要列表 +chatlab topics show --id # 某个分段的原始消息 +chatlab sql "" # Read-only SQL fallback (strings desensitized) +chatlab schema # Database schema +chatlab manifest # Machine-readable command manifest for agents +``` + +With a single session `--session` can be omitted; with multiple sessions, commands return candidates for disambiguation. + +## Output formats + +Pass `--format` explicitly: + +- **`agent`**: recommended for AI agents. A JSON envelope whose body is compact text produced by the full preprocessing pipeline (cleaning, blacklist, denoising, merging consecutive messages, desensitization, token-aware truncation). Every message carries a `[#id]` citation marker; search hits are marked `[#id*]`. +- **`json`**: for programmatic parsing. Structured message items with privacy steps applied (cleaning, blacklist, desensitization) but no merging or denoising. The right choice for structural scouting with `--no-content` / `--fields`. +- **`text`**: human-readable output (TTY default). + +In agent/json mode stdout contains exactly one JSON envelope; logs go to stderr: + +```json +{ + "ok": true, + "command": "messages.search", + "data": { "text": "returned: 2\n\n--- 2026/6/1 ---\n[#1*] 09:00 Wang: how about a trip on May Day..." }, + "meta": { "totalHits": 2, "returnedHits": 2, "hasMore": false, "preprocess": { "desensitized": true }, "apiVersion": 1 } +} +``` + +Failures return `{ "ok": false, "error": { "code", "message", "hint", "candidates" } }` with semantic exit codes: 0 success, 2 invalid argument or disabled capability, 3 not found, 4 ambiguous (with candidates), 5 SQL error. + +## Common query parameters + +- **Time**: `--since` / `--until` accept `2026-06-01`, `"2026-06-01 08:30"`, ISO 8601, `today`, `yesterday`; `--last 30d` supports h/d/w. Date-only `--until` includes the whole day; resolved bounds are echoed in `meta.timeRange`. +- **Members**: `--member` accepts a member id, exact name, or `me` (the data owner); ambiguous names return candidate ids. +- **Paging**: when `meta.hasMore` is true, pass `--cursor `; cursors are bound to the exact query conditions. +- **Token budget**: `--limit` (primary objects), `--max-messages` (context expansion cap), `--max-tokens` (agent text budget, default 4000), `--max-chars` (per-message truncation). + +## Privacy boundaries + +- All query commands apply your ChatLab desensitize rules and blacklist by default — including the `stats keywords` vocabulary, `topics list` summaries, and string cells in `sql` results. +- `--raw` (bypassing preprocessing) is disabled by default; it only works after you explicitly run `chatlab config set cli.allow_raw true` or set `CHATLAB_CLI_ALLOW_RAW=1`. +- If you don't need the SQL fallback, disable it with `chatlab config set cli.allow_sql false`. + +## Agent usage guide + +The npm package ships a `SKILL.md` (command quick reference + task recipes) you can drop into your project's `AGENTS.md`, a Claude Code skill, or Cursor rules. Agents can also run `chatlab manifest` to fetch the machine-readable command tree in one call. + +A typical recipe — "who mentioned this first? give evidence": + +```bash +chatlab messages search "server migration" --sort asc --limit 5 --context 3 --format agent +# Take the message id from the [#1021*] marker in the returned text, then dig in: +chatlab messages context --id 1021 --window 10 --format agent +```