feat(mem0-agent): read path, hooks, maintenance, CLI and skills

- pack.py: single-call context pack, budgeted, sanitized, cached, with
  served-id tracking that turns a citation into POSITIVE feedback
- assist.py: error-signature lookup (never raw stdout, which returned 0 results in v1)
- maintain.py: transactional consolidation (add merged -> verify -> delete sources)
- transcript.py: JSONL parsing into non-overlapping windows via a cursor
- cli.py: the twelve commands the hooks invoke; detached assist queues a block
  that the next prompt hook drains, keeping the hot path network-free
- hooks generated from one spec; plugin manifest, MCP wiring, five skills

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Deshraj Yadav
2026-07-28 01:56:38 -07:00
co-authored by Claude Fable 5
parent e102b21180
commit 3ea00cf88c
33 changed files with 5934 additions and 1 deletions
@@ -0,0 +1,52 @@
---
name: config
description: Show or change how aggressively mem0 captures and retrieves memories, and switch between dual and full memory mode. Use when the user says mem0 is storing too much or too little, wants fewer or more memories injected, or asks about memory settings.
---
# Configure memory behavior
Two dials and one mode. Show the current state first, then change only what was asked for.
```bash
mem0-agent config # show everything
mem0-agent config --capture <level> # conservative | balanced | aggressive
mem0-agent config --retrieval <level> # conservative | balanced | aggressive
mem0-agent config --mode <mode> # dual | full
```
## capture — what gets stored
| Level | Captures |
|---|---|
| `conservative` | explicit "remember this", and corrections only |
| `balanced` *(default)* | + decisions and root-caused gotchas |
| `aggressive` | + completed goals and procedures the assistant proposes |
Mechanical noise — progress updates, ETAs, heartbeats, file lists, repo-file contents — is
dropped at every level. That is not configurable, because storing it is what made the
previous version useless.
## retrieval — what gets injected
| Level | Injects |
|---|---|
| `conservative` | pins, preferences and the open thread (~600 tokens); no error lookups |
| `balanced` *(default)* | the full pack (≤1500 tokens) and high-confidence error lookups |
| `aggressive` | a larger pack (≤2500 tokens) and more eager error lookups |
## mode — how mem0 coexists with repo memory files
- `dual` — `CLAUDE.md` and friends stay authoritative for repo-local notes; mem0 handles
durable, cross-machine knowledge.
- `full` — mem0 is the only memory layer; writes to `MEMORY.md` are blocked and native
auto-memory should be turned off.
Mode is stored per project, so a repo with a curated `CLAUDE.md` can stay `dual` while
another goes `full`.
## Guidance
If the user complains about noise in their context, lower `retrieval` before touching
`capture` — the corpus is usually fine and the injection is what they're feeling. If they
say memories are missing, check `mem0-agent stats` first: a memory written minutes ago is
still being extracted, and extraction is asynchronous.
@@ -0,0 +1,33 @@
---
name: forget
description: Delete memories the user no longer wants kept, by search or by id, with confirmation. Use when the user says forget that, delete that memory, that's wrong, or wants to remove outdated or sensitive stored information.
---
# Forget
Deleting is the one irreversible-feeling operation here, so it always goes: find → show →
confirm → delete.
## How
```bash
mem0-agent forget --query "<what they described>" # find candidates
mem0-agent forget --id <memory_id> --confirm # delete a specific one
```
1. Find the candidates and show them numbered, with their type and full text.
2. Ask which to remove. Never guess when more than one matches.
3. Delete the confirmed ids with `--confirm`.
4. Send negative feedback at the same time (the CLI does this) so the extraction pipeline
learns from the rejection.
## Judgment
- If the memory is **wrong** rather than unwanted, prefer correcting it: store the correct
fact with `/mem0:remember` and let the newer memory supersede the old one. Deletion loses
the history; superseding keeps it.
- If the user is deleting something because it is **stale**, ask whether the replacement
should be stored before you remove it.
- If they want to protect a memory instead of removing it, that's `/mem0:pin`.
- Deletes are soft on the platform: the record is hidden from all reads but not scrubbed
from storage. Say so if the user is deleting for privacy reasons rather than tidiness.
@@ -0,0 +1,37 @@
---
name: health
description: Diagnose mem0 connectivity, credentials, project configuration and read/write health. Use when memory operations fail, searches return nothing, the context pack is empty, or to verify the plugin is working.
---
# Health check
```bash
mem0-agent health # connectivity, identity, scope, config, breaker
mem0-agent health --deep # adds a real write probe and a corpus quality scan
```
Read the output top-down and stop at the first failure — later checks depend on earlier ones.
## What each failure means
| Symptom | Cause | Fix |
|---|---|---|
| `no API key` | not in env or keychain | `mem0-agent onboard`, or export `MEM0_API_KEY` |
| `identity unavailable` | key rejected or network down | verify the key at app.mem0.ai |
| `circuit open` | 3 consecutive API failures | wait out the cooldown; memory is paused, sessions are unaffected |
| `config incomplete` | instructions/categories/decay not applied | `mem0-agent setup` |
| pack empty, corpus non-empty | scope mismatch | compare `user_id`/`app_id` against `mem0-agent stats` |
| a just-written memory is missing | extraction is asynchronous (20s–5min) | wait, then re-check — this is normal, not a fault |
## Things that look broken but aren't
- **Categories are empty on new memories.** Categorization is a background job running
hours behind writes. Retrieval filters on `metadata.type`, which is set at write time, so
this does not affect recall.
- **A memory you deleted still exists in the database.** Deletes are soft; the record is
hidden from every read path.
- **Nothing was captured this session.** Most turns should capture nothing. Check
`mem0-agent stats` for the drop/flag breakdown before assuming a bug.
Report findings plainly. If everything passes, say so in one line and include the corpus
size and current scope.
@@ -0,0 +1,38 @@
---
name: remember
description: Store something the user explicitly asked to be remembered, verbatim and immediately. Use when the user says remember this, save this, note that, don't forget, or otherwise asks for a fact to be recorded.
---
# Remember
The user asked for something to be kept. Store it exactly as they said it — this path
bypasses the extraction gate on purpose, because an explicit request is already a decision
that the fact matters.
## How
Run:
```bash
mem0-agent remember --type <type> --text "<the fact, in one self-contained sentence>"
```
Pick `--type` from the six, by what the fact *is*:
| Type | Use when the fact is |
|---|---|
| `preference` | how they want work done (stored at user scope — it follows them across repos) |
| `decision` | a resolved choice, ideally with the reasoning |
| `convention` | a project rule not written in the repo |
| `insight` | a gotcha, constraint, or non-obvious behavior |
| `runbook` | a procedure verified to work |
## Rules
- **One fact per memory.** Two facts means two calls.
- **Self-contained.** "Use pnpm here" is useless later; "This repo uses pnpm, never npm"
survives on its own.
- **Say it back.** Confirm what was stored in one short line, with the type.
- Don't paraphrase away their meaning. Tighten wording, keep intent.
- If the user's phrasing is a one-off instruction for the current task rather than a
standing rule, say so and don't store it.
@@ -0,0 +1,34 @@
---
name: stats
description: Show what memory captured and retrieved, by type and over time, including what was dropped and why. Use when the user asks how many memories exist, what got stored this session, or whether memory is actually helping.
---
# Stats
```bash
mem0-agent stats # this session plus the corpus for this project
mem0-agent stats --session # just this session's capture/injection activity
```
## What to look at
**Session view** — how many turns were seen, hard-dropped, flagged, and written, plus which
memories were served in the context pack and whether any were referenced. Dropped counts
are grouped by reason, so "why didn't it save that?" has an actual answer.
**Corpus view** — memories by type and age for the current `user_id` + `app_id`.
## Reading the numbers
- **A high drop rate is correct.** Most turns contain nothing durable. The previous version
wrote ~98 memories a day and the corpus became unusable; this one targets fewer than 15.
- **Writes ≫ reads is the warning sign**, not a large drop count. If the corpus grows every
day but the pack is never referenced, the value isn't there — lower `capture` or
investigate what's being stored.
- **A memory written minutes ago may not appear yet.** Extraction is asynchronous
(20s–5min). Don't report it as missing.
- **`categories` being empty is expected** on anything less than a few hours old;
retrieval uses `metadata.type` instead.
Summarize in prose — counts by type, what was captured this session, and whether the served
memories were used. Only surface raw ids when the user is chasing a specific memory.