Files
Saket Aryan df70d7833f fix(plugins): stamp surface identity at record time, not send time
Six defects in 0.3.x plugin telemetry. Defects 1, 2 and 6 were not three bugs:
they were one spool protocol getting three properties wrong.

Identity was decided by the wrong process. `harness` was stamped in record(),
correctly, but `source` was read from a module global in flush() — so whichever
process drained the spool named every event in it. Two processes never call
init(): mcp_server.py, and the detached `python3 telemetry.py` sender that
spawn_flush() starts. record() now stamps source beside harness, and the build
generates core/_harness_id.py per host so identity resolves with no init() call
at all. That also unifies two defaults that disagreed (`<host>_plugin` vs
`MEM0_<HOST>_PLUGIN`), which could yield three source values for one plugin.

Ownership was inferred, not held. Path.replace is os.rename, which preserves
mtime, so a claim made after a quiet minute inherited the spool's age and was
stealable the instant it existed. Claims are touched on creation and the
per-batch rewrite doubles as a lease heartbeat.

Progress was not durable. flush() returned on the first failed batch without
truncating, so the retry re-posted from index 0 — 150 events delivered 250
times. It now rewrites the claim with the unsent remainder after every batch,
bounding a crash to one repeated batch, and each event carries a uuid.

Parked batches starved. They were only reachable when no spool existed, and
because sessions keep recording there usually was one, so a batch parked by a
failed send waited until the 7-day expiry deleted it unsent — despite its own
presence being what starts the sender. flush() drains them in the same run, and
expiry now applies only after a genuine retry has failed.

code.install counted upgrades and repeat sessions. is_first_run() read the
identity file, which only a successful flush writes, so an offline user recorded
an install every session forever. A dedicated install-state.json is claimed
atomically at record time; a non-empty data directory reads as an upgrade.

The docs called this anonymous. Every event carries the account email, and the
hashes were unsalted SHA-256 over a git remote URL or an absolute path
containing the username. READMEs, the module docstring and a new docs section
now say what the code does, and repo/session digests are salted per install.

A cached email outlived an API key change. It is now re-resolved when the key's
fingerprint differs, and $identify aliases anonymous->email only — aliasing one
account to another merges person profiles irreversibly.

All six shipped green because the shared core's only tests lived under one host,
behind a conftest that calls init() at import. Core behaviour was never
exercised uninitialised. Adds agent-plugin-core/tests with no init, including
subprocess tests and coverage for the portable plugin, which has no flush worker
and would pass a native-only test vacuously.

Also puts the three surface headers on the SDKs, CLIs and integrations, and
corrects a README claiming ZAPIER/STRANDS were already in the platform allowlist.

Verified: 59 core tests, 203 claude-code, 11 cursor, 5 codex, 2 kimi, 6
antigravity. ruff and compileall clean. --check clean for all six hosts.
TypeScript changes are not typechecked locally (deps not installed).

Claude-Session: https://claude.ai/code/session_01C7tEmH86HAr7GoAAKCEHZb
2026-09-15 00:14:11 +05:30
..

mem0 CLI (Python)

The official command-line interface for mem0 — the memory layer for AI agents. Python implementation.

Built for AI agents. Pass --agent (or --json) as a global flag on any command to get structured JSON output optimized for programmatic consumption — sanitized fields, no colors or spinners, and errors as JSON too.

Prerequisites

  • Python 3.10+

Installation

pipx install mem0-cli

Using pip

pip install mem0-cli

Note: On macOS with Homebrew Python, pip install outside a virtual environment will fail with an externally-managed-environment error (PEP 668). Use pipx instead, or install inside a virtual environment.

Quick start

# Interactive setup wizard
mem0 init

# Or login via email
mem0 init --email alice@company.com

# Or authenticate with an existing API key
mem0 init --api-key m0-xxx

# Add a memory
mem0 add "I prefer dark mode and use vim keybindings" --user-id alice

# Search memories
mem0 search "What are Alice's preferences?" --user-id alice

# List all memories for a user
mem0 list --user-id alice

# Get a specific memory
mem0 get <memory-id>

# Update a memory
mem0 update <memory-id> "I switched to light mode"

# Delete a memory
mem0 delete <memory-id>

Commands

mem0 init

Interactive setup wizard. Prompts for your API key and default user ID.

mem0 init
mem0 init --api-key m0-xxx --user-id alice
mem0 init --email alice@company.com

If an existing configuration is detected, the CLI asks for confirmation before overwriting. Use --force to skip the prompt (useful in CI/CD).

mem0 init --api-key m0-xxx --user-id alice --force
Flag Description
--api-key API key (skip prompt)
-u, --user-id Default user ID (skip prompt)
--email Login via email verification code
--code Verification code (use with --email for non-interactive login)
--force Overwrite existing config without confirmation

mem0 add

Add a memory from text, a JSON messages array, a file, or stdin.

mem0 add "I prefer dark mode" --user-id alice
mem0 add --file conversation.json --user-id alice
echo "Loves hiking on weekends" | mem0 add --user-id alice
Flag Description
-u, --user-id Scope to a user
--agent-id Scope to an agent
--messages Conversation messages as JSON
-f, --file Read messages from a JSON file
-m, --metadata Custom metadata as JSON
--categories Categories (JSON array or comma-separated)
--graph / --no-graph Enable or disable graph memory extraction
-o, --output Output format: text, json, quiet

Search memories using natural language.

mem0 search "dietary restrictions" --user-id alice
mem0 search "preferred tools" --user-id alice --output json --top-k 5
Flag Description
-u, --user-id Filter by user
-k, --top-k Number of results (default: 10)
--threshold Minimum similarity score (default: 0.3)
--rerank Enable reranking
--keyword Use keyword search instead of semantic
--filter Advanced filter expression (JSON)
--graph / --no-graph Enable or disable graph in search
-o, --output Output format: text, json, table

mem0 list

List memories with optional filters and pagination.

mem0 list --user-id alice
mem0 list --user-id alice --category preferences --output json
mem0 list --user-id alice --after 2024-01-01 --page-size 50
Flag Description
-u, --user-id Filter by user
--page Page number (default: 1)
--page-size Results per page (default: 100)
--category Filter by category
--after Created after date (YYYY-MM-DD)
--before Created before date (YYYY-MM-DD)
-o, --output Output format: text, json, table

mem0 get

Retrieve a specific memory by ID.

mem0 get 7b3c1a2e-4d5f-6789-abcd-ef0123456789
mem0 get 7b3c1a2e-4d5f-6789-abcd-ef0123456789 --output json

mem0 update

Update the text or metadata of an existing memory.

mem0 update <memory-id> "Updated preference text"
mem0 update <memory-id> --metadata '{"priority": "high"}'
echo "new text" | mem0 update <memory-id>

mem0 delete

Delete a single memory, all memories for a scope, or an entire entity.

# Delete a single memory
mem0 delete <memory-id>

# Delete all memories for a user
mem0 delete --all --user-id alice --force

# Delete all memories project-wide
mem0 delete --all --project --force

# Preview what would be deleted
mem0 delete --all --user-id alice --dry-run
Flag Description
--all Delete all memories matching scope filters
--entity Delete the entity and all its memories
--project With --all: delete all memories project-wide
--dry-run Preview without deleting
--force Skip confirmation prompt

mem0 import

Bulk import memories from a JSON file.

mem0 import data.json --user-id alice

The file should be a JSON array where each item has a memory (or text or content) field and optional user_id, agent_id, and metadata fields.

mem0 config

View or modify the local CLI configuration.

mem0 config show              # Display current config (secrets redacted)
mem0 config get api_key       # Get a specific value
mem0 config set user_id bob   # Set a value

mem0 entity

List or delete entities (users, agents, apps, runs).

mem0 entity list users
mem0 entity list agents --output json
mem0 entity delete --user-id alice --force

mem0 event

Inspect background processing events created by async operations (e.g. bulk deletes, large add jobs).

# List recent events
mem0 event list

# Check the status of a specific event
mem0 event status <event-id>
Flag Description
-o, --output Output format: text, json

mem0 status

Verify your API connection and display the current project.

mem0 status

Agent mode

Pass --agent (or its alias --json) as a global flag on any command to get output designed for AI agent tool loops:

mem0 --agent search "user preferences" --user-id alice
mem0 --agent add "User prefers dark mode" --user-id alice
mem0 --agent list --user-id alice
mem0 --agent delete --all --user-id alice --force

Every command returns the same envelope shape:

{
  "status": "success",
  "command": "search",
  "duration_ms": 134,
  "scope": { "user_id": "alice" },
  "count": 2,
  "data": [
    { "id": "abc-123", "memory": "User prefers dark mode", "score": 0.97, "created_at": "2026-01-15", "categories": ["preferences"] }
  ]
}

What agent mode does differently from --output json:

  • Sanitized data: only the fields an agent needs (id, memory, score, etc.) — no internal API noise
  • No human output: spinners, colors, and banners are suppressed entirely
  • Errors as JSON: errors go to stdout as {"status": "error", "command": "...", "error": "..."} with a non-zero exit code

Use mem0 help --json to get the full command tree as JSON — useful for agents that need to self-discover available commands.

Output formats

Control how results are displayed with --output:

Format Description
text Human-readable with colors and formatting (default)
json Structured JSON for piping to jq (raw API response)
table Tabular format (default for list)
quiet Minimal — just IDs or status codes
agent Structured JSON envelope with sanitized fields (set by --agent/--json)

Global flags

These flags are available on all commands:

Flag Description
--json Enable agent mode: structured JSON envelope output, no colors or spinners
--agent Alias for --json
--api-key Override the configured API key for this request
--base-url Override the configured API base URL for this request
-o, --output Set the output format

mem0 --version prints the CLI version. It is only valid before a subcommand, not after one.

Environment variables

Variable Description
MEM0_API_KEY API key (overrides config file)
MEM0_BASE_URL API base URL
MEM0_USER_ID Default user ID
MEM0_AGENT_ID Default agent ID
MEM0_APP_ID Default app ID
MEM0_RUN_ID Default run ID
MEM0_ENABLE_GRAPH Enable graph memory (true / false)

Environment variables take precedence over values in the config file, which take precedence over defaults.

Development

cd cli/python
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

# Run during development
python -m mem0_cli --help
mem0 add "test memory" --user-id alice

Releasing

  1. Update version in pyproject.toml
  2. Create a GitHub Release with tag cli-v<version> (e.g. cli-v0.2.1)

For a pre-release, use a beta version like 0.2.1b1 and check the pre-release checkbox.

Documentation

Full documentation is available at docs.mem0.ai/platform/cli.

License

Apache-2.0