内容
<img src="assets/ghost.png" alt="Ghost" width="120" align="right" />
**Claude Code、Cursor 及任何 MCP 客户端的 MCP 内存服务器。纯 Go 语言。单个二进制文件。不需要外部服务。**
您的代理的内存,存储在您的磁盘上 — 不需要云服务,不需要账号,不需要订阅。一个 SQLite 文件归您所有。
[](https://github.com/wcatz/ghost/actions/workflows/ci.ymlRelease](https://img.shields.io/github/v/releasez/ghost)](https://github.com/wcatz/ghost/releases/latest)
[
[](<!-- TODO: asciinema demo — `ghost mcp init` + a session-start context injection -->
---
##开始
两个命令。不需要账号,不需要密钥,不需要 docker-compose,不需要向量数据库。
```bash
go install github.com/wcatz/ghost/cmd/ghost@latest
ghost mcp init
```
`ghost mcp init` 将 Ghost 注册为 MCP 服务器,安装会话启动钩子,**迁移您现有的 Claude Code 内存** — 已经知道的项目在初始化时导入,其余的在第一次 `ghost_project_context` 调用时自动导入(只读,不会丢失任何数据)— 并禁用内置文件内存,以免两者冲突。它是幂等的和非破坏性的 — 可以随时安全地重新运行,并且 `--dry-run` 预览每一次更改。
然后启动一个会话。Ghost 自动注入您的项目上下文并开始记忆。
没有 Go 工具链?从 [Releases](https://github.com/wcatz/ghost/releases/latest) 获取预编译的二进制文件 — 支持 linux、macOS 和 Windows,amd64 和 arm64,并附有 `checksums.txt`。从源代码构建需要 Go 1.26+(较旧的工具链通过 `GOTOOLCHAIN=auto` 自动获取)。
**使用 Cursor、Goose 或其他 MCP 客户端?** Ghost 通过 stdio 使用标准 MCP — 任意客户端都可以指向该二进制文件:
```json
{ "mcpServers": { "ghost": { "type": "stdio", "command": "ghost", "args": ["mcp"] } } }
```
**Docker**(多架构,amd64 + arm64):
```bash
docker run -i -e XDG_DATA_HOME=/data -v ghost-data:/data ghcr.io/wcatz/ghost:latest
```
`-i` 很重要 — MCP 通过 stdio 通信,而 `XDG_DATA_HOME=/data` 使得卷实际存储 `ghost.db`。为了合并,请对同一个卷运行 `reflect`(MCP 服务器本身从不使用 API 密钥):
```bash
docker run -i -e XDG_DATA_HOME=/data -v ghost-data:/data \
-e ANTHROPIC_API_KEY=sk-ant-... ghcr.io/wcatz/ghost:latest reflect myproject --apply
```
## 为什么不使用内置内存?
ChatGPT、Claude、Gemini 和 Copilot 都内置了内存 — 但每个内存都是封闭在其自己的产品中。您教给 ChatGPT 的内容不会转移到 Claude Code 中,Claude Code 学到的内容也不会转移到 Cursor 或 Goose 中。Ghost 的赌注不是“比任何一个都好” — 而是**一个**内存,跨越每个 MCP 客户端,存储在您自己的磁盘上:一个本地 SQLite 文件,您可以查询、备份和删除,而不是每个产品都有的独立存储。参见下面的[为什么选择 Ghost?](#为什么选择Ghost)以了解与 Claude Code 内置内存的具体比较。
## 为什么选择 Ghost?
编码代理在会话之间会忘记一切。您每天都会重新解释您的架构、约定和那个与暂存数据库相关的陷阱。
Claude Code 的内置内存是一个 markdown 文件,加载窗口有限(约 200 行)。没有搜索,没有分类,没有重复数据删除,内存被每个仓库。Ghost 用一个真正的内存系统取代它:
| | Claude Code 内置 | Ghost---|---|---|
| 存储 | 平坦的 `.md` 文件,加载窗口有限 | SQLite + FTS5,无限制 |
| 搜索 | 无(线性加载) | 全文 + 可选本地向量搜索 |
| 分类 | 无 | 8 个类别,重要性评分 |
| 重复数据删除 | 无(永远追加) | 基于 FTS 的更新 — 保存时| 合并 | 无 | Haiku LLM 或本地 Jaccard 层 |
| 时间衰 无(旧事实同样存在) | 分类感知:约定永不衰减,陷阱逐渐消失 |
| 跨项目 | 无(每个仓库隔离) | `ghost_search_all` + `_global` 项目 |
| 内存图 | 无 | 自动链接相关内存,Obsidian 中的图形视图 |
| 客户端 | 仅 Claude Code | 任意 MCP 客户端 |
切换会将您现有的 Claude Code 内存迁移到 Ghost — 在初始化时或首次联系时。不会丢失任何数据。
## 性能比较
Ghost 的赌注:内存系统应该**小于**它所记忆的内容。其他方案使您在云内存服务(您的代码库的上下文在别人的服务器上,按请求计费)和自托管堆栈(Postgres 加向量数据库,在您保存单个内存之前)之间做出选择。
据我们所知,Ghost 是唯一一个将本地混合向量 + 全文搜索、自动合并、时间衰减评分和内存图打包成单个零基础设施二进制文件的内存系统。截至 2026 年 7 月,该领域的状况 — 欢迎纠正,[请提交问题](https://github.com/wcatz/ghost/issues):
| | 安装内容 | 向量搜索 | 合并 | 时间衰减 | 内存图 | 任意 MCP 客户端 |
|---|---|---|---|---|---|---|
| **Ghost** | 一个静态 Go 二进制文件 | 本地(Ollama,可选) | 是 | 是 | 是 | 是 |
| Engram | 一个 Go 二进制文件 | 否(仅 FTS 否 | 否 | 否 | 是 |
| claude-mem | npm 包 | 是 | 是 | 否 | 否 | 仅 Claude Code |
| Mem0(自托管) | FastAPI + Postgres + Qdrant/Neo4j | 服务器端 | 是 | 否 | 图形变体 | 通过 OpenMemory(Docker) |
| basic-memory | Python(AGPL) | 是 | 手动捕获 | 否 | 维基链接 | 是 |
Mem0、Zep 和 supermemory 是优秀的托管产品 — 但自托管它们意味着运行一个服务栈。如果您只需要一个二进制文件中的全文搜索,Engram 是一个不错的、更简单的选择。
## 您应该问的问题
### 我的数据存储在哪里?
一个 SQLite 文件存储在 `~/.local/share/ghost`(或 `$XDG_DATA_HOME/ghost`)。Ghost 在正常操作中不进行任何网络调用,但有三个例外您可以控制:**本地** Ollama 用于嵌入(可选),Claude API **仅在**您使用 Haiku 层运行 `ghost reflect` 时(需要 `ANTHROPIC_API_KEY`;SQLite 层完全离线),以及 GitHub API **仅在**您运行 `ghost upgrade` 时。就是这个列表。
### 哪些内容会注入到我的代理上下文中?
一个有界的摘要,您可以自己检查。会话启动钩子发出:项目名称、顶级内存、学习上下文、开放任务和活动决策。全局内存(`_global` 项目)即使在 cwd 与已知项目不匹配时也会被注入。查看您的代理看到的内容:
```bash
echo '{"cwd":"'"$PWD"'"}' | ghost hook session-start
```
系统中没有神秘的 blob。保存时重复数据删除可以防止摘要膨胀,时间衰减评分会根据仍然正确的内容对 `ghost_project_context` 和资源读取进行加权。
### 出口故事是什么?
您的内存是一个纯粹的 SQLite 数据库,存储在一个文件中。使用 `sqlite3` 打开它,使用任何工具查询它,使用 `cp` 备份它。没有专有格式,不需要导出请求表单。架构是一个可读的 Go 字符串常量,位于 [`internal/memory/schema.go`](internal/memory/schema.go) 中。如果您明天停止使用 Ghost,您的内存将以一种将比我们都长寿的格式存储在那里。
切换 **进入** 也很简单:`ghost mcp init` 导入 Claude Code 内存,甚至无需运行 init,Ghost 也会在第一次 `ghost_project_context` 调用时自动导入(只读)具有零内存的项目。
### 关闭开关在哪里?
- **每个客户端:** 从您的 MCP 配置中删除 `ghost` 条目。Ghost 仅在客户端通过 stdio 启动它时运行 — 没有守护进程。
- **嵌入:** 在 `~/.config/ghost/config.yaml` 中设置 `embedding.enabled: false`。
- **合并:** 除非您调用 `ghost reflect` — 而且这是一个干燥运行,除非您传递 `--apply`。
- **所有内容:** 删除 `$XDG_DATA_HOME/ghost`,或当 `XDG_DATA_HOME` 未设置时删除 `~/.local/share/ghost`。除此之外什么都没有。
### 运行它需要多少成本?
$0/月。没有计费 API 在热路径中。整个代码库中唯一的付费调用是可选的 Haiku 合并层 — 而且它有一个免费的离线备用。
## 它是如何工作的
Ghost 是一个内存管道:**保存 → 嵌入 → 链接 → 搜索 → 合并 → 衰减**。
### 8 个内存类别
`architecture` · `decision` · `pattern` · `convention` · `gotcha` · `dependency` · `preference` · `fact` — 由 SQLite CHECK 约束强制执行,而不是凭感觉。保存近似值会加强现有的内存,而不是积累副本(FTS 重叠去重,相同类别)。
### 混合搜索
全文(FTS5)和向量结果使用 Reciprocal Rank Fusion(k=60)融合,权重为 70% 向量 / 30% FTS。后台工作器将相似的内存(余弦 ≥ 0.70)链接成一个图,该图支持 Obsidian 镜像的图形视图和未来的链接感知功能;链接在合并重写内存后自我修复。存在一个实验性的图扩展排名奖励,但已禁用 — 我们的基准测试 sweep(`ghost bench --sweep`)显示它会降低精确匹配的排名,因此在重新设计击败该测量之前,它将保持关闭状态 ([方法论](docs/benchmarks.md))。
向量来自本地 Ollama 实例(`nomic-embed-text:v1.5`,768 维),如果实例正在运行。**没有 Ollama?没有错误,没有设置步骤** — Ghost 具有 FTS5 搜索功能齐全,当 Ollama 出现时静默升级到混合搜索:
```bash
ollama pull nomic-embed-text:v1.5
```
### 时间衰减评分
关于您的堆栈的事实不应过期。上个月的调试绕道应该。分数乘子是 `max(floor, 1 / (1 + age_days / scale))`:
| 类别 | 衰减 | 底线 |
|---|---|---|
| `preference`、`convention`、`fact` | 从不 | — |
| `architecture`、`pattern` | 45 天刻度 | 0.3 |
| `decision`、`gotcha`、`dependency` | 30 天刻度 | 0.15 |
固定记忆在上面获得 1.5 倍的提升。
### 可撤销的合并
`ghost reflect` 合并重复项,修剪噪音,并将跨项目知识提升到全局范围。分层:Claude Haiku 首先(需要 API 密钥;成本与内存数量成比例 — 粗略估计为 0.001 美元,用于一个典型的项目,Haiku 4.5 的每个令牌定价估计,而不是测量),然后是完全离线的 SQLite 层(Jaccard ≥ 0.5,相同类别合并)。由于 LLM 重写您的内存存储很可怕,因此防护措施是分层的:
- **默认干燥运行** — 在应用之前查看差异
- **每次替换前自动快照**,每个项目保留 3 个最近的快照;`ghost reflect --restore` 是撤销按钮
- **空集拒绝** — 存储层永远不会用空值替换您的内存
- **质量门控** — 在自动模式下,输出缩小到输入的 30% 以下会被拒绝,并尝试下一个层(当输入 ≥ 6 内存时)
- **手动保存的内存始终保留**
### 任务、决策和全局内存
除了内存之外:任务(`pending`/`active`/`done`/`blocked`)、决策记录以及理由和替代方案 (`active`/`superseded`/`revisit`),以及一个 `_global` 项目,其内存包含在每个项目的上下文中。项目通过最长路径前缀匹配和基准名回落来解析,因此工作树和移动的检出仍然可以找到它们的内存。
### Obsidian 保险库镜像
您的内存属于您,可以浏览。`ghost obsidian export` 将内存、决策和任务镜像到纯 Markdown 笔记中 — 一个文件夹对应一个项目 — Obsidian 以保险库的形式打开,内存链接呈现为 wikilinks,因此图形视图映射您的知识。`ghost obsidian sync` 通过轮询数据库更改来保持镜像新鲜;`--project` 将镜像范围限定在一个项目(加上全局)。镜像是单向的:它只读访问数据库(在活动 MCP 服务器旁边安全),并且只会在带有 `.ghost-vault` 标记的目录内修剪过时的笔记 — 备份不完整时完全退出,因此过时的额外内容不会被无声删除。
```bash
ghost obsidian export --out ~/Documents/GhostVault # 一次性镜像
ghost obsidian sync --interval 30s # 保持新鲜
```
## MCP 接口
18 种工具,4 种资源:
| 组 | 工具 |
|---|---|
| 内存 | `ghost_memory_save` `ghost_memory_search` `ghost_search_all` `ghost_memories_list` `ghost_memory_update` `ghost_memory_delete` `ghost_memory_pin` `ghost_memory_promote` `ghost_save_global` |
| 上下文 | `ghost_project_context` `ghost_list_projects` `ghost_health` |
| 任务 | `ghost_task_create` `ghost_task_list` `ghost_task_update` `ghost_task_complete` |
| 决策 | `ghost_decision_record` `ghost_decisions_list` |
资源:项目上下文、全局内存、项目决策、项目任务 — 在支持它的客户端中固定它们以在上下文压缩时生存。
服务器带有嵌入式指令,教导代理何时保存、使用哪些类别以及如何利用跨项目搜索 — 它在无需配置的情况下主动工作。完整的架构说明见 [docs/architecture.md](docs/architecture.md)。
## 命令行界面
```text
ghost mcp # 在 stdio 上运行 MCP 服务器(由您的 MCP 客户端使用)
ghost mcp init [--dry-run] # 配置 Claude Code 集成
ghost mcp status # 深度健康检查(包括 Ollama 可达性和模型存在)
ghost hook session-start # 会话启动钩子 — 打印实际注入的内容
ghost hook stop # 停止钩子 — 如果使用工具的会话未保存任何内容,则阻止停止
ghost reflect <project> # 内存合并(默认干燥运行;--apply、--restore、--tier)
ghost supersede <project> # 链接被取代的内存(默认干燥运行;--apply、--threshold)
ghost bench [--sweep] # 检索质量基准测试在内置数据集上
ghost obsidian export # 将内存镜像到 Obsidian 保险库(单向;--out、--project)
ghost obsidian sync # 保持保险库镜像新鲜(--interval;轮询数据库更改)
ghost upgrade # 从 GitHub Releases 自更新(linux/macOS;Windows:重新下载)
ghost version # 打印版本
```
## 配置
Ghost 在零配置下工作。当您想要更改某些内容时,层级如下(后者优先):
1. 编译默认
2. `/etc/ghost/config.yaml`
3. `~/.config/ghost/config.yaml`
4. `GHOST_*` 环境变量,以及 `ANTHROPIC_API_KEY` 用于 Haiku 反射层
```yaml
embedding:
enabled: true # 默认;无 Ollama 时降级
ollama_url: "http://localhost:11434"
model: "nomic-embed-text:v1.5"
linking:
enabled: true # 默认启用嵌入时启用
threshold: 0.70 # 最低余弦相似度以自动链接内存
```
注意:环境变量名称将下划线映射为配置点,因此键本身包含下划线(例如 `embedding.ollama_url`)必须在配置文件中设置,而不是通过环境变量。
## 性能基准
以下的每个数字都是确定的、无需裁判的、可重现的,并附有每题日志,完整的方法论见 [docs/benchmarks.md](docs/benchmarks.md)。
**LongMemEval-S** ([共识长期记忆基准](https://arxiv.org/abs/2410.10813);清理后的变体,会话级检索与官方证据标签对比,所有 470 个可回答问题,无LLM裁判):
```text
条件 R@1 R@5 R@10 MRR@10 NDCG@10
仅fts 0.429 0.751 0.832 0.758 0.738
向量 0.558 0.926 0.968 0.911 0.909
混合 0.532 0.930 0.973 0.901 0.903
```
**混合会话Recall@5 93.0%,Recall@10 97.3%** — 在该基准上取得了最佳混合检索结果,使用单个Ghost二进制文件和本地Ollama嵌入。测试工具和每题日志:[`bench/longmemeval/`](bench/longmemeval/)。诚实的细微差别:仅检索的数字与端到端答案准确率百分比不可比较(后者主要取决于生成模型);并且在此聊天式数据上,仅向量与混合绑定 — 关键字腿在精确标识符(端口、版本、主机名)上赢得了它的价值,这下一张表会显示。
**`ghost bench`** — 仓库内的开发事实数据集,以秒为单位运行,在CI中回归保护:
```text
$ ghost bench
条件 R@1 R@5 R@10 MRR@10 NDCG@10
仅fts 0.786 0.964 1.000 0.964 0.965
仅向量 0.786 0.929 0.964 0.952 0.946
混合 0.857 0.964 1.000 1.000 0.989
混合+图 0.500 0.964 1.000 0.780 0.824
14个评级查询,22个记忆。仅检索,无LLM裁判。
```
- **混合融合在这里击败了两个独立的模块**(NDCG@10 0.989 vs 0.965 全文,0.946 向量)— CI断言每个PR的关系。在两个基准测试中,融合是鲁棒性玩法:向量赢得对话式召回,关键词赢得精确标识符。
- **我们运行了消融实验,发现了自己的回归并修复了它。** 图形扩展排名奖励*伤害*检索(`hybrid+graph`),因此它禁用后发布 — 该表继续衡量它,以便重新设计有一个基准可以超越。 `ghost bench --sweep`网格搜索融合参数,如果你想检查我们的调优。
- **过时套件** ("生产环境运行Postgres 14,我们迁移到了16" — 搜索是否将最新事实排在第一位?)仅在CI中运行报告。 在默认配置下,最新事实总是被检索到,但只有8%的时间会优先于其被取代的版本 — 这是已知的所有内存系统都没有衡量过的失败。 默认关闭的最新优先权会将其翻转到100%,但*最新陷阱*装置(较旧的记忆是正确答案)证明了全局最新优先权不能作为默认值:这是一个悬崖,每个能修复过时问题的权重都会破坏旧但仍然正确的检索。 有针对性的修复确实可以做到这一点:定向`supersedes`链接,由一个仅在内存的实际替换同时发生时触发的降级器消费 — 将过时率翻转到**100%,同时将陷阱保持在0.929,不受影响** (全局最新优先权无法实现的免费午餐),因为它只在真正的替换对上起作用。 两个部分现在都已发布:`ghost supersede`创建链接(cosine提出,Haiku确认 — 在标记的真实与平行集合上为8/8),`SearchParams.SupersedeDemote`消费它们。 两者目前都是可选的; 将消费者连接到默认搜索是最后一步(它会改变实时排名)。 发布负面结果、原因和*修复*是重点。
跳过:LOCOMO(公开审计的答案密钥和裁判问题)和DMR。 **使用官方GPT-4o裁判的端到端LongMemEval-S** 下一步; 在此之前,这里不显示答案准确率百分比。
## 与Superpowers配合良好
[Superpowers](https://github.com/obra/superpowers) 构建了代理工作如何完成的结构(先构思、测试驱动开发、子代理执行);Ghost记得*学到了什么*。 一个有效的流程模式: 在规划前加载`ghost_project_context`, 在涉及组件之前加载`ghost_memory_search`, 在做出架构决策时记录`ghost_decision_record`, 在阶段完成时保存`ghost_memory_save`。
## 项目状态
Ghost是一个独立项目,构建原因是作者希望自己的代理不会忘记,并每天在实际基础设施工作中使用。 你可以验证而非信任:
- 纯Go语言,`CGO_ENABLED=0`,7个直接依赖(通过`modernc.org/sqlite`使用SQLite — 无需C工具链);静态二进制文件约12.5 MB
- 测试代码比例接近1:1;CI运行`go vet`、`golangci-lint`和启用竞争检测的测试,每个PR和主分支推送
- GoReleaser构建的6个OS/arch目标的发布版本,附带校验和,以及多架构Docker镜像
小到一个下午就能读完。 这是故意设计的 — 而且由于退出故事是一个SQLite文件,尝试Ghost并离开的成本是一个`go install`和一个`rm`。
## 贡献
欢迎提交问题和PR。 `go test ./...`和`go vet ./...`必须通过;仅限功能分支。
## License
Apache License 2.0 — 见 [LICENSE](LICENSE)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器