Portable context + memory + adapter bridge for coding agents — the reference implementation of DCP, the DejaVue Context Protocol.
Zero ceremony first. Deja Vue is to project memory what .git/ is to
history. Drop it into any git repo in 5 seconds. No infra, no MCP server, no
embeddings to configure, no runtime dependency — a single Python 3 file on the
standard library. This is Axiom 0: every layer above the base memory log is
optional and additive, and nothing is ever mandated. (See the
DCP spec §0.)
On that base it does three things:
- Memory — captures what git cannot: the why — architectural decisions,
rejected alternatives, constraints not obvious from the code, the context the
next coding session needs to hit the ground running. The one command worth
building for is
since: show me everything that changed in this repo — git commits and cognitive context — since I last worked here. - Context — a single
context.mdsource of truth for an agent's operating rules, build/test commands, and architecture map. - Adapter bridge — generate
CLAUDE.md/AGENTS.md/GEMINI.md/ Copilot / Cursor files from that source of truth, non-destructively, so the per-tool files become compatibility targets instead of N drifting copies.
pipx install git+https://github.com/nixpt/dejavuepip install git+https://github.com/nixpt/dejavuecurl -O https://raw.githubusercontent.com/nixpt/dejavue/main/dejavue.py
chmod +x dejavue.py
mv dejavue.py ~/.local/bin/dejavueOr clone and symlink:
git clone https://github.com/nixpt/dejavue
ln -s "$PWD/dejavue/dejavue.py" ~/.local/bin/dejavueAfter installing, add completions for your shell (one-time):
# bash
dejavue completion bash | sudo tee /etc/bash_completion.d/dejavue
# or per-user:
dejavue completion bash >> ~/.bash_completion
# zsh
dejavue completion zsh | sudo tee /usr/share/zsh/site-functions/_dejavue
# or per-user (fpath must include the dir):
dejavue completion zsh > "${fpath[1]}/_dejavue"
# fish
dejavue completion fish > ~/.config/fish/completions/dejavue.fishPre-generated scripts are also available in completions/ for
distro packagers.
Five minutes: init, start, commit, decide, hand off, recall.
$ cd myproject/
$ dejavue init
Installed pre-push hook at .git/hooks/pre-push
Initialized .dejavue/
$ dejavue start --agent claude --goal "Add rate-limiting middleware"
Session started. Goal: Add rate-limiting middleware
# ... make changes, git commit — git is the file-change log, dejavue keeps the why ...
$ git commit -m "add token-bucket rate limiter"
$ dejavue decision "Token-bucket over leaky-bucket" \
--reason "Allows short bursts; simpler to tune per-endpoint" \
--rejected "leaky-bucket: smooths too aggressively for API traffic"
Decision recorded: Token-bucket over leaky-bucket
$ dejavue state --summary "Rate limiter merged to main. Redis not required — in-memory store for now."
State updated.
$ dejavue handoff \
--summary "Token-bucket middleware done, tests green." \
--next "Wire per-user limits; see decisions.md for the burst-allowance rationale."
Handoff written.
Next session (or next agent):
$ dejavue context # boot packet: handoff + state + decisions + last 10 events
$ dejavue since 2026-05-10 # everything that changed since May 10
$ dejavue since --agent claude # since my last session_start
$ dejavue recall "rate limiter" # FTS5 search over all captured events and docs
Git captures mechanical history — every file change, every commit message. What it cannot capture is the reasoning: why this design over that one, what dead ends were tried, what constraints are non-obvious from the code. Future agents and developers rediscover those dead ends at full cost.
Deja Vue fills that gap. It writes a plain-text event log (.dejavue/) that
ships with the repo, requires zero infrastructure, and degrades gracefully when
tools are absent. The format is the contract — other coding-agent tools
(Cursor, Aider, external agent, claude-cli) can read .dejavue/ directly, and
richer MCP servers can consume it without dejavue having to depend on them.
For the full design rationale — including the overlap with adjacent memory
tools, hook strategy, and the rejected-alternatives principle — see
docs/04-design-perspective.md. For the build spec and migration path,
see docs/05-v0.1-scope.md.
Deja Vue is the reference implementation of DCP, a portable context
interchange standard. The full standard is in
docs/dcp-spec.md (DCP/1.0, draft). The idea: .dejavue/
is the single source of truth, and the per-tool instruction files
(CLAUDE.md, AGENTS.md, GEMINI.md, Copilot/Cursor rules) become
generated, non-destructive adapter targets rather than the authority.
DCP organizes context into three layers:
- Instruction layer (
context.md) — what the agent should do: operating rules, build/test commands, architecture map. - Memory layer (
timeline.jsonl+decisions.md+state.md+handoff.md) — what the agent should remember. Deja Vue already is this. - Adapter layer — generated per-tool files plus an
importto bootstrap from existing ones.
The round-trip flow:
dejavue import CLAUDE.md # seed .dejavue/context.md from an existing file (lossless)
$EDITOR .dejavue/context.md # edit the single source of truth
dejavue export --target claude # regenerate CLAUDE.md (and codex/gemini/copilot/cursor/all)
export writes a marker-delimited managed block —
<!-- dejavue:begin DCP/1.0 src=context.md hash=… --> … <!-- dejavue:end --> —
into each tool's real file, preserving any hand-written content outside the
markers (absent→create, marked→replace region, unmarked→append+warn,
--replace→convert). Hand-written instruction files are never blindly
clobbered. The whole protocol holds to Axiom 0: zero ceremony, no mandated
dependency, every layer above the base memory log optional.
DCP and dejavue are released under the MIT License (see LICENSE); stewardship is described in
STEWARDSHIP.md.
dejavue — format + reference CLI (this tool)
.dejavue/ — on-disk format: timeline.jsonl + markdown docs + fts.db
dejavue CLI — reference implementation, zero dependencies
rich MCP servers — consume .dejavue/ via thin shim tools (v0.3 work)
may also maintain their own richer per-repo planning state
(e.g. milestone / phase / learning indexes) as a superset
other coding agents — Cursor, Aider, external agent, claude-cli
read .dejavue/ directly — the format is the open contract
git — mechanical history (commits, diffs)
dejavue adds cognitive history on top
Session lifecycle
| Command | Description |
|---|---|
dejavue init [--ingest] [--map] [--wizard] [--vendor] |
Create .dejavue/, install hooks + .gitattributes + .gitignore, write CLAUDE.md boot stub. --vendor also copies dejavue.py and the skill files into .dejavue/ as an offline fallback (off by default). --wizard seeds context.md interactively. |
dejavue start --goal TEXT |
Record session start with intent. Foundation for since --agent. |
dejavue state --summary TEXT |
Overwrite state.md with current snapshot. |
dejavue handoff --summary TEXT --next TEXT |
Write handoff.md for the next session. |
Capture
| Command | Description |
|---|---|
dejavue decision TITLE --reason TEXT [--rejected "opt: why"] [--outcome TEXT] |
Append architectural decision to decisions.md and timeline. |
dejavue note TEXT [--tag TAG] |
Lightweight timestamped note between annotate and decision. |
dejavue annotate <doc> "note" |
Append a timestamped note to a doc without rewriting it. |
dejavue changed PATH --summary TEXT |
Record a file change event manually. (--auto, the retired post-commit hook mode, is a no-op.) |
dejavue hook posttooluse |
Retired runner hook: drains stdin, writes nothing, exits 0. |
Capture + conventions
Capture is meant to cost one command. An agent that trips over a problem while doing something else should be able to record it and keep going — it does not have to fix it, and it does not have to know where this repo keeps its plans.
| Command | Description |
|---|---|
dejavue plan TEXT [--kind issue|gap|opportunity|idea|cleanup] [--target PATH] [--list] |
Capture an actionable item into the repo's own planner. Finds it automatically — .jagent/planning/TASKS.md, .jagent/TODO.md, TODO.md, docs/TODO.md, TASKS.md — or falls back to .dejavue/plan.md so capture never fails for lack of a planner. Override permanently with dejavue config set plan.target <path>, or once with --target. Always also lands in the timeline, so it stays recallable. |
dejavue rule TEXT [--scope SCOPE] |
Record a soft project rule / convention in rules.md. Surfaced in dejavue context, so an arriving agent reads your conventions instead of violating them by accident. |
The three normative tiers, weakest to strongest:
| Tier | Command | Meaning |
|---|---|---|
| descriptive | pattern |
"this is how the code happens to be written." |
| soft-normative | rule |
"this is how we do things here." Depart from it knowingly and say why. |
| hard-normative | invariant |
"this must always hold." Breaking it is a bug. |
Recall + exploration
| Command | Description |
|---|---|
dejavue context |
Boot packet — handoff + state + decisions + references + last 10 events + staleness warnings. |
dejavue status |
One-liner health: agent, event count, last decision, open next-steps. |
dejavue since <ref> |
Delta since a date, commit hash, or agent's last session. Killer command. |
dejavue log [--since] [--agent] [--type] [--oneline] [--reverse] |
Formatted timeline view with filters. |
dejavue blame <file> |
"Why does this file exist?" — decisions and events mentioning the path. |
dejavue explain <file|commit> |
Causal explanation combining git history, decisions, notes, artifacts, rejected alternatives, and linked events. |
dejavue recall QUERY [--semantic] [--limit N] |
FTS5 keyword (or cosine semantic) search over all artifacts. |
dejavue owners [NAME] |
List domain owners or show timeline events owned by one normalized owner. |
dejavue get <doc> |
Direct fetch of state, handoff, decisions, or references/<name>. |
dejavue list [--type events|decisions|references] |
List available artifacts with paths. |
dejavue roster |
Agent activity summary — who worked here and when. |
Operations
| Command | Description |
|---|---|
dejavue check |
Health check: JSONL validity, hook status, .gitattributes, FTS freshness. |
dejavue ingest [--generate-map] |
Scrape .claude/, CHANGELOG.md, ADRs, and git log. --generate-map auto-populates references/map.md. |
dejavue archive --before DATE [--yes] |
Compact timeline by dropping old file_changed events (dry-run without --yes). |
dejavue config {list,get KEY,set KEY VAL,unset KEY} |
Manage per-repo .dejavue/config. |
dejavue install-skill [--dir PATH] |
Install SKILL.md to ~/.claude/skills/ (or --dir). |
dejavue worthiness |
Print the capture/skip table as a reminder. |
dejavue stats |
Event statistics: counts by type (with bar chart), by agent, date range. |
dejavue export --format {json,md} |
Export full memory snapshot as JSON or Markdown. |
dejavue reference {create,list,update,view} [--type T] |
Manage .dejavue/references/ cards via CLI. --type filters/injects frontmatter. |
dejavue link <sha> |
Show dejavue events recorded for a git commit SHA. |
dejavue search QUERY [--semantic] [--limit N] |
Alias for recall (discoverable name). |
dejavue diff <from> [<to>] [--format patch] |
Compare memory between two refs — decisions added, state diff, event window. |
dejavue timeline [--by day/week/month] |
ASCII activity chart — events per time period. |
dejavue branch {start,summary,close} |
Capture and replay branch intent, closeout, decisions, notes, and commits. |
dejavue merge-summary <base> <branch> |
Summarize what a branch brings into a base ref before merge. |
dejavue squash-summary <branch> [--base REF] |
Synthesize a squash-merge commit message from branch memory and commits. |
dejavue conflict record --reason TEXT [--path PATH] |
Record why a merge conflict was resolved a certain way. |
dejavue epoch {begin,end,list} |
Record named project eras that frame old decisions. |
dejavue milestone NAME [--summary TEXT] |
Record a named project checkpoint. |
dejavue tag {list, filter <tag>} |
List tags with counts or filter events by tag. |
dejavue note-commit <sha> |
Write a git note on a commit linking it to the last dejavue event. |
dejavue version |
Print installed version. |
DCP — adapter bridge
| Command | Description |
|---|---|
dejavue import <FILE> |
Bootstrap context.md losslessly from an existing AGENTS.md / CLAUDE.md; records provenance. Safe first step before export. |
dejavue export --target {claude,codex,gemini,copilot,cursor,all} |
Generate the tool's instruction file from context.md non-destructively. Absent → create; managed block → replace region; hand-written → append + warn; --replace to convert. |
dejavue capabilities [--format json|text] |
Report supported commands, DCP version, optional features, hooks, and adapter status for agents/tooling. |
dejavue promote --to planning |
Graduate .dejavue/ into a .planning/ planning system without losing history — copies artifacts, records provenance, leaves .dejavue/ canonical. |
Each command accepts --help. See dejavue --help for the full flag list.
Core memory-writing commands accept --author-type {human,agent,orchestrator,ci,bot}
to record the kind of writer separately from the --agent identity string.
They also accept repeatable --tension LABEL for unresolved tradeoff axes such as
security or performance.
Use repeatable --value LABEL for soft project philosophy labels such as
local-first or capability-first.
Use --domain-owner NAME to assign one normalized owner for owner-based recall/filtering.
dejavue worthiness prints this table. It is also shown once on first use.
Worthiness gate — only persist if:
CAPTURE SKIP
───────────────────────────────────────── ─────────────────────────────────────────
Decision changes architectural direction Style preferences (let .editorconfig do it)
Constraint non-obvious from the code Things git diff already shows
Blocker requiring external context "Ran tests, passed"
Handoff context next agent must know Per-file mechanical edits
Dead end + why it was rejected LLM reasoning steps
Cross-cutting invariant ("X never depends Routine commits
on Y")
Rule of thumb: if removing this memory wouldn't confuse a future agent reading
the code + git log, don't write it.
The most valuable signal is the rejected alternative — the approach that
was tried and dropped, with the reason. That is the reasoning that costs the
next agent the most to rediscover. Use --rejected "option: reason" on every
dejavue decision call.
dejavue does not copy commits into the timeline. since, explain and
changelog read file history from git directly; the timeline holds what git
can't: decisions, traps, invariants and rules.
Earlier versions installed a post-commit hook that recorded a file_changed
event per touched file and amended HEAD with the timeline update. That hook is
retired. init no longer installs it, and the command an installed hook runs
(dejavue changed --auto …) now exits 0 without writing or amending anything,
so existing hooks go quiet with no per-repo change. Delete
.git/hooks/post-commit whenever convenient; dejavue check marks it obsolete.
The runner-hook consumer dejavue hook posttooluse is retired the same way: it
reads its stdin and exits 0. Record a change by hand with
dejavue changed PATH --summary TEXT when it carries a reason worth keeping.
If a structural index tool appends symbol_index / symbol_index_incremental
events to the timeline (the documented foreign-event schema — JSONL, same
append_event contract), dejavue context surfaces an index freshness
section: when the last full index ran, how old it is, and how many
incremental updates followed. An arriving agent can trust or re-derive
structural answers without reindexing first. Repos with index events older
than 30 days get a staleness warning.
dejavue since 2026-05-10 # ISO date (lexicographic comparison)
dejavue since a81f2cd # commit hash (uses commit timestamp)
dejavue since --agent claude # last session_start for that agent name
Output sections: git delta (log + diff stat), timeline events (newest first), decisions made, state transitions, handoffs, top keywords.
dejavue recall <query> --semantic cosine-ranks events by meaning instead of
keyword overlap. Default endpoint is an OpenAI-compatible /v1/embeddings
URL — works against ollama out of the box (ollama pull nomic-embed-text,
no further config needed).
# Default: hits ollama on localhost
dejavue recall "rate limiter design tradeoffs" --semantic
# Override via env (any /v1/embeddings-compatible endpoint):
DEJAVUE_EMBEDDER_URL=https://api.openai.com/v1/embeddings \
DEJAVUE_EMBEDDER_MODEL=text-embedding-3-small \
dejavue recall "rate limiter design tradeoffs" --semanticLazy caching. The first time a timeline event is seen during a semantic
recall, dejavue embeds its summary and appends a row to
.dejavue/embeddings.jsonl. Subsequent recalls hit the cache. The cache is
keyed by a content hash of the timeline line, so reorderings, duplicate
ingest runs, and worktree merges do not produce phantom entries.
Graceful fallback. If the embedder URL is unreachable, returns 4xx, or returns malformed JSON, dejavue prints one warning line to stderr and falls through to the FTS5 keyword path. Memory writes never block on the embedder being up — this is a design invariant.
.dejavue/embeddings.jsonl is gitignored. It is rebuildable from
timeline.jsonl plus a working embedder, and different agents on the same
repo may legitimately use different models (different vector spaces should
not mix). Treat it like fts.db — local cache, not part of the canonical
on-disk format.
Reference forms:
dejavue recall "<query>" # FTS5 keyword (default)
dejavue recall "<query>" --semantic # cosine-ranked semantic
.dejavue/
timeline.jsonl # append-only event log — commit this
state.md # current state snapshot — commit this
decisions.md # append-only architectural decisions — commit this
handoff.md # latest handoff — commit this
references/ # hand-written reference cards (optional) — commit these
fts.db # sqlite FTS5 index — do NOT commit (rebuildable)
embeddings.jsonl # semantic-recall vector cache — do NOT commit (rebuildable, model-specific)
ingested.lock # ingest marker — do NOT commit (per-checkout)
.first-use # worthiness-gate-shown marker — do NOT commit (per-user)
.locks/ # file locks for concurrent ops — do NOT commit
Add to .gitignore:
.dejavue/fts.db
.dejavue/embeddings.jsonl
.dejavue/*.tmp
.dejavue/.first-use
.dejavue/ingested.lock
.dejavue/.locks/
And add .gitattributes (critical for multi-branch / worktree workflows — see
Concurrency, branches, and worktrees below):
.dejavue/timeline.jsonl merge=union
.dejavue/decisions.md merge=union
Deja Vue is designed for the common cases that real coding agents hit:
Same repo, one agent at a time (sequential handoff): the default flow.
Last agent's state.md/handoff.md wins. timeline.jsonl and decisions.md
accumulate. This is the entire model.
Same repo, multiple agents sequentially across many sessions: identical to
the above. The since command is the lookup tool — show me what changed since
I last touched this repo (or since a specific agent's last session).
Multiple worktrees on different branches (worktree-per-agent dispatch):
the workflow where each dispatched agent gets its own git worktree on its own
task branch, and a coordinator merges those branches back into main in waves.
Each worktree has its own checked-out .dejavue/. Agents accumulate events
on their own branch. When the branches merge back, git would normally
conflict on timeline.jsonl because both sides added unique lines and
the default text merger can't see that append-only semantics make union safe.
.gitattributes with merge=union fixes this: git keeps unique lines from
both sides, no conflict, all events surface after merge. Without this,
every wave merge requires manual resolution on .dejavue/timeline.jsonl.
The two-line .gitattributes file in this repo handles it.
State/handoff overwrites (single-file replace) follow last-writer-wins. If two
branches both edited state.md or handoff.md, git's normal text merger
flags the conflict and a human/agent resolves by hand — usually the latest is
correct.
Multiple agents in the same working tree at the same instant (rare): JSONL
appends are POSIX-atomic up to PIPE_BUF (~4KB) with O_APPEND. fts.db
rebuilds and ingest scrapes are not atomic; running two of these
concurrently in the same directory can corrupt state. fcntl.flock advisory
locking is applied to FTS rebuilds and ingest (v1.0+); JSONL appends are
POSIX-atomic. The rare true-concurrent case is still best avoided.
Git hooks in worktrees: dejavue init installs its pre-push and
post-checkout hooks in the main repo's .git/hooks/. Git worktrees inherit it by default (verified
on git 2.40+). You do not need to run dejavue init separately in each
worktree.
Cross-repo: out of scope. Each repo has its own .dejavue/. Cross-repo
coordination is the job of a workspace-wide coordination layer, not per-repo
memory.
Agent identity: use a stable role name on --agent (e.g. claude,
sonnet, reviewer, coordinator), not a model version. The role is what
the next session looks up; model versions change beneath the role.
- A replacement for git.
- A replacement for richer per-repo planning systems that maintain milestone / phase / decision-tree state. Dejavue is the lightweight episodic layer underneath those, not a substitute for them.
- A vector database or embedding store.
--semanticrecall is available via any OpenAI-compatible/v1/embeddingsendpoint (optional, graceful fallback). - An MCP server. MCP tool wrappers are on the roadmap but not yet shipped; the format is the open contract any MCP server can consume.
- Cross-repo memory. Cross-repo coordination belongs in a separate workspace-wide coordination layer.
Deja Vue is the file format and reference CLI. Richer tools consume dejavue; dejavue does not bundle them.
Analogy: .dejavue/ is to project memory what .git/ is to history. Multiple
tools sit on top of the same on-disk format. See docs/05-v0.1-scope.md
§Architecture for the full ruling.
| Version | Milestone |
|---|---|
| v0.1 | Single-file Python CLI. FTS5-only recall. Zero infrastructure. |
| v0.2 | --semantic flag via external embedder; FTS5 fallback. |
| v1.0 | Format stable. 20 commands: ambient agent-id, staleness warnings, pre-push hook, codebase map, status, log, blame, note. |
| v1.1 | 25 commands: check, archive, roster, config, install-skill, embedder circuit breaker. |
| v1.2 | 31 commands: richer event types, stats, export, reference, link, search, tiered embedder auto-detect. |
| v1.3 | 35 commands: diff, timeline, tag, note-commit, check --fix, event_type FTS indexing, since notes section. |
| v2.0 | DCP/1.0 — context.md instruction layer, import, export --target {claude,codex,gemini,copilot,cursor,all} (non-destructive adapter bridge), promote --to planning, init --wizard, references/glossary.md, init auto-discovery (CLAUDE.md boot stub + in-repo skills). docs/dcp-spec.md ships as a citable standard. |
v2.0.0 — single-file Python CLI and the DCP/1.0 reference implementation.
DCP/1.0 spec at docs/dcp-spec.md (Release Candidate). Format stable and
backward-compatible (additive evolution per DCP §7). Single file, stdlib only,
zero mandated dependency (Axiom 0). Not on PyPI.
Design documents in repo:
docs/dcp-spec.md— the DCP/1.0 standard (three layers, adapter contract,.dejavue/layout, conformance)docs/plans/2026-06-05-dcp-maturation.md— ratified DCP design decisions (internal session)docs/01-origin.md— original conversation that produced the specdocs/02-evolution.md— the spec's evolution (semantic, boot packet, since/recall)docs/03-example.md— early bash demodocs/04-design-perspective.md— design rationale, overlap analysis, hook strategydocs/05-v0.1-scope.md— v0.1 build spec and architecture rulingdocs/08-thin-wrapper.md— minimal shell-out wrapper contract for optional MCP/stdio adaptersskills/dejavue-workflow/SKILL.md— agent-facing workflow skill (Claude Code SKILL.md format, generic — symlink into~/.claude/skills/to load automatically)CHANGELOG.md— release notesCONTRIBUTING.md— contribution guidelines