<p align="center">
  <img src="./assets/logo.png" alt="Claude Persistent Memory" width="120" />
</p>

<h1 align="center">Claude Persistent Memory</h1>

<p align="center">
  <strong>让 Claude Code 拥有跨会话的持久记忆。</strong><br/>
  BM25 + 向量混合语义搜索 · LLM 驱动的结构化 · 多项目隔离
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/@alex900530/claude-persistent-memory"><img src="https://img.shields.io/npm/v/@alex900530/claude-persistent-memory?style=flat-square&color=cb3837" alt="npm"></a>
  <a href="https://github.com/MIMI180306/claude-persistent-memory/blob/main/LICENSE"><img src="https://img.shields.io/github/license/MIMI180306/claude-persistent-memory?style=flat-square&color=blue" alt="License"></a>
  <a href="https://github.com/MIMI180306/claude-persistent-memory/stargazers"><img src="https://img.shields.io/github/stars/MIMI180306/claude-persistent-memory?style=flat-square&color=yellow" alt="Stars"></a>
  <a href="https://github.com/MIMI180306/claude-persistent-memory/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/MIMI180306/claude-persistent-memory/ci.yml?style=flat-square&label=CI" alt="CI"></a>
  <img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen?style=flat-square" alt="Node >= 18">
  <img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey?style=flat-square" alt="Platform">
</p>

<p align="center">
  <a href="./README.md">English</a> | <strong>中文</strong>
</p>

<p align="center">
  <a href="#功能特性">功能特性</a> •
  <a href="#快速开始">快速开始</a> •
  <a href="#系统架构">系统架构</a> •
  <a href="#mcp-工具">MCP 工具</a> •
  <a href="#配置说明">配置说明</a> •
  <a href="#参与贡献">参与贡献</a>
</p>

---

## 功能特性

**混合搜索** — BM25 全文检索（FTS5）+ 向量语义相似度（sqlite-vec），融合排序（0.7 向量 + 0.3 BM25）

**4 通道检索** — 拉取（MCP 工具按需调用）+ 推送（通过 Hooks 在用户输入、工具调用前后自动注入）

**LLM 结构化** — 记忆自动结构化为 `<what>/<when>/<do>/<warn>` XML 格式（Azure OpenAI）

**多项目隔离** — 单个共享的 Embedding 服务器按 `dataDir` 路由请求，每个项目独立数据库，互不干扰

**自动聚类** — 相似记忆自动分组，成熟聚类合并为高置信度的合并记忆

**置信度评分** — 记忆通过验证反馈和使用频率动态调整置信度

**本地优先** — 所有数据存储在本地 SQLite，你的记忆永远不会离开你的设备

## 快速开始

### 安装

```bash
# 设置 Azure OpenAI 凭据（LLM 结构化必需）
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com"
export AZURE_OPENAI_KEY="your-api-key"

# 在任意项目中安装
npm install @alex900530/claude-persistent-memory
```

postinstall 脚本会自动：
1. 生成 `.claude-memory.config.js`（项目配置）
2. 配置 `.mcp.json`（MCP 服务器注册）
3. 配置 `.claude/settings.json`（5 个生命周期 Hooks）
4. 下载并验证 Embedding 模型（bge-m3，约 2GB）
5. 通过 launchd/systemd 注册后台服务
6. 更新 `.gitignore`

在项目目录打开 Claude Code 即可使用记忆功能。

> **提示**：Embedding 模型（约 2GB）在安装时下载并验证。如果下载中断或模型文件损坏，安装会失败。重新运行 `npm install` 即可重试。

### 后续配置

如果安装时未设置 Azure 凭据：

```bash
npx claude-persistent-memory
```

### 从源码安装

<details>
<summary>点击展开</summary>

```bash
git clone https://github.com/MIMI180306/claude-persistent-memory.git
cd claude-persistent-memory
npm install
cp config.default.js config.js
# 编辑 config.js 填入 Azure 凭据

# 启动服务
npm run embedding-server   # 终端 1
npm run llm-server         # 终端 2
```

然后手动配置 `.mcp.json` 和 `.claude/settings.json`，详见[配置说明](#配置说明)。

</details>

## 系统架构

```
┌─────────────────────────────────────────────────────────────┐
│                     Claude Code 会话                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  拉取通道（按需）                   推送通道（自动）          │
│  ┌───────────────────┐    ┌──────────────────────────────┐  │
│  │ MCP 服务器         │    │ UserPromptSubmit Hook        │  │
│  │ memory_search     │    │ PreToolUse Hook              │  │
│  │ memory_save       │    │ PostToolUse Hook             │  │
│  │ memory_validate   │    │ PreCompact Hook (分析)       │  │
│  │ memory_stats      │    │ SessionEnd Hook (聚类)       │  │
│  └────────┬──────────┘    └──────────────┬───────────────┘  │
│           │                              │                  │
│           └──────────┬───────────────────┘                  │
│                      │  dataDir 路由                        │
│                      ▼                                      │
│  ┌───────────────────────────────────────────────────────┐  │
│  │          共享 Embedding 服务器 (TCP :23811)            │  │
│  │          bge-m3 模型（跨项目共享）                     │  │
│  │          数据库连接池（按 dataDir 分项目）              │  │
│  └───────────────────────────────────────────────────────┘  │
│                      │                                      │
│       ┌──────────────┼──────────────┐                       │
│       ▼              ▼              ▼                       │
│  ┌─────────┐   ┌─────────┐   ┌─────────┐                   │
│  │ 项目 A  │   │ 项目 B  │   │ 项目 C  │                    │
│  │memory.db│   │memory.db│   │memory.db│                    │
│  └─────────┘   └─────────┘   └─────────┘                   │
│                                                             │
│  ┌───────────────────────────────────────────────────────┐  │
│  │          LLM 服务器 (TCP :23812)                      │  │
│  │          Azure OpenAI GPT-4.1                         │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

### 多项目支持

Embedding 服务器在所有项目间共享。每个请求携带 `dataDir` 参数路由到对应项目的数据库：

- **Embedding 模型** — 加载一次，所有项目共享（约 2GB 内存）
- **数据库连接** — 按 `dataDir` 池化管理，首次访问时创建（约 5ms）
- **完全隔离** — 在项目 A 中搜索永远不会返回项目 B 的记忆

## MCP 工具

| 工具 | 说明 |
|------|------|
| `memory_search` | 混合 BM25 + 向量搜索。参数：`query`、`limit?`、`type?`、`domain?` |
| `memory_save` | 保存新记忆。参数：`content`、`type?`、`domain?`、`confidence?` |
| `memory_validate` | 反馈循环 — 有帮助（+0.1）或无帮助（-0.05）。参数：`memory_id`、`is_valid` |
| `memory_stats` | 系统统计：记忆总数、类型/领域分布、聚类状态 |

## Hooks

| Hook | 事件 | 超时 | 功能 |
|------|------|------|------|
| `user-prompt-hook.js` | UserPromptSubmit | 1500ms | 嵌入用户查询，搜索，通过 stdout 注入最相关的记忆 |
| `pre-tool-memory-hook.js` | PreToolUse | 300ms | 嵌入工具上下文，搜索，通过 `additionalContext` 注入 |
| `post-tool-memory-hook.js` | PostToolUse | 300ms | 嵌入工具上下文 + 结果，搜索，通过 `additionalContext` 注入 |
| `pre-compact-hook.js` | PreCompact | 异步 | 启动 LLM 分析完整对话记录，提取记忆 |
| `session-end-hook.js` | SessionEnd | 异步 | 增量对话分析 + 聚类 + 成熟聚类合并 |

## 记忆类型

| 类型 | 用途 |
|------|------|
| `fact` | 代码库的稳定事实 |
| `decision` | 架构决策及其理由 |
| `bug` | Bug 修复和根本原因 |
| `pattern` | 常见代码模式 |
| `context` | 会话特定上下文 |
| `preference` | 用户工作流偏好 |
| `skill` | 从成熟聚类晋升而来 |

## 记忆生命周期

```
保存       → memory_save 或从对话记录自动提取
结构化     → LLM 转换为 <what>/<when>/<do>/<warn> XML
嵌入       → bge-m3 生成 1024 维向量
去重       → Jaccard 相似度 >= 0.95 → 更新已有记忆
搜索       → 0.7 * 向量相似度 + 0.3 * BM25 归一化分数
验证       → memory_validate 调整置信度 ±
聚类       → 相似记忆自动分组
合并       → 成熟聚类合并为单条高置信度记忆
```

## 卸载

```bash
npx claude-persistent-memory-uninstall
```

或手动操作：删除 `.mcp.json` 中的 `memory` 条目、`.claude/settings.json` 中的 memory hooks，然后 `npm uninstall @alex900530/claude-persistent-memory`。`.claude-memory/` 数据目录会保留，如不需要请手动删除。

## 配置说明

所有配置项在 `config.default.js` 中（通过 `.claude-memory.config.js` 覆盖）：

```js
module.exports = {
  embeddingPort: 23811,          // Embedding 服务器 TCP 端口
  llmPort: 23812,                // LLM 服务器 TCP 端口
  dataDir: './data',             // memory.db 存储目录（每个项目独立）
  azure: {
    endpoint: process.env.AZURE_OPENAI_ENDPOINT,
    apiKey: process.env.AZURE_OPENAI_KEY,
    deployment: 'gpt-4-1',
  },
  embedding: {
    model: 'Xenova/bge-m3',     // 1024 维，8192 token 上下文
    dimensions: 1024,
  },
  search: {
    maxResults: 3,               // 每次查询返回 top-K 结果
    minSimilarity: 0.6,          // 向量相似度阈值
  },
  cluster: {
    similarityThreshold: 0.70,   // 加入聚类的最低相似度
    maturityCount: 5,            // 聚类成熟所需的记忆数
  },
};
```

## 项目结构

```
claude-persistent-memory/
├── bin/
│   ├── setup.js                  # postinstall + 交互式安装
│   └── uninstall.js              # 卸载脚本
├── hooks/
│   ├── user-prompt-hook.js       # UserPromptSubmit → 记忆注入
│   ├── pre-tool-memory-hook.js   # PreToolUse → 记忆注入
│   ├── post-tool-memory-hook.js  # PostToolUse → 记忆注入
│   ├── pre-compact-hook.js       # PreCompact → 对话分析
│   └── session-end-hook.js       # SessionEnd → 聚类 + 合并
├── lib/
│   ├── memory-db.js              # SQLite + FTS5 + sqlite-vec + 连接池
│   ├── embedding-client.js       # Embedding 服务器 TCP 客户端
│   ├── llm-client.js             # LLM 服务器 TCP 客户端
│   ├── compact-analyzer.js       # 对话记录 → 记忆提取
│   └── utils.js
├── services/
│   ├── embedding-server.js       # 共享 Embedding 服务（bge-m3）
│   ├── llm-server.js             # LLM 代理（Azure OpenAI）
│   └── memory-mcp-server.js      # MCP 服务器（stdio，每项目独立进程）
├── config.default.js
└── package.json
```

## 环境要求

- Node.js >= 18
- macOS 或 Linux
- 约 2GB 内存（用于加载 bge-m3 Embedding 模型）
- 约 2GB 磁盘空间（模型缓存于 `~/.cache/huggingface/transformers-js/`）
- Azure OpenAI API 访问权限（用于 LLM 结构化）

## 注意事项

- **LLM 提供商**：目前仅支持 Azure OpenAI。如需使用其他提供商，请修改 `services/llm-server.js`。
- **端口**：Embedding 和 LLM 服务器默认使用 TCP 23811 / 23812 端口，如有冲突请在配置中修改。
- **多项目**：所有项目共享一个 Embedding 服务器进程。模型加载一次；数据库按 `dataDir` 池化管理。
- **数据存储**：`.claude-memory/` 目录（包含 `memory.db` 和日志）在各项目中自动创建并已加入 gitignore。

## 参与贡献

欢迎贡献代码！请在提交 PR 前阅读 [贡献指南](CONTRIBUTING.md)。

## 许可证

[MIT](LICENSE)
