首页
/ LobeHub CLI 会话管理实战:lh topic 与 lh message 全命令详解

LobeHub CLI 会话管理实战:lh topic 与 lh message 全命令详解

2026-09-05 21:37:56作者:齐冠琰

本文基于 LobeHub 仓库中 CLI 技能的会话管理参考文档 conversation.md 展开,系统讲解 LobeHub CLI(@lobehub/cli,命令别名 lh/lobe/lobehub)中 lh topiclh message 两组会话管理命令的完整用法、参数默认值与输出格式。读完本文,你可以直接在终端或 Agent 工作流中管理对话主题(Topic)与消息(Message):列表、搜索、创建、编辑、批量删除、统计、字数统计与活跃度热力图,并理解这些命令背后的 tRPC 调用链与服务端路由实现。

1. 命令定位与源码位置

LobeHub CLI 是基于 Commander.js + TypeScript 构建的命令行工具,位于 apps/cli/ 目录,入口为 apps/cli/src/index.ts,详细开发指南见 SKILL.md。会话管理由两个命令组承担,源码各占一个文件:

命令组 源码文件 职责
lh topic topic.ts 管理对话主题(threads),即会话容器
lh message message.ts 管理主题内的聊天消息

两个命令组的所有操作都通过 getTrpcClient() 获取类型安全的 tRPC 客户端,再调用后端的 topic.* / message.* 过程。服务端对应实现分别在 topic.tsmessage.ts 两个 tRPC 路由中。

从源码结构看,lh topic 组还挂载了一个子命令文件 view.tstopic view 转录查看),下文会一并覆盖。

2. 主题管理(lh topic

2.1 列表:lh topic list

lh topic list [--agent-id <id>] [-L <n>] [--page <n>] [--json [fields]]
选项 说明 默认值
--agent-id <id> 按 Agent ID 过滤 -
-L, --limit <n> 每页大小 30
-P, --page <n> 页码(从 1 开始) 1
--json [fields] 输出 JSON,可选逗号分隔字段过滤 -

表格模式下输出 ID / TITLE / FAV / UPDATED 四列,收藏主题在 FAV 列显示 ,UPDATED 列用相对时间(timeAgo)展示。

topic.ts 的实现可以看到分页参数的换算逻辑:CLI 的 --limit 映射为 tRPC 的 pageSize,而 --page 会减一后作为 current 传给 topic.getTopics(即第 1 页对应 current: 0)。因此 lh topic list --agent-id <id> -L 10 --page 2 --json id,title 即可拿到某 Agent 主题的第二页、仅保留 id 与 title 字段的 JSON,便于管道处理。

2.2 搜索:lh topic search

lh topic search <keywords> [--agent-id <id>] [--json [fields]]

全量按关键词搜索主题,表格输出 ID / TITLE 两列。底层调用 topic.searchTopics;在服务端 topic.ts 中,topicSearchProcedure 专门注入了 createFtsSearchRepo(usage 为 topic_search)来构建带全文检索能力的 TopicModel——也就是说该命令走的是数据库 FTS 全文搜索通道,而非普通 LIKE 匹配。

2.3 创建:lh topic create

lh topic create -t <title> [--agent-id <id>] [--favorite]
选项 说明 必填
-t, --title <title> 主题标题
--agent-id <id> 关联的 Agent ID
--favorite 创建时即标记为收藏

成功后调用 topic.createTopic 并打印新建主题 ID:✓ Created topic <id>

2.4 编辑:lh topic edit

lh topic edit <id> [-t <title>] [--favorite] [--no-favorite]
  • -t, --title <title>:修改标题;
  • --favorite / --no-favorite:收藏 / 取消收藏(Commander 的 --no-* 约定,两者会写入 favorite: true/false)。

源码中的关键行为:若未指定任何变更(--title--favorite 都缺省),命令会以 No changes specified. 报错退出(exit code 1),不会发起空更新请求。

2.5 删除:lh topic delete

lh topic delete <id1> [id2...] [--yes]
  • 支持一次传入多个 ID 批量删除;
  • --yes 跳过交互式确认,适合脚本与 Agent 自动化场景;
  • 未加 --yes 时会弹出 Are you sure you want to delete N topic(s)? 确认提示,取消则打印 Cancelled.

topic.ts 的实现看,实际源码比参考文档更进一步:

  1. 支持 --file <path> 从文件读取 ID:文件内容可以是一行一个 ID 的纯文本,也可以是 JSON 数组;与命令行位置参数合并后自动去重;
  2. 单条与批量走不同端点:只有 1 个 ID 时调用 topic.removeTopic,多个 ID 时调用 topic.batchDelete,与后端批量语义对齐。

2.6 最近主题:lh topic recent

lh topic recent [-L <n>] [--json [fields]]
选项 说明 默认值
-L, --limit <n> 条数 10

调用 topic.recentTopics,表格输出 ID / TITLE / UPDATED

2.7 转录查看:lh topic view

参考文档未列出该子命令,但 view.tslh topic 组的核心读操作,用于查看主题详情及其消息转录:

lh topic view <id> [-L <n>] [--from <n>] [--to <n>] [--no-messages] [--json]
  • -L, --limit <n>:本页消息数,默认 50,上限 500(源码常量 MAX_LIMIT = 500,超限直接报错);
  • --from <n> / --to <n>:基于 1 的消息下标区间,二者不能与 --limit 同时使用,且 --to 必须不小于 --from
  • --no-messages:只输出主题元数据(标题、收藏、更新时间、状态、模型与 Provider);
  • --json:输出 { topic, messages, pagination } 完整结构。

该子命令的工程细节值得注意:终端渲染前会对消息内容做规范化——剥离终端控制字符、删除孤立代理项(保留 emoji)、把 base64 data URL 脱敏为 [base64 data omitted],单条消息内容超过 20000 字符或工具参数超过 8000 字符时自动截断并提示 use --json for full output;工具调用会以 ⚙ identifier.apiName 加缩进参数的方式渲染。看完当前页后,末尾会打印 Next: --from <n> -L <n> 提示下一页参数,方便人工分页。

2.8 克隆与分享:clone / share / unshare / share-info / import

同样源自 topic.ts,这些命令把主题做成了可复制、可分享的资源:

# 克隆主题(可重命名)
lh topic clone <id> [-t <new-title>]

# 开启分享(默认 link 可见性,也支持 private)
lh topic share <id> [--visibility link|private]

# 关闭分享
lh topic unshare <id>

# 查看分享信息(Topic ID / Share ID / Visibility / Created)
lh topic share-info <id> [--json]

# 导入主题:--agent-id 与 --data 均为必填
lh topic import --agent-id <id> --data '<json>' [--group-id <id>] [--json]

share 成功后会打印 Share ID(调用 topic.enableSharing 返回);share-info 未开启分享时提示 Sharing not enabled for this topic.import 通过 topic.importTopic 把 JSON 主题数据落到指定 Agent 下,可选挂到某个群(--group-id)。

3. 消息管理(lh message

3.1 列表:lh message list

lh message list [--topic-id <id>] [--agent-id <id>] [--role <role>] [--start <date>] [--end <date>] [-L <n>] [--page <n>] [--user] [--json [fields]]
选项 说明 默认值
--topic-id <id> 按主题过滤 -
--agent-id <id> 按 Agent 过滤 -
--role <role> 按角色过滤(user / assistant / tool / system) -
--start <date> / --end <date> 创建时间范围(ISO 或 YYYY-MM-DD -
-L, --limit <n> 每页大小 50(源码默认值,参考文档标注为 30,以当前仓库源码为准)
--page <n> 页码 1
--user 等价于 --role user 的简写 -

表格列(源码实际输出)为 ID / ROLE / AGENT / CONTENT / TOPIC/THREAD / CREATED,其中 CONTENT 截断至 60 字符,TOPIC/THREAD 列在存在 thread 时以 <topicId> › <threadId> 形式展示分支上下文。

参考文档提到"提供 --topic-id--agent-id 时用 message.getMessages,否则用 message.listAll";而当前 message.ts 的实现已统一走 client.message.listAll.query,并把过滤条件(topicId、agentId、role、startDate/endDate、pageSize/current)一次性传入。可以推断这是后端 listAll 过程吸收了原 getMessages 的过滤语义后的简化,命令行用法不受影响。

3.2 搜索:lh message search

lh message search <keywords> [--json [fields]]

跨所有消息做全文搜索(底层 message.searchMessages),表格输出 ID / ROLE / CONTENT(内容截断 60 字符)。

3.3 删除:lh message delete

lh message delete <id1> [id2...] [--yes]

与主题删除一致的交互约定:默认确认提示,--yes 跳过。源码中 1 个 ID 走 message.removeMessage,多个 ID 走 message.removeMessages

3.4 计数:lh message count

lh message count [--topic-id <id>] [--agent-id <id>] [--role <role>] [--start <date>] [--end <date>] [--group-by topic] [--json]
选项 说明
--start <date> / --end <date> 时间范围(ISO 格式,如 2024-01-01
--group-by <field> 按字段分组,目前仅支持 topic(其他取值会报错退出)

两种输出形态:

  • 默认:Messages: <n>(调用 message.count);
  • --group-by topic:表格 TOPIC / COUNT(调用 message.countByTopic);
  • --json{"count": n} 或分组结果数组。

3.5 分布统计:lh message stats

参考文档未提及、但源码中已实现的分析型命令,用于回答"每个主题平均多少轮对话"这类问题:

lh message stats [--agent-id <id>] [--role <role>] [--all-roles] [--start <date>] [--end <date>] [--json]
  • 默认只统计 user 角色的消息("每主题多少轮"的常见口径),--all-roles 改为统计全部角色;
  • 输出指标表:Topics、Total messages、Mean、Median、P90、P99、Min、Max,以及 One-shot(单条消息主题的绝对数与占比,如 12 (3.4%)),底层调用 message.topicStats

3.6 创建与编辑消息:create / edit

# 创建:-r 与 -c 必填
lh message create -r <role> -c <content> [--agent-id <id>] [--topic-id <id>] [--session-id <id>] [--json]

# 编辑:至少指定 --content 或 --role 之一
lh message edit <id> [-c <content>] [--role <role>]

create 通过 message.createMessage 落库并打印新消息 ID;edittopic edit 同样的防护:无任何变更字段时以 No changes specified. 退出。

3.7 附属分析命令

message.ts 还提供了一批数据运维向的子命令:

# 给消息附加文件(文件 ID 逗号分隔)
lh message add-files <id> --file-ids <id1,id2,...>

# 时间段内消息总字数
lh message word-count [--start <date>] [--end <date>] [--json]

# 按消息量对模型排名
lh message rank-models [--json]        # 表格列:MODEL / COUNT

# 按助手上下文删除消息(--agent-id 与 --session-id 至少其一)
lh message delete-by-assistant [--agent-id <id>] [--session-id <id>] [--topic-id <id>] [--yes]

# 按群组删除消息
lh message delete-by-group <groupId> [--topic-id <id>] [--yes]

所有删除类命令均遵循统一的 confirm + --yes 约定(见 SKILL.md 中的 Confirmation Prompts 规范)。

3.8 活跃度热力图:lh message heatmap

lh message heatmap [--json]

调用 message.getHeatmaps,展示消息随时间的频率分布;终端模式下按 date: count 逐行打印,--json 输出原始结构。适合在终端里快速判断哪些日期是活跃会话高峰。

4. 底层调用链与输出约定

把所有命令串起来看,lh topic / lh message 的执行链路是:

  1. 认证getTrpcClient() 自动解析 token(flag > 本地加密存储 ~/.lobehub/credentials.json,AES-256-GCM),详见 apps/cli/src/api/client.tsapps/cli/src/auth/
  2. 类型安全请求:Commander 解析后的选项被组装成 tRPC 输入对象(注意 CLI 的 --limit/--page 会换算为 pageSize/current),通过 client.topic.<proc>.query/mutateclient.message.<proc>.query/mutate 发起;
  3. 服务端路由:进入 topic.ts / message.ts 中的 lambda 过程,其中 topic 路由统一挂了工作区鉴权(wsCompatProcedure + serverDatabase)并注入 TopicModelMessageModelTopicShareModel 等数据模型;搜索类过程额外注入 FTS 检索仓储;
  4. 输出渲染format.ts 提供 printTable / outputJson / timeAgo / truncate / confirm 等工具,保证人工可读表格与脚本可解析 JSON 两种输出形态。

统一约定(与 SKILL.md 的 Output Patterns 一致):

  • --json [fields]:所有查询类命令支持 JSON 输出,可附逗号分隔字段名做投影;
  • --yes:破坏性操作的免确认开关,自动化脚本必须显式使用;
  • -L, --limit:分页/条数控制,不同子命令默认值不同(topic list 为 30,message list 为 50,topic view 为 50 且上限 500,topic recent 为 10)。

5. 典型工作流示例

结合上述命令,一个完整的"体检 → 清理"流程可以是:

# 1. 查看最近活跃的主题
lh topic recent -L 5

# 2. 查看某个主题的完整转录(分页)
lh topic view <topicId> -L 50 --from 1
lh topic view <topicId> -L 50 --from 51

# 3. 全库关键词检索消息
lh message search "部署失败"

# 4. 统计近 30 天消息量与按主题分布
lh message count --start 2026-08-01 --end 2026-08-31
lh message count --group-by topic --json

# 5. 批量清理:导出 ID 后确认删除
lh message list --topic-id <topicId> --json id | jq -r '[]' > /tmp/ids.json
lh message delete --yes $(cat /tmp/ids.json | tr -d '[]" ' | xargs) 2>/dev/null || true

(最后一行的实际用法取决于导出的 JSON 形态;lh message delete 也接受多个位置参数,--yes 用于跳过确认。)

6. 参考与延伸阅读

注意:本文命令参数以当前仓库源码为准。参考文档中个别默认值(如 message list 的 limit 默认值、list 的表格列)与源码存在出入,且部分命令(viewstatscloneshare 系列、create/edit/word-count/rank-models 等)在源码中已实现但参考文档尚未收录——以 lh <command> --help 的实际输出为最终依据。

登录后查看全文
热门项目推荐
相关项目推荐