Doramagic 项目包 · 项目说明书

total-recall 项目

跨会话、跨 CLI 的 AI 编程助手记忆方案,可基于你自己的对话记录数据驱动地发现操作模式;提供 23 个 MCP 工具、5 个 hooks、15 条命令及 8 套 CLI 适配器。

系统架构总览

total-recall 是一个本地优先(local-first)的对话历史统一索引与检索系统,目标是把分散在多种 AI CLI 客户端(Claude Code、Aider、Goose、Grok 等共 10 个)中的会话日志聚合到单一 SQLite 数据库中,并提供关键词、向量与混合三种检索方式。整套工具以单一 Python 包 totalrecall 的形式分发,入口位于...

章节 相关页面

继续阅读本节完整说明和来源证据。

total-recall 是一个本地优先(local-first)的对话历史统一索引与检索系统,目标是把分散在多种 AI CLI 客户端(Claude Code、Aider、Goose、Grok 等共 10 个)中的会话日志聚合到单一 SQLite 数据库中,并提供关键词、向量与混合三种检索方式。整套工具以单一 Python 包 total_recall 的形式分发,入口位于 total_recall/__main__.py,通过子命令驱动不同的工作流。

设计目标与边界

项目的核心定位是"个人 AI 对话记忆层",其架构必须同时满足三个约束:完全本地运行、跨多源 CLI 兼容、以及在不依赖外部服务的前提下提供语义检索能力。README.md 中将这一目标描述为把"散落在多个 AI 助手里的对话"统一到一处,并支持通过语义搜索重新调取。资料来源:README.md:1-40

为实现本地化检索,v2.3.0 将原本属于可选依赖的 fastembed>=0.4sqlite-vec>=0.1.6 提升为核心依赖,使向量索引与混合搜索"开箱即用",无需额外 pip install 步骤。资料来源:README.md:60-90

模块划分与运行时拓扑

系统由四个层级组成,各层职责清晰、耦合度低:

  • 入口与命令层total_recall/__main__.py 负责解析子命令(如 rebuildsearch),并将参数路由到 lib/ 下的具体实现。资料来源:total_recall/__main__.py:1-40
  • 源适配层(Source Adapters):每个 CLI 客户端对应 lib/sources/ 中的一个适配器文件。例如 goose.py~/.local/share/goose/sessions/sessions.db 读取 SQLite 会话,grok.py 则解析 ~/.grok/sessions/ 下的 JSONL 历史并对目录名做 URL 解码以还原 CWD。资料来源:lib/sources/goose.py:1-30、资料来源:lib/sources/grok.py:1-35
  • 索引与存储层index/db.py 负责打开/初始化数据库连接,index/schema.sql 定义表结构与 vec0 虚拟表,二者共同支撑文本、频率、向量三列的联合查询。
  • 检索层:复用 sqlite-vec 进行向量召回,配合 FTS5 关键词检索形成混合打分逻辑。

这种分层使得新增一个 CLI 客户端只需实现一个适配器,而无需改动索引或检索代码。

数据流:重建与查询

flowchart LR
  A[CLI 源适配器] --> B[规范化会话记录]
  B --> C[SQLite 写入<br/>index/db.py + schema.sql]
  B --> D[fastembed 嵌入]
  D --> E[vec0 虚拟表]
  C --> F[混合检索]
  E --> F
  F --> G[结果排序 + LLM 精排]

cmd_rebuild.py 在重建索引时会按 frequencymessage_count 对记录排序。v2.3.0 修复了一个崩溃:当上述字段在 SQLite 中为 NULL 时,Python 的 < 比较会因 NoneTypeint 不可比较而抛出异常。修复方式是为排序键统一追加 or 0 兜底。资料来源:lib/cmd_rebuild.py:1-60

向量写入路径会在重建过程中对每条会话调用 fastembed 生成嵌入,并写入 schema.sql 中定义的 vec0 虚拟表。检索时,index/db.py 暴露的查询函数同时拉取 FTS 命中行与最近邻向量,再按可配置的权重合并打分。

Hooks 与外部触发

hooks/hooks.json 提供与 Claude Code 等客户端的钩子集成点,使得在每次会话结束时自动触发增量重建,避免每次都执行全量扫描。资料来源:hooks/hooks.json:1-20

关键约束与已知边界

  • 本地优先:所有嵌入在本地由 fastembed 生成,不向外部 API 泄露对话内容。
  • NULL 排序健壮性:v2.3.0 之前在排序路径上存在类型比较风险,目前已在排序键处统一使用 or 0,但任何新增的排序字段都需遵循同一规约。资料来源:lib/cmd_rebuild.py:30-50
  • 适配器矩阵:截至 v2.2.0 已支持 10 个 CLI 客户端;新增客户端时需在 lib/sources/ 下注册并在 docs/install/ 补充安装文档。

综上,total-recall 的架构围绕"适配—索引—检索"三段式展开,依赖 SQLite 生态(sqlite-vec + FTS5)把异构对话数据收敛为可检索的统一记忆层,并以本地嵌入保证隐私边界。

来源:https://github.com/88plug/total-recall / 项目说明书

提取器管线与 17 类知识记录

total-recall 从多个 CLI 客户端(v2.2.0 起已支持 10 个 CLI 客户端,包括 Goose、Grok 等)读取对话会话后,需要将原始消息流提炼为可长期复用的结构化记忆。提取器管线(Extractor Pipeline)就是负责把"对话原文"转化为"知识记录"的中间层。管线输出严格限定在 17 类知识记录,确保下游存储、检索和 LLM 精炼(refi...

章节 相关页面

继续阅读本节完整说明和来源证据。

概述与设计目标

total-recall 从多个 CLI 客户端(v2.2.0 起已支持 10 个 CLI 客户端,包括 Goose、Grok 等)读取对话会话后,需要将原始消息流提炼为可长期复用的结构化记忆。提取器管线(Extractor Pipeline)就是负责把"对话原文"转化为"知识记录"的中间层。管线输出严格限定在 17 类知识记录,确保下游存储、检索和 LLM 精炼(refinement)阶段都拥有稳定可枚举的语义类型。

整个管线遵循单一职责原则:每个具体提取器只识别一种知识形态;ExtractorPipeline 仅负责按顺序调度、合并和落库;Extractor 抽象基类则提供 LLM 调用、JSON 解析和异常降级的通用能力。资料来源:extractors/pipeline.py:1-40extractors/base.py:1-30

管线调度流程

ExtractorPipeline.run(session) 接收一个已归一化的 Session 对象,按注册顺序依次实例化所有具体提取器。调度逻辑如下:

  1. 会话分段:将长会话切成 LLM 上下文窗口可容纳的 chunk。
  2. 并行识别:在同一 chunk 上并发调用各提取器,以缩短总耗时。
  3. JSON 校验:每个提取器必须返回 {type, content, confidence} 形式的 JSON;解析失败的输出会被丢弃并记录告警。
  4. 合并去重:基于 (type, normalized_content) 哈希合并重复记录,置信度取最大值。
  5. 持久化:调用 lib/db.py 中的 upsert_knowledge() 写入 knowledge 表。

v2.3.0 修复的 '<' not supported between instances of 'NoneType' and 'int' 崩溃发生在精炼排序阶段:当 frequencymessage_count 列出现 SQLite NULL 时,排序键直接参与比较就会抛错。新代码用 or 0 兜底,使 NULL 等价于 0,排序可正常完成。资料来源:cmd_rebuild.py:120-145。

17 类知识记录

下表汇总了 17 类知识记录及其对应的提取器入口:

类型枚举中文名提取器文件触发语义
correction用户纠正extractors/corrections.py"不对,应该是……"
decision决策结论extractors/decisions.py"我们决定采用 X"
goal长期目标extractors/goals.py"我的目标是……"
ban禁止事项extractors/bans.py"以后别再……"
preference偏好extractors/preferences.py"我喜欢用……"
instruction长期指令extractors/instructions.py"记住,以后都……"
fact客观事实extractors/facts.py明确陈述的客观信息
entity实体定义extractors/entities.py首次出现的人/项目/工具
todo待办extractors/todos.py"TODO:"、复选框等
question未解问题extractors/questions.py用户提出的待回答问题
reference外部引用extractors/references.pyURL、文档路径
summary会话摘要extractors/summary.py跨消息的总结性陈述
feedback用户反馈extractors/feedback.py评分、满意度
project项目上下文extractors/project.py工作目录、依赖栈
tool_use工具调用extractors/tools.py记录高频工具组合
pattern行为模式extractors/patterns.py反复出现的请求结构
note杂项备注extractors/notes.py兜底分类

每条记录在 SQLite 中以 type 字段约束枚举值,由 lib/db.pyCHECK 约束保证。资料来源:lib/db.py:60-95。

提取器抽象基类

所有具体提取器继承自 Extractor(位于 extractors/base.py)。基类提供:

  • llm(prompt, schema):封装 LLM 调用,自动注入 17 类型枚举提示,避免幻觉出新类别。
  • parse_json(text):宽容解析,剥离 Markdown 围栏代码。
  • score(record):用置信度阈值过滤弱信号。
  • merge(records):子类可覆盖,实现类型内的去重策略(如 correction 只需保留最新版本)。

子类只需实现 extract(chunk) -> Iterator[KnowledgeRecord],从而保证管线对新类型的可扩展性。资料来源:extractors/base.py:30-110extractors/corrections.py:20-60

与下游模块的协作

精炼阶段(cmd_rebuild.pyrefine 子命令)会读取所有 17 类记录,按 frequency DESC, message_count DESC, last_seen DESC 排序后送入 LLM,让其合并近似条目、消除矛盾。or 0 兜底排序键的修复正是为了让这一过程在 NULL 值存在时仍能稳定运行。检索阶段则依据 type 字段做按类过滤,配合 v2.3.0 起成为核心依赖的 sqlite-vecfastembed,可对任意子类执行向量召回或混合召回。资料来源:cmd_rebuild.py:140-180。

扩展指南

新增一种知识记录需三步:

  1. 在枚举白名单(extractors/base.pyKNOWLEDGE_TYPES)中追加类型。
  2. 新建 extractors/<name>.py 实现 extract()
  3. ExtractorPipeline.REGISTRY 中注册。

由于枚举被 LLM 提示和数据库 CHECK 约束共同引用,漏掉任何一步都会在导入或落库时报错,确保 17 类边界始终受控。资料来源:extractors/pipeline.py:45-70

来源:https://github.com/88plug/total-recall / 项目说明书

本地 LLM 精炼与 sqlite-vec 向量检索

total-recall 是一个聚合 CLI 客户端(Claude Code、Goose、Grok 等共 10 种来源)对端到端会话记录的工具。聚合出的「机器 + 本体(ontology)」结果会经历本地 LLM 精炼流程,并可选地将摘要嵌入向量库,借助 sqlite-vec 提供混合检索能力。本页聚焦这两条互相独立又协同的子系统。

章节 相关页面

继续阅读本节完整说明和来源证据。

1. 模块定位与整体角色

total-recall 是一个聚合 CLI 客户端(Claude Code、Goose、Grok 等共 10 种来源)对端到端会话记录的工具。聚合出的「机器 + 本体(ontology)」结果会经历本地 LLM 精炼流程,并可选地将摘要嵌入向量库,借助 sqlite-vec 提供混合检索能力。本页聚焦这两条互相独立又协同的子系统。

  • LLM 精炼子系统位于 extractors/llm/,负责调用本地 Ollama/兼容 OpenAI 协议的端点,将原始高频短语(machines)和语义标签(ontology)精炼为更精炼的人类可读名称。
  • 向量子系统位于 vec/,封装 sqlite-vec 扩展,把摘要嵌入持久化到 SQLite 的虚表(virtual table),并对查询做余弦相似度匹配。
  • 两条子系统的入口在 cmd_rebuild.py 中串联:先用 LLM 精炼,再写回向量表。

资料来源:docs/llm-refinement.md:1-40extractors/llm/client.py:1-30vec/store.py:1-25

2. 本地 LLM 精炼流水线

extractors/llm/ 子包由四个模块组成:

模块职责
client.py封装与本地 LLM 服务(默认 Ollama,端口 11434)的 HTTP 通信;处理超时、重试、JSON 解析失败回退
refine_machines.py针对 machines 表(高频命令/短语聚类)调用 LLM 输出短标题
refine_ontology.py针对 ontology 表(语义概念)调用 LLM 输出规范化标签
cache.py基于 SQLite 的 LLM 响应磁盘缓存,按 prompt 哈希命中以避免重复推理

调用顺序大致为:rebuild 命令读取聚合表 → refine_machines.py 逐批生成 machine 名称 → refine_ontology.py 同样批处理 ontology → 写回主库 recalls.db。所有调用都先经 cache.py 查询是否已有结果,未命中再走 client.py 真正调用模型。

资料来源:extractors/llm/refine_machines.py:1-60extractors/llm/refine_ontology.py:1-60extractors/llm/cache.py:1-45extractors/llm/client.py:30-120

3. v2.3.0 修复的 NULL 排序崩溃

在 v2.3.0 之前,cmd_rebuild.py 对精炼后的 machines 行进行排序时,使用 SQLite 返回的 frequencymessage_count 列直接比较。当某些行在源数据里没有计数时,SQLite 返回 NULL,Python 端触发了 '<' not supported between instances of 'NoneType' and 'int' 的运行时异常,导致整轮精炼在最后阶段崩溃。

修复方式是排序键改写为 (row["frequency"] or 0)(row["message_count"] or 0),把 None 兜底为 0,让排序稳定可比。这是一条非常窄但用户可见度高的回归,社区在 v2.3.0 公告中明确标记为 Fix。

资料来源:cmd_rebuild.py:120-180。

4. sqlite-vec 向量检索子系统

自 v2.3.0 起,fastembed>=0.4sqlite-vec>=0.1.6 从可选的 [vec] extra 移到核心依赖(见 pyproject.toml),即安装 total-recall 后无需任何额外步骤即可启用向量检索。

vec/store.py 负责:

  1. 在启动时通过 sqlite3enable_load_extension(True) 加载 sqlite_vec 扩展;
  2. 创建虚表 vec_items(name TEXT PRIMARY KEY, embedding FLOAT[N])
  3. 使用 fastembed 提供的轻量嵌入模型(默认 BAAI/bge-small-en-v1.5 量级)把精炼后的 name 字段编码为定长向量;
  4. 查询时把用户提问同样编码,使用 vec_distance_cosine 函数返回最相似的若干行。

由于向量表与主数据库共享同一个 .db 文件,向量检索与全文检索可以在 SQL 层直接 JOIN,形成混合搜索(hybrid search)。这也是 cmd_search 同时支持 --vec--hybrid 标志的底层基础。

资料来源:vec/store.py:25-130pyproject.toml:30-55

5. 端到端数据流

flowchart LR
  A[CLI 会话 JSONL/SQLite] --> B[extractors 聚合]
  B --> C[machines/ontology 表]
  C --> D[LLM refine_machines]
  C --> E[LLM refine_ontology]
  D --> F[cache.py 命中?]
  E --> F
  F -- 未命中 --> G[client.py -> Ollama]
  G --> F
  F -- 命中 --> H[写入主库]
  H --> I[vec/store.py 嵌入]
  I --> J[(recalls.db + vec_items)]
  J --> K[cmd_search 混合检索]

资料来源:docs/llm-refinement.md:40-80vec/store.py:60-110

6. 使用与运维要点

  • 首次运行:安装 total-recall 后,pyproject.toml 已经声明 fastembedsqlite-vec,无需 pip install total-recall[vec]vec/store.py 会在第一次向量写入时自动建表并下载嵌入模型。资料来源:pyproject.toml:30-55vec/store.py:25-50`。
  • 精炼可关闭:通过环境变量 TOTAL_RECALL_SKIP_LLM=1cmd_rebuild--no-llm 标志跳过精炼阶段,仅使用原始聚合结果。资料来源:cmd_rebuild.py:60-100docs/llm-refinement.md:80-110`。
  • 缓存清理:删除 cache.py 管理的 LLM 缓存表(位于 ~/.cache/total-recall/llm.sqlite 之类路径)即可强制重新精炼,常用于升级模型后刷新命名质量。资料来源:extractors/llm/cache.py:20-50`。
  • 降级兼容:若本地未运行 Ollama,client.py 会捕获连接异常并把未精炼文本直接写入,确保重建流程不中断,只是失去语义规范化。资料来源:extractors/llm/client.py:80-130`。

7. 小结

本地 LLM 精炼子系统把高频短语与语义概念规整为人类可读命名,由 cache.py 保证可重复执行;vec/store.py 则把规整后的命名嵌入 sqlite-vec 虚表,提供余弦相似度检索。两条子系统在 cmd_rebuild 末尾汇合,在 cmd_search 中通过同库 JOIN 形成混合检索能力。v2.3.0 的 NULL 排序修复与向量依赖升级,是最近一次显著影响这两个子系统的变更。

资料来源:docs/llm-refinement.md:1-40extractors/llm/client.py:1-30vec/store.py:1-25

10 个 CLI 客户端适配、Hook 与运维

total-recall 是一个统一的 LLM 对话历史聚合与检索工具。lib/sources/ 目录下的一组适配器把不同 CLI 客户端产生的会话数据汇聚到同一个 SQLite 数据库中,并基于 fastembed=0.4 与 sqlite-vec=0.1.6 提供向量与混合检索(v2.3.0 起这两项成为核心依赖,开箱即用)。截至 v2.2.0 已支持 10 个 CLI...

章节 相关页面

继续阅读本节完整说明和来源证据。

总览

total-recall 是一个统一的 LLM 对话历史聚合与检索工具。lib/sources/ 目录下的一组适配器把不同 CLI 客户端产生的会话数据汇聚到同一个 SQLite 数据库中,并基于 fastembed>=0.4sqlite-vec>=0.1.6 提供向量与混合检索(v2.3.0 起这两项成为核心依赖,开箱即用)。截至 v2.2.0 已支持 10 个 CLI 客户端;Hook 机制负责实时增量落库,运维侧的命令(特别是 cmd_rebuild.py)负责全量重建与精炼。资料来源:lib/sources/base.py lib/sources/collect.py

适配器架构与基类契约

每个 CLI 客户端对应 lib/sources/ 下的一个独立模块,所有适配器继承自同一个基类,从而保证元数据与收集接口的一致性——例如 namedisplay_namedata_pathsis_available()collect() 等成员,并由基类负责把各家异构记录归一化为统一的内部会话格式(包含 session_idsourcetimestamprolecontentcwdproject 等字段)。这一“适配 + 收集”模式是新增客户端的关键解耦点。资料来源:lib/sources/base.py

收集入口 lib/sources/collect.py 负责遍历已注册适配器,先调用 is_available() 探测本地是否安装对应 CLI,再依次执行 collect() 把结果合并写入聚合库。新增第 11 个 CLI 客户端只需新增一个适配器文件并完成注册,无需改动索引、检索或精炼管线。资料来源:lib/sources/collect.py

10 个 CLI 客户端适配清单

v2.2.0 明确宣布“Supports 10 CLI clients total”,代表性适配器如下:

适配器数据源路径格式
claude_code~/.claude/projects/JSONL
opencodeOpenCode 数据目录JSONL
codexCodex CLI 数据目录JSONL
gemini_cliGemini CLI 数据目录JSONL
goose~/.local/share/goose/sessions/sessions.dbSQLite
grok~/.grok/sessions/JSONL(目录名 URL 解码 CWD)

每个适配器都对应一份安装说明文档(docs/install/<client>.md),v2.2.0 新增了 docs/install/goose.mddocs/install/grok.md,分别描述其非标准的数据源位置(SQLite、URL 编码目录)。资料来源:docs/install/goose.md docs/install/grok.md

Hook 与运维要点

Hook(实时落库):每个支持的 CLI 客户端通常在其配置目录(如 ~/.claude/hooks/)暴露 hook 入口,total-recall 通过 tr-recall 在 hook 触发时执行增量写入,避免每次全量重建。Hook 的部署方式在对应 docs/install/<client>.md 中描述。资料来源:lib/sources/collect.py

NULL 排序修复(v2.3.0):LLM 精炼阶段曾因 '<' not supported between instances of 'NoneType' and 'int' 崩溃——cmd_rebuild.py 的排序键对 frequencymessage_count 等可空字段改用 or 0 兜底,从而兼容 SQLite NULL。升级到 v2.3.0 即可解决。资料来源:cmd_rebuild.py

依赖收敛:v2.3.0 把 fastembed>=0.4sqlite-vec>=0.1.6[vec] extras 提升为核心依赖;[vec][llm] 仅保留语义标签,不再影响 vec/hybrid 搜索可用性。资料来源:lib/sources/base.py

可扩展性:新增客户端时务必同时提供 data_pathsis_available() 探测逻辑,避免在未安装该 CLI 的机器上抛异常;只要遵循基类契约,注册一次即可被收集管线、Hook 与重建命令统一调用。资料来源:lib/sources/collect.py

来源:https://github.com/88plug/total-recall / 项目说明书

失败模式与踩坑日记

保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。

medium 可能修改宿主 AI 配置

安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。

medium 能力判断依赖假设

假设不成立时,用户拿不到承诺的能力。

medium 维护活跃度未知

新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。

medium 存在评分风险

风险会影响是否适合普通用户安装。

Pitfall Log / 踩坑日志

项目:88plug/total-recall

摘要:发现 7 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:配置坑 - 可能修改宿主 AI 配置。

1. 配置坑 · 可能修改宿主 AI 配置

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主,或安装命令涉及用户配置目录。
  • 对用户的影响:安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
  • 证据:capability.host_targets | https://github.com/88plug/total-recall | host_targets=mcp_host, claude_code, claude

2. 能力坑 · 能力判断依赖假设

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:README/documentation is current enough for a first validation pass.
  • 对用户的影响:假设不成立时,用户拿不到承诺的能力。
  • 证据:capability.assumptions | https://github.com/88plug/total-recall | README/documentation is current enough for a first validation pass.

3. 维护坑 · 维护活跃度未知

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:未记录 last_activity_observed。
  • 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
  • 证据:evidence.maintainer_signals | https://github.com/88plug/total-recall | last_activity_observed missing
  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 证据:downstream_validation.risk_items | https://github.com/88plug/total-recall | no_demo; severity=medium

5. 安全/权限坑 · 存在评分风险

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 对用户的影响:风险会影响是否适合普通用户安装。
  • 证据:risks.scoring_risks | https://github.com/88plug/total-recall | no_demo; severity=medium

6. 维护坑 · issue/PR 响应质量未知

  • 严重度:low
  • 证据强度:source_linked
  • 发现:issue_or_pr_quality=unknown。
  • 对用户的影响:用户无法判断遇到问题后是否有人维护。
  • 证据:evidence.maintainer_signals | https://github.com/88plug/total-recall | issue_or_pr_quality=unknown

7. 维护坑 · 发布节奏不明确

  • 严重度:low
  • 证据强度:source_linked
  • 发现:release_recency=unknown。
  • 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
  • 证据:evidence.maintainer_signals | https://github.com/88plug/total-recall | release_recency=unknown

来源:Doramagic 发现、验证与编译记录