---
title: "Claude Code Plugin"
description: "The Claude Code plugin integrates Mem0 memory management into the Claude Code developer agent via Model Context Protocol (MCP) server registration, transcript parsing, and host event hooks. It capt..."
last_updated: "2026-10-11T17:37:10.212608+00:00"
canonical_url: "https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/technical/agent-plugins/claude-code-plugin"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [integrations/opencode-plugin/opencode-mem0.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/opencode-plugin/opencode-mem0.ts)
- [integrations/claude-code-plugin/.mcp.json](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/.mcp.json)
- [integrations/claude-code-plugin/core/hook_runner.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/hook_runner.py)
- [integrations/claude-code-plugin/adapters/claude/transcript.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/transcript.py)
- [integrations/codex-plugin/core/hook_runner.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/codex-plugin/core/hook_runner.py)
- [integrations/antigravity-plugin/core/hook_runner.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/antigravity-plugin/core/hook_runner.py)
- [integrations/agent-plugin-core/python/hook_runner.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/agent-plugin-core/python/hook_runner.py)
- [integrations/kimi-plugin/core/hook_runner.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/kimi-plugin/core/hook_runner.py)
- [integrations/cursor-plugin/core/hook_runner.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/cursor-plugin/core/hook_runner.py)
- [integrations/claude-code-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/mcp_server.py)
- [integrations/claude-code-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py)
- [integrations/claude-code-plugin/adapters/claude/hook.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/hook.py)
- [integrations/codex-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/codex-plugin/core/mcp_server.py)
- [integrations/antigravity-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/antigravity-plugin/core/mcp_server.py)
- [integrations/codex-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/codex-plugin/core/memory_core.py)
- [integrations/antigravity-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/antigravity-plugin/core/memory_core.py)
- [integrations/agent-plugin-core/python/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/agent-plugin-core/python/memory_core.py)
- [integrations/kimi-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/kimi-plugin/core/memory_core.py)
- [integrations/kimi-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/kimi-plugin/core/mcp_server.py)
- [integrations/claude-code-plugin/core/flush_worker.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/flush_worker.py)
- [integrations/antigravity-plugin/core/flush_worker.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/antigravity-plugin/core/flush_worker.py)
- [integrations/hermes-plugin-mem0/__init__.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/hermes-plugin-mem0/__init__.py)
- [integrations/cursor-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/cursor-plugin/core/mcp_server.py)
- [integrations/kimi-plugin/core/flush_worker.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/kimi-plugin/core/flush_worker.py)
- [integrations/cursor-plugin/core/flush_worker.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/cursor-plugin/core/flush_worker.py)
- [integrations/codex-plugin/core/flush_worker.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/codex-plugin/core/flush_worker.py)
- [integrations/agent-plugin-core/python/flush_worker.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/agent-plugin-core/python/flush_worker.py)
- [integrations/mem0-agent-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/mem0-agent-plugin/core/mcp_server.py)
- [integrations/agent-plugin-core/python/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/agent-plugin-core/python/mcp_server.py)
- [integrations/antigravity-plugin/hooks/adapter.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/antigravity-plugin/hooks/adapter.py)
</details>

## Overview

The Claude Code plugin integrates Mem0 memory management into the Claude Code developer agent via Model Context Protocol (MCP) server registration, transcript parsing, and host event hooks. It captures session conversations, extracts relevant coding insights, and injects persistent repository context into agent workflows.

Sources: [integrations/claude-code-plugin/.mcp.json:1-10](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/.mcp.json#L1-L10), [integrations/claude-code-plugin/core/memory_core.py:2-7](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L2-L7), [integrations/claude-code-plugin/adapters/claude/transcript.py:1-20](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/transcript.py#L1-L20)

## MCP Server Configuration and Manifest

### Manifest Registration and Environment Configuration

The Claude Code plugin configures its local Model Context Protocol (MCP) server through a declarative manifest file, `.mcp.json`, which defines the execution environment and runtime command. The manifest registers a single server named `mem0` that executes via `python3` targeting the plugin's core script at `${CLAUDE_PLUGIN_ROOT}/core/mcp_server.py`. It injects the runtime data directory through the environment variable `MEM0_CODE_DATA_DIR`, mapped from `${CLAUDE_PLUGIN_DATA}`.

```json
{
  "mcpServers": {
    "mem0": {
      "command": "python3",
      "args": ["${CLAUDE_PLUGIN_ROOT}/core/mcp_server.py"],
      "env": {
        "MEM0_CODE_DATA_DIR": "${CLAUDE_PLUGIN_DATA}"
      }
    }
  }
}
```
Sources: [integrations/claude-code-plugin/.mcp.json:1-10](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/.mcp.json#L1-L10)

### MCP Server Protocol and Tool Definition

The local server implementation in `core/mcp_server.py` adheres to MCP protocol version `2024-11-05`, exposing the `search_memories` tool. The server handles JSON-RPC request methods including `initialize`, `ping`, `tools/list`, and `tools/call`, returning capability listings and execution responses. The exposed tool carries annotations declaring it as read-only, idempotent, and open-world.

```python
PROTOCOL_VERSION = "2024-11-05"
TOOL_NAME = "search_memories"
TOOL_DESCRIPTION = (
    "Search memories from earlier work in this repository. Use it before "
    "repeating investigation or when earlier decisions, fixes, commands, or "
    "results may help."
)
```
Sources: [integrations/claude-code-plugin/core/mcp_server.py:21-27](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/mcp_server.py#L21-L27)

```python
if method == "tools/list":
    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "result": {
            "tools": [
                {
                    "name": TOOL_NAME,
                    "description": TOOL_DESCRIPTION,
                    "inputSchema": TOOL_SCHEMA,
                    "annotations": {
                        "readOnlyHint": True,
                        "idempotentHint": True,
                        "openWorldHint": True,
                    },
                }
            ]
        },
    }
```
Sources: [integrations/claude-code-plugin/core/mcp_server.py:173-191](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/mcp_server.py#L173-L191)

The tool accepts five search parameters with explicit typing and validation rules enforced by `_validate_arguments`.

| Parameter | Type | Validation Rules | Purpose |
| :--- | :--- | :--- | :--- |
| `query` | `string` | Non-empty, max 2000 chars, required | Direct question about earlier work in the repository |
| `top_k` | `integer` | 1 to 20, non-boolean | Maximum memories to return |
| `category` | `string` | Must be in `CODING_MEMORY_CATEGORY_NAMES` | Optional memory category filter |
| `scope` | `string` | Must be in `SEARCH_SCOPES` | Memory search scope (`repo`, `dir`, `mine`) |
| `run_id` | `string` | Non-empty string when provided | Optional coding-agent session ID restriction |

Sources: [integrations/claude-code-plugin/core/mcp_server.py:28-68](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/mcp_server.py#L28-L68)

> [!WARNING]
> Boolean inputs passed to `top_k` are explicitly rejected by `_validate_arguments` even though Python treats booleans as integers; input validation requires strict integer checks between 1 and 20 to prevent malformed query parameters.
> Sources: [integrations/claude-code-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/mcp_server.py#L93-L96)

## Transcript Parsing and Ingestion

### Conversation Stream Reading and Row Parsing

The Claude Code transcript ingestion engine parses newline-delimited JSON records from conversation transcript files. The `_transcript_rows` function opens the transcript path in binary mode, seeks to an optional byte offset, and reads line by line. Each line is decoded as UTF-8 with error replacement, parsed via `json.loads`, and filtered to retain records containing a valid `uuid` field.

```python
def _transcript_rows(
    path: str, offset: int = 0
) -> tuple[list[dict[str, Any]], int, bool]:
    """Parse transcript rows from a byte offset, returning rows, end offset, and whether the offset was honored."""
    if not path:
        return [], 0, False
    rows = []
    try:
        resolved = Path(path).expanduser()
        if not 0 <= offset <= resolved.stat().st_size:
            offset = 0
        end = offset
        with resolved.open("rb") as handle:
            handle.seek(offset)
            for line in handle:
                if not line.endswith(b"\n"):
                    break
                end += len(line)
                try:
                    row = json.loads(line.decode("utf-8", errors="replace"))
                except json.JSONDecodeError:
                    continue
                if isinstance(row, dict) and row.get("uuid"):
                    rows.append(row)
    except OSError:
        return [], offset, False
    return rows, end, offset > 0

```
Sources: [integrations/claude-code-plugin/adapters/claude/transcript.py:39-66](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/transcript.py#L39-L66)

> [!WARNING]
> If a trailing line in the transcript file does not end with a newline byte (`b"\n"`), it is immediately discarded by the parser loop to prevent ingestion of partial, atomically unwritten JSON writes.
> Sources: [integrations/claude-code-plugin/adapters/claude/transcript.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/transcript.py#L53-L55)

### Active Chain Traversal and Message Extraction

The parser constructs an active conversation chain by identifying the latest leaf record matching the target `session_id` while ignoring sidechain records where `isSidechain` is true. Starting from this leaf node, it traverses backward through parent records using `parentUuid` references, collecting nodes into a sequence and reversing them into chronological order.

```python
def _active_transcript_chain(
    rows: list[dict[str, Any]], session_id: str
) -> list[dict[str, Any]]:
    """Follow the current Claude conversation branch from its latest record."""
    by_uuid = {str(row["uuid"]): row for row in rows if row.get("uuid")}
    leaf = next(
        (
            row
            for row in reversed(rows)
            if not row.get("isSidechain")
            and str(row.get("sessionId") or "") == session_id
        ),
        None,
    )
    if leaf is None:
        return []

    chain = []
    seen = set()
    current = leaf
    while current is not None:
        uuid = str(current.get("uuid") or "")
        if not uuid or uuid in seen:
            break
        seen.add(uuid)
        chain.append(current)
        current = by_uuid.get(str(current.get("parentUuid") or ""))
    chain.reverse()
    return chain
```
Sources: [integrations/claude-code-plugin/adapters/claude/transcript.py:68-96](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/transcript.py#L68-L96)

User prompts and subagent interactions undergo redaction and prefix filtering before memory extraction. Human prompt text filtering strips attachment markers and ignores specific system or command prefixes.

| Ignored Prompt Prefix | Purpose |
| :--- | :--- |
| `<local-command-caveat>` | Suppresses local shell execution warnings |
| `<local-command-stdout>` | Suppresses raw stdout captures from tool runs |
| `<local-command-stderr>` | Suppresses raw stderr captures from tool runs |
| `<command-name>` | Suppresses internal command execution markers |
| `<system-reminder>` | Suppresses injected system reminders |
| `<task-notification>` | Suppresses asynchronous task notification banners |

Sources: [integrations/claude-code-plugin/adapters/claude/transcript.py:112-120](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/transcript.py#L112-L120)

## Claude Hook Dispatching and Lifecycle

### Environment Setup and Syspath Bootstrap

The Claude Code hook adapter initializes the execution environment by configuring Python's module search path (`sys.path`). It resolves the directory containing `hook_runner.py` by inspecting the script location and falling back between bundled core directories.

```python

_here = Path(__file__).resolve()
_bundled_core = _here.parents[2] / "core"
_core_dir = _bundled_core if (_bundled_core / "memory_core.py").is_file() else _bundled_core / "python"
sys.path.insert(0, str(_core_dir))
sys.path.insert(0, str(_here.parent))

```
Sources: [integrations/claude-code-plugin/adapters/claude/hook.py:8-14](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/hook.py#L8-L14)

Once the path is resolved, the adapter registers the harness with the memory core and telemetry subsystems using the identifier `claude-code`.

```python
configure_harness("claude-code", data_dir_name="claude-code-plugin", source_tag="claude_code_plugin")
telemetry.init(harness="claude-code", source_tag="CLAUDE_CODE_PLUGIN")
```
Sources: [integrations/claude-code-plugin/adapters/claude/hook.py:25-26](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/hook.py#L25-L26)

### Sidekick Subagent Actions

The Claude hook adapter defines specialized handlers for sidekick subagent lifecycle events. The `_sidekick_start` handler records the start of a subagent with the agent type `mem0:sidekick` and injects any returned context back into the agent runtime via structured hook output.

```python
def _sidekick_start(store, hook_input):
    context = record_subagent_start(store, {"agent_type": "mem0:sidekick", **hook_input})
    if context:
        return {
            "hookSpecificOutput": {
                "hookEventName": "SubagentStart",
                "additionalContext": context,
            },
        }

```
Sources: [integrations/claude-code-plugin/adapters/claude/hook.py:29-38](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/hook.py#L29-L38)

Conversely, `_sidekick_stop` records the conclusion of the sidekick subagent session without returning specialized hook output.

```python
def _sidekick_stop(store, hook_input):
    record_subagent_stop(store, {"agent_type": "mem0:sidekick", **hook_input})
```
Sources: [integrations/claude-code-plugin/adapters/claude/hook.py:40-41](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/hook.py#L40-L41)

### Hook Entry Point Mapping

When invoked as the main script, the adapter delegates execution to `hook_runner.entry_point`, passing custom action bindings and configuration parameters.

| Parameter | Value | Purpose |
| :--- | :--- | :--- |
| `record_stop_fn` | `record_stop` | Transcript parsing function imported from `transcript.py` |
| `extra_actions["post-tool-failure"]` | `lambda s, h: record_tool(s, h, failed=True)` | Records tool execution failures |
| `extra_actions["sidekick-start"]` | `_sidekick_start` | Initializes sidekick subagent session |
| `extra_actions["sidekick-stop"]` | `_sidekick_stop` | Concludes sidekick subagent session |
| `data_dir_env` | `"MEM0_CODE_DATA_DIR"` | Environment variable override for data directory storage |
| `automatic_flush_reasons` | `{"session-end", "pre-compact"}` | Triggers automatic asynchronous flush workers |

Sources: [integrations/claude-code-plugin/adapters/claude/hook.py:44-54](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/hook.py#L44-L54)

> [!NOTE]
> Automatic checkpoint flushing is restricted to explicit lifecycle milestones (`session-end` and `pre-compact`) to prevent unnecessary background worker spawn overhead during incremental tool executions.
> Sources: [integrations/claude-code-plugin/adapters/claude/hook.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/adapters/claude/hook.py#L53-L53)

## Core Memory Management and State

### Harness Configuration and Constants

The shared memory core initializes runtime metadata via `configure_harness()`, establishing default identifiers and environment variables across execution harnesses.

```python
DEFAULT_API_URL = "https://api.mem0.ai"
PLUGIN_VERSION = "0.3.3"

_harness_name: str = "generic"
_harness_env_prefix: str = "MEM0_PLUGIN"
_harness_data_dir_name: str = "mem0-plugin"
_harness_source_tag: str = "mem0_plugin"

```
Sources: [integrations/claude-code-plugin/core/memory_core.py:31-38](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L31-L38)

```python
def configure_harness(
    name: str,
    env_prefix: str = "",
    data_dir_name: str = "",
    source_tag: str = "",
) -> None:
    global _harness_name, _harness_env_prefix, _harness_data_dir_name, _harness_source_tag
    _harness_name = name
    _harness_env_prefix = env_prefix or f"MEM0_{name.upper().replace('-', '_')}"
    _harness_data_dir_name = data_dir_name or f"{name}-plugin"
    _harness_source_tag = source_tag or f"{name.replace('-', '_')}_plugin"

```
Sources: [integrations/claude-code-plugin/core/memory_core.py:40-51](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L40-L51)

Memory persistence and extraction operations adhere to explicit character, exchange, and retry limits defined at the module level.

| Constant Name | Value | Purpose |
| :--- | :--- | :--- |
| `MAX_COMMAND_CHARS` | `2000` | Maximum character length for captured command strings |
| `MAX_RESULT_CHARS` | `2500` | Maximum character length for command execution results |
| `MAX_EPISODE_CHARS` | `12000` | Maximum character length for accumulated episode payloads |
| `CHECKPOINT_EXCHANGES` | `5` | Exchange count threshold for checkpoint triggers |
| `CHECKPOINT_MESSAGES` | `10` | Message count threshold for checkpoint triggers |
| `CHECKPOINT_SOURCE_CHARS` | `40000` | Maximum source text size for checkpoint extraction |
| `DEFAULT_MAX_CONTEXT_CHARS` | `4000` | Default character budget for injected memory context |
| `MAX_EXTRACTION_INPUT_TOKENS` | `24000` | Token limit for LLM memory extraction inputs |
| `MAX_FLUSH_ATTEMPTS` | `5` | Maximum retry attempts for asynchronous flush workers |
| `FORGET_PAGE_SIZE` | `100` | Pagination size for memory deletion operations |
| `FORGET_MAX_PAGES` | `50` | Maximum pagination depth for memory deletion |

Sources: [integrations/claude-code-plugin/core/memory_core.py:62-72](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L62-L72)

> [!NOTE]
> The harness configuration exposes `harness_config()`, which returns a dictionary containing the active plugin name, environment prefix, data directory name, and source tracking tag used by downstream storage and telemetry components.
> Sources: [integrations/claude-code-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L53-L59)

### Memory Instructions and Categorization

Project memory extraction relies on strict prompt instructions that guide the agent to save concise repository facts regarding behavior, implementation locations, constraints, and reasoning.

```python
PROJECT_MEMORY_INSTRUCTIONS = """Save concise repository facts that will help with future coding work.

A completed change should produce one memory explaining the resulting behavior, where it is implemented when useful, and any important constraints or reasoning. Exploration or accepted decisions may produce separate memories only when they are independently useful.

Use the coding agent's final response for conclusions about current repository behavior. Do not save proposed or recommended changes unless the user accepted them or the coding agent completed them. Treat subagent responses as supporting repository evidence, not as decisions.

Write about the repository, not the user, assistant, session, or task. Do not include test results, documentation updates, release notes, or temporary state.

If nothing useful was established, return no memories."""
```
Sources: [integrations/claude-code-plugin/core/memory_core.py:74-82](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L74-L82)

Personal memory extraction uses distinct instructions focused on user preferences, written in the third person.

```python
PERSONAL_MEMORY_INSTRUCTIONS = """Save concise facts about the user that will help in any repository: preferred tools, package managers, languages, coding style, review and communication preferences, and anything the user explicitly asked to be remembered about themselves.

Write in the third person about the user, not about the repository, the assistant, the session, or the task. Do not save repository facts, project decisions, commands, or what was built.

Never save that the user has no preferences or that nothing was learned. If nothing was learned about the user, return no memories."""
```
Sources: [integrations/claude-code-plugin/core/memory_core.py:84-88](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L84-L88)

Coding memories are classified into explicit structural categories to organize project knowledge.

| Category Identifier | Description |
| :--- | :--- |
| `project_knowledge` | What the project is and how its code, APIs, data, files, and components work. |
| `decisions_and_constraints` | Why an approach was chosen, what must remain true, and rules future work must follow. |
| `workflows` | How to run, test, debug, deploy, configure, or otherwise work on the project. |
| `problems_and_fixes` | Bugs, failures, known pitfalls, their causes, and how to fix or avoid them. |
| `results` | Outcomes and measurements from tests, benchmarks, experiments, or investigations. |

Sources: [integrations/claude-code-plugin/core/memory_core.py:90-121](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L90-L121)

> [!WARNING]
> `CODING_MEMORY_CATEGORY_NAMES` is programmatically derived as a tuple of keys from `CODING_MEMORY_CATEGORIES`. Modifying the dictionary structure directly impacts category validation downstream.
> Sources: [integrations/claude-code-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L122-L126)

### Sanitization and Security Redaction

Command matching rules detect test and build invocations using regular expressions across multiple testing frameworks and build tools.

```python
TEST_COMMAND_RE = re.compile(
    r"(?:^|\s)(?:pytest|py\.test|jest|vitest|go\s+test|cargo\s+test|"
    r"npm\s+(?:run\s+)?test|pnpm\s+(?:run\s+)?test|yarn\s+test|"
    r"mvn\s+test|gradle\s+test|make\s+test)(?:\s|$)",
    re.IGNORECASE,
)
BUILD_COMMAND_RE = re.compile(
    r"(?:^|\s)(?:npm|pnpm|yarn)\s+(?:run\s+)?build(?:\s|$)|"
    r"(?:^|\s)(?:cargo|go|mvn|gradle|make)\s+build(?:\s|$)",
    re.IGNORECASE,
)
```
Sources: [integrations/claude-code-plugin/core/memory_core.py:128-138](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L128-L138)

To prevent credential leakage, the memory core scans strings and serialized payloads against a comprehensive list of secret patterns, replacing matched secrets with `[REDACTED]`.

```python
SECRET_PATTERNS = [
    re.compile(r"(?i)(authorization\s*[:=]\s*(?:bearer|token)\s+)[^\s\"']+"),
    re.compile(
        r"(?i)((?:api[_-]?key|secret[_-]?access[_-]?key|session[_-]?token)\s*[:=]\s*)[^\s\"']+"
    ),
    re.compile(
        r"(?i)((?:access[_-]?token|refresh[_-]?token|password|credential)"
        r"\s*[:=]\s*)[^\s&\"']+"
    ),
    re.compile(r"\b(?:sk|m0|mem0_sk|psk)-[A-Za-z0-9_\-]{12,}\b"),
    re.compile(r"\b(?:ASIA|AKIA)[A-Z0-9]{12,}\b"),
    re.compile(r"\b(?:ghp_|github_pat_|xox[baprs]-)[A-Za-z0-9_\-]{12,}\b"),
    re.compile(
        r"-----BEGIN [^-]*PRIVATE KEY-----.*?-----END [^-]*PRIVATE KEY-----",
        re.DOTALL,
    ),
    re.compile(
        r'(?i)("(?:api[_-]?key|password|secret(?:[_-]?access[_-]?key)?'
        r'|(?:access|refresh|session)[_-]?token|token|authorization|credential'
        r')"\s*:\s*")(?:\\.|[^"\\])*'
    ),
]
```
Sources: [integrations/claude-code-plugin/core/memory_core.py:140-161](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L140-L161)

The utility function `redact()` processes arbitrary input values, serializing non-string types via JSON and applying all defined secret regular expression patterns sequentially.

```python
def redact(value: Any) -> str:
    text = (
        value
        if isinstance(value, str)
        else json.dumps(value, ensure_ascii=False, default=str)
    )
    for pattern in SECRET_PATTERNS:
        if pattern.groups:
            text = pattern.sub(r"\1[REDACTED]", text)
        else:
            text = pattern.sub("[REDACTED]", text)
    return text
```
Sources: [integrations/claude-code-plugin/core/memory_core.py:168-179](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L168-L179)

Furthermore, `bounded()` enforces strict character length constraints on redacted text, appending truncation notices when size limits are exceeded.

```python
def bounded(value: Any, limit: int) -> str:
    text = redact(value).strip()
    if len(text) <= limit:
        return text
    return text[:limit] + f"\n...[truncated {len(text) - limit} chars]"

```
Sources: [integrations/claude-code-plugin/core/memory_core.py:182-187](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py#L182-L187)

## Asynchronous Remote Checkpoint Flushing

### Detached Worker Initialization and Handoff

When session end hooks in print-mode processes risk being terminated prematurely, the hook runner persists its state locally and delegates processing to a detached background worker. The worker entry point expects a single argument representing the path to the handoff JSON payload. It configures the runtime environment and telemetry using environment variables such as `MEM0_PLUGIN_HARNESS`, `MEM0_PLUGIN_SOURCE_TAG`, and `MEM0_PLUGIN_ENV_PREFIX`.

```python
def main() -> int:
    if len(sys.argv) != 2:
        return 2
    handoff_path = Path(sys.argv[1])
    os.environ["MEM0_CODE_HANDOFF_PATH"] = str(handoff_path)
    harness = os.environ.get("MEM0_PLUGIN_HARNESS")
    if harness:
        source_tag = os.environ.get("MEM0_PLUGIN_SOURCE_TAG", "")
        configure_harness(
            harness,
            env_prefix=os.environ.get("MEM0_PLUGIN_ENV_PREFIX", ""),
            data_dir_name=os.environ.get("MEM0_PLUGIN_DATA_DIR_NAME", ""),
            source_tag=source_tag,
        )
        telemetry.init(harness=harness, source_tag=source_tag.upper())
```
Sources: [integrations/claude-code-plugin/core/flush_worker.py:25-39](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/flush_worker.py#L25-L39)

Payloads can specify a delay before execution occurs. If `delay_seconds` is greater than zero, the worker writes the configuration to a temporary process-specific file, replaces the original handoff path, and sleeps for the designated duration.

```python
try:
    payload = json.loads(handoff_path.read_text(encoding="utf-8"))
    delay = float(payload.get("delay_seconds") or 0)
    if delay > 0:
        payload.pop("delay_seconds", None)
        temporary = handoff_path.with_suffix(f".{os.getpid()}.tmp")
        try:
            temporary.write_text(json.dumps(payload), encoding="utf-8")
            temporary.replace(handoff_path)
        finally:
            temporary.unlink(missing_ok=True)
        time.sleep(delay)
        if not handoff_path.exists():
            return 0
```
Sources: [integrations/claude-code-plugin/core/flush_worker.py:41-54](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/flush_worker.py#L41-L54)

> [!NOTE]
> If the handoff file is removed during the delay interval, the worker terminates immediately with a status code of `0`.
> Sources: [integrations/claude-code-plugin/core/flush_worker.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/flush_worker.py#L52-L54)

### In-Flight Concurrency and Checkpoint Execution

When `wait_for_inflight` is enabled in the payload, the worker tracks active session operations prior to executing the checkpoint session. It computes a deadline using `MEM0_CODE_EXTRACTION_WAIT_SECONDS` (defaulting to 120 seconds) and periodically touches the handoff heartbeat while waiting for active flushes to clear.

```python
if wait_for_inflight:
    session_id = str(
        hook_input.get("session_id") or "unknown-session"
    )
    repo = store.repo_for_session(session_id, hook_input.get("cwd"))
    deadline = time.monotonic() + float(
        os.environ.get("MEM0_CODE_EXTRACTION_WAIT_SECONDS", "120")
    )
    while (
        store.has_inflight_flush(repo.identity, session_id)
        and time.monotonic() < deadline
    ):
        touch_handoff_heartbeat()
        time.sleep(0.25)
```
Sources: [integrations/claude-code-plugin/core/flush_worker.py:60-73](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/flush_worker.py#L60-L73)

Once conditions are satisfied, the worker invokes `checkpoint_session()` with the `EvidenceStore`, hook inputs, and reason string. Completion status is evaluated against a fixed set of recognized terminal states.

```python
# Hooks capture the conversation before handoff; the worker only flushes it.
result = checkpoint_session(store, hook_input, reason)
print(json.dumps(result, sort_keys=True), flush=True)
completed = result.get("status") in {
    "semantic-succeeded",
    "explicitly-stored",
    "nothing-to-flush",
}
```
Sources: [integrations/claude-code-plugin/core/flush_worker.py:74-81](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/flush_worker.py#L74-L81)

| Status Identifier | Meaning |
| :--- | :--- |
| `semantic-succeeded` | Memory extraction and remote persistence completed successfully. |
| `explicitly-stored` | Checkpoint data was stored directly without additional semantic parsing. |
| `nothing-to-flush` | No new conversation evidence accumulated since the previous checkpoint. |

Sources: [integrations/claude-code-plugin/core/flush_worker.py:77-81](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/flush_worker.py#L77-L81)

### Cleanup and File State Management

Upon completion of the flush cycle, telemetry data is flushed, and handoff files are managed based on success metrics. Successfully completed checkpoints unlink the handoff file, whereas interrupted running states revert their file suffix for future recovery.

```python
finally:
    telemetry.flush()
    if completed:
        try:
            handoff_path.unlink()
        except OSError:
            pass
    elif handoff_path.suffix == ".running":
        try:
            handoff_path.replace(handoff_path.with_suffix(".json"))
        except OSError:
            pass
```
Sources: [integrations/claude-code-plugin/core/flush_worker.py:85-96](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/flush_worker.py#L85-L96)

## Related

- [Python Agent Core](https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/technical/agent-plugins/python-agent-core)
- [IDE Plugins Family](https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/technical/agent-plugins/ide-plugins-family)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/llms.txt) for all pages in this wiki.
