docs(skills): refresh mem0 skills against SDK 2.2.1 / TS 3.3.1 (#7548)

This commit is contained in:
Kartik
2026-10-07 18:36:15 +05:30
committed by GitHub
parent d62ce07fac
commit b7ad69afda
33 changed files with 1239 additions and 814 deletions
+135 -72
View File
@@ -1,20 +1,25 @@
# Mem0 CLI Command Reference
Complete reference for every command, argument, flag, and output mode in the mem0 CLI. Both the Node.js (`@mem0/cli`) and Python (`mem0-cli`) implementations are identical in behavior.
Complete reference for every command, argument, flag, and output mode in the mem0 CLI. Both the Node.js (`@mem0/cli`) and Python (`mem0-cli`) implementations share the same commands and flags. Where they differ, the difference is called out inline.
---
## Global Options
These options are available on every command:
Only these two options are global:
| Flag | Type | Description |
|------|------|-------------|
| `--json` / `--agent` | boolean | Agent mode: wrap output in a structured JSON envelope on stdout. Spinners and progress go to stderr (except Node `import`, see its section). Put it before the subcommand (`mem0 --json list`); Python also accepts it anywhere. On `mem0 init`, `--agent` is the Agent Mode bootstrap flag instead (use `--json` there, after the subcommand). |
| `--version` | boolean | Print version and exit. |
These options are declared per command (not global) on `add`, `search`, `get`, `list`, `update`, `delete`, `import`, `status`, `entity list`, `entity delete`, `event list` and `event status`. `config show` takes only `-o`, and `init` takes only `--api-key`.
| Flag | Type | Description |
|------|------|-------------|
| `--json` / `--agent` | boolean | Agent mode: wrap all output in a structured JSON envelope on stdout. Spinners and progress go to stderr. |
| `-o, --output <format>` | string | Output format. Supported values vary per command (see matrix below). |
| `--api-key <key>` | string | Override the API key for this invocation. Takes precedence over env var and config file. |
| `--base-url <url>` | string | Override the API base URL (default: `https://api.mem0.ai`). |
| `--version` | boolean | Print version and exit. |
---
@@ -41,11 +46,12 @@ Interactive setup wizard. Configures API key and default user ID.
**Behavior:**
- If `~/.mem0/config.json` already exists with an API key, warns and asks for confirmation (or errors in non-TTY unless `--force` is set).
- **Email login flow** (`--email`): sends a 6-digit code to the email via `POST /api/v1/auth/email_code/`. If `--code` is also given, verifies immediately. On success, saves API key, org_id, and project_id. Cannot be combined with `--api-key`.
- **API key flow**: if both `--api-key` and `--user-id` are given, runs fully non-interactively. Otherwise prompts for missing values.
- **Agent Mode flow** (`--agent`): POSTs to `/api/v1/auth/agent_mode/`, mints a shadow API key in <5s with no email required. Pass `--agent-caller <your-name>` to attribute the signup to your AI agent identity. If omitted, run `mem0 identify <your-name>` afterward.
- In non-TTY without sufficient flags, prints a usage hint and exits with error.
- If `~/.mem0/config.json` already exists with an API key, warns and asks for confirmation. In non-TTY it errors with "Existing config would be overwritten." unless `--force` is set. The Agent Mode path (below) runs before this check.
- **Email login flow** (`--email`): sends a 6-digit code to the email via `POST /api/v1/auth/email_code/`. If `--code` is also given, skips sending and verifies immediately via `/api/v1/auth/email_code/verify/`. In non-TTY without `--code`, the code is sent and the command then errors; re-run with `--code`. On success, saves the API key, `user_email`, and `created_via: "email"`, and sets the default user ID to `--user-id`, else `$USER`/`$USERNAME`, else `mem0-cli`. Cannot be combined with `--api-key`. `--code` without `--email` is an error.
- **Claim flow** (`--email` while the existing config is an unclaimed Agent Mode key): runs the same code flow but claims the existing key to that email. The API key value does not change and memories are kept.
- **API key flow**: if both `--api-key` and `--user-id` are given, runs fully non-interactively (and validates the key against the API). In non-TTY, `--api-key` alone is enough (the user ID defaults to `$USER`/`$USERNAME`/`mem0-cli`). In a TTY with no flags, prompts for the auth method (email or API key), then for the missing values.
- **Agent Mode flow** (`init --agent`, `init --json`, or an agent runtime env var such as `CLAUDECODE` or `CURSOR_AGENT`, with no `--api-key`/`--email`; Python also enters it on a global `mem0 --json init` or `mem0 --agent init`, Node does not): first reuses a valid `MEM0_API_KEY` or a valid key already in config (no new key is minted). Otherwise POSTs to `/api/v1/auth/agent_mode/` and mints a shadow API key in <5s with no email required; the generated `user_<slug>` becomes `defaults.user_id`. Limited to 5 signups per day per network. Pass `--agent-caller <your-name>` to attribute the signup to your AI agent identity. If omitted, run `mem0 identify <your-name>` afterward.
- In non-TTY without `--api-key`, `--email`, or an agent signal, prints "Non-interactive terminal detected and --api-key is required." and exits with error.
**Examples:**
```bash
@@ -61,16 +67,16 @@ mem0 init --agent --agent-caller claude-code # AI agent self-identifies during
### `mem0 identify`
Tag your active Agent Mode key with the AI agent that's using it. Run this once after `mem0 init --agent` if you didn't pass `--agent-caller`. Idempotent — re-running just overwrites the value.
Tag your active Agent Mode key with the AI agent that's using it. Run this once after `mem0 init --agent` if you didn't pass `--agent-caller`. Idempotent: re-running just overwrites the value.
**Usage:** `mem0 identify <name>`
**Argument:** `<name>` — the AI agent identity (e.g. `claude-code`, `cursor`, `codex`, `cline`, `aider`, or a custom string).
**Argument:** `<name>`: the AI agent identity (e.g. `claude-code`, `cursor`, `codex`, `cline`, `aider`, or a custom string).
**Behavior:**
- PATCHes `/api/v1/auth/agent_mode/caller/` with `Authorization: Token <current-api-key>` and body `{agent_caller}`.
- Only works on unclaimed agent-mode keys (`platform.agent_mode=true` in config).
- Only works on unclaimed agent-mode keys (`platform.agent_mode=true` in config). Errors with "No API key configured." if no key is set, or "This command only works on unclaimed agent-mode keys." otherwise.
- Backend sanitizes the value: lowercases, drops anything outside `[a-z0-9._/-]`, truncates to 32 chars.
**Examples:**
@@ -82,6 +88,45 @@ mem0 identify my-custom-bot
---
### `mem0 whoami`
Print your AGENTRUSH identifier (`platform.default_user_id` from config). Errors with "No default_user_id found. Run `mem0 init --agent` first." if none is stored.
**Usage:** `mem0 whoami`
---
### `mem0 agent-rush add|search`
Commands for the AGENTRUSH event game. Memories are public to other players, so never include real names, emails, secrets, or PII.
**Usage:** `mem0 agent-rush add <content>` and `mem0 agent-rush search <query>`
- `add`: content must be 50-1000 characters with no URLs. The server requires 3 searches before adding and caps each key at 3 lifetime searches and 3 lifetime adds.
- Requires an API key from config or `MEM0_API_KEY` (otherwise errors with "Not initialized. Run `mem0 init --agent` first."). Node joins unquoted words into one string; Python takes a single quoted argument.
**Examples:**
```bash
mem0 agent-rush search "constraint satisfaction"
mem0 agent-rush add "I enjoy solving constraint-satisfaction problems and writing small solvers."
```
---
### `mem0 version`
Print the CLI version. `mem0 --version` does the same.
---
### `mem0 help`
**Usage:** `mem0 help [--json]`
Prints the command overview. `--json` (or global `--json`/`--agent`) prints a machine-readable command spec. In both CLIs this spec is hand-maintained and can lag behind the real option list, so trust `mem0 <command> --help` and this reference over it.
---
### `mem0 add`
Add a memory from text, messages, file, or stdin.
@@ -106,10 +151,17 @@ Add a memory from text, messages, file, or stdin.
| `-f, --file <path>` | path | - | Read messages from a JSON file. |
| `-m, --metadata <json>` | string | - | Custom metadata as JSON object (e.g. `'{"source":"cli"}'`). |
| `--no-infer` | boolean | false | Skip inference; store the text verbatim. |
| `--categories <cats>` | string | - | Categories as JSON array or comma-separated string. |
| `--expires <date>` | string | - | Expiration date (YYYY-MM-DD). Must be in the future. |
| `--immutable` | boolean | false | Accepted but has no effect on v3: the memory can still be updated and no marker is stored. |
| `--custom-instructions <text>` | string | - | Custom instructions for fact extraction. |
| `--agent-custom-instructions <text>` | string | - | Extraction instructions for agent-scoped memories, overriding the project setting. |
| `--custom-categories <json>` | string | - | Custom categories as a JSON array of `{name: description}` objects. |
| `--structured-data-schema <json>` | string | - | Schema for structured data extraction, as JSON. |
| `--timestamp <unix>` | integer | - | Unix timestamp for the memory. |
| `--categories <value>` | string | - | Rejected with an error. Use `--custom-categories` instead. |
| `-o, --output <fmt>` | string | `text` | Output format: `text`, `json`, `quiet`. |
**Input priority:** `--file` > `--messages` > text argument > stdin (if piped and no text).
**Input priority:** `--file` > `--messages` > text argument > stdin (if piped or redirected, no text, and not in `--json`/`--agent` mode).
Text content is wrapped as `[{"role": "user", "content": "<text>"}]` before sending to the API. Messages from `--messages` or `--file` are sent as-is.
@@ -130,9 +182,8 @@ mem0 add "allergic to nuts" -u alice -m '{"source":"onboarding"}'
mem0 add --messages '[{"role":"user","content":"I like Python"}]' -u alice
mem0 add --file conversation.json -u alice -o json
echo "I prefer dark mode" | mem0 add -u alice
mem0 add "temporary note" -u alice --expires 2025-12-31
mem0 add "important fact" -u alice --immutable
mem0 add "uses vim" -u alice --categories "tools,preferences"
mem0 add "temporary note" -u alice --expires 2027-12-31
mem0 add "uses vim" -u alice --custom-categories '[{"tools":"Editors and developer tooling"}]'
```
---
@@ -147,7 +198,7 @@ Search memories by semantic query.
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `query` | string | Yes | The search query. Falls back to stdin if piped. |
| `query` | string | Yes | The search query. Falls back to stdin if piped or redirected (Python skips this in `--json`/`--agent` mode; Node does not). |
**Options:**
@@ -157,11 +208,15 @@ Search memories by semantic query.
| `--agent-id <id>` | string | - | Filter by agent. |
| `--app-id <id>` | string | - | Filter by app. |
| `--run-id <id>` | string | - | Filter by run. |
| `-k, --top-k, --limit <n>` | integer | 10 | Maximum number of results to return. |
| `--threshold <score>` | float | 0.1 | Minimum similarity score (0.0 to 1.0). |
| `-k, --top-k <n>` | integer | 10 | Maximum number of results to return (must be >= 1). Python also accepts `--limit` as an alias. |
| `--threshold <score>` | float | 0.3 | Minimum similarity score (0.0 to 1.0), applied before hybrid score blending, so a returned item's displayed `score` can be lower than this value. |
| `--rerank` | boolean | false | Enable reranking for improved relevance (Platform only). |
| `--filter <json>` | string | - | Advanced filter expression as JSON (AND/OR operators). |
| `--fields <list>` | string | - | Comma-separated list of fields to return. |
| `--keyword` | boolean | false | Sent to the API as `keyword_search` but not applied by v3 search, which always blends keyword matching into hybrid scoring. |
| `--filter <json>` | string | - | Advanced filter expression as JSON. If it contains `AND` or `OR` it is sent as-is and entity IDs (including config defaults) are not merged in. |
| `--fields <list>` | string | - | Comma-separated list of fields to return. Sent to the API but not applied by v3 search. |
| `--show-expired` | boolean | false | Include expired memories. |
| `--reference-date <date>` | string | - | Reference date for relative queries (YYYY-MM-DD or unix timestamp). |
| `--latest-only` | boolean | false | Only return the latest version of each memory. |
| `-o, --output <fmt>` | string | `text` | Output format: `text`, `json`, `table`. |
**Examples:**
@@ -171,6 +226,8 @@ mem0 search "tools" -u alice -o json -k 5
mem0 search "dietary restrictions" -u alice --threshold 0.5
mem0 search "project setup" -u alice --rerank
mem0 search "preferences" -u alice --filter '{"categories":{"contains":"food"}}'
mem0 search "invoices" -u alice --filter '{"AND":[{"user_id":"alice"},{"categories":{"in":["work"]}}]}'
mem0 search "plans" -u alice --latest-only
echo "preferences" | mem0 search -u alice
```
@@ -221,6 +278,8 @@ List memories with optional filters and pagination.
| `--category <name>` | string | - | Filter by category. |
| `--after <date>` | string | - | Created after (YYYY-MM-DD). |
| `--before <date>` | string | - | Created before (YYYY-MM-DD). |
| `--show-expired` | boolean | false | Include expired memories. |
| `--latest-only` | boolean | false | Only return the latest version of each memory. |
| `-o, --output <fmt>` | string | `table` | Output format: `text`, `json`, `table`. |
**Examples:**
@@ -244,13 +303,15 @@ Update a memory's text or metadata.
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `memory_id` | string | Yes | The UUID of the memory to update. |
| `text` | string | No | New memory text. Falls back to stdin if piped and no `--metadata`. |
| `text` | string | No | New memory text. Falls back to stdin if piped or redirected (Python skips this in `--json`/`--agent` mode; Node does not). |
**Options:**
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `-m, --metadata <json>` | string | - | Update metadata as JSON object. |
| `--expires <date>` | string | - | Expiration date (YYYY-MM-DD). Must be in the future. |
| `--timestamp <unix>` | integer | - | Unix timestamp for the memory. |
| `-o, --output <fmt>` | string | `text` | Output format: `text`, `json`, `quiet`. |
**Examples:**
@@ -282,8 +343,9 @@ Delete a memory, all memories matching a scope, or an entity. This command has t
| `--all` | boolean | false | Delete all memories matching scope filters. |
| `--entity` | boolean | false | Delete the entity itself and all its memories (cascade). |
| `--project` | boolean | false | With `--all`: delete ALL memories project-wide (sends wildcard IDs). |
| `--dry-run` | boolean | false | Show what would be deleted without actually deleting. |
| `--force` | boolean | false | Skip confirmation prompt. |
| `--dry-run` | boolean | false | Show what would be deleted without actually deleting. Ignored by `--all --project`, which deletes (see Dry-run behavior). |
| `--force` | boolean | false | Skip confirmation prompt (`--all` and `--entity` only). Required for those modes in `--json`/`--agent` mode. |
| `--delete-linked` | boolean | false | Single-memory mode: also delete memories linked to this memory. |
| `-u, --user-id <id>` | string | - | Scope to user. |
| `--agent-id <id>` | string | - | Scope to agent. |
| `--app-id <id>` | string | - | Scope to app. |
@@ -296,14 +358,17 @@ Delete a memory, all memories matching a scope, or an entity. This command has t
2. **Bulk delete:** `mem0 delete --all [scope flags]` -- deletes all memories matching the scope. Add `--project` to wipe all memories project-wide (sends wildcard `*` entity IDs).
3. **Entity cascade:** `mem0 delete --entity [scope flags]` -- deletes the entity itself AND all its memories.
You cannot combine `<memory_id>` with `--all` or `--entity`, and you cannot combine `--all` with `--entity`. If none of these are provided, the command prints a usage hint and exits with an error.
You cannot combine `<memory_id>` with `--all` or `--entity`, and you cannot combine `--all` with `--entity`. If none of these are provided, the command prints an error and exits 1.
**Entity IDs:** `--all` resolves IDs like `search` (explicit flags only, else config defaults). Single delete and `--entity` use only explicit flags, and `--entity` requires at least one.
**Dry-run behavior:**
- Single: fetches the memory, displays it, prints "No changes made."
- `--all`: lists matching memories with count, prints "No changes made."
- `--entity`: shows the affected scope without deleting.
- Single: fetches the memory, displays it, and prints "No changes made." (Python: "No changes made (dry run)."). Node also prints "Would delete memory <id8>: <text>".
- `--all`: lists matching memories, prints "Would delete N memories." and the "No changes made" line. In `--json`/`--agent` mode `--all` still requires `--force` even with `--dry-run`, and the command then exits 0 with no output and deletes nothing. Use text mode to see the preview.
- `--entity`: prints "Would delete entity <scope> and all its memories." and the "No changes made" line.
- **Warning:** `--all --project` does not honor `--dry-run`. It skips the preview and deletes every memory in the project (after the confirmation, or immediately with `--force`). Never pass `--dry-run` to `--all --project` expecting a preview. This is a known CLI bug in both CLIs, not intended behavior, so do not rely on it. To preview, run `mem0 delete --all --dry-run` per scope (for example `-u alice`) instead.
**Confirmation:** Without `--force`, all destructive modes prompt `[y/N]`. With `--all --project`, the prompt explicitly warns about project-wide deletion.
**Confirmation:** Without `--force`, `--all` and `--entity` prompt `[y/N]`. Single-memory delete never prompts and ignores `--force`. With `--all --project`, the prompt explicitly warns about project-wide deletion and the scope flags are ignored.
**`--all --project` behavior:** Sends `DELETE /v1/memories/` with `user_id=*&agent_id=*&app_id=*&run_id=*`. The API returns an async response. The CLI prints "Deletion started. Memories will be removed in the background."
@@ -339,7 +404,7 @@ Import memories from a JSON file.
| `--agent-id <id>` | string | - | Override agent ID for all imported items. |
| `-o, --output <fmt>` | string | `text` | Output format: `text`, `json`. |
**File format:** A JSON array (or single object) where each item has a `memory`, `text`, or `content` field for the text, plus optional `user_id`, `agent_id`, and `metadata` fields. CLI-provided `--user-id` and `--agent-id` override per-item values.
**File format:** A JSON array (or single object) where each item has a `memory`, `text`, or `content` field for the text, plus optional `user_id`, `agent_id`, and `metadata` fields. `--user-id` and `--agent-id` override per-item values, and so do the config defaults when neither flag is given. Items with no text count as failed.
**Import format example:**
```json
@@ -350,7 +415,7 @@ Import memories from a JSON file.
]
```
**Behavior:** Iterates through items, calling the add API for each. Displays progress and reports `added` and `failed` counts on completion.
**Behavior:** Iterates through items, calling the add API for each. Displays progress and reports `added` and `failed` counts on completion (text mode writes the summary to stderr in Python and to stdout in Node). In JSON mode the Python CLI sends progress to stderr and includes `scope` in the envelope; the Node CLI writes the progress line to stdout before the JSON (so `| jq` fails) and omits `scope`. Only `-u`, `--agent-id`, `-o`, `--api-key` and `--base-url` are accepted.
**Examples:**
```bash
@@ -372,6 +437,8 @@ Display current configuration with secrets redacted.
|------|------|---------|-------------|
| `-o, --output <fmt>` | string | `text` | Output format: `text`, `json`. |
**Behavior:** `-o json` (or agent mode) returns the standard envelope with `data` shaped as `{"defaults": {"user_id", "agent_id", "app_id", "run_id"}, "platform": {"api_key", "base_url"}}`. The API key is redacted and unset defaults are `null`.
**Examples:**
```bash
mem0 config show
@@ -392,9 +459,9 @@ Get a single configuration value.
|------|------|----------|-------------|
| `key` | string | Yes | Dotted config key (e.g. `platform.api_key`, `defaults.user_id`). |
**Valid keys:** `platform.api_key`, `platform.base_url`, `defaults.user_id`, `defaults.agent_id`, `defaults.app_id`, `defaults.run_id`.
**Valid keys:** `platform.api_key`, `platform.base_url`, `platform.user_email`, `defaults.user_id`, `defaults.agent_id`, `defaults.app_id`, `defaults.run_id`, plus the short forms `api_key`, `base_url`, `user_email`, `user_id`, `agent_id`, `app_id`, `run_id`. Python also resolves any other field path in the config file (e.g. `platform.agent_mode`); Node does not.
API key values are always redacted in output.
An unknown key prints "Unknown config key: <key>" and still exits 0. API key values are always redacted in output. `config get` and `config set` emit a `{key, value}` envelope only in `--json`/`--agent` mode.
**Examples:**
```bash
@@ -427,19 +494,6 @@ mem0 config set platform.base_url https://api.mem0.ai
---
### `mem0 config clear`
Clear the configuration file. Removes `~/.mem0/config.json`.
**Usage:** `mem0 config clear`
**Examples:**
```bash
mem0 config clear
```
---
### `mem0 entity list`
List all entities of a given type.
@@ -507,9 +561,9 @@ List recent background processing events.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `-o, --output <fmt>` | string | `table` | Output format: `text` (table), `json`. |
| `-o, --output <fmt>` | string | `table` | Output format: `table`, `json`. |
**Behavior:** Fetches all events for the project. Displays a table with columns: Event ID (first 8 chars), Type, Status (color-coded), Latency, Created. Status values: `PENDING`, `SUCCEEDED`, `FAILED`, `PROCESSING`.
**Behavior:** Fetches all events for the project. Displays a table with columns: Event ID (first 8 chars), Type, Status (color-coded), Latency, Created. Status values: `PENDING`, `RUNNING`, `SUCCEEDED`, `FAILED`.
**Examples:**
```bash
@@ -585,16 +639,15 @@ mem0 status -o json
## Agent Mode Envelope Format
When `--json` or `--agent` is passed, every command wraps its output in a consistent JSON envelope on stdout:
When `--json` or `--agent` is passed, data commands (add, search, list, get, update, delete, import, config, entity, event, status) wrap their output in a consistent JSON envelope on stdout:
```json
{
"status": "success",
"command": "<command_name>",
"duration_ms": 245,
"scope": { "user_id": "alice", "agent_id": null },
"scope": { "user_id": "alice" },
"count": 10,
"error": null,
"data": { ... }
}
```
@@ -603,38 +656,47 @@ When `--json` or `--agent` is passed, every command wraps its output in a consis
- `status`: `"success"` or `"error"`.
- `command`: The command name (e.g. `"search"`, `"add"`, `"list"`).
- `duration_ms`: Elapsed time in milliseconds (optional).
- `scope`: Active entity scope, omitted if empty (optional).
- `scope`: Active entity scope with empty values dropped, omitted if empty (optional).
- `count`: Number of results, where applicable (optional).
- `error`: Error message string, or `null` on success.
- `data`: Command-specific response data, or `null` on error.
- `data`: Command-specific response data (`null` on error).
- `error`: Present only on error envelopes (see below); success envelopes have no `error` key.
- `mem0_notice`: Present when the platform flags an unclaimed Agent Mode account (optional).
**Sanitized data fields per command in agent mode:**
| Command | `data` shape |
|---------|-------------|
| `add` | `[{id, memory, event}]` or `[{status, event_id}]` for PENDING |
| `search` | `[{id, memory, score, created_at, categories}]` |
| `list` | `[{id, memory, created_at, categories}]` |
| `get` | `{id, memory, created_at, updated_at, categories, metadata}` |
| `update` | `{id, memory}` |
| `delete` | Raw API response |
| `entity list` | `[{name, type, count}]` |
| `add` | `[{id, event}]` for synchronous results (`--no-infer`) or `[{status, event_id}]` for PENDING (default) |
| `search` | `[{id, memory, score, created_at, categories, expiration_date}]` |
| `list` | `[{id, memory, created_at, categories, expiration_date}]` |
| `get` | `{id, memory, created_at, updated_at, categories, metadata, expiration_date}` |
| `update` | `{id, memory, expiration_date}` |
| `delete` (single) | `{id, deleted}` |
| `delete --all` | `{deleted}`, with `scope` in the envelope (Node: raw API result) |
| `delete --all --project` | `{deleted, scope: "project"}` (Node: raw API result) |
| `delete --entity` / `entity delete` | `{deleted}` |
| `entity list` | `[{name, type}]` |
| `event list` | `[{id, event_type, status, latency, created_at}]` |
| `event status` | `{id, event_type, status, latency, created_at, updated_at, results}` |
| `status` | `{connected, backend, base_url}` |
| `config show` | Config object (keys redacted) |
| `import` | `{added, failed, duration_s}` |
| `config show` | `{defaults: {user_id, agent_id, app_id, run_id}, platform: {api_key, base_url}}` (key redacted) |
| `config get` / `config set` | `{key, value}` (agent mode only) |
| `import` | `{added, failed}` |
**`-o json` without agent mode:** `list`, `status`, `import` and `config show` print the same envelope. `add`, `search`, `get`, `update`, `delete` and `entity delete` print the raw API JSON instead. `entity list`, `event list` and `event status` print the envelope in Node and raw JSON in Python.
**Error envelope:**
```json
{
"status": "error",
"command": "search",
"error": "Authentication failed. Your API key may be invalid or expired.",
"error": "Invalid or expired API key.",
"data": null
}
```
The `error` text varies by CLI and failure point (for example a 401 after the upfront key check passes returns "Authentication failed. Your API key may be invalid or expired."). Branch on `status`, not on the message.
---
## Entity ID Resolution
@@ -652,19 +714,20 @@ else:
use all configured defaults
```
This applies to commands with `resolveIds: true`: `add`, `search`, `list`, `delete`, `import`.
This applies to `add`, `search`, `list`, `delete --all`, and `import` (user and agent IDs only). Single `delete` and `entity delete` use only explicitly passed flags.
---
## Filter Building
For `search` and `list`, entity IDs and additional filters are composed into the API filter structure:
For `search` and `list`, entity IDs and additional filters are composed into the API filter structure. `--filter` exists only on `search`; `list` builds its extra filters from `--category`, `--after` and `--before`.
1. If the user provides a pre-built filter via `--filter` containing `AND` or `OR` keys, it is passed through to the API as-is.
1. If the user provides a pre-built filter via `--filter` containing `AND` or `OR` keys, it is passed through to the API as-is (entity IDs, including config defaults, are not merged in).
2. Otherwise, the CLI builds an array of AND conditions:
- Each entity ID becomes a condition: `{"user_id": "alice"}`, etc.
- Category filters: `{"categories": {"contains": "<category>"}}`.
- Date filters: `{"created_at": {"gte": "YYYY-MM-DD"}}` and/or `{"created_at": {"lte": "YYYY-MM-DD"}}`.
- A `--filter` without `AND`/`OR` contributes each of its top-level keys as a condition.
- Category filters (`list`): `{"categories": {"contains": "<category>"}}`.
- Date filters (`list`): one condition `{"created_at": {"gte": "YYYY-MM-DD", "lte": "YYYY-MM-DD"}}`, with only the bounds you passed.
3. If exactly 1 condition: sent as a single object (no wrapping).
4. If 2+ conditions: wrapped as `{"AND": [condition1, condition2, ...]}`.
5. If 0 conditions: no filter sent.
@@ -687,8 +750,8 @@ For `search` and `list`, entity IDs and additional filters are composed into the
| `config set` | msg | - | - | - | msg |
| `entity list` | - | Y | Y | - | `table` |
| `entity delete` | Y | Y | - | Y | `text` |
| `event list` | Y (table) | Y | - | - | `table` |
| `event list` | - | Y | Y | - | `table` |
| `event status` | Y | Y | - | - | `text` |
| `status` | Y | Y | - | - | `text` |
All commands additionally support agent mode (`--json`/`--agent`) which overrides the output format with the JSON envelope.
Agent mode (`--json`/`--agent`) overrides the output format with the JSON envelope for all data commands above (it applies to `config get` and `config set` too). See the envelope section for how `-o json` differs from agent mode.
+54 -26
View File
@@ -13,6 +13,8 @@ Everything about configuring the mem0 CLI: config file format, environment varia
The restricted permissions ensure API keys are not world-readable.
Saving an API key also updates an existing `env.MEM0_API_KEY` entry in `~/.claude/settings.json` and existing `export MEM0_API_KEY=...` lines in `~/.zshrc`, `~/.bashrc`, and `~/.bash_profile`. It never creates new entries.
---
## Config File Schema
@@ -28,7 +30,19 @@ The restricted permissions ensure API keys are not world-readable.
},
"platform": {
"api_key": "",
"base_url": "https://api.mem0.ai"
"base_url": "https://api.mem0.ai",
"user_email": "",
"agent_mode": false,
"created_via": "",
"agent_caller": "",
"claimed_at": "",
"default_user_id": ""
},
"telemetry": {
"anonymous_id": ""
},
"agent_rush": {
"acknowledged_at": ""
}
}
```
@@ -44,12 +58,20 @@ The restricted permissions ensure API keys are not world-readable.
| `defaults.run_id` | string | `""` | Default run ID for scoping commands. |
| `platform.api_key` | string | `""` | API key for the Mem0 Platform. |
| `platform.base_url` | string | `"https://api.mem0.ai"` | Base URL for API requests. |
| `platform.user_email` | string | `""` | Email used for login or claim. Also cached from the ping response during `init`. |
| `platform.agent_mode` | boolean | `false` | `true` while the key is an unclaimed Agent Mode key. |
| `platform.created_via` | string | `""` | How the key was obtained: `agent_mode`, `email`, `api_key`, or `existing_key`. |
| `platform.agent_caller` | string | `""` | Agent name set by `--agent-caller` or `mem0 identify`. |
| `platform.claimed_at` | string | `""` | ISO timestamp once an Agent Mode account is claimed. |
| `platform.default_user_id` | string | `""` | `user_<slug>` returned by the Agent Mode bootstrap. Printed by `mem0 whoami`. |
| `telemetry.anonymous_id` | string | `""` | Persistent anonymous ID used for telemetry. |
| `agent_rush.acknowledged_at` | string | `""` | ISO timestamp when the `agent-rush` public-memory warning was acknowledged. |
---
## `mem0 init` Wizard
The `init` command provides two authentication flows:
The `init` command provides three authentication flows: API key, email login, and Agent Mode (see [Agent Mode Init](#agent-mode-init)).
### API Key Flow (default)
@@ -65,17 +87,17 @@ mem0 init --api-key m0-xxx --user-id alice
1. Displays the mem0 banner.
2. Checks for existing config. If found with an API key, asks for confirmation to overwrite.
3. Prompts for API key (input masked with `*` characters; supports backspace and Ctrl+U to clear).
4. Prompts for default user ID (default value: `mem0-cli`).
5. Validates the connection by calling the status endpoint.
6. Saves config to `~/.mem0/config.json` with `0600` permissions.
7. Prints success message.
3. Asks how to authenticate (`1` email login, recommended; `2` enter an API key) unless `--api-key` was passed.
4. For option 2, prompts for the API key (input masked with `*` characters; supports backspace and Ctrl+U to clear).
5. Prompts for default user ID (default value: `$USER`, then `$USERNAME`, then `mem0-cli`) unless `--user-id` was passed.
6. Validates the connection by calling the status endpoint. A failed check prints an error but the config is still saved.
7. Saves config to `~/.mem0/config.json` with `0600` permissions.
8. Prints success message.
**Non-interactive mode:** When both `--api-key` and `--user-id` are provided, skips all prompts and saves directly. When running in a non-TTY without both flags, prints an error:
**Non-interactive mode:** When both `--api-key` and `--user-id` are provided, skips all prompts and saves directly. In a non-TTY, `--api-key` alone is enough: the user ID falls back to `$USER`, then `$USERNAME`, then `mem0-cli`. A non-TTY without `--api-key` (and without `--email` or an Agent Mode signal) prints an error:
```
Non-interactive terminal detected and missing required flags.
Usage: mem0 init --api-key <key> --user-id <id>
Non-interactive terminal detected and --api-key is required.
```
### Email Login Flow
@@ -92,14 +114,23 @@ mem0 init --email alice@company.com --code 482901
1. Sends a 6-digit verification code to the email via `POST /api/v1/auth/email_code/`.
2. If `--code` is provided, verifies immediately. Otherwise prompts for the code.
3. On success: receives API key, org_id, and project_id from the server.
4. Saves to config. Creates a new account if the email is not registered.
3. On success: receives the API key from the server and saves it with `platform.user_email` and `platform.created_via: "email"`. The default user ID is `--user-id`, else `$USER`, else `mem0-cli`.
Cannot be combined with `--api-key`.
Without `--code` in a non-TTY, `init` sends the code and exits with an error telling you to rerun with `--code`. `--code` requires `--email`, and `--email` cannot be combined with `--api-key`.
**Claiming an Agent Mode account:** If the existing config is an unclaimed Agent Mode key (`platform.agent_mode: true`), `mem0 init --email <email> [--code <code>]` claims that key for the email instead of minting a new one. The API key stays the same.
### Agent Mode Init
```bash
mem0 init --agent --agent-caller <name> --json
```
With `init --agent`, `init --json`, or an agent environment variable (such as `CLAUDECODE`, `CURSOR_AGENT`, `CODEX_CLI`, `CLINE`, `AIDER_SESSION`, `GOOSE_AGENT`, `WINDSURF_AGENT`) and no `--api-key` or `--email`, `init` first reuses a valid `MEM0_API_KEY` or a valid key already in the config. Only when there is no valid key does it mint a new Agent Mode key via `POST /api/v1/auth/agent_mode/`, which is limited to 5 signups per day per network. See [command-reference.md](command-reference.md) for the `init` flags and `identify`.
### Force Overwrite
If `~/.mem0/config.json` already exists with an API key, `mem0 init` warns and asks for confirmation. Use `--force` to skip:
If `~/.mem0/config.json` already exists with an API key, `mem0 init` warns and asks for confirmation (in a non-TTY it exits 1 with "Existing config would be overwritten." instead). Use `--force` to skip:
```bash
mem0 init --api-key m0-new-key --user-id alice --force
@@ -111,7 +142,7 @@ mem0 init --api-key m0-new-key --user-id alice --force
### `mem0 config show`
Displays the current configuration as a formatted table (text mode) or JSON envelope (json mode). API keys are always redacted.
Displays `defaults.*`, `platform.api_key` (redacted), and `platform.base_url` as a formatted table (text mode) or JSON envelope (json mode). Other `platform.*` fields are not shown.
```bash
mem0 config show
@@ -120,7 +151,7 @@ mem0 config show -o json
### `mem0 config get <key>`
Reads a single configuration value. The key uses dotted notation.
Reads a single configuration value. The key uses dotted notation or a short alias (`api_key`, `base_url`, `user_email`, `user_id`, `agent_id`, `app_id`, `run_id`).
```bash
mem0 config get platform.api_key # prints: m0-x...xxxx (redacted)
@@ -130,12 +161,13 @@ mem0 config get defaults.user_id # prints: alice
**Valid keys:**
- `platform.api_key`
- `platform.base_url`
- `platform.user_email`
- `defaults.user_id`
- `defaults.agent_id`
- `defaults.app_id`
- `defaults.run_id`
Unknown keys print an error message.
Python also resolves any other field path in the config (for example `platform.created_via`); Node accepts only the keys above and their short aliases. Unknown keys print "Unknown config key: <key>" and still exit 0, so check the output rather than the exit code. In `--json`/`--agent` mode `config get` and `config set` return `{"key": ..., "value": ...}` in the envelope.
### `mem0 config set <key> <value>`
@@ -148,17 +180,9 @@ mem0 config set platform.base_url https://api.mem0.ai
**Type coercion:**
- Boolean fields accept `true`, `1`, `yes` (case-insensitive) as true. Anything else is false.
- Integer fields are parsed with `parseInt`.
- Integer fields are parsed as integers (Node `parseInt`, Python `int`; Python rejects a non-numeric value as an unknown key).
- String fields are stored as-is.
### `mem0 config clear`
Removes the config file (`~/.mem0/config.json`).
```bash
mem0 config clear
```
---
## Environment Variables
@@ -173,6 +197,7 @@ Environment variables override config file values but are overridden by CLI flag
| `MEM0_AGENT_ID` | `defaults.agent_id` | string | `""` |
| `MEM0_APP_ID` | `defaults.app_id` | string | `""` |
| `MEM0_RUN_ID` | `defaults.run_id` | string | `""` |
| `MEM0_TELEMETRY` | n/a | string | enabled. Set to `false` to disable anonymous telemetry. |
---
@@ -218,7 +243,10 @@ The `config get` and `config set` commands use dotted key paths. Here is the ful
|------------|---------|-------|
| `platform.api_key` | platform | api_key |
| `platform.base_url` | platform | base_url |
| `platform.user_email` | platform | user_email |
| `defaults.user_id` | defaults | user_id |
| `defaults.agent_id` | defaults | agent_id |
| `defaults.app_id` | defaults | app_id |
| `defaults.run_id` | defaults | run_id |
Short aliases (`api_key`, `base_url`, `user_email`, `user_id`, `agent_id`, `app_id`, `run_id`) map to the same fields. Python additionally resolves any other dotted field path.
+44 -37
View File
@@ -6,11 +6,11 @@ Practical recipes for using the mem0 CLI in scripts, pipelines, and agent loops.
## Piping Content via Stdin
The CLI reads from stdin when no text argument is provided and input is piped (not a TTY). This works with `add`, `search`, and `update`.
The CLI reads from stdin when no text argument is provided and stdin is a pipe or a redirected file. This works with `add`, `search`, and `update`. It never reads stdin in `--json`/`--agent` mode for `add`, and Python also skips it there for `search` and `update`, so pass the text as an argument in agent mode.
**Stdin detection method:**
- Python: `not sys.stdin.isatty()`
- Node: `!process.stdin.isTTY`
- Python: `os.fstat(sys.stdin.fileno())` is a FIFO or a regular file
- Node: `fs.fstatSync(0)` is a FIFO or a regular file
### Add from pipe
@@ -69,7 +69,7 @@ The file should be a JSON array where each item has a `memory`, `text`, or `cont
]
```
CLI-provided `--user-id` overrides per-item `user_id` values.
Items may also carry `agent_id`. CLI-provided `--user-id` and `--agent-id` (or configured defaults) override per-item values. A single JSON object is treated as a one-item array, and items without `memory`, `text`, or `content` are counted as failed.
### Import with JSON output
@@ -82,21 +82,24 @@ Output:
{
"status": "success",
"command": "import",
"data": { "added": 42, "failed": 0, "duration_s": 3.14 },
"duration_ms": 3140
"duration_ms": 3140,
"scope": { "user_id": "alice" },
"data": { "added": 42, "failed": 0 }
}
```
This is the Python CLI output. The Node CLI omits `scope` and writes the `Importing memories... n/n` progress line to stdout before the JSON, so its output cannot be piped to `jq`.
---
## Agent Mode for LLM Consumption
Use `--json` or `--agent` to get structured JSON output suitable for LLM tool calling or agent frameworks. Spinners and progress always go to stderr, keeping stdout clean.
Use `--json` or `--agent` to get structured JSON output suitable for LLM tool calling or agent frameworks. Spinners and progress always go to stderr, keeping stdout clean. Put the flag before the subcommand so it works in both the Python and Node CLIs.
### Search with agent mode
```bash
mem0 search "preferences" --user-id alice --agent
mem0 --agent search "preferences" --user-id alice
```
Output (stdout):
@@ -107,7 +110,6 @@ Output (stdout):
"duration_ms": 187,
"scope": { "user_id": "alice" },
"count": 2,
"error": null,
"data": [
{ "id": "mem-abc", "memory": "User prefers dark mode", "score": 0.95, "created_at": "2025-01-15T10:00:00Z", "categories": ["preferences"] },
{ "id": "mem-def", "memory": "User likes monospace fonts", "score": 0.82, "created_at": "2025-01-15T10:01:00Z", "categories": ["preferences"] }
@@ -118,7 +120,7 @@ Output (stdout):
### Add with agent mode
```bash
mem0 add "Uses Python 3.12" --user-id alice --json
mem0 --json add "Uses Python 3.12" --user-id alice
```
### Error handling in agent mode
@@ -126,7 +128,7 @@ mem0 add "Uses Python 3.12" --user-id alice --json
Errors also return valid JSON with `"status": "error"`:
```bash
mem0 search "test" --user-id alice --api-key invalid --agent
mem0 --agent search "test" --user-id alice --api-key invalid
```
Output:
@@ -134,7 +136,7 @@ Output:
{
"status": "error",
"command": "search",
"error": "Authentication failed. Your API key may be invalid or expired.",
"error": "Invalid or expired API key.",
"data": null
}
```
@@ -143,30 +145,30 @@ Output:
## JSON Output + jq
Use `--output json` (or `-o json`) for raw JSON output, then pipe to `jq` for processing.
Use `--output json` (or `-o json`) for JSON output, then pipe to `jq` for processing. `search`, `get`, `add`, `update`, and `delete` print the raw API response. `list`, `status`, and `import` print the standard envelope instead, so read the results from `.data`. Piping `import` to `jq` works only with the Python CLI (Node writes its progress line to stdout ahead of the JSON).
### Extract just memory text
```bash
mem0 list --user-id alice --output json | jq '.[] | .memory'
mem0 list --user-id alice --output json | jq '.data[] | .memory'
```
### Get memory IDs
```bash
mem0 list --user-id alice -o json | jq '.[].id'
mem0 list --user-id alice -o json | jq '.data[].id'
```
### Count memories
```bash
mem0 list --user-id alice -o json | jq 'length'
mem0 list --user-id alice -o json | jq '.count'
```
### Filter by category in jq
```bash
mem0 list --user-id alice -o json | jq '[.[] | select(.categories[]? == "preferences")]'
mem0 list --user-id alice -o json | jq '[.data[] | select(.categories[]? == "preferences")]'
```
### Extract search scores
@@ -183,7 +185,7 @@ mem0 search "tools" --user-id alice -o json | jq '.[] | {memory, score}'
```bash
# Get IDs, then delete each one
mem0 list --user-id alice -o json | jq -r '.[].id' | while read id; do
mem0 list --user-id alice -o json | jq -r '.data[].id' | while read id; do
mem0 delete "$id" --force
done
```
@@ -199,7 +201,7 @@ done < memories.txt
### Copy memories between users
```bash
mem0 list --user-id alice -o json | jq -r '.[].memory' | while IFS= read -r mem; do
mem0 list --user-id alice -o json | jq -r '.data[].memory' | while IFS= read -r mem; do
mem0 add "$mem" --user-id bob
done
```
@@ -216,7 +218,7 @@ mem0 list --user-id alice -o json > alice_memories.json
page=1
while true; do
result=$(mem0 list --user-id alice -o json --page "$page" --page-size 100)
count=$(echo "$result" | jq 'length')
count=$(echo "$result" | jq '.count')
if [ "$count" -eq 0 ]; then
break
fi
@@ -271,7 +273,7 @@ mem0 add "CI run started" --user-id ci-bot
```bash
test_summary=$(cat test-results.txt | head -20)
mem0 add "$test_summary" --agent-id ci-bot --metadata '{"type":"test-results"}' --categories "ci,testing"
mem0 add "$test_summary" --agent-id ci-bot --metadata '{"type":"test-results"}'
```
---
@@ -282,11 +284,11 @@ The CLI reads from stdin only when ALL of these conditions are met:
1. No text argument was provided on the command line.
2. For `add`: no `--messages` and no `--file` flag.
3. For `update`: no `--metadata` flag.
4. stdin is piped (not a TTY).
3. stdin is a pipe or a redirected file (a plain non-TTY such as `/dev/null` does not count).
4. The CLI is not in `--json`/`--agent` mode (`add` in both CLIs, `search` and `update` in Python).
**This means:**
- `mem0 add --user-id alice` in an interactive terminal will NOT hang waiting for input. It will print a usage error.
- `mem0 add --user-id alice` in an interactive terminal will NOT hang waiting for input. It exits 1 with "No content provided".
- `echo "text" | mem0 add --user-id alice` will read "text" from stdin.
- `mem0 add "explicit text" --user-id alice` will use the explicit text, even if stdin is piped.
@@ -303,8 +305,7 @@ The CLI reads from stdin only when ALL of these conditions are met:
```bash
set -e # Exit on error
# This will exit the script if the API key is invalid
mem0 status > /dev/null 2>&1
mem0 status -o json | jq -e '.data.connected' > /dev/null
# Add with error check
if mem0 add "test memory" --user-id alice 2>/dev/null; then
@@ -317,10 +318,16 @@ fi
### Capture memory ID from add
Default adds are asynchronous and return an `event_id`. Use `--no-infer` for a synchronous add whose `.data[0].id` is the memory id.
```bash
# Use agent mode to get structured output
result=$(mem0 add "new fact" --user-id alice --agent 2>/dev/null)
memory_id=$(echo "$result" | jq -r '.data[0].id // empty')
event_id=$(mem0 --agent add "new fact" --user-id alice 2>/dev/null | jq -r '.data[0].event_id // empty')
for _ in $(seq 30); do
status=$(mem0 --agent event status "$event_id" | jq -r '.data.status')
[ "$status" = "SUCCEEDED" ] || [ "$status" = "FAILED" ] && break
sleep 2
done
memory_id=$(mem0 --agent event status "$event_id" | jq -r '.data.results[0].id // empty')
if [ -n "$memory_id" ]; then
echo "Created memory: $memory_id"
fi
@@ -330,7 +337,7 @@ fi
```bash
# Only add if search returns no results
count=$(mem0 search "dark mode" --user-id alice --agent 2>/dev/null | jq '.count // 0')
count=$(mem0 --agent search "dark mode" --user-id alice 2>/dev/null | jq '.count // 0')
if [ "$count" -eq 0 ]; then
mem0 add "User prefers dark mode" --user-id alice
fi
@@ -358,7 +365,7 @@ mem0 list
### Timeout handling
The CLI uses a 30-second timeout for all API requests. For long-running scripts, handle timeouts:
The CLI uses a 30-second timeout for normal API requests (the key-validation ping uses 5 seconds and `init` uses 5, 10 and 30 seconds). For long-running scripts, handle timeouts:
```bash
if ! mem0 search "query" --user-id alice -o json 2>/dev/null; then
@@ -382,13 +389,13 @@ Or use the event system to poll for completion:
```bash
# Add and capture event ID from agent output
result=$(mem0 add "new preference" --user-id alice --agent 2>/dev/null)
result=$(mem0 --agent add "new preference" --user-id alice 2>/dev/null)
event_id=$(echo "$result" | jq -r '.data[0].event_id // empty')
if [ -n "$event_id" ]; then
# Poll until processing completes
while true; do
status=$(mem0 event status "$event_id" --agent 2>/dev/null | jq -r '.data.status')
status=$(mem0 --agent event status "$event_id" 2>/dev/null | jq -r '.data.status')
if [ "$status" = "SUCCEEDED" ] || [ "$status" = "FAILED" ]; then
break
fi
@@ -413,16 +420,16 @@ shift 2
case "$ACTION" in
recall)
mem0 search "$*" --user-id "$USER_ID" --agent 2>/dev/null
mem0 --agent search "$*" --user-id "$USER_ID" 2>/dev/null
;;
remember)
mem0 add "$*" --user-id "$USER_ID" --agent 2>/dev/null
mem0 --agent add "$*" --user-id "$USER_ID" 2>/dev/null
;;
forget)
mem0 delete --all --user-id "$USER_ID" --force --agent 2>/dev/null
mem0 --agent delete --all --user-id "$USER_ID" --force 2>/dev/null
;;
history)
mem0 list --user-id "$USER_ID" --agent 2>/dev/null
mem0 --agent list --user-id "$USER_ID" 2>/dev/null
;;
*)
echo '{"status":"error","error":"Unknown action: '"$ACTION"'"}' >&2