Imported from nixpt/water-spider (
.dejavue/dejavue-workflow/SKILL.md). Install upstream withnpx skills add nixpt/water-spider --skill dejavue-workflow. Copyright stays with the author.
dejavue-workflow
Dejavue is to project memory what .git/ is to history — a repo-local
event log that captures the why git can't (architectural decisions,
constraints non-obvious from the code, dead ends explored). The format
is portable (plain JSONL + markdown + SQLite FTS5); the reference CLI
is a single Python 3 file with no dependencies.
This skill is how a working agent interacts with dejavue: orient on arrival, capture worth-keeping events, hand off cleanly, recall later.
When this skill triggers
- You arrive in a repo and
.dejavue/exists at the root - A task prompt mentions dejavue or says "boot packet"
- You're about to make an architectural decision worth keeping
- You need to know what's changed in a repo since some reference point
- A session is ending and you need to leave a handoff
If dejavue isn't on PATH but the repo has a copy at dejavue.py:
ln -sf "$(pwd)/dejavue.py" ~/.local/bin/dejavue
Or install from the canonical repo per its README. The CLI is stdlib-
only Python 3 — no pip install needed.
Why each pattern exists
Three failure modes dejavue is built to prevent:
-
Cold-start blindness. A new session in a repo doesn't know what the previous session decided, blocked on, or handed off. Without dejavue you re-derive context from git log + scattered TODOs + stale README sections. With dejavue:
dejavue contextis one screen. -
Decision rot. Architectural choices made mid-session get forgotten by the next session. Without capture, the why lives in chat scrollback (gone) or "the code speaks for itself" (it doesn't). With
dejavue decision, decisions land indecisions.mdwith rejected-alternatives — the most valuable signal future agents need. -
Handoff void. Multi-agent / multi-session work loses continuity when each agent posts "done" but doesn't leave next-steps.
dejavue handoffis the structured next-session brief.
Boot packet on arrival
Step 1, before any work. From the repo root:
dejavue context
You get: handoff.md + state.md + decisions.md + last 10 timeline
events. Treat as ground truth for "what was the prior session's frame".
If dejavue context is empty or the directory doesn't exist, the repo
isn't dejavue-enabled. Don't initialize reflexively — see "When NOT to
init dejavue" below.
Capture pattern (session lifecycle)
Session start
dejavue start --agent <your-name> --goal "<one-line goal>"
Records a session_start event. Future agents can run
dejavue since --agent <you> to see everything that's changed since
your last start — even across days or weeks.
Architectural decisions
For decisions that change direction, name a constraint, or close a path:
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" \
--rejected "fixed-window: thundering-herd at boundary" \
--agent <your-name>
The --rejected flag is repeatable and load-bearing. Future
readers need to know what was tried and rejected, not just what won.
Each rejection: "option: reason". This is the single most valuable
artifact dejavue captures — the reasoning that costs the next agent
the most to rediscover.
Two optional enrichments worth using when they apply:
# --supersedes: makes contradiction explicit
dejavue decision "Use embedded SQLite" \
--reason "Zero deps, single process" \
--supersedes "Use service-mode SQLite"
# --durability: filters noise during architectural reasoning
dejavue decision "Axiom 0 — no runtime deps ever" \
--reason "Single-file contract; adoption collapses with pip deps" \
--durability constitutional
--durability choices: temporary · tactical · strategic · constitutional.
The label appears in the decisions.md heading so it's visible without parsing events.
Invariants, traps, and incidents
Three event types that capture memory most projects routinely lose:
# Things that must ALWAYS be true — architectural laws.
# Appends to invariants.md, surfaced by `context`.
dejavue invariant "Capsules never access host FS directly"
dejavue invariant "append-only timeline is immutable; never delete entries"
# Misleading names, fake abstractions, historical hacks.
# Agents waste real time rediscovering these.
dejavue trap "AuthManager does NOT handle OAuth — it only handles sessions"
dejavue trap "The 'cache' in CacheLayer is not a cache; it's a write buffer"
# Operational trauma — outages, data corruption, failed migrations.
# Highest-value memory; also the most reliably forgotten.
dejavue incident "FTS index corrupted after ungraceful shutdown 2026-05-15; rebuilt from JSONL"
dejavue incident "Migration 004 dropped rows where user_id was NULL — data lost in prod"
When unsure which to use: invariant = "this must never change"; trap = "this will mislead you"; incident = "this already hurt us". All three take --tag for grouping.
To look up what was previously rejected on a topic:
dejavue rejected # all decisions with rejected alternatives
dejavue rejected "grpc" # only those mentioning gRPC
dejavue rejected "database" # why we didn't use X database approach
State snapshots
After a meaningful milestone (not every commit):
dejavue state --summary "<2-4 sentences on current state>" \
--agent <your-name>
This OVERWRITES state.md. The state.md is "what's true right now",
not "what happened" — the timeline tracks history. Re-write whenever
the answer to "where are we?" changes materially.
Annotations (lightweight notes)
When you want to add a timestamped note WITHOUT rewriting state/handoff:
dejavue annotate state "note text" # appends to state.md
dejavue annotate handoff "note text" # appends to handoff.md
dejavue annotate decisions "note text" # appends to decisions.md
Good for mid-session context drops, partial updates, or noting an intermediate event without losing the prior content.
Session handoff (end of task)
Before you sign off:
dejavue handoff \
--summary "<what's done, in 1-2 sentences>" \
--next "<1-4 concrete next steps for the receiver>" \
--agent <your-name>
The handoff is what the NEXT agent reads first via dejavue context.
Treat it as the most-important artifact of your session — the
short-format next-steps in --next shape the receiver's whole plan.
Recall pattern (looking things up)
Temporal delta — since is the killer command
dejavue since 2026-05-10 # everything since this date
dejavue since a81f2cd # everything since this commit
dejavue since main..HEAD # git revision range
dejavue since v1.0..v2.0 # between two tags
dejavue since --agent claude # since this agent's last session_start
The "what changed since I was last here?" question, answered in seconds. Output sections: git delta (log + diff stat), timeline events (newest first), decisions made, state transitions, handoffs, top keywords.
Keyword search
dejavue recall "rate limiter"
dejavue recall "auth migration"
FTS5 search over timeline + decisions + state + handoff + references. Returns matched events with timestamps and excerpts. Fast.
Direct fetch
dejavue get state # print state.md
dejavue get handoff # print handoff.md
dejavue get decisions # print decisions.md
dejavue get references/<name> # print a specific reference card
dejavue list # list everything available
Use get when you know exactly what you want; recall when you don't.
The worthiness gate
The single biggest mistake with dejavue is over-capture. The CLI's own
dejavue worthiness output is canonical:
| 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 (dejavue invariant) |
Routine commits |
Misleading name / dangerous assumption (dejavue trap) |
Things obvious from reading the code |
Operational incident (dejavue incident) |
Successful deploys with no lessons |
Rule of thumb: if removing this memory wouldn't confuse a future agent reading the code + git log, don't write it.
Print this in your terminal any time you're uncertain:
dejavue worthiness
Repo state ownership (git tracking)
When .dejavue/ ships in a repo, the split is:
Tracked (commit to repo):
timeline.jsonl— append-only event logstate.md— current statedecisions.md— architectural decisionshandoff.md— latest handoffinvariants.md— architectural invariants (scaffolded byinit, append-only)references/— hand-written reference cards (optional)context.md— DCP adapter source (optional; used byexport --target)dejavue/,dejavue-workflow/— skill dirs copied byinitfor in-repo fallback (optional)
Ignored (per-checkout, rebuildable):
fts.db— SQLite FTS5 index, rebuilt from JSONL on demand.dejavue/.first-use,.dejavue/ingested.lock— markers.dejavue/*.tmp— temp files
Canonical .gitignore entries:
.dejavue/fts.db
.dejavue/*.tmp
.dejavue/.first-use
.dejavue/ingested.lock
.dejavue/.locks/
The post-commit hook (installed by dejavue init) auto-records every
commit's file changes as file_changed events. The hook is one line
calling dejavue changed --auto; no manual changed calls needed for
committed work.
The hook's dirty diff is self-perpetuating — don't chase it to zero
Because the hook fires after the commit completes, the file_changed
event it appends describes a commit that has already happened — it
physically cannot be included in that same commit. The result: right
after every commit, .dejavue/timeline.jsonl shows one new dirty line
(a record of the commit you just made). If you commit that line too,
the hook fires again and appends a record of that commit — forever.
This is expected behavior by construction, not a bug to fix or a sign
something is broken.
What this means in practice (verified live, s408 2026-07-29, on
workspace-meta):
- A single dangling
file_changedline for the most recent commit is normal. Don't loop trying to reach a permanently clean tree — one will always regenerate. - Multiple pending lines, or lines several commits old, ARE worth
sweeping — that's a sign the hook's records piled up uncommitted
across a stretch of work (seen this session in exosphere: BUCKETS-11's
merge-decision + timeline records sat uncommitted since s396, three
sessions earlier). A single
git add .dejavue/ && git commitcloses the gap; don't hand-edit the JSONL. - At session-start or session-close, when checking
git statusfor a clean tree ([[foreman-session-start]], [[foreman-session-close]]): a lone trailing.dejavue/timeline.jsonldiff recording the just-made commit is not a "dirty tree" finding worth flagging or blocking on — distinguish it from real uncommitted work by checking what the diff contains (onefile_changed/commitline referencing a commit hash you recognize as your own last one) before treating the repo as unclean.
merge=union for parallel branches
If multiple agents commit on parallel branches that all touch
.dejavue/timeline.jsonl or .dejavue/decisions.md, every merge
produces a conflict on those append-only artifacts. The fix is in
.gitattributes:
.dejavue/timeline.jsonl merge=union
.dejavue/decisions.md merge=union
.dejavue/invariants.md merge=union
This tells git to take both sides of an append conflict. Apply once per repo; future merges resolve cleanly. State.md and handoff.md are single-file overwrites and stay with git's normal merge (conflicts are rare and a human/agent resolves by hand).
DCP adapter bridge
DCP/1.0 (DejaVue Context Protocol) lets a single context.md source
file feed all the different agent config formats a repo might need
(CLAUDE.md, AGENTS.md, .cursorrules, etc.) without duplicating
content.
Bootstrap context.md from an existing instructions file
If the repo already has a CLAUDE.md or AGENTS.md:
dejavue import CLAUDE.md # reads and seeds .dejavue/context.md
Imports the content into context.md as the canonical DCP source. The
original file is left untouched — import is read-only.
Generate adapter files from context.md
dejavue export --target claude # writes/updates CLAUDE.md
dejavue export --target codex # writes/updates AGENTS.md
dejavue export --target gemini # writes/updates .gemini/GEMINI.md
dejavue export --target cursor # writes/updates .cursorrules
dejavue export --target copilot # writes/updates .github/copilot-instructions.md
dejavue export --target all # all of the above in one pass
Each export is non-destructive: it writes a managed block
(<!-- dejavue:begin DCP/1.0 src=context.md hash=… -->…<!-- dejavue:end -->)
into the target file. Content outside that block is preserved. Re-run
any time context.md changes — the hash guards against spurious writes.
Promote to a richer planning system
When the project has outgrown plain dejavue memory and needs a full planning system:
dejavue promote --to planning # bootstrap a .planning/ planning system
This graduates the project without losing the .dejavue/ history.
Common workflows
Session boot
cd <repo>
dejavue context # boot packet
# ... now you have prior session's frame ...
dejavue start --agent <you> --goal "<one-line>"
Mid-session decision capture (the most common use)
After making a real architectural choice, BEFORE moving on:
dejavue decision "<title>" \
--reason "<why this won>" \
--rejected "<alt>: <why-not>" \
--agent <you>
Takes ~30 seconds. Pays off compounding over future sessions.
Session close
dejavue state --summary "<current-state>" --agent <you>
dejavue handoff --summary "<what's-done>" --next "<next-steps>" --agent <you>
git add .dejavue/
git commit -m "<your message — post-commit hook also records the diff>"
DCP multi-target export
# seed context.md from an existing instructions file, then generate all targets
dejavue import CLAUDE.md
dejavue export --target all
git add .dejavue/context.md CLAUDE.md AGENTS.md
git commit -m "chore: add DCP adapter bridge"
After that, keep context.md as the single source — re-run
dejavue export --target all whenever it changes.
Returning after a gap
dejavue context # what's the latest frame?
dejavue since --agent <you> # what changed since I was here?
dejavue recall "<topic-i-was-working-on>" # specifics from prior work
When NOT to init dejavue
Resist the urge to dejavue init everywhere. Good candidates:
- ✅ A library you're actively designing (lots of architectural choices)
- ✅ A repo where multiple agents will work over time
- ✅ A repo where decisions decay because of long-tail multi-session work
- ✅ A repo with sessions ≥ days apart (cold-start cost is high)
Bad candidates:
- ❌ A repo with only mechanical edits (just use git)
- ❌ A repo you'll work on once and forget
- ❌ A repo that already has a richer planning system you'd duplicate
- ❌ A repo where the owner hasn't opted in
When in doubt, ask the repo owner. .dejavue/ does ship in the repo;
opting users in without their consent is intrusive.
What dejavue init installs
For context: dejavue init does more than create .dejavue/. It also:
-
Writes a
CLAUDE.mdboot stub — appends (or creates) a minimal section pointing agents atdejavue contexton arrival. Idempotent: if the marker (<!-- dejavue:discovery -->) or anydejavue contextreference already exists, the stub is skipped. -
Copies skills to
.dejavue/— copiesdejavue/anddejavue-workflow/from the adjacentskills/directory into the repo's.dejavue/as an in-repo fallback. Agents without the skills in their global~/.claude/skills/can still load them frompython3 .dejavue/dejavue install-skill. -
Installs git hooks — post-commit (auto
file_changedrecording), pre-push (staleness check), post-checkout (printsdejavue statuson branch switch — guards on$3==1, never fires on file checkout);.gitattributesmerge=unionentries for timeline/decisions/invariants.
Use --wizard to also interactively seed context.md for DCP export.
What dejavue is NOT
- Not a replacement for git — it's a companion. Git captures what changed; dejavue captures why.
- Not a chat/conversation log. Don't dump LLM reasoning into the timeline — the worthiness gate filters that out for good reason.
- Not a project planner. State is current-snapshot; decisions are
architectural choices; handoff is short-form. For real planning use
a richer system on top (dejavue's docs note
.planning/as one superset). - Not auto-summarizing commits via LLM. v0.1 records the diff stat + commit message verbatim; deliberate capture is the contract.
See also
- The dejavue README and
docs/directory in the project root for full design rationale, the rejected-alternatives principle, the hook strategy, and the migration path to richer planning systems. dejavue worthiness— print the capture gate any time.dejavue --helpand per-command--helpfor the canonical CLI surface.
License
This skill ships under the same license as the dejavue project
(see LICENSE in the project root).