- Remove userConfig from .claude-plugin/plugin.json — OAuth flow handles
auth via mcp.mem0.ai, userConfig prompt was redundant and confusing
- Add ensure_deps.sh to install mem0ai SDK into persistent plugin venv
- Add requirements.txt (mem0ai) for dependency tracking
- Wire SessionStart hook to auto-install deps on first run
- Update setup_coding_categories.py to find venv site-packages
- Update onboarding SKILL.md with venv-aware install steps
Wire fire-and-forget PostHog telemetry into every lifecycle hook
(session_start, stop, pre_compact, task_completed, user_prompt,
post_tool_use) matching the same project key, endpoint, and payload
structure used by the Python SDK, CLI, and OpenClaw.
- 10% sampling on ALL events to keep PostHog costs predictable
- Anonymous distinct_id: MD5(api_key) or SHA-256(username)
- Opt-out via MEM0_TELEMETRY=false
- Platform detection: Claude Code / Cursor / Codex
- Never sends user content, API keys, or raw identifiers
- 16 new tests (110 total passing)
- SessionStart shows "Mem0 Inactive" banner with identity info when no
API key set, instead of silently exiting with zero output
- on_user_prompt.sh fires error/file-path detection even without API key
(local pattern matching, no API needed). Search rubric still gated.
- parse_export_file.py supports '-' argument for stdin piping
Critical fixes:
- C1: Pin/dream update_memory now reads content first via get_memory
before updating, preventing metadata-only calls that wipe content
- C2: SessionStart memory count uses GET /v3/memories/?page_size=1 for
real count from pagination envelope instead of search limit=100
- C3: on_task_completed.sh uses ${MEM0_PROJECT_ID:-unknown} to avoid
crash when identity resolution fails under set -u
Important fixes:
- I1: session_stats.py tracks recent_ids (memory IDs + timestamps) for
/mem0:forget undo support. Capped at 50 entries.
- I2: /mem0:health --deep mode adds memory quality analysis: duplicate
detection, stale entry scan, contradiction flags, orphan tagging
- I3: /mem0:stats ASCII histogram for category distribution with bar
chart, sorted by count descending
- I4: mem0-mcp skill documents access counter pattern: get_memory then
update_memory to track which memories are actually used
- I5: on_pre_commit.py reads COMMIT_EDITMSG first (current commit),
falls back to HEAD only if EDITMSG unavailable
Tests: 91 -> 94 (3 new for recent_ids tracking)
- on_stop_cursor.sh: add loop_count guard to prevent infinite re-entry
- on_stop.sh: drop set -e so stats failure doesn't kill the reminder
- _identity.py: fix fallback stub signatures to match production (accept cwd arg)
- on_pre_compact.py: add missing infer=False on session_state writes
- on_session_start.sh: handle v3 search response format (dict with results key)
- Align all plugin versions to 0.2.1 (Claude Code, Codex, Cursor)
- Sanitize project_id in onboard marker path (tr '/:' '--') to handle
slashes from env var overrides
- Fire on_pre_compact.py REST backup from PreCompact hook (was only
called from Stop hooks — crash before Stop = data loss)
- Source _identity.sh in on_stop_codex.sh and on_stop_cursor.sh so
MEM0_PROJECT_ID + API key fallback are available
- Note dream --schedule is Claude Code-only (Codex/Cursor lack schedule)
Root cause: .mcp.json required ${MEM0_API_KEY} shell env var which
OAuth flow never populates — MCP server never started, only auth
stubs were exposed.
Fix: switch .mcp.json to ${user_config.MEM0_API_KEY} so Claude Code
reads the key from plugin userConfig (system keychain). Add
resolve_api_key() fallback chain (MEM0_API_KEY -> CLAUDE_PLUGIN_OPTION_MEM0_API_KEY)
to all hook scripts. Update onboard skill and setup_coding_categories.py
to handle keychain-only users. Add 3 tests for key resolution.
- on_pre_compact.py and capture_compact_summary.py now read cwd from
hook stdin and pass it to resolve_project_id/resolve_branch (monorepo safe)
- 5 new tests verify all write functions use app_id top-level and never
put project_id in metadata
- plugin.json declares userConfig.MEM0_API_KEY so Claude Code prompts
for the key at install time (sensitive, stored in system keychain)
Tour was filtering on metadata.type which missed platform-categorized
memories. Rewritten to use get_memories (list all) + group by platform
categories field. All write hooks now use app_id as top-level entity
param instead of metadata.project_id. Branch stamped on every write.