内容
<div align="center">
# 联合内存
**Claude 代码记住每个项目。联合内存使得它所学到的内容可以在每个仓库中为您提供帮助:通过实际结果评分,当您的代码更改时失效,在实时仪表板上可观察。**
[](https://github.com/kirti34n/unified-mem/actions/workflows/ci.yml)
[](https://nodejs.org)
[](LICENSE)
<img src="docs/demo.gif" width="90%" alt="一个全新的 Claude Code 会话,直接从保险库中回答过去的 401 次突发事件,引用了跨仓库的两个关联笔记,然后打开一个文件">
**[点击访问实时仪表板](https://kirti34n.github.io/unified-mem/demo-site/)**: 真实的 UI,无需安装,虚构的数据。
<img src="docs/screenshots/sessions.png" width="82%" alt="仪表板:每个会话,注入了什么内存,每个笔记赚取的实用性评分">
</div>
**目录:** [问题](#问题) · [我们构建的内容](#我们构建的内容) · [它如何帮助您](#它如何帮助您) · [它如何工作](#它如何工作) · [结果](#测量结果) · [仪表板](#仪表板) · [安装](#安装) · [比较](#比较) · [深入了解](#深入了解)
## <img src="docs/icons/target.svg" width="22" height="22"> 问题
Claude 代码自带良好的 [内置内存](https://code.claude.com/docs/en/memory):每个项目的自动内存,加载每个会话,CLAUDE.md 指令层次结构,以及用于继续对话的 `--resume`。联合内存不会取代任何这些功能。它解决了内置层无法做到的三个问题:
1. **跨仓库盲点。** 自动内存仅限于一个仓库。在 `api-core` 中修复的耗时两个小时的竞态条件,在 `web-app` 中第二天就不可见了。因此,同类 bug 导致的同样耗时两个小时的修复代价再次出现。修复、注意事项、约定和个人偏好都在仓库边界停止生效。
2. **没有学习循环。** 没有任何机制衡量记住的事实是否真正有帮助。保存会话的笔记和从未被任何人受益的笔记被同等对待,永远如此。无法自我评估的内存最终会注入噪音,研究表明,不相关的上下文会积极降低模型性能。
3. **没有过期处理。** 没有任何机制注意到当内存所描述的代码被重写时。记住的修复如果不再匹配现实,比没有内存还要糟糕,它会被自信地应用。
## <img src="docs/icons/layers.svg" width="22" height="22"> 我们构建的内容
一个包含小 markdown 笔记(每个声明,每个带有提交和文件出处)的保险库,每个 Claude 代码会话在每个仓库中都写入并读取它。零依赖:纯 Node 内置函数加上 SQLite 全文搜索,保险库是一个您拥有的 git 仓库。
| 组件 | 功能 |
|---|---|
| 三个钩子 | SessionStart 注入内存目录、此仓库的概览卡和固定偏好;UserPromptSubmit 注入与您实际输入的内容匹配的笔记;SessionEnd 队列完成后的记录 |
| 后台工作线程 | 将每个完成的会话提炼成键入的笔记(精确的错误字符串和版本保留原样),然后根据会话的实际结果为每个注入的笔记评分 |
| 每夜作业 | 衰减未使用的笔记,重新验证引用的文件已更改的笔记,仲裁近似重复项,自动链接知识图,重新构建仓库卡 |
| 个人层 | `vault_remember`(MCP 工具或 CLI)将您的偏好固定到每个会话中;`ingest.mjs` 将您自己的文档分段,以便在提示触及时显示 |
| 实时仪表板 | 每个注入、每个评分更改、每个合并作为红/绿差异,以及成本和放弃遥测 |
| 评估框架 + 调整器 | 一个 A/B 框架衡量内存与无内存控制的性能,一个有保护的循环仅在 14+ 个样本的 A/B 显示严格正确性改进时调整检索设置 |
它相对于您已经拥有的内容的位置:
| 层 | 范围 | 持有 | 学习? | 过期? |
|---|---|---|---|---|
| [会话记录](https://code.claude.com/docs/en/sessions) (`--resume`) | 一个对话 | 完整历史 | 否 | 否 |
| [CLAUDE.md 层次结构](https://code.claude.com/docs/en/memory) | 用户/项目 | 您的指令 | 否 | 手动 |
| [自动内存](https://code.claude.com/docs/en/memory) | 一个仓库 | 项目事实 | 启发式 | 无 |
| **联合内存** | **所有仓库** | 持久、有验证的知识 | **从结果中学习** | **git-diff 失效 + 重新验证** |
## <img src="docs/icons/zap.svg" width="22" height="22"> 它如何帮助您
**已解决的问题将保持解决状态。** 输入“为什么这些 401 次在负载下间歇性出现?”并修复它的会话中的笔记在探索开始前就在 Claude 的上下文中:根本原因、确切的修复、提交哈希、关于锁 TTL 的注意事项。在我们的测量运行中,对比臂的最慢错误大约花了 90 秒搜索仓库,仍然得到了错误的答案,而内存从笔记中回答,耗时约 12 秒。
**一次性设置偏好并永久保存。** “记住我更喜欢 pnpm”(在对话过程中通过 `vault_remember` 或 `npm run remember` 从 shell)将该规则固定到未来每个仓库中的每个会话。导入您的样式指南一次,正确的部分就会在提示触及时出现。
**过时的建议会自动失效。** 每个笔记都引用了它所关心的文件。当这些文件更改时,每夜作业会标记笔记,重新读取当前代码,并使用廉价模型恢复或淘汰它。自信但过时的修复成为可见的审查队列。
**无用的笔记会自动消失。** 笔记通过可验证的结果(测试通过,构建绿色)赚取实用性,由一个固定的评分标准根据助手实际执行的操作进行判断。有用的笔记升起并赢得更多的注入;无贡献的笔记以每周 5% 的速度衰减并被存档。保险库趋于平稳,而不是无限增长。
**不相关的提示将保持沉默。** 设计上,“嘿,可以请你解决这个问题吗?”不会注入任何内容,通过频率感知相关性门控。大约一半的真实会话接收零笔记,仪表板显示放弃率,关于保险库不知道的主题的提示被记录为差距,您可以看到它的盲点。
**成本将被限制,而不是期望。** 每个管道 LLM 调用都通过一个预算守护路径,带有本地成本分类账。每日硬上限(默认为 $5),用于小作业的廉价模型调用,内部调用永远不会触发对自身的反射。
## <img src="docs/icons/cpu.svg" width="22" height="22"> 它如何工作
1. **捕获。** SessionEnd 队列记录。工作线程将任何持久的内容提炼成笔记:一个声明,最多 150 个字,键入(`recovery`、`strategy`、`optimization`、`decision`、`convention`),模式门控,秘密扫描,来源戳记。常规会话正确地产生零笔记。
2. **检索。** 每个笔记通过 `0.40·similarity + 0.30·usefulness + 0.15·recency + 0.15·validity` 排名(BM25 全文搜索您的提示和 git 上下文)。积极的底线意味着除非它确实相关或反复证明自己,否则不会有任何内容被带入。
3. **学习。** 在可验证的结果上,每个注入的笔记的 Q 值都会发生变化:`Q ← clamp(Q + α·c·(r − Q))`,其中贡献 `c` 来自一个固定的裁判,读取助手的输出。防护措施:每个会话的增量上限、钳制、非模糊结果无更新、纯粹的勾选不是成功信号。
4. **维护。** 每夜:git-diff 失效、两步验证、重复仲裁(重复/更新/共存)、衰减、存档、图自动链接、实体中心、仓库卡。
5. **衡量。** A/B 框架证明价值与具有完全仓库访问权限的控件相比,并且改进循环仅在 14+ 个样本和高于噪声的胜利时调整配置。
<details>
<summary><b><img src="docs/icons/share.svg" width="16" height="16"> 机械图</b>(点击展开)</summary>
```mermaid
flowchart LR
subgraph session [Claude Code 会话,任意仓库]
A[SessionStart<br/>retrieve.mjs] -->|偏好 + 目录<br/>+ 仓库卡| B((会话))
P[UserPromptSubmit<br/>retrieve-prompt.mjs] -->|即时笔记| B
B --> C[SessionEnd<br/>enqueue.mjs]
end
C -->|队列/| D[worker.mjs<br/>结果评分器 + 裁判 + 反射器]
D -->|新笔记| V[(保险库<br/>markdown + SQLite FTS5)]
V --> A
V --> P
N[consolidate.mjs<br/>每夜] -->|衰减 · 验证 ·<br/>仲裁 · 仓库卡| V
E[eval/run.mjs] --> I[improve.mjs] -->|调整| K[config.json] --> A
```
</details>
<details>
<summary><b><img src="docs/icons/file-text.svg" width="16" height="16"> 会话接收的内容</b>(点击展开)</summary>
在会话开始时,一个紧凑的地图代替数据转储:
```
联合跨仓库内存。这是冷启动目录;匹配的笔记
自动加载每个提示,vault_search 显式拉取,vault_remember 保存个人偏好。
个人偏好(在每个仓库中应用):
- 在每个项目中使用 pnpm,而不是 npm 或 yarn。
内存目录(按仓库的笔记):api-core(4)· web-app(2)· auth-service(1)
此仓库,有什么以及正在发生:
- 分支:main 最近:修复速率限制器;旋转签名密钥
知识库(4 个笔记,按实用性):...
```
当提示与保险库中的内容匹配时:
```
与此提示匹配的保险库笔记(对照当前代码验证):
## JWT 刷新竞赛导致 401 次突发
(仓库:api-core · 文件:src/auth/token.ts · 提交:8f3ab21)
**问题:** 平行请求刷新相同的过期 JWT 比赛...
**修复:** Redis SETNX 锁键控用户 ID(提交 8f3ab21)。50ms 重试,5s TTL。
**注意事项:** 锁 TTL 必须超过 p99 刷新延迟。
```
始终以事实性的语气,带有出处,而不是指令,始终标记以对照当前代码验证。所有八种机制的详细说明:[docs/MECHANISMS.md](docs/MECHANISMS.md)。
</details>
## <img src="docs/icons/flask.svg" width="22" height="22"> 测量结果
内存与诚实竞争:控制臂具有完全的仓库访问权限,可以自由重新导出每个答案。九个问题(六个来自真实事件,三个负面探测)跨五个仓库,每个运行两次,由固定的正则表达式评分,并带有“不知道”的非答案作为失败:
| | 内存 | 控制(仓库访问,关闭联合内存) |
|---|---|---|
| 正确 | **15/18(83%)** | 8/18(44%) |
| 中位数延迟 | 12.3s | 11.9s |
| 负面探测(诚实度) | 5/6 | 5/6 |
差距是重点:通过完全的仓库访问,对比臂重新推导答案的几率为 44%;有匹配的笔记在上下文中,几率为 83%。三个事件(一个 Windows kill-by-port 修复,一个硬编码的日期过滤器,一个 SQLite busy-timeout)控制失败了两次,而内存回答了两次。一个事件(一个 PowerShell 美元吞咽 bug)两个分支都没有,因为保险库中没有笔记:这是现实的内存系统的诚实形状,而不是 100% 的标题。延迟几乎相同,内存没有降低诚实度探测。这是一个九个问题、单个保险库的演示运行,而不是基准测试;该框架在盒子里,因此您可以衡量自己的历史记录 ([docs/EVAL.md](docs/EVAL.md))。
## <img src="docs/icons/monitor.svg" width="22" height="22"> 仪表板
`localhost:7777` 上的六个实时视图:
- <img src="docs/icons/map.svg" width="15" height="15"> **仓库**:内存所知的每个仓库,每个仓库启用/禁用(在第一个会话上自动注册)
- <img src="docs/icons/list.svg" width="15" height="15"> **会话**:每个会话接收的内容以及每个笔记赚取的 Q 增量
- <img src="docs/icons/share.svg" width="15" height="15"> **笔记图**:通过共享实体链接的原子笔记,按学习的有用性大小
- <img src="docs/icons/trend.svg" width="15" height="15"> **Q 演化**:学习中的有用性;上升线帮助,下降线衰减至存档
- <img src="docs/icons/diff.svg" width="15" height="15"> **合并日志**:每次验证、衰减和合并的精确红/绿差异
- <img src="docs/icons/database.svg" width="15" height="15"> **指标**:过期检索率、放弃率、保险库大小趋势、与每日预算的支出
## <img src="docs/icons/info.svg" width="22" height="22"> 安装
**作为插件(推荐,两个命令)。** 在 Claude 代码内部:
```
/plugin marketplace add kirti34n/unified-mem
/plugin install unified-mem@unified-mem
```
这会连接三个钩子和 `vault_search` / `vault_remember` MCP 工具,用于每个仓库,现在和将来。您的保险库位于 `~/.unified-mem/vault`(在插件之外,因此它在更新后存活)。 需要 Node 22.13+ 在您的 PATH 上。插件涵盖了会话部分(注入内存,队列完成会话);要将这些队列会话转换为笔记并运行每夜维护,请启动工作线程和合并器(下一节,或根据 [FAQ](docs/FAQ.md) 中的内容进行调度)。
**先试试仪表板(60 秒,无需安装):**
```bash
git clone https://github.com/kirti34n/unified-mem && cd unified-mem
node scripts/init.mjs # 创建您的保险库:它自己的 git 仓库,与此 checkout 分开
node scripts/seed.mjs # 六周的虚构演示历史以供探索
node scripts/dashboard.mjs # 然后打开 http://localhost:7777
```
<details>
<summary><b>手动安装</b>(无需插件系统)</summary>
`~/.claude/settings.json` 中的三个钩子涵盖您拥有的每个仓库和您以后创建的每个仓库(合并到现有的 `"hooks"` 块;使用您克隆到的路径):
```jsonc
{
"hooks": {
"SessionStart": [{ "hooks": [{ "type": "command",
"command": "node \"/path/to/unified-mem/scripts/retrieve.mjs\"", "timeout": 10 }] }],
"UserPromptSubmit": [{ "hooks": [{ "type": "command",
"command": "node \"/path/to/unified-mem/scripts/retrieve-prompt.mjs\"", "timeout": 5 }] }],
"SessionEnd": [{ "hooks": [{ "type": "command",
"command": "node \"/path/to/unified-mem/scripts/enqueue.mjs\"", "timeout": 5 }] }]
}
}
```
对话工具是可选的(钩子已经在没有它们的情况下注入内存)。注册 MCP 服务器以添加 `vault_search` 和 `vault_remember`:
```bash
claude mcp add --scope user vault-search -- node "/path/to/unified-mem/scripts/mcp-server.mjs"
```
</details>
**启动学习循环并导入您的历史记录。** 补丁是最好的部分:您的保险库开始加载您自己的调试历史记录为空。
```bash
node scripts/worker.mjs --watch # 将完成的会话转化为笔记
node scripts/consolidate.mjs # 每夜维护(cron / Task Scheduler 行在 FAQ 中)
node scripts/backfill.mjs # 挖掘您过去的会话记录成笔记
node scripts/seed.mjs --purge-demo # 丢弃演示数据,一旦真实笔记流动
node scripts/remember.mjs "Prefer pnpm over npm everywhere" # 您的第一个固定偏好
```
仓库在第一次会话时自动注册(每个钩子都是用户级),因此新旧仓库在您在其中打开 Claude 代码时都会被覆盖;在仪表板的仓库视图中管理它们,包括每个仓库的禁用。
Repos 自动注册(每个钩子都是用户级),因此新的和旧的repos都将在您打开Claude Code时被覆盖;从仪表板的Repos视图中管理它们,包括每个仓库的禁用。
所有管道调用(反思的 sonnet,廉价模型的判断和验证)都通过 Claude CLI 进行:本地无内容,独立无内容。每个旋钮(预算,地板,模型,封顶)都在 [docs/CONFIG.md](docs/CONFIG.md) 中记录。
## <img src="docs/icons/life-buoy.svg" width="22" height="22"> 比较
| | 范围 | 从结果中学习 | 过期处理 |
|---|---|---|---|
| Claude 代码 [自动内存](https://code.claude.com/docs/en/memory) | 一个仓库 | 否 | 无 |
| [claude-mem](https://github.com/thedotmack/claude-mem) | 全局存储;按项目自动回忆(跨项目通过手动搜索) | 否 | 无 |
| [Mem0](https://docs.mem0.ai/integrations/claude-code)(Claude 代码插件) | 跨工具,云优先 | 编写时更新,不是结果评分 | 矛盾解决,不是代码感知 |
| [memsearch](https://milvus.io/blog/adding-persistent-memory-to-claude-code-with-the-lightweight-memsearch-plugin.md) | 每个项目(会话 + 蒸馏笔记) | 否 | 无 |
| **联合内存** | [所有仓库](docs/MECHANISMS.md#the-layering-premise) | [有裁判和衰减](docs/MECHANISMS.md#3-q-learning-how-usefulness-is-earned) | [git-diff 失效 + 重新验证](docs/MECHANISMS.md#4-staleness-the-biggest-accuracy-lever) |
事实和互补:指令保留在 CLAUDE.md 中,项目工作内存保留在自动内存中,反射器被明确告知不要干预项目本地上下文。
## <img src="docs/icons/book-open.svg" width="22" height="22"> 深入了解
[机制](docs/MECHANISMS.md) · [配置](docs/CONFIG.md) · [FAQ](docs/FAQ.md) · [评估方法](docs/EVAL.md) · [研究](docs/RESEARCH.md) · [路线图](docs/ROADMAP.md) · [设计文档](docs/PLAN.md)
## <img src="docs/icons/shield.svg" width="22" height="22"> 许可
[MIT](LICENSE)。 捆绑的第三方组件(PrismJS)列在 [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md) 中。
</div>
</div>