# https://github.com/aliildan/mneme 项目说明书

生成时间：2026-06-22 23:43:15 UTC

## 目录

- [项目概述与安装配置](#page-overview)
- [索引、解析与存储引擎](#page-architecture)
- [MCP 工具、检索排序与发现模型](#page-retrieval)
- [记忆模型、GC 与跨项目检索](#page-memory)

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

## 项目概述与安装配置

### 相关页面

相关主题：[索引、解析与存储引擎](#page-architecture)

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

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

- [README.md](https://github.com/aliildan/mneme/blob/main/README.md)
- [package.json](https://github.com/aliildan/mneme/blob/main/package.json)
- [skills/mneme/SKILL.md](https://github.com/aliildan/mneme/blob/main/skills/mneme/SKILL.md)
- [slash-commands/mneme.md](https://github.com/aliildan/mneme/blob/main/slash-commands/mneme.md)
- [src/cli/commands/init.js](https://github.com/aliildan/mneme/blob/main/src/cli/commands/init.js)
- [src/mcp/server.js](https://github.com/aliildan/mneme/blob/main/src/mcp/server.js)
- [src/db/schema.js](https://github.com/aliildan/mneme/blob/main/src/db/schema.js)
- [src/mcp/tools/mneme-get-context.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-get-context.js)
</details>

# 项目概述与安装配置

## 一、项目定位与核心价值

Mneme（取自希腊神话中的记忆女神）是面向 AI 编码代理（AI coding agents）的**本地化上下文与记忆引擎**，作为 `openclaude` 项目的 MCP（Model Context Protocol）服务端伴随工具运行。整个系统以单一 Node.js 包形式分发，目标是解决 AI 代理在大型代码库中上下文检索效率低下、token 浪费严重，以及跨会话丢失已学到的经验这两个核心痛点。

资料来源：[README.md:3-13]()

| 对比维度 | 不使用 Mneme | 使用 Mneme |
| --- | --- | --- |
| 查找代码方式 | `grep` + 整文件载入提示词 | 排序后的符号 + 最小化片段，受 token 预算控制 |
| 复用历史决策 | 代理每周重新发现已学内容 | 完整还原决策、踩坑、学习、待办的原文 |
| 运行成本 | 云端 Embedding API + 全文加载 | 单个 SQLite 文件，零网络、零 Embedding 成本 |
| 跨项目隔离 | 易在不同仓库间混淆记忆 | 按项目哈希隔离，全局共享需显式提升 |

资料来源：[README.md:23-28]()

## 二、运行时架构概览

Mneme 通过 stdio 上的 MCP 协议与编码代理通信，自身不依赖外部网络即可完成索引构建与检索。下图展示了从源码到 MCP 响应的主要数据通路：

```mermaid
graph LR
  A[源码文件] --> B[tree-sitter WASM 解析]
  B --> C[符号 + 边 + 块]
  C --> D[SQLite index.db]
  E[代理调用 MCP 工具] --> F[mneme_get_context]
  F --> G[BM25 排序]
  G --> H[discovery 模型筛选]
  H --> I[按预算打包 snippet]
  I --> J[稳定前缀 + 易变元数据]
```

`mneme_get_context` 的响应被刻意分为两部分：稳定内容（`project_hash`、`symbols`、`snippets`、`token_estimate`、`fallback_reason`、`validated`）位于响应前缀，便于下游模型提示缓存命中；调用级别易变字段（`context_id`、`took_ms`）则被推到响应末尾，符合 README 中"不要破坏提示缓存"的设计原则。

资料来源：[src/mcp/tools/mneme-get-context.js:14-27]()、[README.md:140-148]()

## 三、安装与初始化

### 3.1 前置要求与分发

`package.json` 声明了运行所需的最低 Node 版本与分发字段：

- `"engines": { "node": ">=20" }` —— 要求 Node.js 20 及以上
- `"type": "module"` —— 纯 ESM 模块，无构建步骤
- `"bin": { "mneme": "bin/mneme", "mn": "bin/mneme" }` —— 安装后提供 `mneme` 与 `mn` 两条 CLI 入口

资料来源：[package.json:8-13]()

### 3.2 `mneme init` 一键安装

初始化命令会完成以下动作（在 `src/cli/commands/init.js` 中可见）：

1. 打印供 `~/.claude/settings.json` 使用的 MCP server 配置片段；
2. 调用 `installSlashCommand(root)` 把 `/mneme` 斜杠命令安装到 `.claude/commands/mneme.md`；
3. 调用 `installSkill(root)` 把技能文件安装到 `.claude/skills/mneme/SKILL.md`，该技能文档告诉代理"在 grep 之前先调用 `mneme_get_context`，在重新推导决策之前先调用 `mneme_recall_memory`"；
4. 默认调用 `installGlobalHook()`，把 PostToolUse 钩子写入 `~/.claude/settings.json`，使 Read / Edit / Write / Glob / Grep 调用触发 `mneme touch`，代理可使用 `--no-hook` 跳过这一步。

资料来源：[src/cli/commands/init.js:30-66]()、[skills/mneme/SKILL.md:5-15]()

### 3.3 斜杠命令

`/mneme` 斜杠命令调用 `mneme_list_models`（`refresh: true`），把可选项打印成编号列表，并要求用户输入编号确认（`0` 表示回退为纯确定性 BM25）。确认后调用 `mneme_set_discovery_model` 把所选模型 ID（或者 `null`）写入配置。

资料来源：[slash-commands/mneme.md:4-11]()

## 四、配置与运行参数

配置文件位于 `~/.openclaude/mneme.json`，**每次 MCP 请求都会重新读取**，因此修改后无需重启服务即可生效；解析出错时会回退默认值并打印警告。可配置的关键字段包括：

- `discoveryModel`：可选模型 ID；为 `null` 时退化为纯确定性筛选
- `router.baseUrl`：默认指向 `http://127.0.0.1:11436`，用于与本地路由通信
- `indexer.maxFileBytes`：单文件大小上限，默认 `1048576`（1 MiB）
- `indexer.ignore`：跳过目录清单，默认包含 `.git`、`node_modules`、`dist`、`build`、`.next`、`.venv`、`target`、`.mneme`
- `indexer.languages`：启用的语言插件列表（typescript / python / go / rust / php / csharp）
- `retrieval.*`：检索阶段参数

资料来源：[README.md:88-101]()

## 五、数据库结构

每个项目以哈希命名隔离，落到 `~/.openclaude/mneme/projects/<hash>/index.db`，全局记忆则写入独立的 `global.db`。`src/db/schema.js` 暴露的版本化 DDL 主要包括：

| DDL 段 | 主要表 / 索引 | 用途 |
| --- | --- | --- |
| `DDL_V1` | `meta`、`files`、`symbols`、`edges`、`merkle_nodes` | 项目文件、符号与依赖边、FTS5 全文索引 |
| `DDL_V3_CHUNKS` | `chunks`（含 `symbol_id`、`token_estimate`、`embedded_at`） | 为 `sqlite-vec` 语义检索预留块级存储 |
| `DDL_V2_MEMORY` | `memory`、`memory_fts` + 触发器 | 决策 / 踩坑 / 学习 / 待办的原文记忆 |
| `DDL_V4_OUTCOMES` | `retrieval_outcomes` | 闭环记录检索是否成功，反哺 `mneme stats` |

资料来源：[src/db/schema.js:17-120]()

## 六、命令行速查

初始化完成后，常用命令如下（节选自 README 命令参考）：

| 命令 | 作用 |
| --- | --- |
| `mneme init [--no-hook]` | 初始化项目索引、安装斜杠命令与技能、按需安装 PostToolUse 钩子 |
| `mneme reindex` | 强制全量重解析 |
| `mneme status` | 查看索引健康状况与当前配置 |
| `mneme stats` | 检索成功率、token 中位数等运营指标 |
| `mneme model [n]` | 交互式选择 discovery 模型（`0` 表示无） |
| `mneme gc [--days N]` | 手动软删除超过 N 天的记忆（默认 90 天） |
| `mneme touch` | 把项目索引标记为脏（由 Claude Code 钩子调用） |
| `mneme uninstall-hook` | 从 `~/.claude/settings.json` 中移除钩子条目 |

资料来源：[README.md:70-86]()

## 七、设计原则与已知限制

README 列出的七条核心原则强调：解析错误不静默吞掉、标识符原样存储、discovery 模型只做收窄不做决策、不破坏提示缓存、指标闭环、保持小而可组合、默认项目本地隔离。其中第五与第六条直接驱动了 `retrieval_outcomes` 表与"稳定前缀 + 易变尾部"的响应布局。

资料来源：[README.md:142-150]()

目前已知的限制包括：`sqlite-vec` 语义检索仅有脚手架（`rank-v3.js` 与 `chunks` 表），未接入 embedder；`mneme outcome <id>` CLI 尚未提供，代理直接调用 `mneme_record_outcome`；PHP/C# 还未跟踪方法所属容器（仅 Python 追踪父类）；5k+ 文件规模下的 `<200ms` 全遍历与 `<50ms p50` 检索延迟目标尚未在大仓库验证。182 项测试在约 9 秒内全部通过，可通过 `npm test` 直接复现。

资料来源：[README.md:152-170]()

## See Also

- [MCP 工具与记忆模型](./MCP工具与记忆模型.md)
- [检索与 discovery 模型](./检索与Discovery模型.md)
- [架构与数据流](./架构与数据流.md)

---

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

## 索引、解析与存储引擎

### 相关页面

相关主题：[项目概述与安装配置](#page-overview), [MCP 工具、检索排序与发现模型](#page-retrieval)

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

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

- [src/db/schema.js](https://github.com/aliildan/mneme/blob/main/src/db/schema.js)
- [src/index/validator.js](https://github.com/aliildan/mneme/blob/main/src/index/validator.js)
- [src/parser/ts-extract.js](https://github.com/aliildan/mneme/blob/main/src/parser/ts-extract.js)
- [src/parser/languages/go.js](https://github.com/aliildan/mneme/blob/main/src/parser/languages/go.js)
- [src/mcp/tools/mneme-get-context.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-get-context.js)
- [src/mcp/server.js](https://github.com/aliildan/mneme/blob/main/src/mcp/server.js)
- [README.md](https://github.com/aliildan/mneme/blob/main/README.md)
- [package.json](https://github.com/aliildan/mneme/blob/main/package.json)
</details>

# 索引、解析与存储引擎

## 概述与设计目标

mneme 是一个**本地优先**的代码上下文与记忆引擎，专注于为 AI 编码代理提供精确的符号索引与可逐字回溯的记忆库。整个索引、解析与存储管线**不依赖任何构建步骤**，采用 ESM、Node `>=20` 内置能力，并在单一 SQLite 文件中同时存放符号表与项目级记忆 资料来源：[package.json:8-38]() 资料来源：[README.md:1-50]()。

按照架构计划，索引系统已完整实现 Phase 1、2、4，并通过 tree-sitter WASM 同时支持 7 种语言（TypeScript、JavaScript、Python、Go、Rust、PHP、C#），覆盖测试 182 项、36 套件，端到端运行约 9 秒 资料来源：[README.md:50-70]()。`sqlite-vec` 语义检索管线目前处于挂起状态，当前活跃检索路径是基于符号的 BM25 全文检索 资料来源：[README.md:160-180]()。

## 文件系统扫描与脏文件检测

索引器采用 **Merkle 树**跟踪仓库内每个文件的哈希与父级目录，从而避免全量重解析。`merkle_nodes` 表记录 `(rel_path, kind, hash, parent, updated_at)`，并对 `parent` 建立索引，使增量更新只需对"脏节点"子树进行重算 资料来源：[src/db/schema.js:30-50]()。

当增量触发（例如 PostToolUse 钩子捕获到 Read/Edit/Write/Glob/Grep 调用）时，索引器执行 `validator.js` 中的三阶段流程：

1. **脏文件收集**：扫描项目根，比较 mtime_ms 与 content_hash，输出 `dirty` 与 `removed` 两个列表。
2. **逐文件提取**：对每个脏文件，依次完成 `stat` → 读取字节 → 计算内容哈希 → 调用语言检测 → 调用 tree-sitter 提取 `symbols` 与 `edges` 资料来源：[src/index/validator.js:1-50]()。
3. **单一同步事务**：在 `db.transaction(() => { ... })` 中删除已移除文件级联记录、upsert 文件元数据、替换其符号与边，最后持久化新的 Merkle 根 资料来源：[src/index/validator.js:50-80]()。

为避免污染，索引器内置默认忽略列表 `.git`、`node_modules`、`dist`、`build`、`.next`、`.venv`、`target`、`.mneme`，并跳过超过 `maxFileBytes`（默认 1 MiB）的二进制或巨型文件 资料来源：[README.md:90-110]()。

```mermaid
flowchart LR
    A[PostToolUse 钩子] --> B[validator: 收集 dirty/removed]
    B --> C[language-plugin 提取 symbols + edges]
    C --> D[单事务 upsert + replace]
    D --> E[(SQLite index.db)]
    E --> F[BM25 检索 + discovery 模型筛选]
    F --> G[MCP: mneme_get_context]
```

## 解析管线与语言插件

解析层基于 **tree-sitter WASM**，每种语言以"插件"形式暴露统一接口（`extract`、`chunkBoundaries`）。例如 Go 插件遍历 AST，遇到 `function_declaration`、`method_declaration`、`type_declaration` 时产出符号与块边界，命中后即停止下钻子树 资料来源：[src/parser/languages/go.js:1-30]()。

TypeScript 提取器则更细致：函数前的 JSDoc 块（`/** ... */`）或连续 `//` 行注释会被截取并归入 `doc` 字段（最长 2000 / 500 字符），签名按字节范围切出；并通过沿 `parent` 链回溯区分声明与函数体内部，避免把内部表达式误识别为顶层符号 资料来源：[src/parser/ts-extract.js:1-30]()。

每条符号最终规整为统一形状 `{ id, file_id, name, kind, container, start_line, end_line, exported, signature, doc }`，与 `files`、`edges` 通过外键与 `ON DELETE CASCADE` 关联，便于重解析时整文件替换 资料来源：[src/db/schema.js:50-90]()。

## SQLite 存储模型

存储层以 **SQLite** 为唯一持久化介质。所有表在初始化时通过 `DDL_V1` 一并创建，主表包括 `files`、`merkle_nodes`、`symbols`、`edges` 与 FTS5 虚表 `symbols_fts`（覆盖 `name`、`signature`、`doc` 三列，分词器 `unicode61 remove_diacritics 2`）资料来源：[src/db/schema.js:10-90]()。

为保证 FTS 与基表强一致，schema 定义了三组触发器：`symbols_fts_insert` 在 `AFTER INSERT` 时同步插入；`symbols_fts_delete` 在 `AFTER DELETE` 时同步删除；`symbols_fts_update` 在 `AFTER UPDATE` 时先删后插，确保重解析后检索结果即时生效 资料来源：[src/db/schema.js:90-150]()。

`DDL_V2_MEMORY` 在同一文件中追加 `memory` 表与 `memory_fts` 虚表，使逐字记忆（`kind`、`scope`、`forgotten_at`、`recall_count`）与符号索引共用 SQLite 但逻辑隔离，并按 `scope` 与 `kind` 区分项目级与全局级 资料来源：[src/db/schema.js:150-200]()。

`chunks` 表（Phase 3 预备）为语义检索铺路：每条记录对应一段字节区间、`token_estimate` 与 `text_hash`，并预留 `embedded_at` 列等待 `sqlite-vec` 嵌入管线接入 资料来源：[src/db/schema.js:200-230]()。当前活跃检索路径仍是 **BM25 over symbols**，`mneme_get_context` 工具按 `token_budget`（默认 6000）打包最小片段返回，并通过稳定的响应前缀（缓存敏感字段置于末尾）维持提示缓存命中率 资料来源：[src/mcp/tools/mneme-get-context.js:1-40]()。

## 常见失败模式

- **巨型文件**：超过 `maxFileBytes` 会被静默跳过并写入 `files.parse_error`，需调高阈值或拆分文件。
- **解析异常**：提取阶段抛错会被捕获并继续处理其他脏文件，单点失败不会拖垮全量重建 资料来源：[src/index/validator.js:10-30]()。
- **Merkle 漂移**：批量移动或重命名文件后，建议执行 `mneme reindex` 强制全量重建，否则依赖内容哈希的去重可能误判 资料来源：[README.md:120-140]()。

## 参见

- MCP 工具清单与请求/响应形态：[src/mcp/server.js](https://github.com/aliildan/mneme/blob/main/src/mcp/server.js)
- 检索结果封装与缓存前缀稳定性：[src/mcp/tools/mneme-get-context.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-get-context.js)
- 初始化与全局钩子安装流程：[src/cli/commands/init.js](https://github.com/aliildan/mneme/blob/main/src/cli/commands/init.js)
- Discovery 模型提示词与候选筛选：[src/retrieval/discovery-prompt.js](https://github.com/aliildan/mneme/blob/main/src/retrieval/discovery-prompt.js)

---

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

## MCP 工具、检索排序与发现模型

### 相关页面

相关主题：[索引、解析与存储引擎](#page-architecture), [记忆模型、GC 与跨项目检索](#page-memory)

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

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

- [src/mcp/server.js](https://github.com/aliildan/mneme/blob/main/src/mcp/server.js)
- [src/mcp/tools/mneme-get-context.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-get-context.js)
- [src/mcp/tools/mneme-lookup-symbol.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-lookup-symbol.js)
- [src/mcp/tools/mneme-callers.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-callers.js)
- [src/mcp/tools/mneme-callees.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-callees.js)
- [src/mcp/tools/mneme-list-memories.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-list-memories.js)
- [src/cli/commands/init.js](https://github.com/aliildan/mneme/blob/main/src/cli/commands/init.js)
- [slash-commands/mneme.md](https://github.com/aliildan/mneme/blob/main/slash-commands/mneme.md)
- [src/db/schema.js](https://github.com/aliildan/mneme/blob/main/src/db/schema.js)
- [skills/mneme/SKILL.md](https://github.com/aliildan/mneme/blob/main/skills/mneme/SKILL.md)
- [README.md](https://github.com/aliildan/mneme/blob/main/README.md)
</details>

# MCP 工具、检索排序与发现模型

## 概述

Mneme 通过 MCP（Model Context Protocol）在 stdio 上向 AI 编码代理暴露 15 个工具，核心目标是以最小 token 预算提供高精度的代码上下文与历史决策回忆。所有工具在 `src/mcp/server.js` 中以统一的 `inputSchema` 注册，并由 `bin/mneme mcp` 启动进程托管 [README.md]、资料来源：[src/mcp/server.js:1-60]()。其顶层设计原则是把"选择"留给确定性 BM25 + 预算裁剪，把"扩展候选"留给发现模型（discovery model），避免错误的上下文选择损害代理质量 [README.md]、资料来源：[skills/mneme/SKILL.md:1-15]()。

## MCP 工具一览

工具按职责分为三类，下表汇总其用途：

| 类别 | 代表工具 | 用途 |
| --- | --- | --- |
| 代码检索 | `mneme_get_context`、`mneme_lookup_symbol`、`mneme_callers`、`mneme_callees` | 按任务与 hint 在 token 预算内返回排序后的符号与最小代码片段；直查或沿依赖图 N 跳 |
| 记忆 | `mneme_record_memory`、`mneme_recall_memory`、`mneme_list_memories`、`mneme_forget`、`mneme_promote_memory`、`mneme_gc_memory`、`mneme_search_projects` | 追加、按 text/kind/scope/files/tags 查询、分页、软删除、跨项目显式提升与回收 |
| 运维 | `mneme_index_status`、`mneme_list_models`、`mneme_set_discovery_model`、`mneme_record_outcome` | 索引健康、发现模型选择、把检索结果回写 `retrieval_outcomes` 用于指标闭环 |

资料来源：[src/mcp/server.js:1-200]()、[src/mcp/tools/mneme-lookup-symbol.js]()、[src/mcp/tools/mneme-list-memories.js]()。

## 检索排序与上下文组装

`mneme_get_context` 是主入口，其 handler 在 [src/mcp/tools/mneme-get-context.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-get-context.js) 中组装响应。响应结构有意划分为"稳定内容"（`project_hash`、`symbols`、`snippets`、`token_estimate`、`fallback_reason`、`validated`）与"易变元数据"（`context_id`、`took_ms`），以保证相同输入下前缀稳定、不破坏 prompt cache 命中。资料来源：[src/mcp/tools/mneme-get-context.js:1-80]()。

排序路径当前以 BM25 over symbols 为主：`symbols` 表 + `symbols_fts` FTS5 索引提供全文打分，`token_budget` 默认为 6000、范围 500–50000，由确定性裁剪器在排序后截取最小代码片段。Phase 3 的 `sqlite-vec` 语义检索已留出 `rank-v3.js` 与 `chunks` 表的脚手架，但 embedder 尚未接入，因此 `use_discovery_model: true` 时才会调用本地发现模型进一步窄化候选。资料来源：[src/db/schema.js:1-200]()、[src/mcp/server.js:1-60]()。

`mneme_lookup_symbol` 支持按名称（可选 `kind` 过滤：function/class/method/interface/type/enum/const）直查；`mneme_callers` / `mneme_callees` 在 `edges` 表（`src_file`、`src_sym`、`dst_name`、`dst_file`、`dst_sym`、`kind`）上沿依赖图走 N 跳。调用方拿到 `context_id` 后应调用 `mneme_record_outcome` 回写 `retrieval_outcomes` 表，由 `mneme stats` 汇总成功率与中位 token 数，形成检索闭环。资料来源：[src/db/schema.js:60-140]()、[src/mcp/tools/mneme-callers.js]()、[src/mcp/tools/mneme-callees.js]()。

## 发现模型与配置

发现模型只用于"窄化候选"，不做最终决策——它把数百个候选压到几十个，再交给确定性 BM25 + 预算路径拣选，这是 README 中明文列出的设计原则之一 [README.md]。两个配置入口：

1. **CLI 交互式**：`mneme model` 调用 `/mneme` slash command，由 `init` 安装到 `.claude/commands/mneme.md`。命令体先 `mneme_list_models`（`refresh: true`）列出 Ollama + 精选 Anthropic 模型（Opus 被排除），再用编号回写 `mneme_set_discovery_model`，`0` 表示 none / 仅确定性。资料来源：[slash-commands/mneme.md:1-15]()、[src/cli/commands/init.js]()`、`[README.md]`(README.md)。
2. **配置文件**：`~/.openclaude/mneme.json` 在每次 MCP 请求时重读，`discoveryModel: null` 即关闭模型；解析失败时回退默认并记录告警，无需重启进程。资料来源：[README.md]()。

此外，`init` 默认还会安装 Claude Code PostToolUse 全局钩子，把 Read/Edit/Write/Glob/Grep 调用触发为 `mneme touch`，使索引与文件改动保持同步；可用 `mneme uninstall-hook` 回滚。资料来源：[src/cli/commands/init.js]()。

---

## See Also

- [符号提取与多语言解析（tree-sitter WASM）](symbol-extraction.md)
- [索引验证与 Merkle 增量失效](index-validation.md)
- [记忆模型与作用域隔离](memory-model.md)

---

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

## 记忆模型、GC 与跨项目检索

### 相关页面

相关主题：[MCP 工具、检索排序与发现模型](#page-retrieval)

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

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

- [src/memory/record.js](https://github.com/aliildan/mneme/blob/main/src/memory/record.js)
- [src/memory/recall.js](https://github.com/aliildan/mneme/blob/main/src/memory/recall.js)
- [src/memory/gc.js](https://github.com/aliildan/mneme/blob/main/src/memory/gc.js)
- [src/memory/promote.js](https://github.com/aliildan/mneme/blob/main/src/memory/promote.js)
- [src/mcp/tools/mneme-record-memory.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-record-memory.js)
- [src/mcp/tools/mneme-recall-memory.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-recall-memory.js)
- [src/mcp/tools/mneme-forget.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-forget.js)
- [src/mcp/tools/mneme-promote-memory.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-promote-memory.js)
- [src/mcp/tools/mneme-gc-memory.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-gc-memory.js)
- [src/mcp/tools/mneme-search-projects.js](https://github.com/aliildan/mneme/blob/main/src/mcp/tools/mneme-search-projects.js)
- [src/db/schema.js](https://github.com/aliildan/mneme/blob/main/src/db/schema.js)
- [README.md](https://github.com/aliildan/mneme/blob/main/README.md)
</details>

# 记忆模型、GC 与跨项目检索

## 设计目标与作用域

mneme 的记忆子系统是"为 AI 编程代理提供持久、可检索的工程经验"。它将代理在会话中产生的判断、踩坑、学习与待办以**逐字（verbatim）**形式落盘，供后续会话原样召回，避免代理在不同会话之间反复重新发现同一条信息。

记忆体系遵循一个核心原则：**项目本地优先，跨项目共享需显式提升**。`README.md` 明确指出"默认项目本地，绝不自动提升"——这意味着代理写入的记忆默认只对当前项目可见，只有在被 `mneme_promote_memory` 显式复制到全局作用域后，才可能被其他项目检索到。资料来源：[README.md:91-99]()

| 字段 | 取值 | 说明 |
| --- | --- | --- |
| `kind` | `decision` \| `gotcha` \| `learning` \| `todo` | 记忆的语义类别 |
| `scope` | `project` \| `global` | 项目本地或全局共享 |
| `source` | 字符串，默认 `agent` | 写入来源标识 |
| `superseded_by` | 记忆 id，可空 | 用于标记被新记忆覆盖的旧条目 |
| `forgotten_at` | 时间戳，可空 | 软删除时间，未物理删除 |
| `last_recalled_at` / `recall_count` | 时间戳 / 整数 | 用于热点排序与 GC 决策 |

资料来源：[src/db/schema.js:34-58]()

## 数据布局与 FTS5 检索

物理上存在两个 SQLite 数据库，各司其职：

- `~/.openclaude/mneme/projects/<hash>/index.db` —— 存放当前项目的符号、边、代码块以及**项目作用域**记忆。
- `~/.openclaude/mneme/global.db` —— 存放经显式提升后的**全局作用域**记忆，供跨项目检索使用。

记忆表 `memory` 上构建了 FTS5 虚表 `memory_fts`，将 `body / task / tags / identifiers / files` 纳入全文索引，实现毫秒级的 BM25 召回。`forgotten_at` 字段与多个索引（`memory_kind`、`memory_created`、`memory_forgotten`）配合，使软删除、分类筛选与时间排序都能走索引路径。资料来源：[src/db/schema.js:23-88]()

写入路径（`mneme_record_memory`）要求 `body` 必须为"原样文本，绝不意译"——`README.md` 把这一点列为强制约束，因为后续 `mneme_recall_memory` 召回的是逐字内容，意译会破坏代理再次读到时的语义保真度。资料来源：[src/mcp/server.js:55-65]() [README.md:85-87]()

## 检索、软删除与 GC

### 召回（Recall）

`mneme_recall_memory` 支持按 `text / kind / scope / files / tags` 多维过滤。底层走的是 `memory_fts` 全文索引 + 关系字段过滤的组合，而非向量相似度——这是 mneme 的有意取舍：**保持零网络依赖、零嵌入成本**，并以 `last_recalled_at`、`recall_count` 做轻量热点统计。资料来源：[src/db/schema.js:62-66]() [README.md:25-30]()

### 软删除（Forget）

`mneme_forget` 仅设置 `forgotten_at` 时间戳，**不物理删除**行。`body` 字段被刻意保留用于审计——这与"verbatim memory"原则一致：即使记忆被遗忘，它作为历史事实仍然存在。资料来源：[src/mcp/server.js:71-74]() [README.md:71-73]()

### 垃圾回收（GC）

`mneme_gc_memory` 与 CLI 命令 `mneme gc [--days N]`（默认 90 天）配合工作。GC 的对象是**长期未被召回的软删除记忆**：通过对比 `forgotten_at` 与当前时间，超过阈值的条目才会被清理。活记忆（`forgotten_at IS NULL`）不受 GC 影响。资料来源：[README.md:113-122]() [src/db/schema.js:54-58]()

```mermaid
flowchart LR
  A[代理写入] --> B[mneme_record_memory]
  B --> C{scope = project ?}
  C -- 是 --> D[index.db / memory]
  C -- 否 --> E[global.db / memory]
  D --> F[memory_fts 索引]
  E --> F
  G[后续会话] --> H[mneme_recall_memory]
  H --> F
  F --> I[逐字返回]
  J[mneme_promote_memory] -- 显式复制 --> D
  J --> E
  K[mneme_forget] -- 设置 forgotten_at --> D
  K --> E
  L[mneme_gc_memory / mneme gc] -- 清理过期软删除 --> D
  L --> E
```

## 跨项目检索与隔离

跨项目能力由 `mneme_search_projects` 提供，且**仅作用于记忆，绝不返回代码**。这是 mneme 显式划定的边界：符号索引按项目哈希隔离，跨项目共享的只有"代理学到的工程经验"——避免把 A 项目的私有实现细节泄露到 B 项目的上下文中。资料来源：[README.md:68-74]()

跨项目共享的合法路径只有一条：

1. 代理在 A 项目中调用 `mneme_promote_memory`，将该条记忆从 `index.db` 复制到 `global.db`。
2. B 项目的代理在 `mneme_recall_memory` 中指定 `scope: "global"`，或调用 `mneme_search_projects` 拉取命中。

整个流程没有"自动同步"或"隐式合并"——任何跨项目可见性都源自一次**显式的人类或代理决策**。资料来源：[README.md:91-99]()

## 常见误区与失败模式

- **以为 GC 会清空所有旧记忆**：GC 只处理已被 `forget` 软删除的条目；活跃记忆永不回收。
- **在意译后写入 `body`**：召回返回的是原始字符串，意译会污染后续会话的语义保真度。
- **把项目级记忆当作全局共享**：项目记忆默认隔离，必须显式 `promote` 后才在 `global.db` 出现。
- **跨项目检索时期待拿到符号或代码**：`mneme_search_projects` 严格只返回记忆，代码召回仍由 `mneme_get_context` 在项目本地完成。
- **GC 阈值设得过短**：默认 90 天是为审计追溯保留窗口，调低会过早丢失历史决策的原文。

## 参见

- 符号索引与 FTS5 检索：[src/db/schema.js](https://github.com/aliildan/mneme/blob/main/src/db/schema.js)
- MCP 工具与提示词契约：[src/mcp/server.js](https://github.com/aliildan/mneme/blob/main/src/mcp/server.js)
- 项目总览与设计原则：[README.md](https://github.com/aliildan/mneme/blob/main/README.md)
- `/mneme` 斜杠命令与发现模型选择：[slash-commands/mneme.md](https://github.com/aliildan/mneme/blob/main/slash-commands/mneme.md)

---

<!-- evidence_pipeline_checked: true -->

---

## Doramagic 踩坑日志

项目：aliildan/mneme

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

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

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

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

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

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

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/aliildan/mneme | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/aliildan/mneme | no_demo; severity=medium

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

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

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

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

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

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

<!-- canonical_name: aliildan/mneme; human_manual_source: deepwiki_human_wiki -->
