dejavu
by aduthekaddu
README.md
# dejavu
Per-repo memory for coding agents. dejavu stores decisions, conventions, gotchas and open threads in `.dejavu/` inside your repo. Claude Code, Cursor and Codex read and write the same memory through one MCP server, so a new session starts with what the last one learned.
Entries are markdown files you commit and review in PRs. A local SQLite index (built into Node, no native modules) makes search fast and can be rebuilt from the markdown at any time. Nothing calls a paid API.
## Install
dejavu is not on npm. Install it from a clone (Node 22.13 or newer):
```sh
git clone https://github.com/aduthekaddu/dejavu.git
cd dejavu
npm ci
npm run build
npm link # puts `dejavu` on your PATH
```
Then, in any git repo:
```sh
cd ~/code/my-app
dejavu init
git add .dejavu && git commit -m "Add dejavu memory"
```
## Connect your agent
Each tool starts `dejavu mcp` in the repo. The server finds the repo root from its working directory, or from `DEJAVU_ROOT` if set.
### Claude Code
```sh
claude mcp add --scope project dejavu -- dejavu mcp
```
`--scope project` writes `.mcp.json` in the repo, so teammates get the server too. Drop it to keep the server to yourself.
### Cursor
Create `.cursor/mcp.json` in the repo:
```json
{
"mcpServers": {
"dejavu": {
"command": "dejavu",
"args": ["mcp"],
"env": { "DEJAVU_ROOT": "${workspaceFolder}" }
}
}
}
```
### Codex
Add to `~/.codex/config.toml`:
```toml
[mcp_servers.dejavu]
command = "dejavu"
args = ["mcp"]
```
Codex starts MCP servers in the directory you launch it from, so run `codex` from the repo.
### Tell the agent to use it
Add this to `AGENTS.md` or `CLAUDE.md`, or run `dejavu export --write AGENTS.md`, which also inlines the current memory:
```md
At the start of a task, call the dejavu `context` tool with your task and the files you expect to touch.
When you make a decision, find a convention, or hit a gotcha, save it with `remember`.
Before working on a directory in parallel with other agents, `claim` it. Check `read_cache` before summarizing a file.
```
## MCP tools
| Tool | What it does |
| --- | --- |
| `context` | Returns a brief of the most relevant entries that fits `budget` tokens. Takes optional `task` and `files`. |
| `recall` | Full-text search. Every word must match, as a prefix. |
| `remember` | Saves an entry: `kind`, `title`, and optionally `body`, `why`, `rejected`, `files`, `tags`, `pinned`. |
| `claim` / `release` | Claims a path for `ttlSec` seconds (default 1800). Fails if another agent holds an overlapping path. |
| `read_cache` | With `path` only, returns another agent's summary of that file if its content is unchanged. With `summary`, stores yours. |
## CLI
```sh
dejavu add decision "Store money in cents" --why "floats lose pennies" \
--rejected "decimal strings" --files src/billing.ts --tags billing --pin
dejavu add gotcha "CI runs in UTC" --tags ci
dejavu search billing
dejavu show # list all
dejavu show store-money-in-cents-1a2b3c
dejavu context --budget 800 --task "add refunds" --files src/billing.ts
dejavu capture --since main # propose entries from the diff, ask about each
echo "- decision: retry 3 times because the API flakes" | dejavu capture --since HEAD~3 --yes
dejavu claim src/auth --ttl 900 --agent claude-1
dejavu claim # list active claims
dejavu release src/auth --agent claude-1
dejavu prune # offer to delete stale entries
dejavu export --write CLAUDE.md # add or refresh the memory block
dejavu rebuild # rebuild index.db from the markdown
```
Run `dejavu <command> --help` for every flag.
## How it works
### Entries
There are four kinds:
- `decision` has a title, the reason (`why`) and the alternatives you rejected.
- `convention` is a rule the codebase follows.
- `gotcha` is something that surprised you and will surprise the next agent.
- `open-thread` is unfinished work.
Every entry can link files and commits, carry tags, and be pinned. Each one is a file at `.dejavu/entries/<id>.md`:
```md
---
id: store-money-in-cents-1a2b3c
kind: decision
title: Store money in cents
tags:
- billing
files:
- src/billing.ts
commits: []
pinned: true
createdAt: 2026-10-26T04:00:00.000Z
baseCommit: 9f2c1e0...
---
# Store money in cents
## Why
floats lose pennies
## Alternatives rejected
- decimal strings
```
You can edit these by hand. The next command notices the content changed and reindexes.
### What is committed
`.dejavu/.gitignore` keeps `index.db` and `events.jsonl` out of git. The markdown is the shared record. The index and the event log are local to one machine.
### Ranking and the token budget
`context` scores each entry:
- 2 points for each word of the task that appears in the entry (common words like "the" are ignored).
- For each touched file, 6 points when the entry links that exact file, 4 when it links a parent directory, 2 when it links a file in the same directory.
- Up to 1 point for recency, halving every 30 days.
Pinned entries always come first. Ties break on newer `createdAt`, then on id, so the same inputs give the same brief. Entries are added in that order until the next one would go over budget; an entry that is too big is skipped and smaller ones after it can still fit. Tokens are estimated as characters divided by 4.
### Staleness
Each entry records `baseCommit`, the HEAD when it was written. dejavu runs `git diff --numstat <baseCommit>` on the linked files, which counts committed and uncommitted changes. When 20 or more lines changed, or a linked file was deleted, the entry is stale. `context` and `recall` show it with a warning, and `dejavu prune` offers to delete it.
### Capture
`dejavu capture --since <ref>` reads `git diff <ref>` and proposes:
- an `open-thread` for each added `TODO` or `FIXME` comment,
- a `gotcha` for each added `HACK`, `XXX`, `NOTE` or `WARNING` comment,
- a `decision` for each new dependency in a `package.json`,
- a `convention` for changed lint, format or tsconfig files.
It also reads a summary from stdin. Lines that start with `decision:`, `convention:`, `gotcha:` or `todo:` become entries, and a decision splits into title and why at the word "because". Agents can write this summary at the end of a session.
For smarter proposals, pass `--proposer ./my-proposer.js`. The module's default export gets `{ diff, summary }` and returns proposals in the same shape. It can call any model you like. dejavu never calls one itself.
### Parallel agents and `events.jsonl`
Claims and saved entries are appended to `.dejavu/events.jsonl`, one JSON object per line. Other tools can tail this file. Format version 1:
```json
{"v":1,"type":"claim","at":"2026-10-26T04:00:00.000Z","agent":"claude-1","scope":"src/auth","ttlSec":1800,"note":"token refresh"}
{"v":1,"type":"release","at":"2026-10-26T04:10:00.000Z","agent":"claude-1","scope":"src/auth"}
{"v":1,"type":"remember","at":"2026-10-26T04:11:00.000Z","agent":"claude-1","id":"store-money-in-cents-1a2b3c","kind":"decision","title":"Store money in cents"}
```
- `at` is an ISO 8601 UTC time. `note` is optional.
- A claim is active from `at` until `at + ttlSec`, unless the same agent releases the same scope.
- Scopes are repo-relative paths without a trailing slash. `src/auth` overlaps `src/auth/login.ts` but not `src/authz`. `.` covers the whole repo.
- Claiming again renews the claim.
- Readers should skip lines they cannot parse and types they do not know.
The read cache lives in `index.db`, keyed by the SHA-256 of the file content. A summary is only returned while the file still has the exact content it was written for.
## Development
```sh
npm ci
npm run typecheck && npm run lint && npm test && npm run build
```
Tests use Vitest and run against real temporary git repos. They cover ranking and budgets, staleness, the markdown and SQLite round trip, capture, claims, the read cache, the MCP tools over the SDK's in-memory transport, and the built CLI end to end, including a real stdio MCP session.
## Limits
- Token counts are an estimate, not a real tokenizer.
- Search is keyword search (SQLite FTS5), not semantic search.
- Claims are advisory. An agent that never calls `claim` is not stopped.
- Capture heuristics are simple and will miss things. Review each proposal.
- Node's `node:sqlite` module is still marked experimental in Node 22. The CLI hides the warning.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues