跳到正文
北京时间
原文
Hacker News 热门(buzzing.cc 中文翻译)· vshulcz·· 2026-07-16精选AI 评分76

开源编程智能体内存方案发布,通过 SSH 同步

用于编程代理的开源内存,通过SSH同步

AI 导读

一个面向编程 AI 智能体的开源内存项目在 GitHub 发布,支持通过 SSH 同步记忆数据。该项目允许智能体跨会话保留上下文,无需依赖特定云服务,用户可自托管。代码已开源,便于开发者集成与定制。

推荐理由

给Claude Code、Cursor这些编程代理加了个可同步的持久内存,通过SSH就能跨机器共享上下文,做多机协作开发的可以试试。

正文 · AI 翻译

你的智能体早已解决了这个问题。deja 能找到它。
在约 12 ms 内搜索 3.3 GB 的智能体历史记录——单个零依赖二进制文件,完全本地运行。

Claude Code、Codex、opencode、aider、Gemini CLI、Cursor、Antigravity、Grok Build 和 Qwen Code 会把每一段对话写入本地文件——数 GB 已调试过的问题和设计决策,你却无法搜索。deja 是一个零依赖二进制文件,把这些历史记录变成一层记忆:

功能 作用
搜索 deja "connection pool exhausted"——在数 GB 数据上约 12 ms,可追溯:你安装它之前数月的日志
智能体回忆 MCP recall 工具——智能体回答“我们三周前修好了这个”,而不是重新调试,跨多个 harness
自动回忆 install --auto 添加一个 SessionStart 钩子:相关记忆在你提问之前就进入上下文;Claude Code 还会在压缩之前捕获当前对话记录
脱敏 API keys、JWT、私钥在索引时会被剥离——缓存可以安全保留
统计 deja stats——你的智能体工作,一览无余:harness、热门项目、活动迷你图
deja share <id>——把某次会话的脱敏摘要交给同事,密钥已提前清除
同步 deja sync export/import——在机器之间迁移记忆,仅追加、幂等
记住 deja remember "text" 或 MCP remember——保留持久性的决策与结论
追溯 deja blame <path>——哪些会话改动过这个文件,做出了什么决定以及为什么
语义 可选:将 deja embed 指向本地的 Ollama/LM Studio,改写后的查询依然能命中

隐私

deja forget 会从重建的索引中移除匹配的会话,并记录精确的会话墓碑,这样后续的 deja index 就无法从源历史中恢复它们。墓碑存储在 ~/.config/deja/tombstones(或 $XDG_CONFIG_HOME/deja/tombstones);使用 --dry-run、--list 或 --unforget。摄取排除项在 ~/.config/deja/exclude(感知 XDG)中每行一个不区分大小写的项目模式,或在 DEJA_EXCLUDE_PROJECTS 中以逗号分隔。deja stats --redaction 按 harness 和规则报告脱敏情况,以及墓碑和语义 sidecar 的相关事实。

单个二进制文件。无需下载模型,无需运行服务,除非你同步或分享,否则任何数据都不会离开你的机器。(opencode 和 Cursor IDE 的索引会调用 sqlite3 CLI,该 CLI 在 macOS 和大多数 Linux 发行版上已预装;Cursor CLI 的转录记录不需要它。)

安装

curl -fsSL https://raw.githubusercontent.com/vshulcz/deja-vu/main/install.sh | sh

或者:

go install github.com/vshulcz/deja-vu/cmd/deja@latest   # Go
npx @vshulcz/deja-vu "query"                            # npm, no install
brew install vshulcz/tap/deja-vu                        # Homebrew

将它接入你使用的智能体(会修改配置,并保留一个 .bak):

deja install --all     # MCP recall for every agent it finds on this machine
deja install --auto    # same, plus session-start auto-recall where supported

安装还会为它检测到的 harness 写入用户级指引:Claude Code、Codex、Gemini CLI、Qwen、Copilot 和 OpenCode 使用各自对应的指引文件(或已配置的 XDG_CONFIG_HOME)。重新运行会重写 deja 的技能或标记块,而不改动周围的用户内容。使用 deja install --all --no-guidance 可选择退出;Cursor 和 Grok 没有文档记载的用户级指引位置,会被跳过。

安装会报告是否找到了本地历史,并在历史存在时立即构建首个索引。

就是这样。下一次会话时,问你的智能体:

我们之前处理过 jwt refresh rotation 吗?查一下你的记忆

——或者用 --auto,不用问:智能体在每次会话开始时就已经知道你在那个项目里解决了什么。

CLI

$ deja "jwt refresh token"
[claude] api        · Jul 8 · 8f31c0a9 — 2 matches
  login started failing after refresh token rotation; jwt kid mismatch in tests
  fixed by reloading jwks cache after rotateKey and adding a clock-skew test
[codex]  web        · Jul 1 · b77d91e2 — 1 match
  refresh token cookie needed SameSite=Lax in local callback flow
命令 功能说明
deja <query> 搜索所有历史记录。多个词 = AND,常见英文填充词会被忽略,支持子串匹配(code 能找到 opencode),双引号短语要求文本连续;零结果查询会先尝试词形变化,再尝试相近拼写。--re、--harness、--project、--since 30d、--role、--json。
deja ctx <query> 最佳匹配的紧凑 markdown 摘要——可直接送入提示词。
deja blame <path> 查找讨论过某个文件的会话,最新的和最具体的排在最前。支持 --json、--all 以及常用过滤器。
deja share <id> 为同事生成经过脱敏的会话摘要:密钥已隐去,工具噪音已剔除。
deja stats 标题计数、总计、按 harness 拆分、热门项目、月度迷你走势图。--json 也一样。
deja doctor [--json] 自诊断:存储解析状态、sqlite3 是否存在、每个智能体的 MCP 接线、索引健康状况、版本;--json 会为脚本输出相同的检查项。
deja sync export <dir> [--full] / import <dir> / ssh <host> [--pull] 在机器之间迁移记忆——通过共享文件夹或一条 ssh 命令。带水印、仅追加、幂等。
deja show <id> / deja last [n] 读取单个会话 / 列出最近的会话。
deja resume <id> [--exec] 在其原生 harness 中重新打开找到的会话(claude --resume、codex resume、opencode -s、grok --resume)。
deja sources 发现的存储、大小、消息数和脱敏计数。
deja mcp stdio MCP 服务器(即 deja install 所接入的)。
deja remember "text" [--project name] 在 notes 源中存储一条明确的事实。
deja warmup 构建/刷新索引而不进行搜索——在 cron 或 shell 启动时很方便。
deja index [--rebuild] 与 warmup 相同;--rebuild 会强制进行完整重建。冷构建会逐个 harness 地播报进度。
deja update 下载最新的 GitHub release,校验其 checksum,并替换当前二进制文件。
deja statusline 为你的状态栏提供一行信息:今天为智能体提供的 recalls 次数。deja install statusline 会将其接入 Claude Code(不会改动已有的 statusline)。

词干化 JSON 搜索会设置 "stemmed": true,并包含所使用的 catalog 变体。

搜索命中会带有 exact、close 或 semantic 置信度层级;接近命中会包含匹配到的变体,语义命中会包含 cosine。

分享你的统计数据

运行 deja stats --card 来生成一个自包含的 deja-stats.svg,用于 README 或个人资料页。该命令会打印一段嵌入代码片段;如果你希望把它放在个人资料或仓库中,请将 SVG 提交上去。

运行 deja stats --html 来生成一个自包含、可浏览的 deja-stats.html 时间线。HTML 导出仅嵌入元数据:日期、harness、项目、消息数量,以及已脱敏的首条用户标题;它绝不包含消息正文。

deja update 用于独立安装。Homebrew 和 npm 安装则通过包管理器更新。

Doctor JSON

deja doctor --json 会为每一项检查报告明确的状态,即使发现问题也以 0 退出。存储状态为 ok、missing、empty、unreadable 或 parsed-zero;最后一种状态意味着会话文件存在,但最新的文件没有产生任何会话。

{
  "stores": [{"name": "claude", "state": "ok", "paths": ["/home/me/.claude/projects"], "files": 42}],
  "index": {"state": "stale", "path": "/home/me/.cache/deja/index.db"},
  "mcp": [{"name": "claude-code", "state": "wired", "path": "/home/me/.claude.json"}],
  "sqlite3": {"state": "ok"},
  "version": {"state": "ok", "current": "1.2.3", "latest": "1.2.3"}
}

索引状态为 ok、missing 或 stale;MCP 状态为 wired、not-wired 或 config-missing。sqlite3 状态为 ok 或 missing。版本状态为 ok、update-available、ahead、dev 或 unknown。

不使用 MCP 的上下文管道:

claude "Prior context: $(deja ctx 'database migration')"

在更改文件之前,先查看其历史记录:

deja blame cmd/deja/main.go

语义召回(可选)

语义搜索是一个可选启用的层,用于对接本地 Ollama、LM Studio 或 OpenAI 兼容的嵌入向量端点。设置 DEJA_EMBED_URL,可选设置 DEJA_EMBED_MODEL,然后运行 deja embed。Ollama 默认为 nomic-embed-text;如果没有配置且可访问的运行时,普通的词法搜索和 MCP 召回将保持不变。--no-embed 或 DEJA_EMBED=off 会在单次调用中禁用重排序。如果没有嵌入向量端点,语义零结果回退机制就不存在。

向量附属文件与索引存放在一起,文件名为 .vectors.bin,而不是存放在 index.db 中。对于 1,024 维模型,Float32 向量每 1k 条消息大约占用 4 KB,外加一个小的记录键。嵌入向量在本地进行,会消耗 CPU、内存和模型服务器时间;它从不发送原始源文件,只发送经过脱敏、截断到约 2k 字符的索引文本。

跨机器同步

将两台机器指向同一个共享文件夹(Syncthing、iCloud、git 仓库——任何能移动文件的方式):

deja sync export ~/Sync/deja   # machine A: appends new batches since last export
deja sync import ~/Sync/deja   # machine B: picks up what it hasn't seen

或者当另一台机器只需通过 ssh 跳转即可访问时,跳过共享文件夹:

deja sync ssh mini          # push new records to mini and import them there
deja sync ssh mini --pull   # fetch mini's new records into this machine

ssh 模式使用你系统的 ssh/scp 以及远程机器上的 deja 二进制文件(在 PATH 中查找,回退到 ~/.local/bin/deja)。

批次就是普通的 JSONL,输出时会做脱敏处理。导入是幂等的,所以你可以把这个文件夹当作只追加的日志保留,并按需在 cron 中运行这两条命令。记录永远不会回传到其来源。--full 会无视水位标记重新导出全部内容——在旧批次已丢失后新增机器时很有用。已同步的会话会出现在搜索中的 imported:<project> 下、recall 中,以及会话启动时的自动召回里。

教会你的智能体记住

deja install --all 接入了 MCP 召回(Claude Code、Codex、opencode、Cursor、Gemini CLI、Antigravity、Grok Build、Qwen Code——aider 没有 MCP 客户端,改用管道传入 deja ctx);deja install --auto 功能相同,并在运行框架支持的情况下增加了会话启动时的自动召回(Claude Code hook、Codex hooks.json、一个 opencode 插件——Cursor、Gemini CLI、Antigravity、Grok Build 和 Qwen Code 没有可注入上下文的 hook,所以 MCP 就是它们的完整安装方式)。要让智能体自行去调用记忆,请把下面这段加入你的 CLAUDE.md / AGENTS.md:

Before debugging or re-implementing something, run `deja "<query>"` (or the
 MCP recall tool) — past agent sessions across Claude Code, Codex, opencode, aider, Gemini CLI, Cursor, Antigravity, Grok Build and Qwen Code
are indexed locally. Cite what you reuse.

MCP 工具

工具 参数 返回
recall query、harness?、limit? 密集匹配片段,≤4KB——对上下文开销很小。
recall_context query、harness? 最佳匹配会话的 Markdown 摘要。
blame path、harness?、project?、since?、limit? 讨论过某个文件的会话,附带标题和匹配到的上下文。
remember text、project? 存储一条持久化的决策或结论,供日后召回。

借助 --auto,SessionStart 钩子还会自动把当前项目近期的记忆注入进来——只读、上限 2KB,且绝不会延迟或中断智能体启动。由于 SessionStart 在每次上下文压缩后也会触发,同样的记忆会在 Claude Code 压缩后立即被重新注入——而 PreCompact 钩子会提前把对话记录捕获到索引中。

安全

子智能体的对话记录默认会被跳过(它们大多与父会话重复);设置 DEJA_INCLUDE_SUBAGENTS=1 可将其纳入索引。写入中途被捕获的文件会被安全处理——残缺的尾部行会在下一轮被补上。

凭据在索引时会被脱敏:AWS 密钥、通用的 api_key=/token= 赋值、bearer token 和原始 JWT、PEM 私钥块、服务商 token(ghp_、sk-、npm_、xox.、AIza),以及 scheme://user:pass@host URL。其值会被替换为 [redacted:<kind>];周围的文本仍可被搜索。deja sources 会显示每个存储的计数。可通过 DEJA_NO_REDACT=1 选择退出(不安全)。deja share 和 deja sync export 会在输出时重新应用脱敏。

安全模型记录了数据流、脱敏限制、信任假设以及发布验证。

支持的运行框架

运行框架 存储 状态
Claude Code ~/.claude/projects/**/*.jsonl ✅
Codex CLI ~/.codex/sessions/** + history.jsonl ✅
opencode ~/.local/share/opencode/opencode.db ✅
aider .aider.chat.history.md ✅
Gemini CLI ~/.gemini/tmp/*/chats/** ✅
Cursor state.vscdb + ~/.cursor/projects/**/agent-transcripts/*.jsonl ✅
Antigravity ~/.gemini/antigravity*/brain/*/.system_generated/logs/transcript.jsonl ✅
Grok Build ~/.grok/sessions/**/updates.jsonl ✅
Qwen Code ~/.qwen/projects/**/chats/*.jsonl ✅

通过 DEJA_CLAUDE_ROOT、DEJA_CODEX_ROOT、DEJA_OPENCODE_DB、DEJA_AIDER_ROOTS、DEJA_GEMINI_ROOT、DEJA_CURSOR_ROOT、DEJA_CURSOR_CLI_ROOT、DEJA_ANTIGRAVITY_ROOT、DEJA_GROK_ROOT、DEJA_QWEN_ROOT、DEJA_INDEX_DIR 自定义位置。每个智能体自身的重定位变量也会被遵循:CLAUDE_CONFIG_DIR、CODEX_HOME、GEMINI_CLI_HOME、CURSOR_CONFIG_DIR、GROK_HOME、AIDER_CHAT_HISTORY_FILE,以及 Linux 上 opencode 的 XDG_DATA_HOME。

DEJA_RECALL=safe 是默认值:SessionStart 召回保持在当前项目内,过滤掉弱相关或重复的结果,优先选择最近 90 天的内容,并且最多注入 2KB。DEJA_RECALL=aggressive 会跨项目搜索,并将注入上限提高到 4KB。DEJA_RECALL=off 会禁用 SessionStart 召回输出。

会话格式注册表

会话格式注册表记录了每个受支持运行框架所观察到的存储路径、记录 schema、角色映射、时间戳以及兼容性说明。合成测试夹具会持续用解析器核对这些描述。

性能

在真实语料上测得——1,250+ 个会话,跨三个运行框架约 3.3GB:

测量项 结果
热搜索 ~12 ms 典型,~25 ms 最坏情况
冷索引(一次性) ~10 s
索引大小 约占语料的 ~2.4%

索引是增量的:当某个会话文件增长时,只会重新读取该文件。

基准测试

运行可复现的召回基准测试:

deja bench recall
deja bench recall --json

该合成数据集目前已被词法搜索打满(recall@5 为 1.00,中位数约 ~0.7 ms),因此它充当排序变更的回归底线,而非用来炫耀的数字;如果召回率下降,CI 会失败。语料生成器和相关性标签都是经过审查的普通 Go 代码——在信任任何数字之前,先审查"相关"的含义,包括我们的数字。当本地嵌入向量端点启动后,同一条命令会报告混合列。

工作原理

~/.cache/deja 中的本地倒排索引:解析 JSONL/SQLite 存储 → 脱敏凭证 → records.bin + token 分桶 → manifest.json 跟踪每个文件的状态,因此重复运行只会摄取发生变化的内容。MCP 服务器、统计、分享和同步都读取同一个索引。详情见:docs/ARCHITECTURE.md。

隐私:索引和搜索均在本地进行。网络仅由 deja update、deja sync ssh 以及 deja doctor 版本检查使用。本地文件输入,本地缓存输出。

常见问题

会有任何东西离开我的机器吗?索引和搜索均在本地进行。deja update 从 GitHub 下载发布版本,用户主动调用的 deja sync ssh 通过系统 SSH 客户端传输经过脱敏处理的批次。目录导出和分享仅发送到你选择的目标位置。完整数据流请参阅 安全模型。

这与 cass 有何不同?cass 是会话搜索领域的"大杂烩"方案:22 个提供商、Rust、可选的语义嵌入向量、一个 TUI。deja 则押注相反的方向——一个小的 Go 二进制文件、纯词法搜索、八种 harness、零配置——外加围绕它的记忆层组件:自动召回、脱敏、分享、同步。

那与 MemPalace / Mem0 / Letta 相比呢?那些是记忆平台:嵌入向量、向量存储、捕获钩子或 API,从部署之后开始记录。deja 完全没有捕获步骤——它索引你的智能体已经写入磁盘的内容,包括你安装它之前数月的历史记录。它们可以共存。

那我的日志中已经存在的密钥怎么办?它们保留在原始 harness 文件中(那是你的智能体的数据),但它们不会进入 deja 的索引、摘要、分享或同步导出。

那 Windows 呢? 已有构建版本,CI 会在 Windows 上运行测试套件;macOS/Linux 是经过实战检验的路径。欢迎提供实地反馈:#9。

我可以排除某个项目吗? 目前还不行——已计划为 --exclude(#8)。目前你可以把 DEJA_*_ROOT 指向一份过滤后的副本。

我该如何抹掉所有内容?

deja uninstall --all
rm -rf ~/.cache/deja

贡献

make build test lint — 参见 CONTRIBUTING.md。添加一个 harness 从 parser registry 开始。当前的优先事项和非目标见 ROADMAP.md。适合新手的问题已打上标签。

来源:Hacker News 热门(buzzing.cc 中文翻译) · github.com