fix(mem0-plugin): v0.2.2 (#5234)
This commit is contained in:
@@ -1,123 +0,0 @@
|
||||
---
|
||||
name: mem0-digest
|
||||
description: >
|
||||
Summarize recent memory activity for the current project. Shows new memories,
|
||||
categories touched, and growth trends over the past 7 days.
|
||||
TRIGGER: user runs /mem0:digest, or asks "weekly summary", "what's new in memory",
|
||||
"mem0 digest", "memory recap".
|
||||
---
|
||||
|
||||
# Mem0 Weekly Digest
|
||||
|
||||
Summarize recent memory activity for the current project.
|
||||
|
||||
## Execution
|
||||
|
||||
### Step 1: Fetch recent memories
|
||||
|
||||
Call `search_memories` in parallel with different time-scoped queries:
|
||||
|
||||
1. `query="decisions made this week"`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}, {"created_at": {"gte": "<7 days ago YYYY-MM-DD>"}}]}`, `limit=20`
|
||||
2. `query="bugs errors fixes"`, same time filter, `limit=20`
|
||||
3. `query="patterns conventions learnings"`, same time filter, `limit=20`
|
||||
|
||||
Also call `get_memories` with `user_id` + `app_id` to get the full count for comparison.
|
||||
|
||||
### Step 2: Deduplicate and analyze
|
||||
|
||||
Merge results by memory ID. For each memory, extract:
|
||||
- `created_at` date
|
||||
- `categories[0]` or `metadata.type`
|
||||
- First 100 chars of content
|
||||
|
||||
Group into:
|
||||
- **New this week** (created in last 7 days)
|
||||
- **Older** (created before, but surfaced by search)
|
||||
|
||||
Calculate:
|
||||
- Total memories in project
|
||||
- Memories added in last 7 days
|
||||
- Most active categories this week
|
||||
- Days with most activity
|
||||
|
||||
### Step 3: Display
|
||||
|
||||
```
|
||||
## mem0 Weekly Digest — <project_id>
|
||||
Period: <start_date> to <today>
|
||||
|
||||
### New Memories This Week: <N>
|
||||
<category>: <count>
|
||||
- <memory summary, 80 chars> (<date>)
|
||||
- ...
|
||||
<category>: <count>
|
||||
- ...
|
||||
|
||||
### Activity Pattern
|
||||
Most active day: <day> (<N> memories)
|
||||
Categories touched: <list>
|
||||
|
||||
### Project Totals
|
||||
Total memories: <N> (up <N> from last week)
|
||||
Top categories: <top 3 by count>
|
||||
|
||||
### Highlights
|
||||
<2-3 sentence summary of the most important decisions, learnings, or patterns stored this week>
|
||||
```
|
||||
|
||||
### Step 4: Write digest to file
|
||||
|
||||
After displaying, write the digest to `~/.mem0/weekly-digest.md` for persistence
|
||||
and external consumption (email, Slack, etc.):
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.mem0
|
||||
```
|
||||
|
||||
Write the full digest output (same markdown shown in terminal) to `~/.mem0/weekly-digest.md`
|
||||
using the Write tool. **Overwrite** the file each time — it always contains the latest digest.
|
||||
|
||||
Also append a one-line summary to `~/.mem0/digest-history.log` for trend tracking:
|
||||
|
||||
```bash
|
||||
echo "<YYYY-MM-DD> | <project_id> | +<new_count> memories | top: <top_category>" >> ~/.mem0/digest-history.log
|
||||
```
|
||||
|
||||
Print at the end:
|
||||
```
|
||||
Digest saved to ~/.mem0/weekly-digest.md
|
||||
```
|
||||
|
||||
### Step 5: Schedule recurring digests
|
||||
|
||||
When invoked with `--schedule` (e.g., `/mem0:digest --schedule weekly`), register
|
||||
a cloud routine via Claude Code's `/schedule` command:
|
||||
|
||||
```
|
||||
/schedule <frequency> /mem0:digest
|
||||
```
|
||||
|
||||
For example:
|
||||
- `/schedule weekly on Monday 9am /mem0:digest` — digest every Monday morning
|
||||
- `/schedule daily at 8am /mem0:digest` — daily digest
|
||||
|
||||
Print:
|
||||
```
|
||||
Digest scheduled: <frequency>
|
||||
Manage at: https://claude.ai/code/routines
|
||||
```
|
||||
|
||||
If `/schedule` is unavailable, print a cron one-liner the user can install manually:
|
||||
```bash
|
||||
# macOS/Linux — weekly Monday 9am
|
||||
(crontab -l 2>/dev/null; echo "0 9 * * 1 cd PROJECT_DIR && claude -p '/mem0:digest' >> /tmp/mem0-digest.log 2>&1") | crontab -
|
||||
```
|
||||
|
||||
### Step 6: Empty state
|
||||
|
||||
If no memories in the last 7 days:
|
||||
```
|
||||
No new memories in the past week for <project_id>.
|
||||
Total project memories: <N>.
|
||||
Tip: mem0 captures learnings automatically as you work. Start coding!
|
||||
```
|
||||
@@ -235,6 +235,58 @@ In auto mode:
|
||||
)
|
||||
```
|
||||
|
||||
## Forget mode (targeted deletion)
|
||||
|
||||
When invoked with `--forget` (e.g., `/mem0:dream --forget auth module decisions`
|
||||
or `/mem0:dream --forget <memory_id>`), skip consolidation and go straight to
|
||||
search-confirm-delete:
|
||||
|
||||
### F1: Parse input
|
||||
|
||||
The argument after `--forget` is either:
|
||||
- A search query: `/mem0:dream --forget auth module decisions`
|
||||
- A memory ID: `/mem0:dream --forget <memory_id>`
|
||||
|
||||
If no argument after `--forget`, ask: "What should I forget? Provide a search query or memory ID."
|
||||
|
||||
### F2: 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": "<id>"}, {"app_id": "<project_id>"}]}`
|
||||
- `limit=10`
|
||||
- Show numbered list:
|
||||
```
|
||||
Found <N> memories matching "<query>":
|
||||
1. <content, 120 chars> (type: <type>, created: <date>) [ID: <short_id>]
|
||||
2. ...
|
||||
```
|
||||
|
||||
### F3: Confirm
|
||||
|
||||
Ask: "Delete which memories? Enter numbers (e.g., 1,3,5), 'all', or 'cancel'."
|
||||
For a single memory ID: "Delete this memory? [y/N]"
|
||||
|
||||
**Never delete without confirmation.**
|
||||
|
||||
### F4: Delete and report
|
||||
|
||||
Call `delete_memory` for each confirmed entry. Report: `Deleted <N> memories.`
|
||||
|
||||
### Undo recent writes
|
||||
|
||||
If the user says "undo last N memories" or "undo last write":
|
||||
1. Run `python3 "$SCRIPT_DIR/session_stats.py" peek` to get `recent_ids`.
|
||||
2. Show last N entries, ask for confirmation.
|
||||
3. Delete confirmed entries via `delete_memory`.
|
||||
|
||||
---
|
||||
|
||||
## Scheduling recurring dreams
|
||||
|
||||
When invoked with `--schedule` (e.g., `/mem0:dream --schedule weekly`), register a
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
---
|
||||
name: mem0-forget
|
||||
description: >
|
||||
Delete memories by search query or memory ID. Shows matches for confirmation
|
||||
before deleting. Safe — always confirms before destructive action.
|
||||
TRIGGER: user runs /mem0:forget <query>, or says "forget this", "delete memory",
|
||||
"remove that memory about X".
|
||||
---
|
||||
|
||||
# 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>`
|
||||
- `user_id=<active_user_id>`
|
||||
- `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<project_id>"}]}`
|
||||
- `limit=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. Read session stats to get recently written memory IDs:
|
||||
```bash
|
||||
SCRIPT_DIR="${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}/scripts"
|
||||
python3 "$SCRIPT_DIR/session_stats.py" peek
|
||||
```
|
||||
2. Parse the `recent_ids` array from the JSON output. Each entry has `id`, `category`, `ts`.
|
||||
3. Show the last N entries (default 1) and ask for confirmation.
|
||||
4. Delete confirmed entries via `delete_memory`.
|
||||
|
||||
If `recent_ids` is empty, tell the user: "No recent memory IDs tracked this session. Use a search query instead."
|
||||
@@ -1,106 +0,0 @@
|
||||
---
|
||||
name: mem0-import-tools
|
||||
description: >
|
||||
Import memories from competing AI tool configuration files into mem0.
|
||||
Supports Cursor (.cursorrules), GitHub Copilot (.github/copilot-instructions.md),
|
||||
Cline (memory-bank/), and Continue (.continue/rules.md).
|
||||
TRIGGER: user runs /mem0:import-tools, or asks "import from cursor",
|
||||
"import cursorrules", "import from cline", "import from copilot",
|
||||
"import from continue", "migrate from cursor", "migrate memories".
|
||||
---
|
||||
|
||||
# Mem0 Import from Competing Tools
|
||||
|
||||
Import configuration and memory files from other AI coding tools into mem0.
|
||||
|
||||
## Supported Tools
|
||||
|
||||
| Tool | Default file/directory |
|
||||
|------|----------------------|
|
||||
| Cursor | `.cursorrules` |
|
||||
| GitHub Copilot | `.github/copilot-instructions.md` |
|
||||
| Cline | `memory-bank/` (directory of `.md` files) |
|
||||
| Continue | `.continue/rules.md` |
|
||||
|
||||
## Execution
|
||||
|
||||
### Step 1: Detect which tool files exist
|
||||
|
||||
Check for the presence of each tool's file/directory in the current working directory:
|
||||
|
||||
```bash
|
||||
# Check each location
|
||||
test -f .cursorrules && echo "cursor: .cursorrules"
|
||||
test -f .github/copilot-instructions.md && echo "copilot: .github/copilot-instructions.md"
|
||||
test -d memory-bank/ && echo "cline: memory-bank/"
|
||||
test -f .continue/rules.md && echo "continue: .continue/rules.md"
|
||||
```
|
||||
|
||||
### Step 2: Report findings and ask user
|
||||
|
||||
List all found files to the user. For example:
|
||||
|
||||
```
|
||||
Found the following tool configuration files:
|
||||
[1] Cursor rules: .cursorrules
|
||||
[2] Cline memory bank: memory-bank/
|
||||
|
||||
Which would you like to import? (enter numbers, comma-separated, or "all"):
|
||||
```
|
||||
|
||||
If no files are found, print:
|
||||
```
|
||||
No competing tool configuration files found in the current directory.
|
||||
Checked: .cursorrules, .github/copilot-instructions.md, memory-bank/, .continue/rules.md
|
||||
```
|
||||
and stop.
|
||||
|
||||
### Step 3: Run the import script for each selected tool
|
||||
|
||||
Determine the plugin root. Use the appropriate variable for the current platform:
|
||||
- Claude Code: `${CLAUDE_PLUGIN_ROOT}`
|
||||
- Codex: `${CODEX_PLUGIN_ROOT}`
|
||||
- Cursor: `${CURSOR_PLUGIN_ROOT}`
|
||||
|
||||
For each tool the user selected, run the corresponding sub-command:
|
||||
|
||||
**Cursor (.cursorrules):**
|
||||
```bash
|
||||
python3 "<PLUGIN_ROOT>/scripts/import_competing_tools.py" cursorrules --path .cursorrules
|
||||
```
|
||||
|
||||
**GitHub Copilot:**
|
||||
```bash
|
||||
python3 "<PLUGIN_ROOT>/scripts/import_competing_tools.py" copilot --path .github/copilot-instructions.md
|
||||
```
|
||||
|
||||
**Cline:**
|
||||
```bash
|
||||
python3 "<PLUGIN_ROOT>/scripts/import_competing_tools.py" cline --path memory-bank/
|
||||
```
|
||||
|
||||
**Continue:**
|
||||
```bash
|
||||
python3 "<PLUGIN_ROOT>/scripts/import_competing_tools.py" continue --path .continue/rules.md
|
||||
```
|
||||
|
||||
### Step 4: Report results
|
||||
|
||||
After each script runs, echo its output to the user. Then print a combined summary:
|
||||
|
||||
```
|
||||
Import complete.
|
||||
Cursor: <N> memories
|
||||
Copilot: <N> memories
|
||||
Total: <N> memories imported into project <project_id>
|
||||
```
|
||||
|
||||
Adjust the summary to reflect only the tools that were actually imported.
|
||||
|
||||
## Notes
|
||||
|
||||
- Memories are imported with `infer=False` — no AI inference is applied, content is stored as-is.
|
||||
- Each section or file becomes a separate memory tagged with `metadata.source=<tool>-import` and `metadata.type=project_profile`.
|
||||
- Sections shorter than 50 characters are automatically skipped (too short to be useful).
|
||||
- Content longer than 10,000 characters is automatically truncated per chunk.
|
||||
- You can re-run this skill safely — duplicate content will be caught by mem0's deduplication.
|
||||
@@ -98,6 +98,87 @@ If any failed:
|
||||
Imported <N>/<total> memories into project <project_id> (<failed> failed)
|
||||
```
|
||||
|
||||
## Importing from competing AI tools (`--tools`)
|
||||
|
||||
When invoked with `--tools` (e.g., `/mem0:import --tools`), detect and import
|
||||
from competing AI tool configuration files:
|
||||
|
||||
### Supported tools
|
||||
|
||||
| Tool | File/directory |
|
||||
|------|---------------|
|
||||
| Cursor | `.cursorrules` |
|
||||
| GitHub Copilot | `.github/copilot-instructions.md` |
|
||||
| Cline | `memory-bank/` (directory of `.md` files) |
|
||||
| Continue | `.continue/rules.md` |
|
||||
|
||||
### T1: Detect
|
||||
|
||||
```bash
|
||||
test -f .cursorrules && echo "cursor: .cursorrules"
|
||||
test -f .github/copilot-instructions.md && echo "copilot: .github/copilot-instructions.md"
|
||||
test -d memory-bank/ && echo "cline: memory-bank/"
|
||||
test -f .continue/rules.md && echo "continue: .continue/rules.md"
|
||||
```
|
||||
|
||||
### T2: Ask user
|
||||
|
||||
List found files, ask which to import (numbers, comma-separated, or "all").
|
||||
If none found:
|
||||
```
|
||||
No competing tool configuration files found.
|
||||
Checked: .cursorrules, .github/copilot-instructions.md, memory-bank/, .continue/rules.md
|
||||
```
|
||||
|
||||
### T3: Run import
|
||||
|
||||
For each selected tool:
|
||||
```bash
|
||||
python3 "<PLUGIN_ROOT>/scripts/import_competing_tools.py" <tool> --path <file>
|
||||
```
|
||||
|
||||
Tools: `cursorrules`, `copilot`, `cline`, `continue`.
|
||||
|
||||
### T4: Report
|
||||
|
||||
```
|
||||
Import complete.
|
||||
Cursor: <N> memories
|
||||
Copilot: <N> memories
|
||||
Total: <N> memories imported into project <project_id>
|
||||
```
|
||||
|
||||
Notes: `infer=False`, tagged `metadata.source=<tool>-import`, sections <50 chars
|
||||
skipped, chunks >10k chars truncated, safe to re-run (deduplication handles it).
|
||||
|
||||
---
|
||||
|
||||
## Importing Claude Code's native MEMORY.md
|
||||
|
||||
When invoked with a path to Claude Code's native `MEMORY.md` file (typically
|
||||
`~/.claude/projects/<proj-key>/memory/MEMORY.md`), or when `on_session_start.sh`
|
||||
detects native auto-memory and the user chooses to import:
|
||||
|
||||
1. Read the file. It contains newline-separated memory entries (one fact per line,
|
||||
sometimes with `- ` bullet prefix).
|
||||
2. Split by non-empty lines. Each line becomes one memory.
|
||||
3. Skip lines shorter than 20 characters or lines that are just headers (`#`).
|
||||
4. For each line, call `add_memory` with:
|
||||
- `messages=[{"role": "user", "content": "<line>"}]`
|
||||
- `user_id=<active_user_id>`
|
||||
- `app_id=<active_project_id>`
|
||||
- `metadata={"type": "task_learning", "source": "memory-md-import", "confidence": 0.8}`
|
||||
- `infer=False`
|
||||
5. Report: `Imported <N> memories from MEMORY.md into project <project_id>`
|
||||
6. Suggest disabling native auto-memory:
|
||||
```
|
||||
To avoid duplicate memory systems, add to ~/.claude/settings.json:
|
||||
"autoMemoryEnabled": false
|
||||
```
|
||||
|
||||
This handles the cold-start gap when a user has been using Claude Code's native
|
||||
memory and switches to mem0.
|
||||
|
||||
## Error Handling
|
||||
|
||||
- If the parser script is not found at `<PLUGIN_ROOT>/scripts/parse_export_file.py`, print an error and stop.
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
name: mem0-list-projects
|
||||
description: >
|
||||
List all project scopes (app_ids) that have stored memories for the current
|
||||
user. Essential for /mem0:switch-project discoverability and cross-project
|
||||
workflows.
|
||||
TRIGGER: user runs /mem0:list-projects, or asks "what projects does mem0 know",
|
||||
"list my mem0 projects", "show all projects", "which app_ids exist".
|
||||
---
|
||||
|
||||
# Mem0 List Projects
|
||||
|
||||
Show all known project scopes for the current user.
|
||||
|
||||
## Execution
|
||||
|
||||
### Step 1: Fetch memories to discover app_ids
|
||||
|
||||
There is no dedicated "list projects" API endpoint. Discover projects by fetching
|
||||
the user's memories and extracting distinct `app_id` values.
|
||||
|
||||
Call `get_memories` with:
|
||||
- `user_id=<active_user_id>`
|
||||
- `page_size=200`
|
||||
|
||||
Do NOT pass `app_id` — we want memories across ALL projects.
|
||||
|
||||
If the response indicates more pages, paginate until all are fetched (up to 1000
|
||||
memories max to avoid excessive API calls).
|
||||
|
||||
### Step 2: Extract distinct projects
|
||||
|
||||
For each memory, read the `app_id` field (may also appear as `metadata.app_id`
|
||||
on older memories). Collect distinct values.
|
||||
|
||||
For each project, count:
|
||||
- Total memories
|
||||
- Most recent `created_at` date
|
||||
- Top 3 `metadata.type` values by frequency
|
||||
|
||||
### Step 3: Display
|
||||
|
||||
```
|
||||
## mem0 Projects for <user_id>
|
||||
|
||||
| Project | Memories | Last Active | Top Categories |
|
||||
|---------|----------|-------------|---------------|
|
||||
| <app_id_1> | <count> | <date> | decision, convention, anti_pattern |
|
||||
| <app_id_2> | <count> | <date> | task_learning, environmental |
|
||||
| ... | | | |
|
||||
|
||||
Active project: <current_project_id> ← (current)
|
||||
Total: <N> projects, <M> total memories
|
||||
```
|
||||
|
||||
Mark the current project with `← (current)`.
|
||||
|
||||
### Step 4: Empty state
|
||||
|
||||
If zero memories found:
|
||||
```
|
||||
No projects found for user <user_id>.
|
||||
Run /mem0:onboard in a project directory to get started.
|
||||
```
|
||||
|
||||
### Step 5: Suggest next actions
|
||||
|
||||
```
|
||||
Switch project: /mem0:switch-project <name>
|
||||
Search across all: /mem0:tour --all-projects
|
||||
```
|
||||
@@ -49,6 +49,21 @@ filters={"AND": [
|
||||
|
||||
Empty results are normal. Proceed without context — they don't mean the system is broken.
|
||||
|
||||
### Contradiction detection at search time
|
||||
|
||||
After receiving search results, scan for contradictions before using them:
|
||||
|
||||
1. If 2+ results address the **same topic** (same `metadata.type`, overlapping file paths or entity names) but assert **opposing facts**, surface BOTH to the user instead of silently picking one.
|
||||
2. Format:
|
||||
```
|
||||
⚠️ Conflicting memories found:
|
||||
- [mem0:<id1>] "<content1>" (confidence: <score1>, <date1>)
|
||||
- [mem0:<id2>] "<content2>" (confidence: <score2>, <date2>)
|
||||
Which is current?
|
||||
```
|
||||
3. After the user resolves: update the loser via `update_memory` to mark it superseded, or delete it. Store the winner's fact as authoritative if not already.
|
||||
4. If the user doesn't resolve, default to the more recent memory with higher confidence, but note the ambiguity in your response.
|
||||
|
||||
### How to search well
|
||||
|
||||
When you do search, run **2–4 parallel** `search_memories` calls at different angles instead of one query echoing the user's prompt.
|
||||
@@ -130,6 +145,31 @@ search_memories(query="auth",
|
||||
|
||||
Extract key learnings and store them using the `add_memory` tool:
|
||||
|
||||
### REQUIRED metadata fields
|
||||
|
||||
Every `add_memory` call MUST include these metadata fields. Do NOT omit them:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `type` | string | YES | Memory category: `decision`, `task_learning`, `anti_pattern`, `convention`, `user_preference`, `environmental`, `session_state`, `compact_summary` |
|
||||
| `confidence` | float | YES | 0.0–1.0 confidence score. Default: `0.7` for inferred learnings, `0.9` for explicit user statements |
|
||||
| `files` | list[str] | YES | File paths relevant to this memory. Use `["*"]` for project-wide learnings |
|
||||
| `source` | string | YES | How the memory was captured: `user_request`, `auto_capture`, `post_commit`, `error_recovery` |
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"type": "decision",
|
||||
"confidence": 0.9,
|
||||
"files": ["src/auth/login.py", "src/auth/middleware.py"],
|
||||
"source": "user_request"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**If you omit `confidence` or `files`, the memory will be harder to rank and retrieve later.**
|
||||
|
||||
- **Decisions made** -> Include metadata `{"type": "decision"}`
|
||||
- **Strategies that worked** -> Include metadata `{"type": "task_learning"}`
|
||||
- **Failed approaches** -> Include metadata `{"type": "anti_pattern"}`
|
||||
|
||||
@@ -82,7 +82,7 @@ Then retry the categories script.
|
||||
|
||||
## Step 5: Mark project as onboarded
|
||||
|
||||
Create a marker file so SessionStart won't re-trigger onboarding next session:
|
||||
The marker file is already created by `on_session_start.sh` on first display of the onboard prompt. Touch it here for idempotency:
|
||||
|
||||
```bash
|
||||
_SAFE_PID=$(printf '%s' "<active_project_id>" | tr '/:' '--')
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: mem0-peek
|
||||
description: >
|
||||
Quick search — compact one-liner results. Faster and lighter than /mem0:tour.
|
||||
Takes a search query as argument.
|
||||
TRIGGER: user runs /mem0:peek <query>, or says "quick search mem0",
|
||||
"what do we know about X", "peek at memories about Y".
|
||||
---
|
||||
|
||||
# Mem0 Peek
|
||||
|
||||
Quick search with compact output. Lighter than `/mem0:tour`.
|
||||
|
||||
## Execution
|
||||
|
||||
### Step 1: Parse query
|
||||
|
||||
The user provides a search query: `/mem0:peek auth middleware`
|
||||
|
||||
If no query provided, ask: "What should I search for?"
|
||||
|
||||
### Step 2: Search
|
||||
|
||||
Run 2 parallel `search_memories` calls:
|
||||
|
||||
1. Broad: `query=<user's query>`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}]}`, `limit=10`
|
||||
2. Targeted: `query=<user's query>`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}, {"metadata": {"type": "decision"}}]}`, `limit=5`
|
||||
|
||||
### Step 3: Display
|
||||
|
||||
Deduplicate by ID, then show compact results:
|
||||
|
||||
```
|
||||
## mem0 peek: "<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>.
|
||||
```
|
||||
@@ -1,10 +1,12 @@
|
||||
---
|
||||
name: mem0-pin
|
||||
description: >
|
||||
Pin important memories so they surface prominently. Updates metadata to mark
|
||||
a memory as pinned. Pinned memories should be prioritized during search.
|
||||
TRIGGER: user runs /mem0:pin <query or ID>, or says "pin this memory",
|
||||
"mark as important", "always remember this".
|
||||
Pin important memories so they surface prominently and are protected from
|
||||
consolidation. New pins use immutable: true (SDK v2.1.33+) to prevent
|
||||
deduplication from modifying or removing the memory. Existing memories get
|
||||
metadata.pinned: true as a search-time filter; full consolidation protection
|
||||
requires delete + re-add. TRIGGER: user runs /mem0:pin <query or ID>, or
|
||||
says "pin this memory", "mark as important", "always remember this".
|
||||
---
|
||||
|
||||
# Mem0 Pin
|
||||
@@ -35,12 +37,28 @@ This is required because `update_memory` replaces the full memory — a metadata
|
||||
|
||||
### Step 3: Pin it
|
||||
|
||||
There are two sub-cases depending on whether the user wants to pin an **existing** memory or create a **new** pinned memory from scratch.
|
||||
|
||||
#### 3a: Pinning a new memory (preferred path for full protection)
|
||||
|
||||
Use `add_memory` with `immutable: true` as a top-level parameter. The `immutable` flag is a first-class platform parameter (added in SDK v2.1.33) that prevents the memory from being modified or removed by consolidation/deduplication. `metadata.pinned: true` is also included as a search-time filter aid.
|
||||
|
||||
```python
|
||||
add_memory(
|
||||
messages=[{"role": "user", "content": "<text to pin>"}],
|
||||
user_id=<user_id>,
|
||||
immutable=True,
|
||||
metadata={"pinned": True},
|
||||
)
|
||||
```
|
||||
|
||||
#### 3b: Pinning an existing memory
|
||||
|
||||
Call `update_memory` with:
|
||||
- `memory_id=<selected_id>`
|
||||
- `data=<original_text>` (preserve the existing content)
|
||||
- `metadata=` merge `original_metadata` with `{"pinned": true}`
|
||||
|
||||
Example:
|
||||
```python
|
||||
updated_meta = {**original_metadata, "pinned": True}
|
||||
update_memory(memory_id=<selected_id>, data=<original_text>, metadata=updated_meta)
|
||||
@@ -48,12 +66,23 @@ update_memory(memory_id=<selected_id>, data=<original_text>, metadata=updated_me
|
||||
|
||||
**Important:** `update_memory` requires the `data` (text) parameter. Passing only metadata may error or wipe content. Always read first, then update with the full text and explicit metadata.
|
||||
|
||||
**Consolidation-protection limitation:** `update_memory` cannot set the `immutable` flag on an existing memory. If the user needs full consolidation protection for an existing memory, they must delete it and re-add it using `add_memory` with `immutable: true` (path 3a above). In the confirm step (Step 4), note this limitation if the user pinned an existing memory via `update_memory`.
|
||||
|
||||
### Step 4: Confirm
|
||||
|
||||
For new pins created via `add_memory` with `immutable: true`:
|
||||
```
|
||||
Pinned: "<memory content, first 80 chars>..."
|
||||
Memory ID: <id>
|
||||
Pinned with consolidation protection (immutable). This memory will not be modified or removed by deduplication.
|
||||
```
|
||||
|
||||
For existing memories pinned via `update_memory`:
|
||||
```
|
||||
Pinned: "<memory content, first 80 chars>..."
|
||||
Memory ID: <id>
|
||||
Pinned memories surface first when relevant to a search.
|
||||
Note: consolidation protection (immutable flag) requires delete + re-add. Say "re-pin this with full protection" to do that.
|
||||
```
|
||||
|
||||
### Unpin
|
||||
|
||||
@@ -94,3 +94,56 @@ Print a compact dashboard with an ASCII histogram for category distribution:
|
||||
- **Access count buckets:** Read `metadata.access_count` (default 0 if absent). Buckets: 0, 1–5, 6–20, 20+.
|
||||
|
||||
Skip any section with zero data.
|
||||
|
||||
## Weekly digest mode
|
||||
|
||||
When invoked with `--weekly` (e.g., `/mem0:stats --weekly`), append a weekly
|
||||
activity digest after the standard stats dashboard:
|
||||
|
||||
### W1: Fetch recent memories
|
||||
|
||||
Call `search_memories` in parallel with time-scoped queries:
|
||||
1. `query="decisions made this week"`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}, {"created_at": {"gte": "<7 days ago YYYY-MM-DD>"}}]}`, `limit=20`
|
||||
2. `query="bugs errors fixes"`, same time filter, `limit=20`
|
||||
3. `query="patterns conventions learnings"`, same time filter, `limit=20`
|
||||
|
||||
### W2: Analyze
|
||||
|
||||
Merge by ID. Group into "New this week" by `categories[0]` or `metadata.type`.
|
||||
Calculate: memories added last 7 days, most active categories, most active day.
|
||||
|
||||
### W3: Display
|
||||
|
||||
Append after the standard stats:
|
||||
|
||||
```
|
||||
### Weekly Digest (<start_date> to <today>)
|
||||
|
||||
New Memories This Week: <N>
|
||||
<category>: <count>
|
||||
- <memory summary, 80 chars> (<date>)
|
||||
- ...
|
||||
|
||||
Activity Pattern
|
||||
Most active day: <day> (<N> memories)
|
||||
Categories touched: <list>
|
||||
|
||||
Highlights
|
||||
<2-3 sentence summary of most important decisions/learnings this week>
|
||||
```
|
||||
|
||||
### W4: Write digest file
|
||||
|
||||
Write to `~/.mem0/weekly-digest.md` (overwrite). Append one-line to
|
||||
`~/.mem0/digest-history.log`:
|
||||
```
|
||||
<YYYY-MM-DD> | <project_id> | +<new_count> memories | top: <top_category>
|
||||
```
|
||||
|
||||
### W5: Empty state
|
||||
|
||||
If no new memories in 7 days:
|
||||
```
|
||||
No new memories in the past week for <project_id>.
|
||||
Total project memories: <N>.
|
||||
```
|
||||
|
||||
@@ -11,6 +11,55 @@ description: >
|
||||
|
||||
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 `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": "<id>"}]}`, `limit=20` — again no `app_id`.
|
||||
3. Group results by `app_id` first, then by category within each project.
|
||||
4. Display:
|
||||
```
|
||||
## Cross-Project Tour for <user_id>
|
||||
|
||||
### <app_id_1> (<N> memories)
|
||||
#### Architecture Decisions
|
||||
- <memory content>
|
||||
...
|
||||
|
||||
### <app_id_2> (<N> memories)
|
||||
...
|
||||
|
||||
---
|
||||
Total: <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>"}]}`, `limit=10`
|
||||
- Targeted: `query=<query>`, `filters={"AND": [{"user_id": "<id>"}, {"app_id": "<pid>"}, {"metadata": {"type": "decision"}}]}`, `limit=5`
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user