Project memory committed in the repository

the decisions behind the code, in the repository with it

Your agent tried retry with jitter on the webhook sender in August, watched it break idempotency, and reverted it. That is in your session history and nowhere else. A teammate's agent, in a fresh clone, will suggest it again on the first slow receiver. deja sync moves history between your own machines. This moves the few lines that matter to the people you work with, through the repository.

Share project decisions through git: deja-vu extracts decisions, rejected approaches and gotchas from your local session history into a merge-friendly .deja/memory.jsonl.
$brew install deja-vu && deja repo candidates
$npx @vshulcz/deja-vu repo candidates
deja-vu on GitHubQuick start →

Picking entries

$ deja repo candidates
2 candidates for webhooks, newest first. nothing is written until you pick
4cd7e7bb9c rejected Reverted the retry with jitter: it broke idempotency because the sender re-signs each attempt with a new delivery id.  (session s1, claude 2026-08-03)
c5ea828bb3 decision Reverted the retry with jitter: it broke idempotency because the sender re-signs each attempt with a new delivery id. We decided to keep one delivery id per event and let the outbox table own retries.  (session s1, claude 2026-08-03)
add the ones that hold for everyone: deja repo add <id> [<id>...]

$ deja repo add 4cd7e7bb9c
added 1 entry to .deja/memory.jsonl
wrote .deja/.gitattributes so parallel additions merge line by line, and a short .deja/README.md for whoever opens the folder
nothing is committed: review with `git diff .deja/` and commit it like code

Candidates come from this project's history in every agent deja reads: notes you promoted (accepted becomes a decision, rejected stays rejected), notes you stored with deja remember, reversals you or an agent reported in a session, and what a session settled. The last two are found by pattern, with no model, so most of the list is yours to throw away. --since 90d and --limit narrow it. To write one in your own words:

deja repo add --kind gotcha "the staging receiver drops payloads over 1 MB"

An agent can write one too, through the MCP remember mode with the project set to repo:, repo:rejected or repo:gotcha. Its skill tells it to do that only when you ask. Either way the file changes in your working tree and nothing else happens: you read the diff and commit it with the code it explains.

What is in the file

{"id":"4cd7e7bb9c","kind":"rejected","text":"Reverted the retry with jitter: it broke idempotency because the sender re-signs each attempt with a new delivery id.","date":"2026-10-25","from":"claude 2026-08-03"}

One JSON line per entry. kind is decision, rejected or gotcha. from is the agent and the day of the session it came from. No path, no session id, no machine or user name goes in. Before an entry is written it goes through the secret rules deja applies everywhere and then the pass deja share uses for home paths, email addresses, internal host names and private IP addresses. If the result still matches a secret rule, or redaction is turned off with DEJA_NO_REDACT=1, the entry is refused. Pattern redaction is a floor, so read the diff.

Entries are capped at 600 characters, and deja reads at most 500 of them or 1 MB from a file.

When deja creates .deja/ it also writes a four-line README.md there, saying what the folder is and how a teammate uses it, for someone who finds it while browsing the repository. It is written that one time only: edit it or delete it and deja leaves it that way. The same goes for .gitattributes.

Merging and removing

The id is a hash of the kind and the text, so the same entry added by two people is one line. Lines are kept sorted by id, which spreads new entries through the file, and two branches that each add one usually merge without touching the same lines. When they do land in the same place, .deja/.gitattributes asks git for a union merge (memory.jsonl merge=union), which keeps both lines instead of leaving conflict markers. Duplicates from a merge are read once and tidied on the next write. A union merge can bring back a line one side deleted if the other side changed the line next to it, so check the diff after a merge that touched the file.

To remove an entry, delete its line. If the file holds a line deja cannot read, such as a conflict marker, deja repo counts it, recall skips it, and deja repo add refuses until it is fixed, so deja never rewrites away something a person put there.

What a teammate gets

After a clone, the entries show up like other memory, in any agent deja is installed for. At session start they come right after your own standing decisions, read straight from the file, rejected and gotcha entries first:

from this repository's .deja/memory.jsonl (committed by the people working on it):
  · [rejected] Reverted the retry with jitter: it broke idempotency because the sender re-signs each attempt with a new delivery id. (in .deja/memory.jsonl, from claude 2026-08-03)

Recall, search and the MCP tool find them by topic, ranked like notes, under the project repo:<name>, where the name is what your own checkout is called on your machine. deja repo lists what the file holds. The index reads the file of every checkout deja has been run in, and drops it when the checkout is gone. deja sync does not send these entries, since the repository already carries them.

Repository text is treated like everything else recall hands an agent: as untrusted reference data, inside the same frame, never as instructions. A repository you cloned from a stranger can still put words in front of your agent, the way its README or CLAUDE.md can. The trust policy has a repo origin for that:

{"activations": {"auto": {"repo": false}}}

That keeps repository entries out of session start and the prompt hooks while leaving them in search. repo:<project> names one repository, and the most specific rule wins. DEJA_RECALL=off turns the session-start block off with the rest.

Across machines · One rules file · Privacy and trust scopes · CLI reference

Found this useful? Star deja-vu on GitHub.