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

生成时间：2026-07-17 21:51:53 UTC

## 目录

- [系统架构总览](#page-1)
- [提取器管线与 17 类知识记录](#page-2)
- [本地 LLM 精炼与 sqlite-vec 向量检索](#page-3)
- [10 个 CLI 客户端适配、Hook 与运维](#page-4)

<a id='page-1'></a>

## 系统架构总览

### 相关页面

相关主题：[提取器管线与 17 类知识记录](#page-2), [本地 LLM 精炼与 sqlite-vec 向量检索](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/88plug/total-recall/blob/main/README.md)
- [docs/architecture.md](https://github.com/88plug/total-recall/blob/main/docs/architecture.md)
- [hooks/hooks.json](https://github.com/88plug/total-recall/blob/main/hooks/hooks.json)
- [total_recall/__main__.py](https://github.com/88plug/total-recall/blob/main/total_recall/__main__.py)
- [index/db.py](https://github.com/88plug/total-recall/blob/main/index/db.py)
- [index/schema.sql](https://github.com/88plug/total-recall/blob/main/index/schema.sql)
- [lib/sources/goose.py](https://github.com/88plug/total-recall/blob/main/lib/sources/goose.py)
- [lib/sources/grok.py](https://github.com/88plug/total-recall/blob/main/lib/sources/grok.py)
- [lib/cmd_rebuild.py](https://github.com/88plug/total-recall/blob/main/lib/cmd_rebuild.py)
</details>

# 系统架构总览

`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.4` 与 `sqlite-vec>=0.1.6` 提升为核心依赖，使向量索引与混合搜索"开箱即用"，无需额外 `pip install` 步骤。资料来源：[README.md:60-90]()

## 模块划分与运行时拓扑

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

- **入口与命令层**：`total_recall/__main__.py` 负责解析子命令（如 `rebuild`、`search`），并将参数路由到 `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 客户端只需实现一个适配器，而无需改动索引或检索代码。

## 数据流：重建与查询

```mermaid
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` 在重建索引时会按 `frequency` 与 `message_count` 对记录排序。v2.3.0 修复了一个崩溃：当上述字段在 SQLite 中为 NULL 时，Python 的 `<` 比较会因 `NoneType` 与 `int` 不可比较而抛出异常。修复方式是为排序键统一追加 `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）把异构对话数据收敛为可检索的统一记忆层，并以本地嵌入保证隐私边界。

---

<a id='page-2'></a>

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

### 相关页面

相关主题：[系统架构总览](#page-1), [本地 LLM 精炼与 sqlite-vec 向量检索](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [extractors/pipeline.py](https://github.com/88plug/total-recall/blob/main/extractors/pipeline.py)
- [extractors/base.py](https://github.com/88plug/total-recall/blob/main/extractors/base.py)
- [extractors/corrections.py](https://github.com/88plug/total-recall/blob/main/extractors/corrections.py)
- [extractors/decisions.py](https://github.com/88plug/total-recall/blob/main/extractors/decisions.py)
- [extractors/goals.py](https://github.com/88plug/total-recall/blob/main/extractors/goals.py)
- [extractors/bans.py](https://github.com/88plug/total-recall/blob/main/extractors/bans.py)
- [lib/db.py](https://github.com/88plug/total-recall/blob/main/lib/db.py)
- [cmd_rebuild.py](https://github.com/88plug/total-recall/blob/main/cmd_rebuild.py)
</details>

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

## 概述与设计目标

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

整个管线遵循单一职责原则：每个具体提取器只识别一种知识形态；`ExtractorPipeline` 仅负责按顺序调度、合并和落库；`Extractor` 抽象基类则提供 LLM 调用、JSON 解析和异常降级的通用能力。资料来源：[extractors/pipeline.py:1-40]()、[extractors/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'` 崩溃发生在精炼排序阶段：当 `frequency` 或 `message_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.py | URL、文档路径 |
| `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.py` 的 `CHECK` 约束保证。资料来源：[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-110]()、[extractors/corrections.py:20-60]()。

## 与下游模块的协作

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

## 扩展指南

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

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

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

---

<a id='page-3'></a>

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

### 相关页面

相关主题：[系统架构总览](#page-1), [提取器管线与 17 类知识记录](#page-2)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [docs/llm-refinement.md](https://github.com/88plug/total-recall/blob/main/docs/llm-refinement.md)
- [extractors/llm/client.py](https://github.com/88plug/total-recall/blob/main/extractors/llm/client.py)
- [extractors/llm/refine_machines.py](https://github.com/88plug/total-recall/blob/main/extractors/llm/refine_machines.py)
- [extractors/llm/refine_ontology.py](https://github.com/88plug/total-recall/blob/main/extractors/llm/refine_ontology.py)
- [extractors/llm/cache.py](https://github.com/88plug/total-recall/blob/main/extractors/llm/cache.py)
- [vec/store.py](https://github.com/88plug/total-recall/blob/main/vec/store.py)
- [cmd_rebuild.py](https://github.com/88plug/total-recall/blob/main/cmd_rebuild.py)
- [pyproject.toml](https://github.com/88plug/total-recall/blob/main/pyproject.toml)
</details>

# 本地 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-40]()、[extractors/llm/client.py:1-30]()、[vec/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-60]()、[extractors/llm/refine_ontology.py:1-60]()、[extractors/llm/cache.py:1-45]()、[extractors/llm/client.py:30-120]()。

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

在 v2.3.0 之前，`cmd_rebuild.py` 对精炼后的 `machines` 行进行排序时，使用 SQLite 返回的 `frequency` 或 `message_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.4` 与 `sqlite-vec>=0.1.6` 从可选的 `[vec]` extra 移到**核心依赖**（见 `pyproject.toml`），即安装 `total-recall` 后无需任何额外步骤即可启用向量检索。

`vec/store.py` 负责：

1. 在启动时通过 `sqlite3` 的 `enable_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-130]()、[pyproject.toml:30-55]()。

## 5. 端到端数据流

```mermaid
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-80]()、[vec/store.py:60-110]()。

## 6. 使用与运维要点

- **首次运行**：安装 `total-recall` 后，`pyproject.toml` 已经声明 `fastembed` 与 `sqlite-vec`，无需 `pip install total-recall[vec]`。`vec/store.py` 会在第一次向量写入时自动建表并下载嵌入模型。资料来源：[pyproject.toml:30-55]()`、`[vec/store.py:25-50]()`。
- **精炼可关闭**：通过环境变量 `TOTAL_RECALL_SKIP_LLM=1` 或 `cmd_rebuild` 的 `--no-llm` 标志跳过精炼阶段，仅使用原始聚合结果。资料来源：[cmd_rebuild.py:60-100]()`、`[docs/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 排序修复与向量依赖升级，是最近一次显著影响这两个子系统的变更。

---

<a id='page-4'></a>

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

### 相关页面

相关主题：[系统架构总览](#page-1), [提取器管线与 17 类知识记录](#page-2)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [lib/sources/base.py](https://github.com/88plug/total-recall/blob/main/lib/sources/base.py)
- [lib/sources/collect.py](https://github.com/88plug/total-recall/blob/main/lib/sources/collect.py)
- [lib/sources/claude_code.py](https://github.com/88plug/total-recall/blob/main/lib/sources/claude_code.py)
- [lib/sources/opencode.py](https://github.com/88plug/total-recall/blob/main/lib/sources/opencode.py)
- [lib/sources/codex.py](https://github.com/88plug/total-recall/blob/main/lib/sources/codex.py)
- [lib/sources/gemini_cli.py](https://github.com/88plug/total-recall/blob/main/lib/sources/gemini_cli.py)
- [lib/sources/goose.py](https://github.com/88plug/total-recall/blob/main/lib/sources/goose.py)
- [lib/sources/grok.py](https://github.com/88plug/total-recall/blob/main/lib/sources/grok.py)
- [cmd_rebuild.py](https://github.com/88plug/total-recall/blob/main/cmd_rebuild.py)
- [docs/install/goose.md](https://github.com/88plug/total-recall/blob/main/docs/install/goose.md)
- [docs/install/grok.md](https://github.com/88plug/total-recall/blob/main/docs/install/grok.md)
</details>

# 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 客户端**；Hook 机制负责实时增量落库，运维侧的命令（特别是 `cmd_rebuild.py`）负责全量重建与精炼。资料来源：[lib/sources/base.py]() [lib/sources/collect.py]()

## 适配器架构与基类契约

每个 CLI 客户端对应 `lib/sources/` 下的一个独立模块，所有适配器继承自同一个基类，从而保证元数据与收集接口的一致性——例如 `name`、`display_name`、`data_paths`、`is_available()`、`collect()` 等成员，并由基类负责把各家异构记录归一化为统一的内部会话格式（包含 `session_id`、`source`、`timestamp`、`role`、`content`、`cwd`、`project` 等字段）。这一“适配 + 收集”模式是新增客户端的关键解耦点。资料来源：[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 |
| `opencode` | OpenCode 数据目录 | JSONL |
| `codex` | Codex CLI 数据目录 | JSONL |
| `gemini_cli` | Gemini CLI 数据目录 | JSONL |
| `goose` | `~/.local/share/goose/sessions/sessions.db` | SQLite |
| `grok` | `~/.grok/sessions/` | JSONL（目录名 URL 解码 CWD） |

- `goose` 是首个使用 SQLite 作为后端存储的适配器，读取 `~/.local/share/goose/sessions/sessions.db` 中的会话表，由 `lib/sources/goose.py` 实现。资料来源：[lib/sources/goose.py]()
- `grok` 适配器从 `~/.grok/sessions/` 读取 JSONL 历史，并通过 URL 解码从目录名中还原工作目录 CWD，由 `lib/sources/grok.py` 实现。资料来源：[lib/sources/grok.py]()
- 其余适配器（`claude_code`、`opencode`、`codex`、`gemini_cli` 等）均以 JSONL 为主，差异主要在字段命名、嵌套结构与时间戳格式上，由各文件独立完成解析与归一化。资料来源：[lib/sources/claude_code.py]() [lib/sources/opencode.py]() [lib/sources/codex.py]() [lib/sources/gemini_cli.py]()

每个适配器都对应一份安装说明文档（`docs/install/<client>.md`），v2.2.0 新增了 `docs/install/goose.md` 与 `docs/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` 的排序键对 `frequency`、`message_count` 等可空字段改用 `or 0` 兜底，从而兼容 SQLite NULL。升级到 v2.3.0 即可解决。资料来源：[cmd_rebuild.py]()

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

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

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：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

<!-- canonical_name: 88plug/total-recall; human_manual_source: deepwiki_human_wiki -->
