chore: import upstream snapshot with attribution
pi-agent-plugin checks / lint (push) Has been cancelled
pi-agent-plugin checks / test (20) (push) Has been cancelled
pi-agent-plugin checks / test (22) (push) Has been cancelled
pi-agent-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / check_changes (push) Has been cancelled
TypeScript SDK CI / changelog_check (push) Has been cancelled
ci / changelog_check (push) Has been cancelled
ci / check_changes (push) Has been cancelled
ci / build_mem0 (3.10) (push) Has been cancelled
ci / build_mem0 (3.11) (push) Has been cancelled
ci / build_mem0 (3.12) (push) Has been cancelled
CLI Node CI / lint (push) Has been cancelled
CLI Node CI / test (20) (push) Has been cancelled
CLI Node CI / test (22) (push) Has been cancelled
CLI Node CI / build (push) Has been cancelled
CLI Python CI / lint (push) Has been cancelled
CLI Python CI / test (3.10) (push) Has been cancelled
CLI Python CI / test (3.11) (push) Has been cancelled
CLI Python CI / test (3.12) (push) Has been cancelled
CLI Python CI / build (push) Has been cancelled
openclaw checks / lint (push) Has been cancelled
openclaw checks / test (20) (push) Has been cancelled
openclaw checks / test (22) (push) Has been cancelled
openclaw checks / build (push) Has been cancelled
opencode-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (22) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (22) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:03:45 +08:00
commit 555e282cc4
1802 changed files with 338080 additions and 0 deletions
@@ -0,0 +1,52 @@
---
name: mem0-context-loader
description: Searches and injects relevant memories into context before starting work on a task. Use when beginning a new task, switching context, or when project history, past decisions, or coding conventions need to be loaded.
---
# Context Loader
Pre-fetches relevant memories to prime context before working on a task.
## When to use
- Session start (invoke manually or auto-triggered by skill description matching)
- User starts work on a specific feature or file set
- Complex multi-step task begins
- User says "what do we know about X" or "context for X"
## Steps
1. **Extract topics** from current message/task. Identify: file paths, module names, feature areas, error patterns.
2. **Run 2-4 parallel `search_memories` calls** with different angles:
| Query angle | Filter | Purpose |
|---|---|---|
| Feature/module name | `{"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}, {"metadata": {"type": "decision"}}]}` | Architecture decisions |
| File paths mentioned | `{"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}, {"metadata": {"type": "convention"}}]}` | Coding patterns |
| Error keywords (if any) | `{"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}, {"metadata": {"type": "anti_pattern"}}]}` | Known pitfalls |
| Broad project context | `{"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}]}` | Catch-all |
3. **Deduplicate** results by memory ID across all search responses.
4. **Output compact context block** (max 10 memories):
```
context-loader: loaded <N> memories for "<task summary>"
- [decision] <content> [mem0:<short_id>]
- [convention] <content> [mem0:<short_id>]
- [anti_pattern] <content> [mem0:<short_id>]
```
5. If **zero results**: output nothing. Don't announce empty context.
## Constraints
- **Read-only** — never modify or delete memories
- **Max 10 memories** returned (most relevant only)
- **Silent on empty** — only surfaces findings if relevant context exists
- Skip memories already visible in current session context
## Output formatting
IMPORTANT: Do NOT use markdown in your output. OpenCode TUI renders text verbatim — markdown like **bold**, ## headers, and | table | syntax appears as raw characters. Use plain text with indentation for structure. Use dashes for lists. Use spaces to align columns instead of markdown tables.
@@ -0,0 +1,237 @@
---
name: mem0-dream
description: Consolidates stored memories by merging duplicates, resolving contradictions, and pruning stale entries. Use when memory count is high, search results feel noisy or repetitive, or periodic cleanup is needed to maintain memory quality.
---
# Mem0 Dream — Memory Consolidation
This skill performs a memory consolidation pass: it fetches all project memories,
identifies near-duplicates, flags contradictions, and prunes stale entries based on
configured retention policies. All proposed changes are shown as a diff for user
approval before anything is modified.
**IMPORTANT: Execute steps strictly in order (1 → 2 → 3 → 4 → 5 → 6). Each step depends on the previous one. Do NOT run steps in parallel or skip ahead.**
## Step 1: Load Retention Policies
Check for a project config file in the project root (current working directory):
1. Look for `.mem0.json` first. If it exists, parse it as JSON and read the
`retention` field (a dict of `category → days | null`).
2. If `.mem0.json` is not present, look for `.mem0.md`. If it exists, scan it
for a `retention:` section or YAML front matter with retention settings and
parse what you find.
3. If neither file exists, skip config loading entirely.
If no config is found or the config contains no retention settings, fall back to
these built-in defaults:
| `metadata.type` | Default retention |
|---|---|
| `session_state` | 90 days |
| `compact_summary` | 90 days |
| all others | no pruning |
Store the resolved policies for use in Step 3.
---
## Step 2: Fetch ALL Project Memories
Call `get_memories` to retrieve every memory for the active project:
```python
get_memories(
filters={"AND": [{"user_id": "<active_user_id>"}, {"app_id": "<active_project_id>"}]},
page_size=200,
)
```
If the response indicates more pages exist, paginate until all memories are fetched.
Collect the full list before proceeding. If zero memories are found, print:
```
No memories found for project <project_id>. Nothing to consolidate.
```
…and stop.
---
## Step 3: Analyze — Find Issues
Work entirely in-memory; do not modify anything yet.
Group memories by `metadata.type` (use `"unknown"` when the field is absent).
For each group, identify the following:
### 3a. Near-duplicate pairs (merge candidates)
Two memories are near-duplicates when they express the same fact or decision but
phrased differently (e.g., "Use PostgreSQL for auth" and "Auth DB is PostgreSQL").
Heuristics — two memories are near-duplicates if **all** of these hold:
- Similarity threshold: estimated cosine similarity > 0.9 (use noun/keyword overlap as proxy — if >60% of significant nouns overlap, treat as >0.9 similarity).
- Same `metadata.type`.
- Neither memory is pinned (`metadata.pinned != true`).
For each qualifying pair, draft a merged version that is more complete and specific
than either original.
### 3b. Contradictions
Two memories contradict when they assert opposing facts about the same topic
(e.g., "Deploy to ECS" vs. "Deploy to Vercel").
Identify the likely winner: the more recent memory with higher confidence wins.
Store both IDs and their content for user review.
### 3c. Prune candidates
A memory is a prune candidate when **any** of the following is true:
1. Its `metadata.type` has a retention policy and the memory is older than the
configured number of days (compare `created_at` to today).
2. Its confidence score is below 0.3 AND it contains no information unique to
this project (no file paths, identifiers, or domain-specific nouns).
**Always skip memories where `metadata.pinned == true`**, regardless of age or
confidence.
---
## Step 4: Print Diff Report
Print a structured diff to the terminal before making any changes. Use exactly
this format:
```
## dream — consolidation report
Merges (<N>):
[mem0:<id1>] + [mem0:<id2>] → "<merged content, 100 chars>"
Conflicts (<N>):
[mem0:<idA>] vs [mem0:<idB>] — "<topic>" [A/B/skip]
Prune (<N>):
[mem0:<id>] — <type>, <age>d old
Proposed: <N> merges, <N> prunes, <N> conflicts. Apply? [Y/n]
```
If there are zero items in any category, omit that section entirely.
If there are zero total proposals (no merges, no prunes, no conflicts), print:
```
Dream complete. No duplicate, contradictory, or stale memories found.
```
…and stop.
---
## Step 5: Wait for User Input and Apply
### 5a. Contradictions
For each `CONFLICT` pair in the report, wait for the user to type `A`, `B`, or
`skip` (case-insensitive). If they enter nothing (empty), treat as `skip`.
Record the winner for each pair before proceeding to the final apply confirmation.
### 5b. Final confirmation
After all conflict resolutions are collected, prompt:
```
Apply? [Y/n]
```
If the user types `n` or `no` (case-insensitive), print `Cancelled. No changes made.`
and stop.
If the user confirms (`Y`, `yes`, or empty / Enter), apply all changes in this order:
#### Merges
For each approved merge pair:
1. `delete_memory(<id1>)`
2. `delete_memory(<id2>)`
3. `add_memory` with:
- `text="<merged content>"`
- `user_id=<active_user_id>`
- `app_id=<active_project_id>` (top-level, not in metadata)
- `metadata={"type": "<original type>", "branch": "<active_branch>", "confidence": <higher of the two original scores>, "source": "mem0-dream"}`
- `infer=False`
#### Contradictions (resolved)
For each resolved conflict where the user chose A or B:
- Delete the loser (the non-chosen memory): `delete_memory(memory_id=<loser_id>)`
Contradictions where the user chose `skip` are left untouched.
#### Prunes
For each prune candidate:
- `delete_memory(<memory_id>)`
---
## Step 6: Print Summary
After all changes are applied, print:
```
Dream complete — merged: <N>, pruned: <N>, conflicts resolved: <N>, skipped: <N>
```
---
## Auto mode
When invoked with `--auto` (e.g., `/mem0-dream --auto`), run non-interactively:
- **Merges**: applied automatically (no contradiction, both are compatible).
- **Prunes**: applied automatically (age/confidence-based, no ambiguity).
- **Contradictions**: skipped — they require human judgment.
### Concurrency guard
Before doing any work, check for a lock file at `/tmp/mem0_dream_auto.lock`:
- If the lock file exists and is less than 10 minutes old, print `[mem0-dream --auto] Another run in progress — skipping.` and stop.
- Otherwise, create the lock file (write the current timestamp). Delete it when done (in all exit paths).
### Execution
In auto mode:
1. Load policies and fetch memories (Steps 13) as normal.
2. Apply merges and prunes silently without printing the diff or prompting.
3. Print a compact summary:
```
[mem0-dream --auto] project=<id> merged=<N> pruned=<N> conflicts_skipped=<N>
```
4. If contradictions were detected but skipped, check if a `mem0-dream-auto` reminder already exists before storing one:
- Search for existing reminders: `search_memories(query="mem0-dream contradictions manual review", filters={"AND": [{"user_id": "<active_user_id>"}, {"app_id": "<active_project_id>"}, {"metadata": {"source": "mem0-dream-auto"}}]}, top_k=1)`
- If a result exists with similarity > 0.9, skip storing the reminder (one already exists).
- If no match, store the reminder:
```python
add_memory(
text="mem0-dream detected <N> contradiction(s) requiring manual review. Run /mem0-dream to resolve them interactively.",
user_id="<active_user_id>",
app_id="<active_project_id>",
metadata={"type": "task_learning", "source": "mem0-dream-auto", "branch": "<active_branch>"},
infer=False,
)
```
## See also
- `/mem0-forget` — targeted deletion of specific memories (search + confirm + delete)
- `/mem0-status --deep` — quick quality scan without applying changes
## Output formatting
IMPORTANT: Do NOT use markdown in your output. OpenCode TUI renders text verbatim — markdown like **bold**, ## headers, and | table | syntax appears as raw characters. Use plain text with indentation for structure. Use dashes for lists. Use spaces to align columns instead of markdown tables.
@@ -0,0 +1,74 @@
---
name: mem0-forget
description: Deletes memories by search query or memory ID with confirmation before removal. Use when removing outdated decisions, incorrect memories, sensitive data, or cleaning up after experiments. Also handles undo of recent additions.
---
# Mem0 Forget
Delete specific memories from mem0.
## Execution
### Step 1: Parse input
The user provides either:
- A search query: `/mem0-forget auth module decisions`
- A memory ID: `/mem0-forget <memory_id>`
If no argument, ask: "What should I forget? Provide a search query or memory ID."
### Step 2: Find memories
**If memory ID provided** (looks like a UUID or hex string):
- Call `get_memory` with the ID to verify it exists.
- Show: `Found: "<memory content first 120 chars>" (created <date>)`
**If search query provided:**
- Call `search_memories` with:
- `query=<user's query>`
- `filters={"AND": [{"user_id": "<active_user_id>"}, {"app_id": "<project_id>"}]}`
- `top_k=10`
- Show numbered list:
```
Found <N> memories matching "<query>":
1. <content, 120 chars> (type: <type>, created: <date>) [ID: <short_id>]
2. ...
```
### Step 3: Confirm
Ask: "Delete which memories? Enter numbers (e.g., 1,3,5), 'all', or 'cancel'."
For a single memory ID, ask: "Delete this memory? [y/N]"
**Never delete without confirmation.** This is destructive.
### Step 4: Delete
For each confirmed memory, call `delete_memory` with the memory ID.
### Step 5: Report
```
Deleted <N> memories.
```
If any deletions failed, report which ones and why.
## Undo recent writes
If the user says "undo last N memories" or "undo last write":
1. Check the `MEM0_SESSION_ID` environment variable (set by the plugin's shell.env hook).
2. If `MEM0_SESSION_ID` is set, call `search_memories` with:
- `query="recently added"`
- `filters={"AND": [{"user_id": "<active_user_id>"}, {"app_id": "<project_id>"}, {"metadata": {"session_id": "<MEM0_SESSION_ID>"}}]}`
- `top_k=20`
3. Sort results by creation time descending and show the last N entries (default 1). Ask for confirmation.
4. Delete confirmed entries via `delete_memory`.
If `MEM0_SESSION_ID` is not set or the search returns no results, tell the user: "No recent memory IDs tracked this session. Try `/mem0-tour` to browse recent memories, or `/mem0-forget <search query>` to find specific ones."
## Output formatting
IMPORTANT: Do NOT use markdown in your output. OpenCode TUI renders text verbatim — markdown like **bold**, ## headers, and | table | syntax appears as raw characters. Use plain text with indentation for structure. Use dashes for lists. Use spaces to align columns instead of markdown tables.
@@ -0,0 +1,71 @@
---
name: mem0-pin
description: Pins or unpins a memory to protect it from pruning during dream consolidation. Use when a memory is critical and must never be removed, such as architecture decisions, security constraints, or immutable team conventions.
---
# Mem0 Pin
Pin a memory to mark it as high-priority and protect from pruning.
## Execution
### Step 1: Find the memory
The user provides either a search query or memory ID.
**If memory ID:**
- Call `get_memory` with the ID.
**If search query:**
- Call `search_memories` with the query, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}]}`, `top_k=5`.
- Show numbered list with content previews.
- Ask: "Which memory to pin? Enter a number."
### Step 2: Read current content
Call `get_memory` with the selected memory ID. Store:
- `original_text` — the memory's text content
- `original_metadata` — the existing `metadata` dict
### Step 3: Pin it
The `update_memory` tool updates a memory by `id`. To pin durably, append a pin
marker to the text so it travels with the memory:
```python
pinned_text = "[PINNED] " + original_text if not original_text.startswith("[PINNED]") else original_text
update_memory(id=<selected_id>, text=pinned_text)
```
**For new memories** (user wants to pin text that isn't stored yet):
1. Call `add_memory` with:
- `text="[PINNED] <the user's text>"`
- `user_id=<active_user_id>`
- `app_id=<active_project_id>`
- `metadata={"pinned": true, "type": "decision", "confidence": 1.0}`
- `infer=False`
2. The response contains `event_id`. Call `get_event_status(event_id=<event_id>)` once to retrieve the memory ID, then confirm.
### Step 4: Confirm
```
Pinned: "<memory content, first 80 chars>"
Memory ID: <id>
```
Append `...` only if content exceeds 80 characters.
### Unpin
If the user says "unpin":
1. Call `get_memory` to read current content.
2. Remove the pin marker from the text:
```python
unpinned_text = original_text.removeprefix("[PINNED] ")
update_memory(memory_id=<id>, text=unpinned_text)
```
3. Print: `Unpinned: "<content>..."`
## Output formatting
IMPORTANT: Do NOT use markdown in your output. OpenCode TUI renders text verbatim — markdown like **bold**, ## headers, and | table | syntax appears as raw characters. Use plain text with indentation for structure. Use dashes for lists. Use spaces to align columns instead of markdown tables.
@@ -0,0 +1,61 @@
---
name: mem0-remember
description: Stores a memory verbatim from user input with appropriate type classification and metadata. Use when the user says remember this, save this, store this, note that, or explicitly asks to record a decision, preference, convention, or learning.
---
# Mem0 Remember
Store a fact or learning directly into mem0.
## Execution
### Step 1: Extract the content
The user provides the content as an argument: `/mem0-remember <text>`
If no text was provided, ask: "What should I remember?"
### Step 2: Classify the memory
Based on the content, pick the best `metadata.type`:
| Content signal | Type |
|---|---|
| "we decided...", "always use...", "never..." | `decision` |
| "X doesn't work because...", "don't try..." | `anti_pattern` |
| "I prefer...", "use X instead of Y" | `user_preference` |
| "the convention is...", "we always..." | `convention` |
| "learned that...", "figured out..." | `task_learning` |
| setup, env, tooling, config | `environmental` |
| anything else | `task_learning` |
### Step 3: Store
Call `add_memory` with:
- `text="<the user's text>"`
- `user_id=<active_user_id>`
- `app_id=<active_project_id>`
- `metadata={"type": "<classified_type>", "branch": "<active_branch>", "confidence": 1.0, "source": "remember_command"}`
- `infer=False`
`infer=False` because the user stated the fact explicitly — no extraction needed.
`confidence=1.0` because the user explicitly asked to store this.
### Step 4: Confirm
The `add_memory` response returns `event_id` (not `memory_id`) because writes are async.
Call `get_event_status(event_id=<event_id>)` once.
- If status is `SUCCEEDED`: print the memory ID from the result.
- If status is `PENDING` or `processing`: print with the event ID as fallback.
```
Remembered as <type>: "<content, first 80 chars>"
Memory ID: <id from event status>
```
Append `...` only if content was truncated (longer than 80 chars).
## Output formatting
IMPORTANT: Do NOT use markdown in your output. OpenCode TUI renders text verbatim — markdown like **bold**, ## headers, and | table | syntax appears as raw characters. Use plain text with indentation for structure. Use dashes for lists. Use spaces to align columns instead of markdown tables.
@@ -0,0 +1,119 @@
---
name: mem0-scope
description: Views or changes the default memory scope (project, session, or global) used when saving and searching memories. Use when the user wants to control whether memories are scoped to this repo, this run, or shared across all their projects.
---
# Mem0 Scope
View or change the **default memory scope** — the scope the memory tools use when
no explicit `scope` is given. The setting persists in `~/.mem0/settings.json`
(`default_scope`) and the plugin reads it fresh on each memory operation, so a
change takes effect immediately in the current session.
The three scopes:
- `project` (default) — this repo only. Filters by `user_id` + `app_id`.
- `session` — this run only. Adds `run_id` (the current session) so memories are
isolated to this conversation.
- `global` — across ALL your projects. Reads use `app_id="*"`; writes drop
`app_id` so the memory is user-wide.
## Execution
### Step 1: Determine intent
Look at the user's message for a target scope word: `project`, `session`, or
`global` (also accept "repo"→project, "run"→session, "all"/"everywhere"→global).
- No target word present → **View mode** (Step 2).
- A target word present → **Change mode** (Step 3).
### Step 2: View mode — show the current scope
1. Read the current default scope from settings:
```bash
_S="$HOME/.mem0/settings.json"
[ -f "$_S" ] && grep -o '"default_scope"[[:space:]]*:[[:space:]]*"[a-z]*"' "$_S" | grep -o '[a-z]*"$' | tr -d '"' || echo "project"
```
If the command prints nothing, the scope is `project` (the default).
2. (Optional) Show how many memories live in the current scope by calling
`get_memories` with `scope="<current>"`, `page_size=1`, and reading the
`count` (or result length) from the response.
3. Display using the identity the plugin exported (do NOT re-shell git):
```
Mem0 memory scope
Current default scope: <current>
project - this repo only (user + app_id) <marker if active>
session - this run only (adds run_id) <marker if active>
global - all your projects (app_id = *) <marker if active>
User: ${MEM0_USER_ID}
Project: ${MEM0_APP_ID}
Session: ${MEM0_SESSION_ID}
To change: /mem0-scope session (or project / global)
```
Put `[active]` next to the current scope. If you fetched a count in step 2,
add a `Memories in scope: <N>` line.
### Step 3: Change mode — set a new scope
1. Validate the target is one of `project`, `session`, `global`. If not, show the
three options and stop.
2. Read the existing settings so you preserve every other key. Use the Read tool
on `~/.mem0/settings.json` (it may not exist yet — treat a missing file as
`{}`).
3. Write the file back with the Write tool, keeping ALL existing keys and only
setting `"default_scope"` to the target. Pretty-print with 2-space indent and
a trailing newline. Do not drop `global_search`, `dream`, `auto_save`, or any
other field that was present.
Example resulting file (when other keys already existed):
```json
{
"auto_save": true,
"search_limit": 10,
"default_scope": "global"
}
```
4. Confirm:
```
Default memory scope changed: <old> -> <new>
<one line describing the effect — see below>
Applies immediately to memory tools in this session.
To revert: /mem0-scope <old>
```
Effect lines:
- project → "New memories and searches are limited to this repo."
- session → "New memories and searches are limited to this run (this conversation)."
- global → "New memories and searches span all your projects. delete_all_memories still needs an explicit scope=global to delete user-wide."
### Notes
- This only changes the **default**. Any memory tool call can still pass an
explicit `scope` to override it for that one call.
- `delete_all_memories` deliberately ignores the default scope: deleting
user-wide always requires an explicit `scope="global"`, so changing the
default can never turn a routine cleanup into a cross-project wipe.
- `global` scope (this user, all their projects) is distinct from the separate
`global_search` setting (all users). Leave `global_search` untouched here.
## Output formatting
IMPORTANT: Do NOT use markdown in your output. OpenCode TUI renders text verbatim — markdown like **bold**, ## headers, and | table | syntax appears as raw characters. Use plain text with indentation for structure. Use dashes for lists. Use spaces to align columns instead of markdown tables.
@@ -0,0 +1,56 @@
---
name: mem0-search
description: Searches memories and displays compact one-liner results, or looks up a specific memory by ID. Use for quick memory lookups, checking if a decision was recorded, resolving [mem0:id] citations, or browsing memories without full category detail.
---
# Mem0 Search
Quick search with compact output. Lighter than `/mem0-tour`.
## Execution
### Step 1: Parse query
The user provides a search query: `/mem0-search auth middleware`
If no query provided, ask: "What should I search for?"
**Memory ID detection:** If the query matches any of these patterns, treat it as a
direct memory ID lookup instead of a search:
- Bare hex: `^[a-f0-9]{8}$` (short ID) or `^[a-f0-9]{8}-[a-f0-9-]+$` (full UUID)
- Citation ref: `[mem0:<hex>]` — extract the hex portion
When an ID is detected:
1. Call `get_memory(<id>)` directly (if short ID, try as prefix of full UUID)
2. If found, skip to Step 3 and display the single result
3. If not found, fall through to search using the ID as query text
### Step 2: Search
Run 2 parallel `search_memories` calls:
1. Broad: `query=<user's query>`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}]}`, `top_k=10`, `rerank=true`
2. Targeted: `query=<user's query>`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}, {"metadata": {"type": "decision"}}]}`, `top_k=5`, `rerank=true`
### Step 3: Display
Deduplicate by ID, then show compact results:
```
## mem0 search: "<query>" (<N> results)
1. [decision] Auth module uses JWT with RS256 keys (2025-05-15) [mem0:a3f8b2c1]
2. [anti_pattern] Don't use symmetric HS256 — leaked in env (2025-05-10) [mem0:7e2d9f4a]
3. [convention] All middleware in src/middleware/ (2025-05-08) [mem0:c4d5e6f7]
```
Format: `<number>. [<type>] <content, 80 chars> (<date>) [mem0:<short_id>]`
If no results:
```
No memories matching "<query>" for project <project_id>.
```
## Output formatting
IMPORTANT: Do NOT use markdown in your output. OpenCode TUI renders text verbatim — markdown like **bold**, ## headers, and | table | syntax appears as raw characters. Use plain text with indentation for structure. Use dashes for lists. Use spaces to align columns instead of markdown tables.
@@ -0,0 +1,197 @@
---
name: mem0-status
description: Diagnoses mem0 connectivity, API key validity, and memory read/write functionality. Use when memory operations fail, searches return empty, add_memory errors occur, or to verify the plugin is working correctly.
---
# Mem0 Status
Run a diagnostic check on the mem0 plugin. Useful for troubleshooting.
## Execution
Run ALL checks, then display a single summary. Do not stop on the first failure.
### Check 1: API key
```bash
_KEY="${MEM0_API_KEY:-}"
[ -n "$_KEY" ] && echo "${_KEY:0:6}..." || echo "NOT_SET"
```
- If `NOT_SET`: FAIL — "No API key configured"
- If set: PASS — the command already prints only the first 6 chars
### Check 2: Identity resolution
Resolve identity from the `MEM0_*` environment variables set by the plugin's `shell.env` hook. These are the exact values the plugin uses to scope memories, so report them directly. Do NOT re-run `git` here: the plugin already resolved branch and project from git at session start, and re-shelling git can disagree with it — e.g. it prints an empty branch that renders as `(not a git repo)` while the Session check below shows `branch=main`. One source of truth keeps the two lines consistent.
```bash
echo "user_id=${MEM0_USER_ID:-${USER:-default}}"
echo "project_id=${MEM0_APP_ID:-}"
echo "branch=${MEM0_BRANCH:-main}"
_S="$HOME/.mem0/settings.json"
_SCOPE="$(grep -o '"default_scope"[[:space:]]*:[[:space:]]*"[a-z]*"' "$_S" 2>/dev/null | grep -o '[a-z]*"$' | tr -d '"')"
echo "default_scope=${_SCOPE:-project}"
```
- `user_id`: from `MEM0_USER_ID`, falling back to `$USER`
- `project_id`: from `MEM0_APP_ID`
- `branch`: from `MEM0_BRANCH` (the plugin's resolved value; falls back to `main` outside a git repo)
- `default_scope`: from `~/.mem0/settings.json` (`default_scope`), falling back to `project`. This is the scope memory tools use when none is given; change it with `/mem0-scope`.
PASS if `user_id` and `project_id` are non-empty. WARN if `project_id` is empty — the `shell.env` hook may not have fired (restart OpenCode). Report the branch verbatim from `MEM0_BRANCH`; never invent a string like `(not a git repo)`.
### Check 3: Memory tool connectivity
Call `search_memories` with:
- `query="health check"`
- `filters={"AND": [{"user_id": "<active_user_id>"}, {"app_id": "<active_project_id>"}]}`
- `top_k=1`
- If returns successfully (even empty): PASS
- If errors: FAIL — show the error message
### Check 4: Memory write capability
Call `add_memory` with:
- `text="Health check probe — safe to delete."`
- `user_id=<active_user_id>`
- `app_id=<active_project_id>`
- `metadata={"type": "health_check", "probe": true}`
- `infer=False`
The response returns `event_id` (v3 writes are async). Call `get_event_status(event_id=<event_id>)` to check processing.
- If status is `SUCCEEDED`: PASS — extract the memory ID from the event result, then call `delete_memory` with that ID to clean up.
- If status is `PENDING` after 5 seconds: PASS (write accepted, processing delayed)
- If errors: FAIL — show the error.
### Check 5: Session context
Check that the plugin's `shell.env` hook has injected session context into the environment:
```bash
echo "session_id=${MEM0_SESSION_ID:-}"
echo "app_id=${MEM0_APP_ID:-}"
echo "branch=${MEM0_BRANCH:-}"
```
- If all three are non-empty: PASS — "Session active"
- If any are missing: WARN — "Plugin env vars not set; shell.env hook may not have fired"
### Check 6: Auto-dream readiness
Explain whether auto-dream (memory consolidation) is eligible to run, and if not, exactly which gate is blocking. Auto-dream runs at most once per session and only when **all** gates pass: time since last consolidation ≥ `minHours`, sessions since ≥ `minSessions`, and project memory count ≥ `minMemories`.
Read the gate state and thresholds:
```bash
_ST="$HOME/.mem0/mem0-dream-state.json"
_SET="$HOME/.mem0/settings.json"
echo "sessions_since=$(grep -o '"sessionsSince"[[:space:]]*:[[:space:]]*[0-9]*' "$_ST" 2>/dev/null | grep -o '[0-9]*$' || echo 0)"
echo "last_consolidated_ms=$(grep -o '"lastConsolidatedAt"[[:space:]]*:[[:space:]]*[0-9]*' "$_ST" 2>/dev/null | grep -o '[0-9]*$' || echo 0)"
echo "min_hours=$(grep -o '"minHours"[[:space:]]*:[[:space:]]*[0-9]*' "$_SET" 2>/dev/null | grep -o '[0-9]*$' || echo 24)"
echo "min_sessions=$(grep -o '"minSessions"[[:space:]]*:[[:space:]]*[0-9]*' "$_SET" 2>/dev/null | grep -o '[0-9]*$' || echo 5)"
echo "min_memories=$(grep -o '"minMemories"[[:space:]]*:[[:space:]]*[0-9]*' "$_SET" 2>/dev/null | grep -o '[0-9]*$' || echo 20)"
echo "now_s=$(date +%s)"
echo "dream_env=${MEM0_DREAM:-unset}"
```
For the memory count, reuse the project memory count from Check 3/4 (or call `get_memories` with the project filter, `page_size=1`, and read `count`).
Compute each gate:
- **time**: `hours_since = (now_s - last_consolidated_ms/1000) / 3600`. Passes when `≥ min_hours`. If `last_consolidated_ms` is 0 it has never run → time gate passes.
- **sessions**: passes when `sessions_since ≥ min_sessions`.
- **memories**: passes when project memory count `≥ min_memories`.
Report:
- If `dream_env` is `false`/`0`/`no`/`off`, or `dream.enabled` is false in settings: WARN — "Auto-dream disabled".
- If all three gates pass: PASS — "eligible (runs at next session start)".
- Otherwise: WARN — list the blocking gate(s), e.g. `sessions 2/5, memories 3/20`. This is expected, not an error — auto-dream is just waiting. Note the user can run `/mem0-dream` to consolidate now, or lower the thresholds via the `dream` block in `~/.mem0/settings.json`.
### Display
```
## mem0 status
PASS API Key m0-dVe...
PASS Identity user=kartik, project=mem0, branch=main
PASS Default scope project
PASS Memory Tools 142ms
PASS Write/Read write + delete OK
PASS Session session_id=abc123, app_id=mem0, branch=main
WARN Auto-dream waiting — sessions 2/5, memories 3/20 (/mem0-dream to run now)
All checks passed.
```
The Auto-dream line is informational: WARN here means "waiting on gates", not a failure. Show PASS when eligible, or "disabled" when turned off.
If any check fails, add a `## Troubleshooting` section with specific fix steps for each failure.
## Extended mode: Memory Quality Analysis
When invoked with `--deep` (e.g., `/mem0-status --deep`), run the standard 6 checks above **plus** a memory quality scan.
### Quality Check 1: Duplicates
Call `get_memories` with `filters={"AND": [{"user_id": "<active_user_id>"}, {"app_id": "<active_project_id>"}]}`, `page_size=200`. Compare all pairs within the same `metadata.type` group for high textual overlap (shared nouns/keywords > 60%). Report:
```
Potential duplicates: <N> pairs
[mem0:<id1>] ≈ [mem0:<id2>] — both about "<shared topic>"
```
### Quality Check 2: Stale memories
Flag memories where:
- `metadata.type` is `session_state` or `compact_summary` AND older than 90 days
- `metadata.confidence` < 0.3 AND older than 30 days
```
Stale candidates: <N>
[mem0:<id>] — session_state, 142d old
```
### Quality Check 2b: Low-confidence memories
Flag memories where `metadata.confidence` < 0.5 (regardless of age). Report separately from stale:
```
Low-confidence memories: <N>
[mem0:<id>] — confidence=0.3, "<content preview>"
```
### Quality Check 3: Contradictions
Within each `metadata.type` group, flag pairs that assert opposing facts about the same topic. Use semantic judgment — look for negation patterns, conflicting tool/framework choices, or reversed decisions.
```
Possible contradictions: <N>
[mem0:<idA>] vs [mem0:<idB>] — conflicting on "<topic>"
```
### Quality Check 4: Orphan memories
Memories with no `metadata.type` set, or with `metadata.type` not in the 17 known coding categories. These were likely written without proper tagging.
```
Untagged/orphan memories: <N>
```
### Quality summary
```
## Memory Quality
Duplicates: <N> · Stale: <N> · Contradictions: <N> · Orphans: <N>
```
If all counts are 0: `Memory quality: clean.`
If any non-zero: append `Run /mem0-dream to fix.`
To fix issues found by `--deep`, run `/mem0-dream` for automated consolidation (merges, prunes, conflict resolution).
## Output formatting
IMPORTANT: Do NOT use markdown in your output. OpenCode TUI renders text verbatim — markdown like **bold**, ## headers, and | table | syntax appears as raw characters. Use plain text with indentation for structure. Use dashes for lists. Use spaces to align columns instead of markdown tables.
@@ -0,0 +1,156 @@
---
name: mem0-tour
description: Browses all stored memories grouped by category with full content display. Use when reviewing all project memories, exploring stored knowledge, onboarding to a project, or getting an overview of captured decisions, conventions, and learnings.
---
# Mem0 Project Tour
Show the user what mem0 has stored for the current project.
## Cross-project mode
When invoked with `--all-projects` (e.g., `/mem0-tour --all-projects` or
`/mem0-tour --all-projects auth middleware`), search across ALL projects:
1. Call `get_memories` with `filters={"AND": [{"user_id": "<active_user_id>"}]}`, `page_size=200`**no `app_id` filter**.
2. If a search query was also provided, run `search_memories` with `query=<query>`,
`filters={"AND": [{"user_id": "<active_user_id>"}]}`, `top_k=20` — again no `app_id`.
3. Group results by `app_id` first, then by category within each project.
4. Display:
```
## <app_id_1> (<N> memories) ← current
**Architecture Decisions** — <memory content>
...
## <app_id_2> (<N> memories)
...
<N> memories across <M> projects
```
5. Mark the current project with `← (current)` in the heading.
If `--all-projects` is NOT present, use the standard single-project flow below.
## Peek mode (compact search)
When `/mem0-tour` receives a search query argument (e.g., `/mem0-tour auth middleware`)
WITHOUT `--all-projects`, run in **peek mode** — compact one-liner results:
1. Run 2 parallel `search_memories` calls:
- Broad: `query=<query>`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}]}`, `top_k=10`, `rerank=true`
- Targeted: `query=<query>`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}, {"metadata": {"type": "decision"}}]}`, `top_k=5`, `rerank=true`
2. Deduplicate by ID, display compact results:
```
## mem0 search: "<query>" (<N> results)
1. [decision] Auth module uses JWT with RS256 keys (2025-05-15) [mem0:a3f8b2c1]
2. [anti_pattern] Don't use symmetric HS256 — leaked in env (2025-05-10) [mem0:7e2d9f4a]
3. [convention] All middleware in src/middleware/ (2025-05-08) [mem0:c4d5e6f7]
```
Format: `<number>. [<type>] <content, 80 chars> (<date>) [mem0:<short_id>]`
3. If no results: `No memories matching "<query>" for project <project_id>.`
If no query argument and no `--all-projects` flag, use the full tour flow below.
## Execution
### Step 1: Fetch ALL memories for this project
Call `get_memories` to fetch all memories for this project:
`filters={"AND": [{"user_id": "<active_user_id>"}, {"app_id": "<active_project_id>"}]}`, `page_size=100`
### Step 2: Run supplementary semantic searches
In parallel, run these `search_memories` calls to get relevance-ranked results for key topics:
- `query="architecture decisions design choices"`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}]}`, `top_k=10`, `rerank=true`
- `query="bugs errors failures anti-patterns"`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}]}`, `top_k=10`, `rerank=true`
- `query="project setup tooling conventions preferences"`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}]}`, `top_k=10`, `rerank=true`
**Do NOT filter by `metadata.type` in these calls.** The platform auto-assigns `categories` — filtering on `metadata.type` misses memories that were auto-categorized but don't have an explicit `metadata.type`.
### Step 3: Merge and group
Merge all results by memory ID (deduplicate). For each memory, determine its group using this priority:
1. **Platform `categories` field** (array on each memory, auto-assigned by Mem0). Use the first category value.
2. **`metadata.type` field** (if present, set explicitly by hooks/agent). Use as fallback if no `categories`.
3. **"other"** bucket for memories with neither.
Map category names to display names:
| Platform category / metadata.type | Display name |
|---|---|
| `architecture decisions`, `architecture_decisions`, `decision` | Architecture Decisions |
| `anti patterns`, `anti_patterns`, `anti_pattern` | Anti-Patterns |
| `task learnings`, `task_learnings`, `task_learning` | Task Learnings |
| `coding conventions`, `coding_conventions`, `convention` | Coding Conventions |
| `user preferences`, `user_preferences`, `user_preference` | User Preferences |
| `project profile`, `project_profile` | Project Profile |
| `tooling setup`, `tooling_setup`, `environmental` | Tooling & Setup |
| `technology`, `professional_details` | Tooling & Setup |
| `session_state` | Session State |
| `compact_summary` | Compact Summaries |
| anything else | Other |
### Step 4: Display results
Sort groups by descending memory count. Display in compact tabular format:
First show the category summary table:
```
mem0 tour
Session (ses_abc123) branch: main
Project: my-project - 349 memories
Category Count
-----------------------------------------
tooling_setup 119
bug_fixes 78
architecture_decisions 32
task_learnings 14
...
```
Then for each category (sorted by count descending), show memories as numbered one-liners. Truncate each memory to 100 chars max:
```
tooling_setup (119)
1. User requires that no git commit or push be performed without explicit permission...
2. OpenCode plugins are loaded from ~/.config/opencode/plugins/ for global installation...
3. Assistant determined that the symlink method for loading the Mem0 plugin was failing...
... and 116 more
bug_fixes (78)
1. Fixed getAll filter format from flat object to AND-wrapped array for mem0ai TS SDK v3...
2. Root cause of user_id mismatch: plugin derived kartik.labhshetwar from git email...
... and 76 more
```
Show top 5 memories per category by recency. If a group has more than 5, note `... and <N> more`.
Skip empty groups entirely.
### Step 5: Print totals
```
<N> memories across <M> categories
project: <project_id> branch: <active_branch>
Identity - user: <user_id> project: <project_id> branch: <branch>
```
### Step 6: Empty state
If zero memories found for this project, print:
```
No memories stored yet for project <project_id>.
Start working - mem0 captures learnings automatically, or use /mem0-remember to save something now.
```
## Output formatting
IMPORTANT: Do NOT use markdown in your output. OpenCode TUI renders text verbatim - markdown like **bold**, ## headers, and | table | syntax appears as raw characters. Use plain text with indentation for structure. Use dashes for lists. Use spaces to align columns instead of markdown tables.