商业产业 Hacker News Agent 2026-07-15T16:15 正文 ok 1246 words

🔶 面向编程Agent的开源记忆系统,通过SSH同步

英文标题:🔶 Open-source memory for coding agents, synced over SSH

deja-vu 是一个零依赖的命令行工具,可将 Claude Code、Codex 和 opencode 等编程代理的会话历史转化为可快速检索的记忆层。它能在数 GB 的日志中以 7–9 毫秒完成全文搜索,并通过 MCP 回忆工具和会话启动钩子自动向代理提供相关上下文。该工具内置密钥脱敏、跨机器同步和会话分享功能,完全离线运行,不发送任何数据到外部。对于重度的编程代理用户,deja-vu 能大幅减少重复调试时间,并让过去的解决方案可被有效复用。
打开原文相关 8 · 机会 3
media1.1 KB media2.2 KB media1.3 KB media1.2 KB media1.3 KB media1.2 KB media326.4 KB media48.7 KB

中文

deja-vu 标志

你的代理已经解决过这个问题。deja 帮你把它找出来。

vshulcz.github.io/deja-vu

CI 构建状态 Release 发布 npm 版本 OpenSSF Scorecard 安全评分 MIT License

deja 演示

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

搜索 deja "connection pool exhausted" —— 在数 GB 数据上 7–9 毫秒完成,回溯生效:安装前数月内的日志也能搜。
代理回忆 MCP recall 工具 —— 代理会回答“我们三周前修过这个问题”,而不是重新调试,跨多个编程代理套件。
自动回忆 install --auto 添加 SessionStart 钩子:在你提问之前,相关记忆就已经进入上下文。
脱敏 API 密钥、JWT、私钥在索引时就被剥离 —— 缓存可以安全保留。
统计 deja stats ——你的代理工作一览:使用的编程代理、热门项目、活动火花图。
分享 deja share <id> —— 把一份已经清理过敏感信息的会话摘要交给同事,密钥已经擦除。
同步 deja sync export/import —— 在不同机器间迁移记忆,只追加、幂等。

只有一个二进制文件。不需要下载模型,不需要运行服务,任何数据都不会离开你的机器。(opencode 的索引会调用系统中已安装的 sqlite3 命令行,macOS 和大多 Linux 发行版已预装。)

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

或:

shell go install github.com/vshulcz/deja-vu/cmd/deja@latest # Go npx @vshulcz/deja-vu "query" # npm,无需安装 brew install vshulcz/tap/deja-vu # Homebrew

将它接入你使用的代理(会编辑配置,保留 .bak 备份):

shell deja install --all # 为 claude-code、codex、opencode 配置 MCP 回忆 deja install claude-code --auto # 外加 SessionStart 自动回忆钩子

就这样。下一次会话时,问你的代理:

我们以前处理过 JWT 刷新令牌轮换吗?检查你的记忆

——如果用了 --auto,甚至不用问:代理在每次会话开始时就已经知道你在该项目里解决过哪些问题。

$ deja "jwt refresh token" [claude] api · Jul 8 · 8f31c0a9 — 2 处匹配 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 处匹配 refresh token cookie needed SameSite=Lax in local callback flow

命令 作用
deja <query> 搜索所有历史。多词 = 与逻辑,子串匹配(code 会找到 opencode)。支持 --re、--harness、--project、--since 30d、--role、--json。
deja ctx <query> 最佳匹配的紧凑 Markdown 摘要——可以直接管道送入提示。
deja share <id> 为同事生成已脱敏的会话摘要:密钥已擦除,工具噪声已去除。
deja stats 总量、按编程代理拆分数据、热门项目、月度火花图。也可用 --json。
deja sync export <dir> [--full] / import <dir> / ssh <host> [--pull] 在机器间迁移记忆——通过共享文件夹或一条 ssh 命令。带水印,只追加,幂等。
deja show <id> / deja last [n] 阅读某条会话 / 列出最近的会话。
deja sources 发现的存储位置、大小、消息与脱敏计数。
deja mcp 标准输入输出的 MCP 服务器(deja install 所接入的就是它)。
deja warmup 构建/刷新索引而不执行搜索——适用于 cron 或 shell 启动脚本。

不使用 MCP 的上下文管道:

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

让两台机器指向同一个共享文件夹(Syncthing、iCloud、Git 仓库——任何能移动文件的东西都可以):

shell deja sync export ~/Sync/deja # 机器 A:追加自上次导出之后的新批次 deja sync import ~/Sync/deja # 机器 B:取走尚未见过的新记录

或者当另一台机器只是一跳 ssh 之隔时,跳过共享文件夹:

shell deja sync ssh mini # 将新记录推送到 mini 并在那里导入 deja sync ssh mini --pull # 把 mini 上的新记录取回本机

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

批次是纯文本 JSONL 格式,导出时已脱敏。导入是幂等的,因此可以把这个文件夹当作纯追加日志,也可以从 cron 同时运行两条命令。记录绝不会被回传到它们的来源机器。--full 会无视水印重新导出所有内容——适合在旧批次已删除时为新机器补充全量。同步后的会话在搜索、recall 以及会话启动自动回忆中会显示在 imported:<project> 之下。

教会你的代理记住过去

deja install --all 会接入 MCP 回忆和会话启动钩子。要让代理自己主动访问记忆,请把以下内容加入你的 CLAUDE.md 或 AGENTS.md:

markdown 在调试或重新实现某件事之前,运行 deja "<query>"(或 MCP 回忆工具)—— Claude Code、Codex 和 opencode 的历史代理会话都已在本地索引。如果你复用了过去的方案,请注明出处。

工具 参数 返回值
recall query、harness?、limit? 紧凑的匹配摘要,≤4KB——占用上下文极少。
recall_context query 最佳匹配会话的 Markdown 摘要。

使用 --auto 后,SessionStart 钩子还会自动注入当前项目最近的相关记忆——只读,上限 2KB,绝不会延迟或破坏代理启动。

内置脱敏

凭证在索引时就被脱敏:AWS 密钥、通用的 api_key=/token= 赋值、Bearer 令牌和裸 JWT、PEM 私钥块、各平台令牌(ghp_、sk-、npm_、xox.、AIza)以及 scheme://user:pass@host 格式的 URL。这些值会被替换为 [redacted:<类型>];周围的文本仍然可被搜索。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、Gemini CLI #6、#7 计划中

可通过环境变量自定义路径:DEJA_CLAUDE_ROOT、DEJA_CODEX_ROOT、DEJA_OPENCODE_DB、DEJA_INDEX_DIR。

性能

基于真实语料——1,250 多个会话,来自三个编程代理,约 3.3GB:

热搜索 7–9 毫秒 典型值,最差约 40 毫秒
冷构建索引(仅一次) ~10 秒
索引大小 约为语料库的 2.4%

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

实现原理

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

隐私: 索引和搜索代码中不存在任何网络路径。本地文件进,本地缓存出。

常见问题

有任何数据会离开我的电脑吗? 没有。工具中没有任何网络代码。sync 会将文件写入你选择的目录;如何移动它们由你决定。

这个和 cass 有什么不同? cass 是会话搜索的“集大成”方案:22 个提供方,Rust 编写,可选语义嵌入,配有 TUI。deja 走了相反的路线——一个小巧的 Go 二进制文件,纯词法搜索,只支持三个编程代理,零配置——再加上它周围的记忆层组件:自动回忆、脱敏、分享、同步。

与 MemPalace / Mem0 / Letta 相比呢? 那些是记忆 平台:涉及嵌入、向量存储、捕获钩子或用于向前录制的 API。deja 根本没有任何捕获步骤——它直接索引你的代理已经写到磁盘的内容,包括安装之前数月的历史。它们可以共存。

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

Windows 支持? 已提供编译产物,CI 在 Windows 上运行测试套件;macOS/Linux 是经过充分测试的平台。欢迎提交运行反馈:#9。

能否排除某个项目? 暂不支持——计划中的 --exclude 功能(#8)。目前你可以把 DEJA_*_ROOT 指向一个已经过滤过的副本。

如何彻底清除所有数据?

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

开发

make build test lint —— 见 CONTRIBUTING.md。添加一个新的编程代理支持只需要一个解析器文件:docs/ARCHITECTURE.md。已标记适合首次贡献的 issue。

MIT © Vladislav Shulcz

English / 原文

deja-vu

Your agents already solved this. deja finds it.

vshulcz.github.io/deja-vu

CI Release npm OpenSSF Scorecard MIT License

deja demo

Claude Code, Codex and opencode write every conversation to local files — gigabytes of debugged problems and design decisions you can't search. deja is a zero-dependency binary that turns those histories into a memory layer:

|
---|---
Search | deja "connection pool exhausted" — 7–9 ms over gigabytes, retroactive: months of logs from before you installed it
Agent recall | MCP recall tool — the agent answers "we fixed this three weeks ago" instead of re-debugging, across harnesses
Auto-recall | install --auto adds a SessionStart hook: relevant memory lands in context before you ask
Redaction | API keys, JWTs, private keys are stripped at index time — the cache is safe to keep
Stats | deja stats — your agent work, wrapped: harnesses, top projects, activity sparkline
Share | deja share <id> — hand a colleague a sanitized digest of a session, secrets already scrubbed
Sync | deja sync export/import — move memory between machines, append-only, idempotent

One binary. No models to download, no services to run, nothing leaves your machine. (opencode indexing shells out to the sqlite3 CLI, preinstalled on macOS and most Linux distros.)

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

or:

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

Wire it into the agents you use (edits config, keeps a .bak):

deja install --all          # MCP recall for claude-code, codex, opencode
deja install claude-code --auto   # + SessionStart auto-recall hook

That's it. Next session, ask your agent:

have we dealt with jwt refresh rotation before? check your memory

— or with --auto, don't ask: the agent starts each session already knowing what you solved in that project.

$ 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
Command What it does
deja <query> Search all histories. Multi-word = AND, substrings match (code finds opencode). --re, --harness, --project, --since 30d, --role, --json.
deja ctx <query> Compact markdown digest of the best match — pipe it into a prompt.
deja share <id> Sanitized session digest for a colleague: secrets redacted, tool noise stripped.
deja stats Totals, per-harness split, top projects, monthly sparkline. --json too.
deja sync export <dir> [--full] / import <dir> / ssh <host> [--pull] Move memory between machines — via a shared folder or one ssh command. Watermarked, append-only, idempotent.
deja show <id> / deja last [n] Read one session / list recent ones.
deja sources Discovered stores, sizes, message and redaction counts.
deja mcp The stdio MCP server (what deja install wires in).
deja warmup Build/refresh the index without searching — handy in cron or shell startup.

Context piping without MCP:

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

Point both machines at one shared folder (Syncthing, iCloud, a git repo — anything that moves files):

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

Or skip the shared folder when the other machine is a ssh hop away:

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 mode uses your system ssh/scp and the deja binary on the remote (looked up on PATH, falling back to ~/.local/bin/deja).

Batches are plain JSONL, redacted on the way out. Import is idempotent, so keep the folder as an append-only log and run both commands from cron if you like. Records never echo back to their origin. --full re-exports everything regardless of watermarks — useful when adding a machine after old batches are gone. Synced sessions show up under imported:<project> in search, recall, and session-start auto-recall.

Teach your agent to remember

deja install --all wires up MCP recall and the session-start hook. To make the agent reach for memory on its own, add this to your 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 and opencode
are indexed locally. Cite what you reuse.
Tool Arguments Returns
recall query, harness?, limit? Dense matching snippets, ≤4KB — cheap on context.
recall_context query Markdown digest of the best-matching session.

With --auto, a SessionStart hook also feeds the current project's recent memory in automatically — read-only, capped at 2KB, and it never delays or breaks agent startup.

Credentials are redacted at index time: AWS keys, generic api_key=/token= assignments, bearer tokens and raw JWTs, PEM private key blocks, provider tokens (ghp_, sk-, npm_, xox., AIza), and scheme://user:pass@host URLs. The value is replaced with [redacted:<kind>]; surrounding text stays searchable. deja sources shows per-store counts. Opt out with DEJA_NO_REDACT=1 (unsafe). deja share and deja sync export re-apply redaction on the way out.

Harness Store Status
Claude Code ~/.claude/projects/**/*.jsonl ✅
Codex CLI ~/.codex/sessions/** + history.jsonl ✅
opencode ~/.local/share/opencode/opencode.db ✅
aider, Gemini CLI #6, #7 planned

Custom locations via DEJA_CLAUDE_ROOT, DEJA_CODEX_ROOT, DEJA_OPENCODE_DB, DEJA_INDEX_DIR.

Measured on a real corpus — 1,250+ sessions, ~3.3GB across three harnesses:

|
---|---
Warm search | 7–9 ms typical, ~40 ms worst-case
Cold index (once) | ~10 s
Index size | ~2.4% of corpus

The index is incremental: when a session file grows, only that file is re-read.

Local inverted index in ~/.cache/deja: parse JSONL/SQLite stores → redact credentials → records.bin + token buckets → manifest.json tracks per-file state so repeat runs only ingest what changed. The MCP server, stats, share and sync all read the same index. Details: docs/ARCHITECTURE.md.

Privacy: no network path exists in the indexing or search code. Local files in, local cache out.

Does anything leave my machine? No. There is no network code in the tool. sync writes files to a directory you choose; moving them is up to you.

How is this different from cass? cass is the kitchen-sink take on session search: 22 providers, Rust, optional semantic embeddings, a TUI. deja is the opposite bet — one small Go binary, pure lexical, three harnesses, zero setup — plus the memory-layer pieces around it: auto-recall, redaction, share, sync.

And from MemPalace / Mem0 / Letta? Those are memory platforms : embeddings, vector stores, capture hooks or APIs that record going forward. deja has no capture step at all — it indexes what your agents already wrote to disk, including months of history from before you installed it. They can coexist.

What about secrets already in my logs? They stay in the original harness files (that's your agent's data), but they don't enter deja's index, digests, shares or sync exports.

What about Windows? Builds exist, CI runs the suite on Windows; macOS/Linux are the battle-tested paths. Field reports welcome: #9.

Can I exclude a project? Not yet — planned as --exclude (#8). Today you can point DEJA_*_ROOT at a filtered copy.

How do I wipe everything?

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

make build test lint — see CONTRIBUTING.md. Adding a harness is one parser file: docs/ARCHITECTURE.md. Good first issues are labeled.

MIT © Vladislav Shulcz