---
title: "Claude Code Integration"
image: "https://recall.edheltzel.codes/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://recall.edheltzel.codes/llms.txt
> Use this file to discover all available pages before exploring further.

# Claude Code Integration

**Preferred install:** Claude Code's native plugin. It owns the nine `do-recall-*` skills and the `recall-memory` MCP server.

Claude lifecycle hooks are **not** in the plugin. Plugin hooks *merge* with `settings.json` rather than replacing them, so shipping `Stop` / `SessionStart` / `PreCompact` in the bundle would double-capture for anyone who also ran `recall install`. Auto-capture, tiered L0/L1 injection, and pre-compaction flushing stay installer-owned.

The checked-in marketplace catalog is `.claude-plugin/marketplace.json`. The plugin bundle is `hosts/plugins/recall-claude/`. Source in this repository does not mean the plugin is installed on a given machine.

## Install (preferred)

Start with the canonical [Installation guide](https://recall.edheltzel.codes/docs/installation/#install-recall). It owns the current source-checkout and local-tarball bootstrap and the warning about the unrelated npm package.

Then add this repository as a marketplace and install its plugin:

```bash
claude plugin marketplace add /absolute/path/to/Recall
claude plugin install recall@recall-marketplace
```

The local repository path is required for the current checked-in marketplace. A future remote marketplace can drop that clone prerequisite after its distribution policy is defined.

### Hooks and the installer (required for automatic capture)

Finish the selected bootstrap path in the [Installation guide](https://recall.edheltzel.codes/docs/installation/#install-recall); it specifies the matching installer command.

With the plugin active, `./packaging/install.sh`, `recall install`, and `./packaging/update.sh` keep the Claude hooks, skip duplicate skill symlinks, and reconcile the user-scope `recall-memory` MCP entry under the database-path rules below. Running only the plugin gives skills and MCP, not automatic capture.

Plugin-state detection fails closed. A missing `~/.claude/plugins/installed_plugins.json` confirms that the plugin is absent. An unreadable or invalid installed-plugin file, or an unreadable or invalid `settings.json` after an installation is detected, makes ownership unknown. In that state, install and update return an error before changing ownership-dependent skill links or MCP configuration. Restore read access or valid JSONC, then rerun the command.

## What MCP covers

MCP is the primary cross-host seam.

The plugin exposes all nine Recall operations: `memory_search`, `memory_hybrid_search`, `memory_recall`, `context_for_agent`, `memory_add`, `memory_stats`, `loa_show`, `memory_dump`, and `decision_update`.

They query and write the same SQLite store as the CLI.

The bundled `.mcp.json` carries no `env` block, so the server resolves its database from `RECALL_DB_PATH` in Claude's environment, falling back to `~/.agents/Recall/recall.db`. Export `RECALL_DB_PATH` in your shell when the store lives elsewhere.

## Migrating an existing install

An existing Recall install keeps working. It also keeps its own copies of what the plugin now ships, and Claude does **not** resolve that for you:

- **Skills.** `~/.claude/skills/do-recall-*` and the plugin's nine skills both load.
- **MCP.** Claude namespaces plugin components, so the plugin registers as `plugin:recall:recall-memory` while a user-scope `recall-memory` keeps its own name. Both connect, and the same nine tools are exposed twice from two processes.

Claude collapses the two MCP entries only when they resolve to an identical command and environment. `install.sh` writes `bun run <path>` plus an `env` block, so a real existing install always duplicates.

`install.sh` and current `update.sh` reconcile this, and both are idempotent. After installing the plugin, run:

```bash
./packaging/update.sh
```

If you are upgrading from a release that predates this reconciliation, the old updater is already loaded before it pulls the new lifecycle code. Complete that first upgrade with:

```bash
recall update
recall install
```

Run `recall install` once after that first `recall update`. Later updates reload changed lifecycle files automatically. See [Upgrading](https://recall.edheltzel.codes/docs/upgrading/#first-update-from-an-older-updater).

With the plugin active they:

1. Remove the `~/.claude/skills/do-recall-*` symlinks that point into `~/.agents/Recall/shared/skills/`. Only Recall-owned symlinks are removed; real files, user-authored skills, and other tools' links are left alone, and a skill directory is deleted only when it is already empty.
2. Reconcile the user-scope `recall-memory` MCP registration: remove it when the selected database is the default, or keep it for a non-default database the plugin cannot carry.
3. Leave hooks and canonical files untouched.

Skill canonicals under `~/.agents/Recall/shared/skills/` are still refreshed, because Pi, omp, and `recall doctor` read them.

**A registration pinned to a non-default database is kept only when no explicit database override is present.** An explicit `--db-path` or an inherited `RECALL_DB_PATH` or `MEM_DB_PATH` replaces the stored pin. If that override selects `~/.agents/Recall/recall.db`, the installer removes the user registration so the plugin serves the default database.

Without an override, re-running `update.sh` preserves the stored custom pin. A non-default override still keeps both surfaces because the plugin's bundled config cannot carry your custom path. Collapsing them is a deliberate manual step, because only you can confirm the environment Claude actually launches with:

```bash
export RECALL_DB_PATH=/path/to/your/recall.db   # where you launch Claude from
claude mcp list                                  # confirm plugin:recall:recall-memory connects
claude mcp remove recall-memory -s user          # then drop the duplicate
```

`recall doctor` reports the state under **Claude native plugin**: `PASS` when the plugin is the sole owner, `WARN` when duplicates exist or plugin ownership cannot be read or parsed, and `INFO` when the plugin is absent or disabled. `doctor --fix` does not apply ownership-dependent skill or MCP repairs while ownership is unknown.

Uninstalling is a separate, user-owned action — `uninstall.sh` does not remove the plugin:

```bash
claude plugin uninstall recall@recall-marketplace
./packaging/install.sh   # restores the lifecycle-owned skills and MCP registration
```

## What the plugin does not cover

**Lifecycle hooks are not in the bundle.** This is the one place where the plugin is deliberately not self-sufficient: a plugin-only user gets skills and MCP, not automatic capture. Installer-owned `Stop` runs `RecallExtract.ts`, which shells ambient text to `recall capture`. Without hooks, run `bun hooks/lib/hosts/claude/ambient-capture.ts` against `~/.claude/projects`. Guide: [Capture adapter](https://recall.edheltzel.codes/docs/reference/capture-adapter/).

## Differences from the Codex package

Named explicitly rather than assumed away, because identical `SKILL.md` bytes do not imply identical behavior across hosts:

| | Codex (`hosts/plugins/recall/`) | Claude (`hosts/plugins/recall-claude/`) |
| --- | --- | --- |
| Manifest | `.codex-plugin/plugin.json` | `.claude-plugin/plugin.json` |
| Marketplace | `.agents/plugins/marketplace.json` | `.claude-plugin/marketplace.json` |
| Skill payload | Generated adapters with a Codex routing preamble | Byte-verbatim copies of `agent-skills/` |
| `disable-model-invocation` | Stripped; replaced by `agents/openai.yaml` because Codex does not interpret it | Kept — it is Claude's own frontmatter contract |
| MCP naming | `recall-memory` | `plugin:recall:recall-memory` (namespaced) |
| Pre-existing install to reconcile | None — Codex had no lifecycle installer | Nine skill symlinks and a user-scope MCP entry |
| Lifecycle capture | Plugin-owned; see [Codex Integration](https://recall.edheltzel.codes/docs/integrations/codex/) | Implemented, but by the installer's hooks — not the plugin |

The Claude bundle needs no routing preamble because `agent-skills/` is already authored against Claude's frontmatter. Rewriting the bodies would change behavior relative to the skills users already have, which is the opposite of a safe migration.

Skills are copied rather than symlinked into the bundle. Claude drops symlinks that leave the plugin root when a plugin is installed from a local path, and a checkout with `core.symlinks=false` would degrade the payload silently.

## Current boundaries

The following are unresolved rather than guessed:

- **End-to-end enforcement of `disable-model-invocation` for plugin-shipped skills is unverified.** The installed CLI carries the runtime enforcement for the field, and the bundle ships it unchanged, but confirming that a plugin-loaded `do-recall-dump` is explicit-only needs an authenticated session — and `claude plugin validate --strict` does not inspect skill frontmatter at all, so passing validation is not evidence.
- Skill *invocation* names under a plugin. `claude plugin details` lists all nine by their canonical names; the namespacing observed for MCP was not separately confirmed for skills.
- Remote marketplace publication, update, and release ownership.
- The installed plugin-cache path as a durable runtime dependency.

None of these block the nine MCP operations or the skill surface.

## Maintaining the package

Maintainer-only. Not the install path.

Canonical skills live in `agent-skills/`. Regenerate the Claude payload with `bun run build:claude-plugin` (`scripts/build-claude-plugin.ts`). Do not hand-edit `hosts/plugins/recall-claude/skills/`. Skill names use `do-recall-*`.

```bash
claude plugin validate hosts/plugins/recall-claude --strict
claude plugin validate . --strict
bun test tests/plugins/claude-plugin.test.ts
bun run test:e2e:claude-plugin
```

The unit test asserts one plugin identity, byte-identical skills, and that no hooks ship in the bundle. The e2e test validates both manifests in strict mode against the current local Claude CLI into a disposable `HOME`.

Source: https://recall.edheltzel.codes/docs/integrations/claude-code/index.mdx
