Help us improve
Share bugs, ideas, or general feedback.
From dejavu
Guides agents to deliberately search or skip memory using dejavu MCP tools, with query strategies and metadata filters for decisions, user preferences, conventions, and anti-patterns.
npx claudepluginhub jsingletonai/dejavu --plugin dejavuHow this skill is triggered — by the user, by Claude, or both
Slash command
/dejavu:dejavu-mcpThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You have access to persistent memory via the dejavu MCP tools. Follow this protocol to maintain context across sessions.
Integrates Mem0 persistent memory for Claude Code tasks using MCP tools. Retrieves relevant memories on new tasks, stores learnings like decisions and strategies, captures session states.
Proactively saves decisions, conventions, bugs, discoveries, and preferences to persistent Engram memory across sessions using mem_save and related tools.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
You have access to persistent memory via the dejavu MCP tools. Follow this protocol to maintain context across sessions.
Decide whether persistent memory context would improve your response, then act accordingly. Don't search by default — search deliberately.
Search WHEN the user:
Skip WHEN:
add_memory), not a searchEmpty results are normal. Proceed without context — they don't mean the system is broken.
When you do search, run 2–4 parallel search_memories calls at different angles instead of one query echoing the user's prompt.
Query phrasing:
"auth module decisions" beats "what did we decide about auth"."Postgres choice".get_memories ordered by created_at.Metadata filters match the same type values written under "After completing significant work" below.
Two rules from the v2 filter spec:
AND / OR / NOT) with an array. A bare {"user_id": "..."} won't work.{"metadata": {"type": "decision"}}, never {"metadata.type": "decision"}. Only top-level metadata keys are filterable.Combine user_id with one metadata clause per call:
metadata.type clause | Use for |
|---|---|
{"metadata": {"type": "decision"}} | design / architecture / "how should we" questions |
{"metadata": {"type": "anti_pattern"}} | debugging, error handling, things that failed before |
{"metadata": {"type": "user_preference"}} | tooling, stack, style — always include for code work |
{"metadata": {"type": "convention"}} | established patterns in this project |
Full filter (replace <your_user_id> with the active user_id from your runtime):
filters={"AND": [{"user_id": "<your_user_id>"}, {"metadata": {"type": "decision"}}]}
User asks: "Refactor the auth module to use JWT."
Don't:
search_memories(query="Refactor the auth module to use JWT")
# Hits whatever shares words. Misses prior decisions and preferences.
Do (parallel — substitute the active user_id for <your_user_id>):
search_memories(query="auth module decisions",
filters={"AND": [{"user_id": "<your_user_id>"}, {"metadata": {"type": "decision"}}]})
search_memories(query="JWT",
filters={"AND": [{"user_id": "<your_user_id>"}]})
search_memories(query="auth refactor failures",
filters={"AND": [{"user_id": "<your_user_id>"}, {"metadata": {"type": "anti_pattern"}}]})
search_memories(query="auth",
filters={"AND": [{"user_id": "<your_user_id>"}, {"metadata": {"type": "user_preference"}}]})
Extract key learnings and store them using the add_memory tool:
{"type": "decision"}{"type": "task_learning"}{"type": "anti_pattern"}{"type": "user_preference"}{"type": "environmental"}{"type": "convention"}
metadata.type(which you set explicitly) andcategories(which the platform auto-tags after the project's custom-category list — seescripts/setup_coding_categories.py) are complementary. Always setmetadata.typefor explicit filtering; the platform fills incategorieson its own. Don't try to setcategoriesonadd_memorycalls — per-request overrides aren't supported on the managed API.
Some memory types are state snapshots that go stale fast; others are durable facts that should outlive the session that created them. Mark the difference with expiration_date on writes.
| Type | Expiration | Why |
|---|---|---|
session_state, compact_summary | expiration_date ≈ today + 90 days | Describe a single moment of project state. Useless after a quarter; clutter the recall surface. |
decision, anti_pattern, convention, user_preference, task_learning, environmental | omit expiration_date | Durable facts. A decision made last year is still a decision; same for a convention or a user preference. |
add_memory accepts expiration_date as a string ("YYYY-MM-DD"). The two server-side hooks (on_pre_compact.py, capture_compact_summary.py) already set this for the types they write. When you write directly via the MCP tool, follow the same rule.
When the user is asking about current state ("where were we", "what's the active task", "the latest decision on X"), filter recall to recent memories so stale snapshots don't surface:
# Last 90 days only
{"AND": [{"user_id": "<id>"}, {"metadata": {"type": "session_state"}}, {"created_at": {"gte": "<90 days ago, YYYY-MM-DD>"}}]}
Skip the recency filter when the user is asking about durable facts ("what conventions does this project use", "have we hit this bug before") — those are timeless and recency would hide them.
Memories can be as detailed as needed -- include full context, reasoning, code snippets, file paths, and examples. Longer, searchable memories are more valuable than vague one-liners.
infer=False for already-structured contentWhen you've done the extraction work yourself — pre-compaction summaries, decisions, anti-patterns, conventions you've explicitly identified — pass infer=False so the platform stores your text verbatim instead of running a second extraction pass over it.
add_memory(
messages=[{"role": "user", "content": "<your structured fact>"}],
user_id="<active user_id>",
metadata={"type": "decision"},
infer=False,
)
Stick to one mode per distinct piece of content — don't mix infer=True (default) and infer=False for the same fact, you'll get duplicates. Default (infer=True) is right for raw conversational signal you want extracted; infer=False is right for pre-extracted structure.
If context is about to be compacted or the session is ending, store a comprehensive session summary:
## Session Summary
### User's Goal
[What the user originally asked for]
### What Was Accomplished
[Numbered list of tasks completed]
### Key Decisions Made
[Architectural choices, trade-offs discussed]
### Files Created or Modified
[Important file paths with what changed]
### Current State
[What is in progress, pending items, next steps]
Include metadata: {"type": "session_state"}