deja-vu
MCP serverDocs & knowledgedeja-vu: local memory over the session histories of twenty-five coding agents.
Unavailable. This server has no hosted endpoint yet, so ahel can't serve it.
Connect ahel once, and every AI you use reads what you have installed.
From the project's README
As published by vshulcz/deja-vu in README.md.
Install
curl -fsSL https://raw.githubusercontent.com/vshulcz/deja-vu/main/install.sh | sh
deja install --auto
Ten seconds to install, about ten to index, and it is useful. The second command wires MCP recall into every agent it finds, turns on session-start recall where the agent supports it, and builds the first index so the next session does not pay for it.
Start a new agent session and ask it something you worked on months ago:
have we dealt with jwt refresh rotation before? check your memory
It does not have to be asked, either — with auto-recall the agent already knows what you solved in that project when the session opens.
brew install deja-vu, go install github.com/vshulcz/deja-vu/cmd/deja@latest,
or npx @vshulcz/deja-vu "query" to try it without installing anything. Desktop apps that
take MCP servers as bundles can open the .mcpb from the
latest release; it carries the binary.
Claude Code, Codex, Cursor, Qwen, OpenClaw and Copilot can take the same plugin bundle from their own marketplaces instead:
claude plugin marketplace add vshulcz/deja-vu && claude plugin install deja-vu@deja-vu
On Windows the install script exits with unsupported OS — it is a shell script. Use
Scoop instead, from the main bucket every Scoop install already has:
scoop install deja-vu
Or take deja-vu_<version>_windows_amd64.zip from the
latest release and put deja.exe on
your PATH, e.g. in %USERPROFILE%\.local\bin.
The binary alone is a complete install for searching: index, search, show, ctx, blame,
--json and redaction need nothing else. deja install is what wires MCP into your agents
and turns on session-start recall — worth having, and optional. On a binary-only setup
deja doctor reports every MCP target as not-wired, which is that setup working as
intended. deja warmup also leaves a skill at ~/.agents/skills/deja-search/SKILL.md
that teaches an agent the CLI contract — deja search --json, ctx, blame, how to read
tier and total — so it knows history is searchable without MCP. The copy in the repo is
skills/deja-search/SKILL.md.
deja install --all is --auto without the session-start recall: agents answer from memory
when they decide to call it, rather than starting each session with it. The
agent setup guide covers what each
harness supports, aider's read-only context file, and the Windows cmd /c deja mcp wrapper.
Install also writes user-level guidance for the harnesses it detects: Claude Code, Codex, opencode, Gemini CLI, Antigravity, Qwen, Kimi Code, pi, Copilot, VS Code Copilot Chat, Cursor, Goose, OpenClaw, Hermes, Roo Code, omp, Amp, prime-agent, DeepSeek Harness, Continue, Crush and Zed each get it in their own guidance file (or under the configured XDG_CONFIG_HOME). Re-run rewrites deja's skill or marked block without changing surrounding user content. Use deja install --all --no-guidance to opt out; Grok Build gets the shared skill in ~/.agents/skills, which is what it reads; the ~/.grok/GROK.md written beside it is for the unrelated community CLI that shares that directory. Cursor has no user-level instructions file, so it gets the shared skill in ~/.agents/skills — one of the four places Cursor reads skills from — read only when something looks relevant rather than every session.
What you get
Solve it in Codex. Claude remembers. Twenty-five coding agents write every conversation to local files, and deja turns those files into one memory layer all of them read.
| Retroactive search | deja "connection pool exhausted" over gigabytes, including everything from before you installed deja. Natural-language questions fall back to a relevance tier. Time is a hint, not a filter. |
| Cross-agent recall | The MCP recall tool answers "we fixed this three weeks ago" in whichever agent asks, whoever solved it originally. |
| It survives compaction | Measured over 43 compactions: the summary keeps 77% of the decisions and 0.2% of the commands you ran. deja hands back the other 99.8% — and on Claude Code and Codex it captures the task, the files and the commands as the compaction starts, then returns them once in the next session. |
| Recall at the point of action | Before an agent edits a file or runs a command, deja names that file's prior decision, that command's working invocation, or the program this machine does not have. When a command fails, a PostToolUse hook answers with what followed that same error here before — the pair an agent never thinks to ask for. |
| It indexes the work, not just the talk | The files each turn opened, the commands that ran with their exit status, and the exact spans an edit replaced. That is the part every summary throws away. |
| It knows what held | deja promote <id> --state rejected --note "why" marks a decision you reverted. Every later hit for that session shows it was tried and rejected, with the reason. Nothing is deleted, and --state accepted takes the mark back. |
| It says when the ground moved | A hit reports 4 files this session touched have changed since, and says nothing when it cannot tell. It never claims anything is unchanged. |
| Sync and handoff | deja sync ssh laptop moves memory between machines, append-only, no cloud in the middle. deja handoff --to codex packages the live context so you can continue in another agent. |
| Redaction | Keys, tokens, JWTs and private key blocks are stripped at index time, so the cache is safe to keep. |
Your own work, wrapped
deja stats --card draws it in the terminal; give it a filename and it writes an
SVG for a profile README. To post it anywhere else, turn it into a
PNG — that page converts it in your own
browser.
The full feature reference lives in the docs.
Privacy
Indexing and search are local. The network is used only by deja update, deja sync ssh,
and the version check in deja doctor.
Credentials are redacted at index time: AWS keys, api_key= and token= assignments,
bearer tokens and raw JWTs, PEM private key blocks, provider tokens, scheme://user:pass@host
URLs, and high-entropy values for shapes no pattern knows. The value becomes
[redacted:<kind>] and the surrounding text stays searchable. deja share and
deja sync export re-apply redaction on the way out.
deja forget removes sessions from a rebuilt index and writes tombstones, so a later
deja index cannot restore them from the source history. --unforget lifts a tombstone.
Project exclusions are one pattern per line in ~/.config/deja/exclude.
The security model documents data flows, redaction limits, trust assumptions and release verification.
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
Ask your history
| Command | What it does |
|---|---|
deja <query> | Search every history. Multi-word is AND and quoted phrases require contiguous text; a query with no exact match then tries word forms and close spellings, which is where a substring reaches its word (code finds opencode). |
deja | With an index and a terminal: today's sessions, recalls served, a question you asked in more than one session, and a wall your agents keep hitting. |
deja wip | What the last session in this directory was doing: the task, what it settled, the files in flight, the last command and whether it failed — derived from the transcript, not from a note someone remembered to write. |
deja blame <path> | Which sessions discussed a file, what was decided, and why. |
deja files <topic> | The other direction: which files the work on a subject actually touched. |
deja how <tool> | How this machine actually runs a thing, with the real flags, from what agents ran before. |
deja fix <error> | What this machine ran after that same error before, when the error did not come back. |
deja friction | Errors that hit three or more separate sessions, with the harnesses named. |
Use what it finds
| Command | What it does |
|---|---|
deja ctx <query> | Markdown digest of the best match, ready to pipe into a prompt. |
deja resume <id> | Reopen a found session in its native harness. |
deja restore <path> | Hand back a span an agent replaced, from the old_string its edit recorded. Never writes over the original. |
deja promote <id> | Distill a session into a curated note with provenance, tags and a lifecycle state. Notes outrank raw transcripts. |
deja share <id> | A sanitized session digest for a colleague, with secrets already scrubbed. |
Move it and check it
| Command | What it does |
|---|---|
deja sync export/import/ssh | Move memory between machines. Watermarked, append-only, idempotent. |
deja view | Your whole memory as one local HTML file. No server, nothing leaves the machine. |
deja stats | Your agent work, wrapped. --card draws it in the terminal, --card <file>.svg writes one for a profile, --html a browsable timeline. |
deja doctor [--deep] | Self-diagnosis, and with --deep, proof of the index against the sources. |
deja mcp | The stdio MCP server, which is what deja install wires in. |
Full reference: commands and JSON output.
MCP tools
The server exposes one tool, deja, with a mode. deja install wires it in, so
this is only needed to configure an agent by hand. The six older tool names
(recall, recall_context, blame, fix, how, remember) still answer for
anything already wired to them.
| Tool | Arguments | Returns |
|---|---|---|
deja | mode, plus query, path, error, what, text, tags?, harness?, project?, since?, limit?, offset?, all? | Depends on the mode, below. |
| Mode | Arguments it reads | Returns |
|---|---|---|
recall | query, harness?, limit?, offset? | Dense matching snippets, capped at 4KB. |
context | query, harness? | Markdown digest of the best-matching session. |
blame | path, harness?, project?, since?, limit?, all? | Sessions that discussed a file. |
fix | error, project?, limit? | What this machine ran, or changed, after that same error before. |
how | what, project?, limit? | The real invocation, from what agents ran here. |
remember | text, project?, tags? | Stores a durable decision for later recall. |
Supported harnesses
With auto-recall installed, Claude Code and Codex hand deja the transcript as a
compaction starts, and it keeps what the summary is about to drop: the task, the
conclusions, the files, the commands with what each one did, and what was left
open. The next hook for the same session and workspace gives it back once, inside
a 4 KB budget, with a line saying whether the repository moved since. deja stats
counts the tool calls before the first edit after a compaction, which is the
number this is measured against. See automatic compaction
recovery for what is read, what is stored and where the
limits are.
aider · Amp · Antigravity · Claude Code · Cline · Codex CLI · Copilot CLI · VS Code Copilot Chat · Cursor · DeepSeek Harness · Gemini CLI · Goose · Grok Build · Hermes · Kimi Code · omp (Oh My Pi) · OpenClaw · opencode · Continue · Crush · pi · prime-agent (PrimeIntellect) · Qwen Code · Roo Code · Zed.
| Harness | MCP recall | Auto-recall | Skill | Command | Resume | Handoff | Needs |
|---|---|---|---|---|---|---|---|
| aider | ⚠ | ✅ | ✕ | ⚠ | ✕ | ✅ | deja aider |
| Amp | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Antigravity | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Claude Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Cline | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Codex CLI | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Copilot CLI | ✅ | ✕ | ✅ | ✅ | ✅ | ✅ | — |
| VS Code Copilot Chat | ✅ | ✕ | ✅ | — | ✕ | paste | — |
| Cursor | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | sqlite3 (IDE chats) |
| DeepSeek Harness | ✅ | ✅ | ✅ | ✅ | ✕ | paste | zstd |
| Gemini CLI | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Goose | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | deja goose |
| Grok Build | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | sqlite3 (grok-dev store) |
| Hermes | ✅ | ✅ | ✅ | ✅ | ✅ | paste | sqlite3 |
| Kimi Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| omp (Oh My Pi) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| OpenClaw | ✅ | ✅ | ✅ | ✅ | ✅ | paste | — |
| opencode | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | sqlite3 |
| Continue | ✅ | ⚠ | ✅ | ✅ | — | paste | — |
| Crush | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | sqlite3 |
| pi | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| prime-agent (PrimeIntellect) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Qwen Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Roo Code | ✅ | ⚠ | ✅ | ✅ | ✅ | paste | roo CLI (editor tasks reopen in the editor) |
| Zed | ✅ | ✕ | ✅ | ✅ | ✕ | paste | sqlite3 + zstd |
✅ works · — possible, not built yet · ✕ the harness has no such mechanism · ⚠ blocked by an upstream bug · ? not investigated
Custom store locations go through DEJA_*_ROOT variables, and each agent's own relocation
variable is honored too. The
session format registry documents
the observed paths, record schemas and role mapping per harness, with synthetic fixtures
keeping those descriptions checked against the parsers.
Harnesses with a package of their own
deja install --auto wires all six of these like every other harness, and
that stays the shortest path. They also have a package in their own ecosystem,
for people who install extensions there rather than from a CLI:
| Harness | Package | Install |
|---|---|---|
| opencode | npm opencode-deja | opencode plugin opencode-deja |
| DeepSeek Harness | npm dsh-deja | dsh plugin --profile web add dsh-deja |
| Zed | deja-context-server | Zed → Extensions → deja |
| Kimi Code | plugin deja | /plugins install https://github.com/vshulcz/deja-vu |
| Codex CLI | plugin deja-vu | codex plugin marketplace add https://github.com/vshulcz/deja-vu then codex plugin add deja-vu@deja-vu |
| Grok Build | plugin deja | grok plugin marketplace add xai-org/plugin-marketplace then grok plugin install deja |
Either path is enough on its own, and having both is not a problem: the
opencode, dsh, Kimi, Grok and Codex packages read what deja install wrote and
contribute only what is missing, and in Zed both halves use one server id, so
there is nothing to have twice whichever order you install in.
Each uses the deja you already have; the copy it bundles is only the fallback.
The same search is also a skill, for any agent that loads a SKILL.md:
npx skills add https://github.com/vshulcz/deja-vu --skill deja-search # skills CLI: Claude Code, Cursor, Goose, Copilot…
openclaw skills install @vshulcz/deja-search # ClawHub
hermes skills install vshulcz/deja-vu/skills/deja-search # Hermes
The skill drives the deja binary from the install step above; it does not bundle one.
Semantic recall (optional)
Point deja embed at a local Ollama, LM Studio or OpenAI-compatible endpoint with
DEJA_EMBED_URL and rephrased queries still hit. Without a reachable runtime, lexical
search and MCP recall continue unchanged. OpenAI Platform works with its standard key:
export OPENAI_API_KEY='sk-...'
export DEJA_EMBED_URL='https://api.openai.com/v1/embeddings'
export DEJA_EMBED_MODEL='text-embedding-3-small'
deja embed
With no DEJA_EMBED_URL set, deja probes localhost:11434 and localhost:1234,
so a machine already running Ollama or LM Studio is picked up without being asked.
DEJA_EMBED_OFF=1, or DEJA_EMBED_URL=off, turns that probe off — any other
configured DEJA_EMBED_URL still wins.
For another authenticated OpenAI-compatible endpoint, set DEJA_EMBED_KEY explicitly:
export DEJA_EMBED_URL='https://example.com/v1/embeddings'
export DEJA_EMBED_MODEL='embedding-model'
export DEJA_EMBED_KEY='...'
deja embed
DEJA_EMBED_KEY takes precedence. OPENAI_API_KEY is used automatically only for an
HTTPS api.openai.com URL; it is never implicitly sent to local or third-party endpoints.
The sidecar sits beside the index as .vectors.bin, not inside index.db. Float32 vectors
cost roughly 4 MB per 1k messages for a 1,024 dimension model. A remote endpoint receives
the redacted indexed text, truncated to about 2k characters, but never raw source files.
With Ollama or LM Studio, embedding stays local and needs no key.
Proof
deja bench recall # ranking floor: 100 queries, half Russian, CI fails if recall drops
deja bench context # 30 seeded task chains plus five negative controls
deja bench block # does the answer survive into what deja hands over
deja bench prompt # what the per-prompt hook fires on, and what it fires on wrongly
deja bench ingest # what an update costs: unchanged, a turn, a new transcript, a rename, a rewrite
bench block asks the question the other three cannot: with the right session in
hand, does the block carry what that session settled. Eight sessions discuss each
subject and one of them settles it, in the middle of its own transcript rather
than at the end — so the baseline arm, the newest turns of the top hit, scores
zero and an arm above zero had to choose.
| Arm | Carries the answer | Median tokens |
|---|---|---|
deja-block (session-start block) | 1.00 | 665 |
deja-digest (context digest) | 1.00 | 1656 |
newest-turn (baseline) | 0.00 | 289 |
cold | 0.00 | 0 |
The context experiment compares deja-recall against full-history, naive grep and cold context. With the default seed:
| Arm | Median tokens | Median coverage | Negative-control tokens |
|---|---|---|---|
| deja-recall | 1,096 | 1.00 | 0 |
| full-history | 80,547 | 1.00 | 78,145 |
| naive-grep | 273,238 | 1.00 | 0 |
| cold | 0 | 0.00 | 0 |
Same fact coverage as grepping the raw logs for about 250x fewer tokens, and about 70x fewer than replaying the matched sessions in full, while injecting nothing on the chains where no prior fact is relevant. The corpus generator and the relevance labels are ordinary reviewed Go. Audit what "relevant" means before trusting any figure, ours included.
Measured on a real store of 2,419 sessions and 179k messages, 1.9 GB of transcripts:
| Measurement | Result |
|---|---|
| Lookup, in process | ~0.7 ms median (deja bench recall, 100 queries, half of them Russian), ~19 ms on the LongMemEval-S haystacks |
deja <query>, end to end | ~0.2 s median on that store: process start, the freshness check over every store, ranking, printing |
| Freshness check alone | ~50 ms when nothing changed |
| Index size | 200 MB, ~10% of corpus |
The index is incremental. When a session file grows, only that file is re-read.
How it works
Local inverted index in ~/.cache/deja: parse the JSONL and SQLite stores, redact
credentials, write records.bin plus token buckets, and track per-file state in
manifest.gob so repeat runs only ingest what changed. The MCP server, stats, share and
sync all read that one index. Details in docs/ARCHITECTURE.md.
FAQ
Does anything leave my machine? No, unless you ask it to. See the data flows.
Shortened here. Read the whole README on GitHub.
Signals
- GitHub stars
- 802
- Forks
- 72
- Last commit
- Sep 2026
Advanced
- Delivery
- deja-vu MCP server → your ahel gateway (mcp.ahel.ai) → every connected AI client.
- Catalog kind
- mcp-server
- Gateway key
io-github-vshulcz-deja-vu- Source
- github.com/vshulcz/deja-vu