---
name: everme-install
description: One-shot EverMe install or upgrade for any AI Agent — registers a new EverMe account (or logs in an existing one), upgrades EverCli and connected plugins, installs missing EverMe integrations for locally detected agents, and optionally imports cold-start memory.
version: 2
keywords: [everme, evercli, install, mcp, claude-code, claude-desktop, openclaw, cursor, codex, hermes, devin, opencode, kimicode, manus, hosted-mcp, memory, onboarding]
audience: ai-agent
---

# EverMe Install — Agent Skill

This document is the canonical install contract for any AI Agent (Claude Code, Claude Desktop, OpenClaw, Cursor, Codex, Hermes, Devin, opencode, Kimi Code, …) that helps a user connect their machine to EverMe.

> **Claude Code ≠ Claude Desktop.** Two different Anthropic products with **separate config directories** (`~/.claude/` vs `~/Library/Application Support/Claude/`), different plugin formats, and different install paths in this document.
> - **Claude Code** is the CLI (`claude` command). It loads native Claude Code plugins via `claude plugin install`. EverMe's path: `evercli plugin install claude-code` (§3.2).
> - **Claude Desktop** is the macOS/Windows desktop app from claude.ai/download. It loads stdio MCP servers via `claude_desktop_config.json` — it does **not** understand Claude Code plugins. EverMe's path: `evercli plugin install claude-desktop` (§3.4.1).
>
> If a user mentions "Claude" without qualifying which, ask which one — the install path is different.

**Goal:** complete the install end-to-end with **at most one browser click** from the user.

**What this skill is.** The install/upgrade + verify contract: EverCli upgrade,
account login (Device Flow or API key), plugin refresh or `evercli plugin
install` per host, optional cold-start memory import, `evercli doctor`
verification, restart handoff. Everything needed to get one machine connected
end-to-end.

**What this skill is NOT.** Not the runtime API reference, not the data-model spec, not the in-session troubleshooting guide. If you need:

- evercli command details beyond install → `evercli <subcommand> --help`
- error semantics during a live agent session → the plugin's logs and the backend, not this doc

Read every section before executing. Pick the right branch (new user or existing user) based solely on whether the user's message contains an `emk_*` API key — that decides the **login method only**. Both branches then flow through §3 (install plugins) and §4 (historical import) identically; §4 is offered unconditionally to every user and is never gated by branch.

---

## 0 · When to use this skill

Trigger when the user pastes any of:

- A message containing `https://everme.evermind.ai/SKILL.md` (the prompt copied from the official "Install via AI Agent" tab).
- "Install EverMe" / "帮我安装 EverMe" / "set up EverMe on this machine".
- "Upgrade EverMe" / "Update EverMe" / "升级 EverMe" / "更新 EverMe".
- The message includes an EverMe API key (`emk_` followed by 32 hex chars).
- A browser recovery message saying the EverMe authorization link expired or
  asking the Agent to start a new authorization flow.

**Device Flow recovery shortcut.** If the user sends the localized browser
recovery message (for example, `EverMe 授权链接已过期，请重新发起授权并把新的授权链接发给我。`), do not repeat CLI installation, plugin installation, or memory scanning. Discard the old `deviceCode`, run §2A.1 immediately, and send the new `verificationUrl` using §2A.2. Never ask the user to refresh the expired page.

**Legacy compatibility note — "data import instruction" trigger.** The web
dashboard's dedicated **Data Import** button has been removed; the standard
install prompt above is now the **only** web entry point into this skill. If
a user still pastes the sentence "follow the data import instruction" (e.g.
from an old bookmark or screenshot), do not treat it as a separate branch —
pick §2A or §2B below exactly as for any other message, ensure §1–§3 are
satisfied (idempotent — re-running is safe), then go straight to §4, which is
identical to what every other user gets.

**Hosted-agent exception (check before anything else):** if the user is asking to connect **Manus** (or any cloud-hosted agent with no local config on this machine), none of the local install steps below apply — there is no `evercli` path for it. Answer with the web link instead; see §3.5.

**Branch selection (do this first, silently) — `emk_` decides login only:**

| Signal in user message | Branch |
|---|---|
| Contains `emk_[a-f0-9]{32}` | **B · Existing user** — API-key login (§2B), skip Device Flow |
| No API key | **A · New user** — Device Flow (§2A) |

Both branches converge immediately after login: §3 (install plugins) and §4
(historical import) run **identically** for A and B. §4 is not optional and
not branch-gated — every user gets the same unconditional scan (§4.1), the
same idempotent skip-already-submitted behavior, and the same
single-consent two-pass upload flow (§4.3) whenever new sessions exist.

In both branches:

- Always pass `--format json` to every `evercli` command.
- Always parse the JSON envelope (`{ok, data, error?, meta?}`) before deciding the next step.
- Never invent flags. Only the flags listed in this doc exist.

### 0.1 · Response language

Choose `responseLanguage` before sending the first progress update:

1. An explicit language request wins.
2. Otherwise, if the user's latest natural-language request contains Chinese,
   use `zh-CN`.
3. Otherwise, use English.

Use `responseLanguage` for every agent-authored progress update, explanation,
warning, confirmation request, action heading, error summary, and final
handoff. If the user changes language, switch from the next message onward.

Commands, file paths, JSON keys, status values (`queued`, `extracted`, ...),
error types, IDs, and tokens stay literal. Parse CLI JSON internally and
summarize it in `responseLanguage`; do not paste a long English CLI transcript
to a Chinese user unless they explicitly ask for raw output.

Where a section shows a `zh-CN` template followed by an English one, the
`zh-CN` block is listed first only for convenience — the order is not a
preference. Use the block matching `responseLanguage`.

### 0.2 · User action message contract

The original "install EverMe" request authorizes ordinary package installation
and idempotent EverMe config writes. Do not interrupt the flow with redundant
yes/no questions. A separate user action is required only for:

- browser authorization;
- uploading historical data;
- privilege elevation such as `sudo`;
- replacing or rebinding an EverMe entry owned by another account;
- connecting a newly detected agent that has never been connected, on a machine
  that already carries EverMe wiring — see the `machineAlreadyConnected`
  definition in §3.1, which deliberately counts a local entry left by any
  account, not only the current one (§3.1.1);
- host-owned manual registration or approval steps;
- restarting the host so the plugin loads.

Whenever user action is required, present exactly one action block in this
order:

1. what has completed and what is happening now;
2. why the action is required;
3. what it changes or exposes;
4. what continues after completion;
5. a visually distinct final heading: `### ⚠️ 需要你操作` for `zh-CN`, or
   `### ⚠️ Action required` for English;
6. one concrete action line beginning with `👉` at the very end.

Do not put a link, command, yes/no question, or reply keyword before its
explanation. Do not add any explanation after the final action line. Prefer
semantic reply labels (`确认导入` / `跳过`, `Import` / `Skip`) over ambiguous
`yes` / `no`.

---

## 1 · Install or upgrade EverCli (all branches)

Prerequisite: Node.js ≥ 18 (used by the npm wrapper to download and verify the platform-native binary on first install). Most developer machines already have it; if not, install from <https://nodejs.org>.

Always run this step, including when `evercli` is already present. This is the
upgrade path for returning users as well as the install path for a new machine.

Send one localized progress update before running the command. Example:

- `zh-CN`: `正在安装或升级 EverCli。npm 会获取并校验最新的原生二进制文件，并尽力刷新这台机器上已经接入 EverMe 的插件。`
- English: `Installing or upgrading EverCli. npm will fetch and verify the latest native binary and best-effort refresh EverMe plugins already connected on this machine.`

```bash
npm i -g @everme/cli@latest
```

The npm wrapper auto-detects OS/arch (Darwin/Linux/Windows × amd64/arm64), downloads the matching pre-built binary from GitHub Releases, verifies SHA-256, and exposes it as the `evercli` command.

Its `postinstall` also enumerates local agent hosts and best-effort refreshes
supported plugins that already have an EverMe entry. Re-running the command is
configuration-idempotent, but some host refreshes rotate that platform's local
Agent token; the host restart in §6 is therefore required.

Do **not** claim that every installed plugin was upgraded merely because npm
exited successfully. Plugin refresh is deliberately non-fatal: a host failure
prints a warning and the CLI upgrade continues. Capture and report lines such
as `Skipping plugin refresh`, `Could not enumerate plugin hosts`, or
`<platform>: refresh failed`. Known boundaries:

- DSH refresh runs only when the host is installed, its EverMe-managed entry
  is intact, and `plugin list` resolves a `registeredAgent` under the current
  account. Stale files or another account's local entry are skipped; §3 then
  handles first install or confirmed rebind after login.
- Kimi Code can stage the latest bundle automatically, but loading it still
  requires the host-owned TUI step in §3.2.
- Cursor, Claude Desktop, Codex and opencode may only pin an `npx` package to
  `@latest`; the new payload is loaded after the §6 restart.
- A root, `sudo`, CI, or `EVERME_SKIP_PLUGIN_UPGRADE` install skips plugin
  refresh. Do not use `sudo` merely to make refresh run.

**Possible install hiccups:**

- `EBADPLATFORM` — your OS/arch isn't pre-built. Bail and tell the user.
- `EACCES` on `npm install -g` — do not run `sudo` automatically. Prefer a
  user-owned npm prefix (`npm config set prefix ~/.npm-global`, then add
  `~/.npm-global/bin` to `PATH`). If the user prefers system-wide installation,
  explain that `sudo` grants administrator privileges and ask explicitly using
  the §0.2 action-message contract; place `sudo npm i -g @everme/cli@latest` as
  the final action line only after they approve.
- Behind a firewall — set `https_proxy` env var before `npm i`.

**Verify:**

```bash
evercli --version
```

Expected output (version reflects whatever is currently published on the
`@latest` dist-tag):

```
evercli <version>          # e.g. 0.1.1
  commit:   <short-sha>
  built:    <ISO-8601 timestamp>
  go:       go1.25.x
  platform: darwin/arm64
```

If the binary is not on `PATH`, ask the user to open a new shell. Do not retry the install silently.

---

## 2A · New user — Device Flow

Use this branch when the user message contains **no** `emk_*` key.

### 2A.1 · Start the Device Flow

```bash
evercli auth login --no-wait --format json
```

Expected success envelope:

```json
{
  "ok": true,
  "data": {
    "status": "pending",
    "userCode": "ABCD-EFGH",
    "verificationUrl": "https://everme.evermind.ai/cli-auth?userCode=ABCD-EFGH",
    "expiresInSec": 3600,
    "deviceCode": "dc_xxxxxxxxxxxx",
    "resumeCommand": "evercli auth login --device-code dc_xxxxxxxxxxxx --format json"
  }
}
```

Capture `data.deviceCode` — you need it in step 2A.3.

### 2A.2 · Hand off to the browser

Use the template matching `responseLanguage`. Preserve the structure and fold
the reply instruction into the same final action line — per §0.2 the action
block ends with exactly one action line.

`zh-CN`:

> EverCli 已准备完成，接下来需要把这台机器关联到你的 EverMe 账号。
> 此授权只连接当前 EverCli，不会上传历史会话；链接有效期为 1 小时。
> 授权完成后，我会继续安装本机 Agent 插件并扫描可导入的本地记忆。
>
> ### ⚠️ 需要你操作
> 👉 打开授权页面 **{data.verificationUrl}**，完成后回复「**好了**」。

English:

> EverCli is ready. The next step links this machine to your EverMe account.
> This authorization connects only the current EverCli and does not upload
> historical sessions. The link is valid for one hour. After authorization, I
> will install the local Agent plugins and scan for importable memory.
>
> ### ⚠️ Action required
> 👉 Open the authorization page **{data.verificationUrl}**, then reply **Done**.

Do **not** poll the device-code endpoint in a loop. Wait for the user to reply.

The code expires in 1 hour. If the user takes longer, the next poll will return `status: expired` — restart from 2A.1.

### 2A.3 · Resume after authorization

When the user confirms (for example `Done`, `好了`, or an equivalent response):

```bash
evercli auth login --device-code <dc_xxxxxxxxxxxx> --format json
```

Possible outcomes:

| `data.status` | Meaning | Next step |
|---|---|---|
| `approved` | Login complete. `apiKey` is now in the OS keychain. | Continue to §3 |
| `pending` | User hasn't authorized yet | Wait, ask user to retry the browser step, then re-run this command |
| `denied` | User clicked "Deny" | Acknowledge, restart from 2A.1 if they changed their mind |
| `expired` | 1-hour window elapsed | Discard the old `deviceCode`, immediately run §2A.1, and send the new §2A.2 link |

On `approved`, expected fields: `accountId`, `email`, `apiKeyPrefix` (e.g. `emk_a1b2`), `isNewKey: true`, `scopes`.

If the browser says authorization was already completed, treat it as the
user's §2A.3 confirmation and poll the saved `deviceCode` once. If the CLI says
the authorization was already consumed, verify with
`evercli auth me --format json`; when that succeeds, continue to §3 instead of
starting another Device Flow.

Report the result in `responseLanguage`: login succeeded for **{data.email}**,
the visible API-key prefix is `{data.apiKeyPrefix}`, and the full key is stored
in the OS keychain.

---

## 2B · Existing user — API-key login

Use this branch when the user message contains an `emk_*` key.

```bash
evercli auth login --api-key emk_xxxxxxxxxxxx --format json
```

Expected success envelope:

```json
{
  "ok": true,
  "data": {
    "status": "approved",
    "accountId": "...",
    "email": "user@example.com",
    "apiKeyPrefix": "emk_a1b2",
    "isNewKey": false,
    "scopes": ["mem:read", "mem:write", "mem:search", "plugin:manage"]
  }
}
```

On `ok: false` with `error.type: "auth"`, the key is invalid or revoked. Ask the user to double-check the value (no retries — the message could be a typo).

Report the result in `responseLanguage`: welcome back **{data.email}**; the API
key was validated and saved to the OS keychain.

---

## 3 · Scan local agents and install plugins (all branches)

The CLI's `plugin install` writes the per-agent config each platform expects. How the *plugin source* itself reaches the user's machine differs per platform — important for provenance, audit, and corporate-firewall allowlisting:

| Platform | Registry / channel | When fetched | evercli's role |
|---|---|---|---|
| `@everme/memory-mcp` (Claude Code, OpenClaw) | **npm** via `npx -y` | On-demand at agent startup (no global install) | Writes the `npx` invocation into the host's MCP config |
| `@everme/claude-code` | **npm** via `npm install -g` (then `claude plugin marketplace add <local path>`) | First time `evercli plugin install claude-code` runs | Triggers the global npm install, then `claude plugin install` |
| `@everme/openclaw` | **clawhub** — OpenClaw's own registry / proxy (resolves as `clawhub:@everme/openclaw`), **not** the public npm registry | When the user runs `openclaw plugins install @everme/openclaw` (manual step — see §3.2) | Writes `~/.openclaw/openclaw.json` and registers the agent; does **not** fetch the package itself |
| `@everme/memory-mcp` (Cursor, Claude Desktop, Codex, Devin, opencode) | **npm** via `npx -y` | On-demand at agent startup | `evercli plugin install <host>` writes the MCP entry + mints/rotates the `agentId` / `agentToken` automatically; **no manual paste**. Codex also gets the EverMe marketplace + skill via the same command. opencode uses its own `mcp` JSON shape (`~/.config/opencode/opencode.json`). |
| `@everme/cursor` / `@everme/devin` hook packages (Cursor, Devin) | **npm** via `npx -y` | On-demand when the host fires a hook | `evercli plugin install <host>` registers the hook commands in the host's `hooks.json`; the packages auto-capture transcripts turn-by-turn (see the per-host notes in 3.4) |
| EverMe Hermes provider (Hermes) | **embedded in evercli** (no npm / no pip) | Written to disk at install; loaded by Hermes at startup | `evercli plugin install hermes` writes the native `MemoryProvider` into `~/.hermes/plugins/everme/`, drops creds in `~/.hermes/everme.env` (`0600`), sets `memory.provider: everme`, and removes any legacy `mcp_servers.everme`. Hook-driven auto capture/recall — **not** model-initiated tool calls. |
| `@everme/kimicode` bundle (Kimi Code) | **npm** — bundle staged by evercli to `~/.kimi-code/everme/`; `@everme/memory-mcp` via `npx -y` for the MCP server | Bundle staged when `evercli plugin install kimicode` runs; MCP server fetched on-demand at agent startup | `evercli plugin install kimicode` stages the bundle to `~/.kimi-code/everme/` + writes `~/.kimi-code/everme.env`; it does **not** register the plugin. The user runs `/plugins install ~/.kimi-code/everme` in the Kimi Code TUI to register (no headless install). |

If the user's machine is behind a firewall, all three channels need outbound HTTPS — npm to `registry.npmjs.org`, clawhub to OpenClaw's hub host. Allowlist accordingly.

### 3.1 · Detect installed agents

```bash
evercli plugin list --format json
```

Expected envelope:

```json
{
  "ok": true,
  "data": {
    "platforms": [
      {
        "platform": "claude-code",
        "displayName": "Claude Code",
        "installed": true,
        "configPath": "/Users/.../.claude/everme.env",
        "hasEverMeEntry": false
      },
      {
        "platform": "codex",
        "displayName": "Codex",
        "installed": true,
        "configPath": "/Users/.../.codex/everme.env",
        "hasEverMeEntry": true,
        "registeredAgent": {
          "id": "agt_...",
          "tokenPrefix": "evt_a1b2",
          "connectionStatus": "connected",
          "localTokenState": "match"
        }
      },
      {
        "platform": "openclaw",
        "displayName": "OpenClaw",
        "installed": false,
        "hasEverMeEntry": false
      }
    ]
  }
}
```

**Absent is the normal shape here.** `configPath`, `registeredAgent`,
`detectError` and `cloudLookupFailed` are all omitted when empty rather than
sent as `""`, `null` or `false`, so test for presence. `platform`,
`displayName`, `installed` and `hasEverMeEntry` are always present. Read every
`registeredAgent == null` / `!= null` condition below as "absent or null" /
"present"; this document writes them that way for readability, not because the
key is emitted with a `null` value.

**A missing `registeredAgent` is not automatically "not connected."** Each
platform's row comes from a cloud lookup performed per platform, and that
lookup is non-fatal by design: on failure the command still succeeds and the
field is simply absent. `cloudLookupFailed: true` is how you tell the two
apart — absent field plus no failure flag means genuinely unregistered, while
absent field plus `cloudLookupFailed: true` means the question was never
answered. Check the flag before concluding anything from a missing row; case
4 below is the branch for the second reading.

`registeredAgent.localTokenState` compares the local credential against that
cloud row (`"match"`, `"mismatch"`, or `"unreadable"`); it never carries the
token itself, only the comparison result. **Do not gate the import on it from
here** — §4 gets that decision from `import conversations plan`, which reads
the local token directly and so still answers when this lookup does not. Use
this field for §3.1's classification only.

Before classifying, decide whether this machine is already an EverMe machine:

```
machineAlreadyConnected = data.platforms[] contains any entry with
                          registeredAgent != null          (cloud signal)
                       OR data.platforms[] contains any entry with
                          hasEverMeEntry == true            (local signal)
```

Both signals are needed, because each one alone is blind to a case the other
catches. `registeredAgent` is account-scoped and machine-scoped — it is the
current account's agent on this fingerprint — so it correctly reports `false`
for a returning user on a brand-new laptop. But it comes from a cloud lookup
that can fail without failing the command, and `cloudLookupFailed` tells you
that happened rather than leaving you to guess — it does not, however, recover
the answer. On the cloud signal alone a network blip would still turn an
already-connected machine into a first-time one and install a newly detected
agent silently, which is exactly what this check exists to prevent.
`hasEverMeEntry` is read from local config, so it survives the outage, but it
carries no account identity: an entry left by a different EverMe account still
counts.

Taking the two together fails safe, and that is why the OR stands even now
that the failure is visible: a flag saying "the lookup did not run" is not a
substitute for the answer, and the local signal is what supplies one. The only
case the local signal adds is a machine holding another account's EverMe
config, which costs one extra question — and that platform is already being
handled by case 3 or case 4 below.

This one boolean decides whether a first install is covered by the original
"install EverMe" request or needs its own confirmation. Then classify
`data.platforms[]` against the **current account**:

1. **Needs first install:** `installed: true && hasEverMeEntry: false`. Split
   by `machineAlreadyConnected`:
   - **1a · First-time setup of this machine** (`machineAlreadyConnected ==
     false`). The user is connecting this machine right now and asked for
     exactly that. Include it in §3.2 automatically — do not ask.
   - **1b · Newly detected agent on an already-connected machine**
     (`machineAlreadyConnected == true`). The user asked to install or upgrade
     EverMe, not to connect an agent they never mentioned. Do not install it
     silently. Confirm using §3.1.1 and include in §3.2 only what they approve.
2. **Already connected to this account:** `installed: true &&
   hasEverMeEntry: true && registeredAgent != null`. Do not reinstall it merely
   because the user is returning; §1 already attempted its supported refresh.
3. **Local EverMe entry not registered to this account:** `installed: true &&
   hasEverMeEntry: true && registeredAgent == null && cloudLookupFailed` is
   absent or false. It may be stale or belong to another EverMe account. Do not
   overwrite it silently. Explain that continuing will replace the local
   platform token and bind this host to the account that just logged in, then
   request confirmation using §0.2. Include it in §3.2 only after
   confirmation.
4. **Cannot tell:** `installed: true && hasEverMeEntry: true &&
   registeredAgent == null && cloudLookupFailed: true`. The lookup that would
   have answered did not run, so this platform's registration is **unknown**,
   not absent. Say the check could not be completed and leave it alone: do
   **not** put it in §3.2, and do **not** ask the user to confirm a rebind.
   A confirmed rebind rotates that platform's token, so a working install
   would be broken to work around a lookup failure — and case 3's wording
   ("may be stale or belong to another account") would be a claim you cannot
   support. `evercli plugin install <host>` remains available if the user
   asks for it later.

Keep any platform named by a §1 `refresh failed` warning visible in the final
report and verify it in §5; npm success alone is not a refresh success signal.

If no entry has `installed: true`, tell the user no supported local agent was
detected and stop here. If supported agents are installed but every one is
already connected and no confirmed rebind is needed, say that the connected
plugins were checked/upgraded in §1 and continue directly to §4.

#### 3.1.1 · Confirm newly detected agents (case 1b only)

Reached only when `machineAlreadyConnected == true` and at least one platform
is `installed: true && hasEverMeEntry: false`. Skip this section entirely on a
first-time machine (case 1a) — asking there would break the "at most one
browser click" goal.

Ask **once** for the whole set. Do not ask per platform: one block listing
every newly detected agent turns N interruptions into one, which is what §0.2
is protecting.

**State the cold-start consequence, and state it correctly per platform.**
Declining is not free for every host, because §4's import uploads each
platform's history under *that platform's* agent token, which only
`evercli plugin install` writes. Two classes:

- **Agents with importable local history** — `claude-code`, `codex`, `hermes`,
  `openclaw`, `kimicode`, `raven`, `workbuddy`, `minimaxcode`, `pi`,
  `qwenwork` (plus the Markdown notes attributed to them). Say plainly that
  skipping means this agent's existing local history is **not** imported in
  this run, and that they can connect it later with
  `evercli plugin install <host>` and re-run the import — it is idempotent, so
  nothing is uploaded twice.
- **Plugin-only hosts** — `claude-desktop`, `cursor`, `devin`, `opencode`,
  `dsh`. §4.1 does not scan them, so there is no history to lose. Say only
  that skipping means their future conversations are not captured. Do **not**
  claim a history-import cost these hosts do not have.

Present one §0.2 action block. Content, in order: what §1–§3.1 already
completed; that these agents were found on this machine but have never been
connected; what connecting writes (the host's EverMe config, a per-platform
agent token, and a restart of that host in §6) and what skipping costs, per the
two classes above; that the import in §4 continues either way for the platforms
already connected.

`zh-CN` final block:

> ### ⚠️ 需要你操作
> 👉 回复「全部接入」接入以上全部，回复「跳过」全部不接入，或直接点名要接入哪几个（例如「只接入 Codex」）。

English final block:

> ### ⚠️ Action required
> 👉 Reply **Connect all** to connect all of them, **Skip** to connect none, or name the ones you want (for example, "only Codex").

Wait for the semantic choice. Carry the approved set into §3.2 and the declined
set into §4 (see the `approvedPlatforms` definition at the top of §4) — a
declined platform must not reach `--platform`, or every one of its sessions
fails on token resolution.

A decline is a normal outcome, not a failure: do not retry it, do not re-ask
later in the same run, and do not report it as a §5 warning. If the user
declines every newly detected agent and no confirmed rebind is pending, §3.2
has nothing to install — skip it and continue to §4 with the platforms that
were already connected.

### 3.2 · Install plugins in one call

Pass as positional arguments every case-1a first install, every newly detected
agent the user approved in §3.1.1, and every user-confirmed rebind. Nothing
declined in §3.1.1 belongs here. If this set is empty, skip the command and
continue to §4.

```bash
evercli plugin install <p1> <p2> ... --no-prompt --format json
```

Example:

```bash
evercli plugin install claude-code openclaw --no-prompt --format json
```

Expected success envelope:

```json
{
  "ok": true,
  "data": {
    "installed": [
      {
        "platform": "claude-code",
        "agentId": "agt_...",
        "tokenPrefix": "evt_****",
        "configPath": "/Users/.../.claude/everme.env",
        "backupPath": "/Users/.../.claude.json-bak"
      }
    ],
    "skipped": null,
    "failed": null
  }
}
```

**Partial failure** (`ok: false`, top-level `error.type: "conflict"`): report per-platform reasons from `data.failed[]` and continue to §4 (import) and §5 (verify). Do not abort the whole install — partial success is recoverable and §5 will tell the user concretely what's missing.

Once this command has run (fully or partially), §3.1's platform listing is
stale — it predates these installs, so do not reuse it to decide what to
import. §4 asks `import conversations plan` instead, which reads the current
state each time it runs; see the `approvedPlatforms` definition there.

#### OpenClaw post-install step (only if `openclaw` was installed)

If `openclaw` appears in `data.installed[]`, explain the process before showing
the command. `evercli` has already written `~/.openclaw/openclaw.json` and
registered the cloud agent, but OpenClaw itself must fetch the in-process
context-engine package through its own CLI.

What the user will see in OpenClaw's install log:

```
Resolving clawhub:@everme/openclaw…
Downloading @everme/openclaw…
```

**`clawhub` is OpenClaw's own registry / proxy** — not the public npm registry. The package is resolved as `clawhub:@everme/openclaw` and fetched from OpenClaw's hub. Tell users behind a corporate firewall they may need to allowlist the clawhub host in addition to `registry.npmjs.org`.

Use the localized §0.2 action block and make the command its final line. Wait
for completion before continuing.

`zh-CN` final block:

> ### ⚠️ 需要你操作
> 👉 运行：`openclaw plugins install @everme/openclaw`

English final block:

> ### ⚠️ Action required
> 👉 Run: `openclaw plugins install @everme/openclaw`

#### Kimi Code post-install step (only if `kimicode` was installed)

If `kimicode` appears in `data.installed[]`, explain first that EverCli has
staged the plugin, minted/rotated the agent token, written
`~/.kimi-code/everme.env`, and copied the bundle to
`~/.kimi-code/everme/`. Kimi Code owns its internal plugin registry, so the
user must register and load the staged bundle inside the Kimi Code TUI.

`/plugins install` copies the bundle into `plugins/managed/` and writes the
manifest-embedding record; `/plugins reload` loads it. Use one localized §0.2
action block, keep both commands together, and put them at the end. Wait for
completion before continuing.

`zh-CN` final block:

> ### ⚠️ 需要你操作
> 👉 请在 Kimi Code 中依次运行：`/plugins install ~/.kimi-code/everme`，然后运行：`/plugins reload`

English final block:

> ### ⚠️ Action required
> 👉 In Kimi Code, run `/plugins install ~/.kimi-code/everme`, then `/plugins reload`

### 3.3 · What evercli writes (and what it never touches)

For audit / corporate-security review: `evercli plugin install` only writes the per-platform files and keys listed below. **Anything outside this scope is not modified by evercli.** If you see an agent claiming to "fix" config outside this list, that's an anomaly — push back.

| Platform | File touched | Keys / contents evercli writes |
|---|---|---|
| Claude Code | `~/.claude/everme.env` | The entire file (KEY=value, mode `0600`). Contents: `EVERME_API_BASE`, `EVERME_AGENT_ID`, `EVERME_AGENT_TOKEN` |
| Claude Code | `claude` plugin registry (via `claude plugin marketplace add` + `claude plugin install`) | Adds the `everme` marketplace entry, then installs `everme@everme`. Does **not** edit `~/.claude/settings.json` |
| OpenClaw | `~/.openclaw/openclaw.json` | Appends to `plugins.allow`, sets `plugins.slots.memory` / `plugins.slots.contextEngine`, writes `plugins.entries["@everme/openclaw"]` |
| Cursor | `~/.cursor/mcp.json` + `~/.cursor/hooks.json` + `~/.cursor/everme.env` | Upserts `mcpServers.everme-memory` (preserves any other servers); registers EverMe hook entries (`sessionStart` / `stop` / `preCompact` via `npx -y @everme/cursor`, sibling hooks preserved); writes creds to `everme.env` (mode `0600`) |
| Devin | `~/.codeium/windsurf/mcp_config.json` + `~/.codeium/windsurf/hooks.json` + `~/.codeium/windsurf/everme.env` | Upserts `mcpServers.everme-memory` (same JSON shape as Cursor); registers the `post_cascade_response_with_transcript` hook (`npx -y @everme/devin`, sibling hooks preserved); writes creds to `everme.env` (mode `0600`) |
| Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) / `%APPDATA%\Claude\claude_desktop_config.json` (Windows) / `~/.config/claude-desktop/claude_desktop_config.json` (Linux) | Upserts `mcpServers.everme-memory` (preserves any other servers) |
| Codex | `~/.codex/config.toml` + `codex plugin marketplace add` | Upserts `[marketplaces.everme]`, `[plugins."everme@everme"]`, `[mcp_servers.everme]`, `[mcp_servers.everme.env]`. Marketplace add runs **before** the backend mints a fresh token. |
| Hermes | `~/.hermes/plugins/everme/` + `~/.hermes/everme.env` + `~/.hermes/config.yaml` | Writes the evercli-embedded native `MemoryProvider` package into `~/.hermes/plugins/everme/`; writes creds to `~/.hermes/everme.env` (mode `0600`: `EVERME_API_BASE` / `EVERME_AGENT_ID` / `EVERME_AGENT_TOKEN`); sets `memory.provider: everme` in `config.yaml`; and removes any legacy `mcp_servers.everme` entry. Sibling MCP servers and unrelated top-level config are preserved. |
| opencode | `~/.config/opencode/opencode.json` | Upserts `mcp.everme-memory` (preserves any other servers and top-level keys). opencode's own entry shape: `type: "local"`, `command` argv array, `environment` (not `env`), `enabled: true` |
| Kimi Code | `~/.kimi-code/everme.env` + `~/.kimi-code/everme/` | Writes the entire `everme.env` (KEY=value, mode `0600`: `EVERME_API_BASE`, `EVERME_AGENT_ID`, `EVERME_AGENT_TOKEN`) and stages a copy of the plugin bundle (incl. `node_modules`) at `~/.kimi-code/everme/`. Does **not** write `~/.kimi-code/plugins/installed.json` or `~/.kimi-code/plugins/managed/` — registration is the TUI `/plugins install` step |

`evercli plugin install` supports `claude-code`, `openclaw`, `cursor`, `claude-desktop`, `codex`, `hermes`, `devin`, `opencode`, and `kimicode`. VS Code Copilot / Cline are future candidates. **Manus is deliberately not in this list** — it is a cloud-hosted agent connected through the EverMe web dashboard, not through evercli (see §3.5). For any host outside this list there is **no** manual `register` fallback — `evercli plugin register` was retired in V1.

**Files evercli will never write during install:**

- `~/.claude/settings.json` and `~/.claude.json` (Claude Code's own configs — evercli only writes the everme env file)
- Your shell profile (`.zshrc` / `.bashrc` / `.profile`)
- `package.json`, `package-lock.json`, or any file inside your project directories
- Any file outside `$HOME/.claude/`, `$HOME/.openclaw/`, `$HOME/.cursor/`, `$HOME/.hermes/`, `$HOME/.codeium/windsurf/`, `$HOME/.config/opencode/`, `$HOME/.kimi-code/`, the Claude Desktop config dir, and `$HOME/.codex/`

**Backups.** When evercli replaces an existing entry, it writes a `.bak` sibling first. The path appears in `data.installed[].backupPath` of the install JSON envelope. Restore by `mv <path>.bak <path>`.

### 3.4 · Per-host install notes

Every V1 host uses the **same** command — `evercli plugin install <host>` — and writes the local config + mints the agent token automatically. There is no manual paste step. The per-host notes below cover what gets written, where, and any post-install restart required.

#### 3.4.1 · Claude Desktop

**Scope.** The macOS / Windows desktop app from claude.ai/download. **Not** Claude Code (the CLI). Linux uses Anthropic's experimental build.

```bash
evercli plugin install claude-desktop
```

**Writes:** `mcpServers.everme-memory` into the OS-appropriate config file
(macOS `~/Library/Application Support/Claude/claude_desktop_config.json`, Windows `%APPDATA%\Claude\claude_desktop_config.json`, Linux `~/.config/claude-desktop/claude_desktop_config.json`). Any sibling MCP servers are preserved.

**Restart:** quit Claude Desktop fully (⌘Q on macOS), then relaunch. The MCP server icon should list `everme-memory` with four tools (`mem_context`, `mem_search`, `mem_save_fact`, `mem_save_turn`).

#### 3.4.2 · Codex

**Scope.** Codex CLI + Codex Desktop App both consume `~/.codex/config.toml`, so a single install covers both. **ChatGPT Desktop / Codex Web are out of scope** — they run in OpenAI's cloud and cannot spawn local stdio MCP subprocesses.

```bash
evercli plugin install codex
```

**Writes** end up in two distinct sections of `~/.codex/config.toml` (unrelated keys untouched), split between two writers:

```toml
# Written by `codex plugin marketplace add` during evercli's Prepare step.
# Exact key shape (source_type, source, last_updated) depends on whether
# Codex fetched the marketplace from GitHub or a local path; evercli does
# NOT overwrite this section.
[marketplaces.everme]
last_updated = "2026-05-26T10:32:09Z"
source_type = "git"
source = "EverMind-AI/EverMe"

# Written by evercli's Commit step.
[plugins."everme@everme"]
enabled = true

[mcp_servers.everme]
command = "npx"   # npx.cmd on Windows
args = ["-y", "@everme/memory-mcp"]

[mcp_servers.everme.env]
EVERME_API_BASE = "https://api.everme.evermind.ai"
EVERME_AGENT_ID = "agt_..."
EVERME_AGENT_TOKEN = "evt_..."
```

The marketplace add runs **before** the backend mints a fresh token, so a marketplace failure (network, missing `codex` CLI, bad `--sparse` path) leaves no stranded cloud agent. The EverMe Codex skill (`everme-memory`, telling Codex when to call `mem_*` tools) ships through this marketplace.

**Restart:** exit the current `codex` session (or quit the Codex app) and relaunch.

#### 3.4.3 · Cursor

```bash
evercli plugin install cursor
```

**Writes:** `mcpServers.everme-memory` into `~/.cursor/mcp.json` (global; same `mcpServers` JSON shape as Claude Desktop), EverMe hook entries (`sessionStart` / `stop` / `preCompact`, each running `npx -y @everme/cursor`) into `~/.cursor/hooks.json` (sibling hooks preserved), and creds into `~/.cursor/everme.env` (mode `0600`).

**Restart:** quit and relaunch Cursor.

**Behavior:** hook-driven capture — `stop` / `preCompact` auto-save the transcript turn-by-turn, `sessionStart` injects recalled context. The MCP tools remain available for on-demand recall.

#### 3.4.4 · Hermes

```bash
evercli plugin install hermes
```

**Writes:** the evercli-embedded native `MemoryProvider` package into `~/.hermes/plugins/everme/` (`__init__.py`, `client.py`, `config.py`, `plugin.yaml`, `README.md`); creds into `~/.hermes/everme.env` (mode `0600`: `EVERME_API_BASE`, `EVERME_AGENT_ID`, `EVERME_AGENT_TOKEN`); sets `memory.provider: everme` in `~/.hermes/config.yaml`; and removes any legacy `mcp_servers.everme` entry. Sibling MCP servers and unrelated Hermes config are preserved.

**Why a native provider (not MCP):** Hermes discovers memory providers under `$HERMES_HOME/plugins/<name>/` and drives them through framework hooks. This gives **deterministic, hook-driven** capture/recall that does not depend on the model voluntarily calling save tools — superseding the older `mcp_servers.everme` MCP path (which evercli now migrates away by deleting that entry).

**Restart:** quit the Hermes app / runtime and relaunch.

**Behavior:** hook-driven. Every turn is auto-captured via the provider's `sync_turn` hook (agent-memory endpoint); durable facts mirror from Hermes builtin memory writes via `on_memory_write` (deduped and coalesced to the personal-memory endpoint); recall is auto-injected via `prefetch` + the system-prompt profile block. The model can still call the read-only `mem_search` / `mem_context` tools on demand, but capture/recall never rely on it.

#### 3.4.5 · opencode

**Scope.** The `opencode` CLI (sst/opencode). Reads MCP servers from a top-level `mcp` map in `~/.config/opencode/opencode.json` ( `$XDG_CONFIG_HOME/opencode/opencode.json` when set), with an entry shape that differs from the `mcpServers` family.

```bash
evercli plugin install opencode
```

**Writes:** `mcp.everme-memory` into `~/.config/opencode/opencode.json` (preserves other top-level keys and sibling `mcp.*` entries). opencode's entry shape: `type: "local"`, a `command` argv array (`["npx", "-y", "@everme/memory-mcp"]`), an `environment` object (not `env`) carrying `EVERME_API_BASE` / `EVERME_AGENT_ID` / `EVERME_AGENT_TOKEN`, and `enabled: true`. Only `opencode.json` is written, not `opencode.jsonc` (round-tripping JSONC comments is lossy).

**Restart:** quit and relaunch `opencode`.

**Behavior:** MCP-based, so recall/save are model-driven tool calls like Claude Desktop.

#### 3.4.6 · Kimi Code

**Scope.** The `kimi` CLI / Kimi Code. Config dir is `~/.kimi-code/` (`$KIMI_CODE_HOME`); the plugin id is `everme`. Unlike every other V1 host, install is **two steps** — Kimi Code has **no** headless install command, and its `plugins/installed.json` is an internal manifest-embedding record evercli must not hand-write.

**Step 1 — stage (evercli):**

```bash
evercli plugin install kimicode
```

This mints/rotates the agent token, writes `~/.kimi-code/everme.env` (mode `0600`: `EVERME_API_BASE`, `EVERME_AGENT_ID`, `EVERME_AGENT_TOKEN`), and stages the plugin bundle (with its `node_modules`) at `~/.kimi-code/everme/`. It does **not** write `~/.kimi-code/plugins/installed.json` or `~/.kimi-code/plugins/managed/`.

**Step 2 — register (inside the Kimi Code TUI):**

```
/plugins install ~/.kimi-code/everme
/plugins reload
```

`/plugins install` copies the staged bundle into `plugins/managed/` and writes the correct record; `/plugins reload` (or `/new`) loads it.

**MCP server:** the bundle declares an MCP server `everme-memory` with four tools (`mem_context`, `mem_search`, `mem_save_fact`, `mem_save_turn`), launched via a wrapper that loads `~/.kimi-code/everme.env` so the per-user `EVERME_AGENT_TOKEN` reaches it. The bundle also ships lifecycle hooks (SessionStart recall, SessionEnd save) and skills.

**Restart:** inside Kimi Code run `/plugins reload`, or start a new session (`/new`).

**Behavior:** hook-driven auto recall/save — SessionStart injects recalled context; SessionEnd flushes the whole session for extraction in one pass (there is no per-turn Stop hook; sessions with fewer than 2 messages skip the write) — **plus** the model-callable `everme-memory` MCP tools.

#### 3.4.7 · Devin

**Scope.** Devin's local IDE (the Windsurf-derived editor). Config dir is `~/.codeium/windsurf/` (`EVERCLI_DEVIN_CONFIG_DIR` overrides for tests); detection probes `Devin.app`, the `devin` CLI, or an existing config.

```bash
evercli plugin install devin
```

**Writes:** `mcpServers.everme-memory` into `~/.codeium/windsurf/mcp_config.json` (same `mcpServers` JSON shape as Cursor; sibling servers preserved), the `post_cascade_response_with_transcript` hook (running `npx -y @everme/devin`) into `~/.codeium/windsurf/hooks.json` (sibling hooks preserved), and creds into `~/.codeium/windsurf/everme.env` (mode `0600`).

**Restart:** quit and relaunch Devin.

**Behavior:** the transcript hook auto-captures each turn after Devin responds. Devin has **no** context-injection hook, so recall is model-driven via the `everme-memory` MCP tools (`mem_context` / `mem_search`) — remind the user (or the agent) to call them at session start.

### 3.5 · Manus (hosted MCP — web dashboard, not evercli)

**Scope.** Manus runs entirely in Manus's own cloud. There is no local process, no local config file, and no stdio MCP subprocess on the user's machine — so `evercli plugin install` has nothing to write and does **not** support a `manus` platform. Do not attempt any evercli command for Manus.

**Registration link.** The web flow lives at:

```
https://everme.evermind.ai/register-remote-agent?platform=<platform>&name=<display-name>
```

- `platform` — the hosted platform id. Currently the only supported value is `manus`.
- `name` — the display name for this agent in the user's dashboard. Default to `MyManus`; only substitute a different name if the user explicitly asked for one (URL-encode it).

Present the registration explanation in `responseLanguage`. Explain that Manus
is hosted, the page creates an endpoint plus a one-time token, the token must be
copied immediately, and losing it requires rotating the same agent rather than
creating a duplicate. Put the registration link only in the final §0.2 action
block.

Required explanation points, localized:

- Manus connects as a hosted MCP agent through the EverMe dashboard, not by
  changing local files;
- registration generates a hosted MCP endpoint and a one-time `evt_*` token;
- the token is displayed once and must be copied immediately;
- losing it requires **Rotate token** on the same agent at
  <https://everme.evermind.ai/agents>; do not create a duplicate agent.

Final action line:

- `zh-CN`: `打开注册页面：<https://everme.evermind.ai/register-remote-agent?platform=manus&name=MyManus>`
- English: `Open the registration page: <https://everme.evermind.ai/register-remote-agent?platform=manus&name=MyManus>`

**Facts you (the agent) should know when answering follow-ups:**

- The token is displayed **once** at creation/rotation and never again — EverMe stores only a hash. "I lost the token" → rotate, don't re-create.
- Each registration through this link creates an **independent** agent; duplicates can be cleaned up with **Disconnect** on the <https://everme.evermind.ai/agents> page.
- Disconnecting immediately invalidates the agent's token; rotating the token on a disconnected agent reconnects it.
- Manus's read/write permissions are managed per-agent on the same dashboard page.
- `evercli doctor` (§5) knows nothing about hosted agents — the dashboard's `connectionStatus` is the only health signal for Manus.

---

## 4 · Historical data import (all branches)

This section applies to **every** user — new (§2A) or existing (§2B) — with
no branch gating and no per-branch opt-out. Existing users' live sessions are
already in the cloud, but their local pre-EverMe history is not; this import
brings it in. The import is idempotent: sessions already submitted are
skipped automatically, and even if the local skip-record is ever lost,
re-uploading a session lands on the **same** server-side session — it never
creates a duplicate.

**Run the scan unconditionally, without asking.** The moment login (§2A/§2B)
and plugin install (§3) are done, run §4.1's scan immediately — do **not**
ask the user for permission first, and do **not** skip it. The scan is
local-only, read-only, and uploads nothing; say so explicitly when you
present its results. Consent is required only for the *upload* step (§4.3) —
never for the scan.

**`approvedPlatforms` — ask the CLI, do not derive it.** Scanning is
unrestricted, but uploading is not: the importer resolves *that platform's*
agent token for every session, and a platform whose credential is missing or
wrong does not fail politely. One command answers it:

```bash
evercli import conversations plan --format json
```

It is read-only — it uploads nothing and writes nothing — and its envelope
carries one row per platform that can hold sessions:

```json
{
  "ok": true,
  "data": {
    "platforms": [
      { "platform": "claude-code", "included": true,  "checked": true,  "reason": "token_match" },
      { "platform": "codex",       "included": false, "checked": false, "reason": "cloud_unverified" },
      { "platform": "hermes",      "included": false, "checked": true,  "reason": "token_mismatch", "remedy": "plugin_install" }
    ]
  },
  "meta": { "count": 3 }
}
```

```
approvedPlatforms = { P in §4.1's scan results : P is included in plan output }
```

That intersection is the whole derivation. **Do not reconstruct the decision
from `plugin list`, from §3.2's install report, or from the order in which
those ran.** The document did it that way before this command existed, and
getting it wrong was not a small error: it silently skipped the entire import
on a first-time machine.

Read the three fields as follows:

- **`included`** — pass this platform to `--platform`, or do not. Nothing else
  decides that.
- **`checked`** — whether the credential question got an answer at all.
  `checked: false` (always with `included: false`) means the confirming lookup
  did not come back, so this platform is skipped **this run** rather than
  judged. Say the check could not be completed; do not call it disconnected,
  and do not present it as something the user can fix.

  A readable credential is not sufficient on its own, which is why this state
  defers instead of importing. The gateway resolves identity from the token
  itself, never from what the caller claims, so a still-valid credential that
  belongs to some **other** agent row — an account used on this machine
  before being the common case — is accepted, and this machine's history is
  filed under that row: no error, no warning, nothing to notice later.
  Skipping a platform costs one run of its import and says so on screen;
  guessing costs the data.
- **`reason`** — a stable string, safe to branch on:

  | `reason` | `included` | What to tell the user |
  |---|---|---|
  | `token_match` | yes | nothing; this is the normal state and the only one that imports |
  | `token_mismatch` | no | this agent's local credential belongs to a different EverMe agent, so its history is not imported |
  | `token_not_current_agent` | no | this agent's local credential is not the one EverMe has registered for it on this machine — often left by an account used here before — so its history is not imported |
  | `agent_disconnected` | no | this agent's EverMe connection was revoked, so its history is not imported |
  | `token_unreadable` | no | this agent's EverMe credential cannot be read, so its history is not imported |
  | `no_local_token` | no | this agent is not connected on this machine |
  | `cloud_unverified` | no | the credential check could not be completed, so this agent is skipped this time — nothing to fix, a later run will import it |

- **`remedy`** — present only when the user can act. `plugin_install` means
  `evercli plugin install <platform>` rewrites the credential, after which
  re-running the import brings that platform in (idempotent, so nothing
  uploads twice). **Absent means absent:** never offer a reinstall for a
  `cloud_unverified` row — it would rotate a working credential to work around
  a lookup that was never the problem.

A platform the user declined in §3.1.1 is a separate matter: `plan` reports
credentials, not consent. A declined platform may well come back `included`,
and it still must not be imported. Drop it yourself, and report it as declined
rather than borrowing a reason from the table above.

Never pass a platform outside this set. `markdown` needs one extra step,
because a Markdown item uploads under the agent that owns it, not under
`markdown`. Read ownership from `data.groups[]`: a Markdown group's `area` is
`<owner>:<zone>` (for example `codex:memory/notes`), so the segment before the
colon is the owning platform. Include `markdown` only when **every** Markdown
group's owner is in `approvedPlatforms`. If any Markdown group is owned by a
platform outside it, omit `markdown` from `--platform` entirely and say those
notes come in on a later re-run once that agent is connected.

Do **not** try to exclude those notes per file: `data.items[]` does not carry
the owning platform (the scan view drops it), and `data.groups[]` carries the
owner but not the paths, so no `--exclude <path>` list can be built from this
envelope. Dropping the whole `markdown` platform for one run is the only
correct option available, and it costs a deferred import rather than a screen
of upload failures.

This flow relies on current evercli behavior (synchronous upload with a final
flush by default plus the offline `--async` bulk mode; a `summary` envelope on
scan; `--limit` selecting only the newest sessions). If the scan envelope has
no `summary` field (an older evercli), fall back to the generic wording
"already-imported sessions are skipped automatically" instead of citing
counts, and suggest the user upgrade: `npm i -g @everme/cli@latest`. Never
cite an already-imported count from scan output regardless of CLI version —
scan does not compute one (§4.1).

### 4.1 · Scan for importable sessions

```bash
evercli import conversations scan --format json
```

This command walks all supported platform session directories (Claude Code, Codex, Hermes, OpenClaw, Kimi Code, Raven, WorkBuddy, MiniMax Code, Pi, QwenWork) and returns every discovered session with its file path, date, message/tool call counts, and source-file size. It also collects Markdown notes, but from **four agent homes only** — Claude Code (`$CLAUDE_CONFIG_DIR`, default `~/.claude`), Codex (`$CODEX_HOME`, default `~/.codex`), OpenClaw (`$OPENCLAW_CONFIG_DIR`, default `~/.openclaw`), and Hermes at a **hard-coded `~/.hermes`** — and within them only from curated locations: the agent's top-level persona/identity files (e.g. `CLAUDE.md`, `USER.md`, `SOUL.md`, `MEMORY.md`) and its memory / project-notes folder. The other session platforms above contribute sessions but no Markdown; do not tell the user their notes were scanned. The Hermes path is the one asymmetry worth knowing: Hermes *sessions* are materialized from a home resolved through `$EVERCLI_HERMES_CONFIG_DIR` / `$HERMES_HOME`, but the Markdown zone is anchored at a literal `~/.hermes` — so a user who relocated their Hermes home gets their Hermes sessions scanned and their Hermes notes silently missed. Do not claim otherwise, and do not suggest an env var can fix the Markdown side. Installed-software documentation — plugin or skill `SKILL.md` / `README.md`, dependency files under `node_modules`, vendored packages, caches, and build output — is deliberately **not** scanned, so tooling docs never end up in your memory. Each Markdown file is attributed to the agent whose folder contains it (a Markdown file under no known agent folder is skipped — it has no agent to import into). Missing platforms are announced explicitly — they are never silently empty. The session your agent is currently writing is skipped automatically (it is already being captured live), and any such paths are surfaced under `skippedActive`.

**Scan cannot tell you what was already imported.** It is an offline preview by
contract — it queries no server — and nothing local records the already-synced
set (the local ledger that once did was retired in favour of the server's turn
watermark). So every parseable session comes back `status: "ready"`,
`summary.alreadySubmitted` reads `0`, and `summary.new` counts the whole
parseable set, including sessions imported last week. Treat these numbers as an
**upper bound**, never as "this much is new".

The authoritative already-synced set comes from the server watermark, which
only `run` consults. You do not have to wait for the upload to see it: §4.1.1
gets the same lookup out of `run --dry-run` before the consent step. The
`status` field is still in the scan envelope because `run` annotates it
internally; do not expect `scan` to populate it.

The top-level `summary` also carries workload metrics for that upper-bound
subset: total messages, total source bytes, and the largest session by messages
and bytes.

Expected envelope:

```json
{
  "ok": true,
  "data": {
    "items": [
      {
        "platform": "claude-code",
        "path": "/Users/.../.claude/projects/myproj/sess-abc.jsonl",
        "date": "2026-05-01T10:23:00Z",
        "messages": 34,
        "toolCalls": 12,
        "sizeBytes": 184320,
        "status": "ready"
      },
      {
        "platform": "hermes",
        "path": "/Users/.../.hermes/sessions/sess-xyz.json",
        "date": "2026-04-28T09:00:00Z",
        "messages": 18,
        "toolCalls": 5,
        "sizeBytes": 92160,
        "status": "ready"
      }
    ],
    "notFound": {
      "codex": "directory not found for codex (checked: [/Users/.../.codex/sessions]); use --path to override"
    },
    "driftWarnings": [],
    "skippedActive": [],
    "summary": {
      "new": 2,
      "alreadySubmitted": 0,
      "unsupported": 0,
      "newMessages": 52,
      "alreadySubmittedMessages": 0,
      "newSizeBytes": 276480,
      "largestNewSessionMessages": 34,
      "largestNewSessionSizeBytes": 184320
    }
  }
}
```

Branch on the result — this is the fork the rest of §4 depends on:

- **`data.items` is empty** → tell the user in one line, e.g. "No importable
  local history found on this machine." Skip the rest of §4 entirely. (If
  `data.notFound` covers all platforms, you can add that as the reason in
  the same line; if it doesn't — directories exist but hold nothing
  importable — say so plainly rather than implying nothing was scanned.)
- **`summary.new == 0`** (every item is `"unsupported"` — present but not
  importable, e.g. corrupt or unrecognized files) → treat this like the
  empty-`items` branch above: tell the user no importable local history was
  found, and skip the rest of §4. Do **not** describe this as "all previously
  imported" — nothing here was ever submitted, and scan could not have told
  you if it had been.
- **`summary.alreadySubmitted > 0`** → cannot happen from `scan`; see the note
  above. If you ever see it, you are reading a `run` result, not a scan. Never
  present an "all previously imported, nothing new" message from scan output:
  a returning user with nothing new still scans as all-new, so that message
  would be a guess. §4.1.1 is where that answer is available.
- **`summary.new > 0`** → continue to §4.1.1, then to §4.2 with the new-session
  subset, restricted to `approvedPlatforms`. If every new session belongs to an
  excluded platform, that subset is empty: there is nothing to consent to, so
  do **not** run §4.2. Tell the user which platforms hold the new sessions and
  why each one was excluded, taking the wording from that platform's `reason`
  and `remedy` in §4's plan output — a row with a `remedy` gets
  `evercli plugin install <host>` and a re-run, a row without one has nothing
  for the user to fix and must not be handed a reinstall. Then skip to §5.

Compatibility: if an older CLI omits the workload fields, calculate message
counts from `items[]`. If `sizeBytes` is also absent, report sessions and
messages only; never fail the install because optional workload metrics are
unavailable.

#### 4.1.1 · Look up what is already imported, before asking for consent

`scan` cannot answer this (see §4.1), but `run --dry-run` can: it performs the
same server-watermark lookup the real upload does, then returns before
uploading anything. Run it so the consent screen shows real numbers instead of
an upper bound.

```bash
evercli import conversations run --platform <approvedPlatforms...> \
  --dry-run --force
```

**`--force` is safe here only because `--dry-run` returns before the upload
loop.** It re-uploads nothing; it only keeps already-imported sessions visible
in the listing instead of dropping them. Never carry `--force` into §4.3's real
commands, where it does mean "re-upload everything".

**This command ignores `--format json`** — dry-run renders the text preview
whatever the format flag says, and its own output even hints at `--format json`
for machine detail, which does not apply on this path. Read the counts off the
text instead: the `TOTAL:` line ends with `(<N> new · <M> imported)`, derived
from the server watermark.

**Only the session split is exact.** That parenthetical counts sessions and
nothing else. The `messages` figure on the same `TOTAL:` line is the sum over
every session shown — which, under `--force`, includes the `<M>` already
imported — and §4.1's `newMessages`, `newSizeBytes` and largest-session
figures carry the same all-inclusive meaning. So this step upgrades the
session count from an upper bound to a fact, and leaves message counts and
byte sizes as upper bounds. Say it that way; do not present them as the
workload of the `<N>` sessions that will actually be sent.

**Do not add `--detail` to that command.** The renderer prints the grouped
table *or* the per-session table, never both, and the `TOTAL:` line belongs to
the grouped one — so `--detail` silently costs you the counts. If the user
wants the per-session breakdown, run it a second time with `--detail` added;
each row's `STATUS` column then reads `submitted` (fully synced) or `ready`
(not). A second dry-run is cheap and uploads nothing.

Paths in the `--detail` table are truncated to their last 52 characters when
longer than 55. That is fine for showing the user, but useless for building an
`--exclude` list — take exclusion paths from §4.1's JSON `items[].path`
instead.

**If `<N> new` is `0`**, there is nothing to upload and no consent to ask for:
skip §4.2 and go to §5. Do **not** offer `--force` to re-upload; mention it
only if the user asks. This is the one place that answer is trustworthy —
§4.1's scan can never reach it, because scan counts every session as new
(§4.1).

Scope the claim correctly, though. This command only covers
`approvedPlatforms`, so `0 new` means **those** platforms are fully imported —
not that nothing on this machine is left. If §4.1's scan found sessions on any
platform you excluded, say that too: all `<M>` sessions on the covered agents
were imported previously, and platform X still holds history this run did not
import. Give the reason the way §4.2's scope detail does — from that
platform's `reason` and `remedy` in §4's plan output, which already separates
"not connected, a reinstall fixes it" from "the credential check could not be
completed", a different statement that calls for no reinstall. Never say
"everything local
is already stored" unless the excluded set was empty.

Two limits to respect when you report this:

- **No partial progress.** A session reads `submitted` only when the watermark
  covers all of its turns, so one that is 90% uploaded looks exactly like one
  never uploaded. The real upload still resumes from the unsynced tail and
  re-sends nothing; the preview simply cannot show that state.
- **No watermark number.** Only the derived per-session state is rendered.

If the lookup degrades, everything reads as new. Two of the three ways that
happens print a stderr warning — `no agent token available to query sync state`
and `could not query sync state (...)`. The third is silent: a session whose
turn count was never computed can never be marked. Whenever you see either
warning, go back to the §4.2 upper-bound wording rather than reporting a count
of new sessions, and say the already-imported figure was unavailable.

### 4.2 · REQUIRED: Show the user the session list and privacy warning before uploading

**This step is mandatory. Do not upload anything without explicit user confirmation.** (Only reached when §4.1 found at least one session on an `approvedPlatforms` platform and §4.1.1 reported at least one of them as new.)

Present one localized action message using §0.2. It must contain, in order:

1. **Workload summary** — the upper bound on what will be attempted:
   - `{summary.new}` sessions;
   - `{summary.newMessages}` messages;
   - `{summary.newSizeBytes}` formatted as KiB/MiB;
   - largest session: `{summary.largestNewSessionMessages}` messages and
     `{summary.largestNewSessionSizeBytes}` formatted as KiB/MiB.

   Report the session split from §4.1.1: `<N>` new and `<M>` already
   imported, and say `<N>` is what will actually be sent. The message and
   byte figures above stay upper bounds either way — §4.1.1 sharpens only the
   session count (see there) — so do not attach them to `<N>`. Never derive
   the already-imported figure from `scan`: it does not compute one (§4.1).
   If §4.1.1 warned that its lookup degraded, drop the split entirely,
   present every figure as an upper bound, and say that what is already
   stored will be skipped during the upload and reported then.

   The `summary` fields cover **every scanned platform**. If any scanned
   platform is outside `approvedPlatforms`, they overstate this upload on a
   second axis — in that case derive every number above from `data.items[]`
   filtered to the platforms you will actually pass to `--platform`, instead
   of reading `summary`. That filter is a plain `items[].platform` match,
   which is why `markdown` is included or dropped as a whole (see §4).
2. **Scope detail** — platform, path, date, message count, and size for new
   items. Include `data.notFound` so the user knows what was not scanned.
   List each scanned platform left out of `approvedPlatforms` on its own line,
   with its actual reason, how many sessions it would have contributed, and
   what closes the gap. Keep the reasons distinct — they call for different
   things from the user:
   - declined in §3.1.1 → the user's own choice; report it as that;
   - any plan row carrying a `remedy` (`token_mismatch`, `token_unreadable`,
     `no_local_token`) → `evercli plugin install <host>`, then re-run the
     import;
   - a plan row with no `remedy` → nothing for the user to fix and **no**
     reinstall suggestion; say the credential check could not be completed
     and a later run will import it.
3. **Performance expectation** — do not estimate from session count alone. If
   the largest new session is at least 500 messages or 5 MiB, explicitly say it
   is a large multi-turn session and the foreground activation may take several
   minutes. Never promise an exact ETA. The foreground pass imports one session;
   all remaining sessions submit in the background.
4. **Privacy impact** — these local files may contain secrets, passwords, API
   keys, PII, or confidential business data. Upload sends their content to the
   cloud and cannot be fully undone. Automatic redaction is not a guarantee.
5. **Control and idempotency** — explain `--platform` and repeatable
   `--exclude <path>`. Already-imported sessions are skipped automatically;
   reinstalling the CLI does not erase the record, and a replay lands on the
   same server-side session.
6. **The only action block**, at the end:
   - `zh-CN`: heading `### ⚠️ 需要你确认`; final line
     `👉 回复「确认导入」开始上传，或回复「跳过」取消。`
   - English: heading `### ⚠️ Confirmation required`; final line
     `👉 Reply **Import** to upload, or **Skip** to cancel.`

Wait for the exact semantic choice (`确认导入` / `Import`, or an unambiguous
equivalent). **This is the only confirmation in the entire import** and covers
both §4.3 passes. On decline, upload nothing, say the import was skipped in
`responseLanguage`, and continue to §5.

### 4.3 · One consent, two passes: one synchronous session, then automatic background bulk

**A cold start is TWO commands and you MUST run BOTH.** Running only the first
one imports a single session, not the remaining history, so it is *not* a
completed cold start:

1. **Activation, foreground** — `run ... --limit 1 --no-prompt`. Wait for the
   command to exit. Only `extracted` means activation is visible.
2. **Remaining history, background** — unless step 1 found a blocking
   prerequisite described below, launch the same command without `--limit`,
   plus `--async`, as soon as step 1 exits and without asking again.

Both passes skip already-imported sessions on their own, so a returning user's
re-run reports what was already stored and what this run added. The per-pass
detail below defines the exact commands and status-specific timeout, failure,
and exclusion handling for this rule.

The single §4.2 import confirmation authorizes **both** passes below — do **not** ask the
user a second question between them. Never import everything in one
foreground go, and never run the bulk pass in the foreground. Run two passes:

**Step 1 — activation session (foreground, synchronous).** After the §4.2
consent, import only the single most recent **new** conversation. Do not add a
date window: a user whose latest local session is older than seven days still
needs one immediately-visible memory before the remainder moves to the
background.

```bash
evercli import conversations run --platform <approved platforms...> \
  --limit 1 [--exclude <path>...] --no-prompt
```

Run this **in the foreground** and wait for it to exit. It is bounded to one
session. Upload is synchronous with a final flush, so when the session reports
`extracted`, at least one memory is visible on
<https://everme.evermind.ai> and EverMe can be reported as active. A successful
command exit alone is not the activation signal: `queued`,
`extraction_pending`, and `no_extraction` must not be described as visible or
effective.

If the activation session fails with `50301`, `context deadline exceeded`,
`Memory service temporarily unavailable`, or an equivalent timeout, do **not**
declare the whole import failed. The upstream request may still complete after
the local timeout, so record the failed Session path as
`<uncertain-activation-path>` and do not retry that path. Tell the user the
first memory is taking longer to extract and continue to Step 2 automatically.

Stop before Step 2 only for prerequisites that make every upload unsafe or
impossible: authentication/login failures, missing or invalid credentials,
missing platform Agent tokens, broken EverMe configuration, an unwired host,
or an unavailable EverCli binary. Other per-session failures are reported and
excluded; they do not block the remaining offline import.

Carry any `--exclude` paths the user specified in §4.2 through BOTH passes.
The actual filter order is `--exclude`, then the submitted-drop, then
`--limit`, so `--limit 1` selects the newest non-excluded, not-yet-submitted
session across the approved platforms.

`run` prints one stderr summary line whenever it drops previously-submitted
sessions — `skipped N previously imported session(s); pass --force to
re-upload` — applied after `--exclude` and before `--limit`. Do not calculate
the remaining count from that line; use §4.1's scan `summary.new` and subtract
one only when Step 1 actually reported `extracted`.

**Step 2 — remaining history (background, automatic — no second question).**
After Step 1 exits, launch the bulk pass in the background unless Step 1 found
one of the blocking prerequisites above. The §4.2 import confirmation already
covered it. Re-run the same platform scope without the limit. If Step 1 had an
uncertain or failed Session, carry its exact path into Step 2 as an additional
`--exclude` so an upstream request that finishes late cannot be duplicated:

```bash
evercli import conversations run --platform <approved platforms...> \
  [--exclude <user-excluded-path>...] \
  [--exclude <uncertain-activation-path>] \
  --no-prompt --async
```

`--async` is the offline bulk path: every session's batches are durably
accepted as `queued` without a flush. The server derives an idempotency key per
chunk, so replaying an interrupted upload does not duplicate it. Extraction is
eventually consistent and continues after the CLI has finished submitting the
sessions. If evercli rejects the flag as unknown, upgrade it with
`npm i -g @everme/cli@latest`; do not silently turn the whole history into a
foreground synchronous run.

Sequence matters: launch Step 2 only **after** Step 1's command has exited,
never while it is still running — both invocations share the same local
idempotency state, and the windowless bulk pass would re-select the window
sessions before Step 1 marks them submitted. "After Step 1 exits" does not
mean "after asking again" — the launch is automatic.

Run this **in the background**, not the foreground — it can cover a large
history and must not block the conversation. If your host environment
supports launching a background task (e.g. a background-agent or
background-shell primitive), use that. Otherwise, fall back to:

```bash
nohup evercli import conversations run --platform <approved platforms...> [--exclude <path>...] --no-prompt --async > everme-import.log 2>&1 &
```

Once Step 2 is launched, report both passes to the user in one message. Choose
the wording from Step 1's actual status.

When Step 1 reported `extracted`:

> EverMe is active: the latest **1** session ({platform}) was extracted and is
> visible in the Memory Hub at **<https://everme.evermind.ai>**.
>
> The remaining **{summary.new - 1}** sessions are being submitted in the
> background. `queued` means durable upload accepted, not visible yet; their
> extracted memories will appear progressively. Already-imported sessions are
> skipped automatically.

When Step 1 reported `extraction_pending` or `no_extraction`:

> The activation session was uploaded, but immediate extraction was not
> confirmed, so I cannot claim that a memory is visible yet. The remaining
> **{summary.new - 1}** sessions are being submitted in the background and will
> appear progressively as extraction completes.

When Step 1 timed out with an unknown outcome:

> The first memory is taking longer to extract and may still finish on the
> server. I excluded that uncertain Session from retry to avoid a duplicate.
> The remaining **{summary.new - 1}** sessions are now processing in the
> background. You can continue to the Memory Hub; memories will appear
> progressively.

They can check progress by tailing the log file (`tail -f everme-import.log`
for the `nohup` fallback), on the Memory Hub page, or by re-running §4.1.1's
dry-run lookup and watching the `imported` count climb. Re-running the *scan*
does **not** show progress: it reports the same counts before and after a
successful import, because it never learns the already-synced set (§4.1). The run is
interruption-safe: if it stops for any reason, re-running the exact same
command resumes — already-submitted sessions (including ones from the
interrupted attempt) are skipped automatically, per the idempotency note in
§4.2.

**Do not wait for Step 2 to finish before continuing.** Once it is launched
(backgrounded, or `nohup`'d and detached), move straight on to §5 (verify)
and §6 (handoff) in the same turn — do not block on the background job.
Use §6's "remaining **{m}** uploading in background" wording for the
handoff, not a totals report; a totals report only makes sense once the run
has actually finished. If you happen to observe the run finish later in the same
conversation (e.g. the user asks for a status check), report totals
(imported / skipped / failed) then and point the user at
<https://everme.evermind.ai> again. Failed sessions can be retried by
re-running the same command.

### 4.4 · Session import mechanics (shared by both steps)

Both Step 1 and Step 2 above invoke the same underlying command:

```bash
evercli import conversations run --platform <platform> [--since ...] [--limit N] --no-prompt [--async]
```

Specify one or more `--platform` values, taken from `approvedPlatforms` as defined at the top of §4 (e.g. `--platform claude-code --platform hermes`). The `--no-prompt` flag is required for non-interactive execution; it is only accepted when an explicit platform scope is given (to prevent accidental bulk import in CI).

Each platform uploads under its own identity (per-platform agent token). The command has two upload modes; the flag decides which:

- **Synchronous (default, Step 1's mode).** Each session is uploaded and flushed before the next one starts, and extraction is **triggered** by the time the session reports done. Slow but immediate: Step 1 therefore caps the run at one activation session.
- **Asynchronous (`--async`, Step 2's mode).** Every batch uses the offline import channel. Each session normally logs one `→ queued` line once its batches are durably accepted. There is no flush phase and the CLI does not wait for extraction. The session is marked submitted after the queued acknowledgement; replaying an interrupted request is safe because the server derives an idempotency key for each chunk.

Whether extraction has also **completed** is what the per-session status says — report it honestly (see the status table below): only `extracted` means the memories are on the page now.

Filter order inside `run` is `--since` → `--exclude` → submitted-drop →
`--limit`. After applying `--since`/`--exclude` and before applying
`--limit`, `run` drops sessions already marked `submitted` and prints one
stderr summary line: `skipped N previously imported session(s); pass
--force to re-upload`. This happens on every invocation, foreground or
background, with or without a window — and when `--since` scoped the run,
that skip-count reflects only in-window sessions, not the account-wide
total (use §4.1's scan `summary` for the full picture; see §4.3).

Additional flags available to the user (mention as relevant):

- `--dry-run` — scan and print a preview without uploading anything
- `--since YYYY-MM-DD` — only include sessions updated on or after this date; applied before `--exclude`, the submitted-drop, and `--limit`
- `--limit N` — cap the run to the N **most recent new** sessions (by date, newest first), applied last, after `--since`, `--exclude`, and the submitted-drop (see §4.3)
- `--exclude <path>` — exclude a specific session by path (repeatable; use the path shown in the scan list). Applied right after `--since`, so it only matches sessions inside that invocation's `--since` window, if any (see §4.3)
- `--force` — re-upload sessions already marked as submitted. In §4.3's real commands this is destructive of the user's quota and time; the only place this document uses it is §4.1.1, paired with `--dry-run`, where it merely keeps already-imported sessions visible in a preview that uploads nothing
- `--async` — the offline bulk mode described above (durable queued acknowledgement, no flush, eventual extraction). Older evercli builds reject it with `unknown flag: --async`; upgrade evercli rather than falling back to an unbounded foreground synchronous run

Per-item output looks like:

```
  [claude-code] /Users/.../.claude/projects/myproj/sess-abc.jsonl → extracted
  [hermes] /Users/.../.hermes/sessions/sess-xyz.json → extracted
```

Per-session status → what to tell the user:

| Status in the log | Meaning | Wording to use |
|---|---|---|
| `extracted` | Upload + flush + extraction all completed | "memories extracted — visible on the page now" |
| `queued` | The write was **accepted and enqueued** upstream; extraction has not run yet | "still processing — memories will appear on the page shortly." **Never** describe a `queued` session as extracted. |
| `extraction_pending` | Synchronous upload landed but its extraction trigger did not complete | "data is safe on the server — still processing." The session is marked submitted locally, so a bare re-run skips it. |
| `no_extraction` | The flush ran but boundary detection found nothing actionable to extract for this session (rare for imports) | "uploaded, but the server found nothing to extract for this session" |

On failure for individual items, the item is marked `failed` in local state and can be retried by re-running the same command. Other items are not affected.

**Markdown files are covered by the conversation import:** each agent's curated persona / memory Markdown zones are collected by `evercli import conversations scan/run` (the `markdown` platform). The legacy flat-file `import scan/run` pipeline is retired.

---

## 5 · Verify install (all branches)

**This step is required.** Do not jump to §6 final handoff until §5 has been run and passed. Silent half-failures (plugin "installed" but MCP server not picked up, agent registered but credentials unreadable, etc.) are the #1 source of bad first-run experience — `evercli doctor` is built specifically to catch them.

### 5.1 · Run the doctor

```bash
evercli doctor --format json
```

Expected success envelope:

```json
{
  "ok": true,
  "data": {
    "checks": [
      { "name": "network.everme-api",           "ok": true,  "severity": "critical" },
      { "name": "network.readyz",               "ok": true,  "severity": "warning"  },
      { "name": "credential.backend",           "ok": true,  "severity": "info"     },
      { "name": "credential.readable",          "ok": true,  "severity": "critical" },
      { "name": "plugin.claude-code.mcp-visible","ok": true, "severity": "warning"  }
    ],
    "summary": { "criticalFailed": 0, "warningFailed": 0 }
  }
}
```

Handling:

| Result | Action |
|---|---|
| `summary.criticalFailed > 0` | **Stop.** Read `error.hint` on each failed check. Address before continuing. Do NOT send the final handoff. |
| `summary.warningFailed > 0` | Continue, but call the specific warnings out in §6 so the user knows what to fix manually (the most common is `plugin.claude-code.mcp-visible` — needs user to approve via `/mcp` in Claude Code). |
| All `ok: true` | Continue to §6. |

The `plugin.claude-code.mcp-visible` check degrades to `severity: info` (and `ok: true`) when `claude` is not on PATH — that's expected on machines without Claude Code, not a failure.

### 5.2 · Cross-check the EverMe web dashboard

In `responseLanguage`, explain that <https://everme.evermind.ai/agents> is the
authoritative cloud-side view. Each registered machine and agent should appear
with the matching `agentId`, recent `lastActiveAt`, and
`connectionStatus: connected`.

This is the authoritative source of truth for "is my install really live" — it reflects what the backend sees, not just what your local config claims.

---

## 6 · Final handoff message (all branches)

Render the handoff in `responseLanguage`. Preserve the required information and
order below, but localize the prose. **All branches end with one restart action
and no text after it** — the EverMe plugin only loads on agent startup.

Restart command, by platform (include only the lines for platforms you
installed or refreshed):

| Platform | Restart |
|---|---|
| Claude Code | **Quit your current `claude` session** (Ctrl-D, type `/exit`, or close the terminal), then start a fresh one: `claude` |
| Claude Desktop | Fully quit the app (⌘Q on macOS, right-click tray icon → Quit on Windows), then relaunch from Applications / Start menu |
| OpenClaw | `openclaw gateway restart` |
| Codex (CLI) | Exit the current `codex` session (Ctrl-D or `/exit`), then run `codex` again |
| Codex (VS Code) | Reload the VS Code window (`Cmd-Shift-P` → "Developer: Reload Window") |
| Hermes | Quit the Hermes app / runtime and relaunch |
| Cursor | Quit Cursor (⌘Q) and reopen the project |
| Devin | Quit the Devin IDE and reopen the project |
| opencode | Quit the current `opencode` session and relaunch `opencode` |
| Kimi Code | Inside Kimi Code run `/plugins reload`, or start a new session (`/new`) |
| DeepSeek Harness | Restart the DSH Web session; a new Headless run loads the refreshed profile automatically |

The body must contain:

- new user: account email and masked `{apiKeyPrefix}****`; existing user:
  account email;
- successfully installed or refreshed platforms;
- newly detected agents the user declined in §3.1.1, if any — name them, say
  their history was not imported (only for the classes that have any), and give
  `evercli plugin install <host>` as the way to connect one later. Report this
  as a choice that was honored, not as an error;
- import outcome, including sessions and messages when available;
- health-check result and concrete warnings;
- dashboard link: <https://everme.evermind.ai/agents>;
- a short post-restart verification suggestion before the action block (new
  user: remember and recall a simple preference; existing user: recall an older
  discussion).

Finish with the localized §0.2 action heading and only the restart instructions
for installed platforms. The final restart command/instruction is the last line
of the message.

---

## 7 · Error and exit-code reference

Every `evercli` command returns one of these envelopes:

```json
// success
{ "ok": true,  "data": {...}, "meta": {...} }

// failure
{ "ok": false, "error": { "type": "...", "message": "...", "hint": "...", "detail": {...} }, "meta": {...} }
```

Exit codes:

| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Business error (validation, conflict, upstream) |
| 2 | Input validation |
| 3 | Auth (not logged in, key invalid) |
| 4 | Network / unreachable |
| 5 | Internal error |
| 130 | Cancelled (Ctrl+C) |

Common `error.type` values: `auth`, `network`, `conflict`, `validation`, `not_logged_in`, `plugin_not_detected`, `io`, `internal`.

Always surface `error.hint` to the user when present — it's written to be actionable.

---

## 8 · What NOT to do

- **Do not** invent flags. The only flags that exist on `evercli auth login` are `--api-key`, `--device-code`, `--no-wait`, `--format`. No `--scopes`, no `--browser`, no `--email`.
- **Do not** use `evercli onboard` — it has been removed. The three atomic commands above are the only supported path.
- **Do not** poll the device-code endpoint silently. Hand off to the user and wait for them to reply.
- **Do not** auto-connect a newly detected agent on a machine that already has EverMe connected. `installed: true && hasEverMeEntry: false` authorizes a silent install only on a first-time machine (§3.1 case 1a). On an already-connected machine it is case 1b and requires the §3.1.1 confirmation — the user asked to install or upgrade EverMe, not to connect an agent they never mentioned.
- **Do not** pass a platform to `--platform` that `import conversations plan` did not mark `included`, and do not re-derive that decision from `plugin list` or from the install report. The importer resolves that platform's agent token once per session: without a usable one you get a screen of `resolve evt for <platform>` errors and a wrong import count, not a clean skip — and with one belonging to a different agent you get no error at all, just history filed under the wrong identity. `plan` is the only place that distinction is computed; deriving it here by hand is what produced six rounds of contradictory rules.
- **Do not** auto-import memory. Always ask first for the *upload* step. Use `evercli import conversations scan` to preview sessions, show workload + paths + the privacy warning (§4.2), and require the localized semantic confirmation (`确认导入` / `Import`) before running `evercli import conversations run`.
- **Scanning locally without asking is expected — this does not contradict the rule above.** Run `evercli import conversations scan` unconditionally, the moment login + plugin install finish, with no permission check (§4). It is local, read-only, and uploads nothing, so it carries none of the risk the confirmation rule exists to prevent. Only the upload (`evercli import conversations run`) requires confirmation.
- **Do not** ask a second question before the bulk pass — the single §4.2 import confirmation authorizes both §4.3 passes. A synchronous `50301` / timeout is a degraded activation, not a reason to stop: exclude its Session path and launch Step 2. Stop only for authentication, credential, platform-token, configuration, wiring, or missing-CLI prerequisites. `Skip` / `跳过` means **no upload at all**. And **do not** launch Step 2 while Step 1 is still running: the two invocations share the same local idempotency state, and the unbounded bulk pass could re-select the activation session before Step 1 finishes.
- **Do not** report a `queued` session as extracted. `queued` means server-side extraction is still in progress — say it is "processing" and its memories will appear on the page shortly. Only sessions the log reports as `extracted` are done (see the §4.4 status table).
- **Do not** echo the full `emk_*` value back to the user — only the `apiKeyPrefix` returned by the CLI. The keychain holds the truth.
- **Do not** write `emk_*` or `evt_*` (full or prefixed-with-context) to any local file the agent might persist for itself — including but not limited to `MEMORY.md`, `~/.claude/projects/*/memory/`, `.cursorrules`, OpenClaw memos, session-summary notes, or auto-generated commit messages. These secrets belong only to the OS keychain (written by `evercli auth login` / `plugin install`) and the §6 handoff shown once to the user. Agent memory systems frequently sync to cloud storage or git — both wrong places for credentials. If your agent is about to save a turn that contains a key, redact it to the `emk_a1b2****` prefix form first.
- **Do not** retry-loop on `error.type: auth` — let the user correct the input.
- **Do not** attempt to restart the user's agent for them. Tell them to restart it manually — give the exact command for their platform (see §6 restart table).
- **Do not** skip §5 verify. `evercli plugin install` exiting 0 is necessary but not sufficient — the doctor command is the only thing that catches silent half-failures like "plugin registered but MCP server not approved" or "credentials written but unreadable."
- **Do not** assume `@everme/openclaw` comes from npm. It's resolved through **clawhub** (`clawhub:@everme/openclaw`) by the OpenClaw CLI — see §3 channel table and §3.2.
- **Do not** `npm install` `@everme/memory-mcp` or `@everme/claude-code` manually — `evercli plugin install` handles the fetch for you (the former via `npx -y` at agent startup, the latter via `npm install -g` triggered by evercli). `@everme/openclaw` is the exception: the user runs `openclaw plugins install @everme/openclaw` themselves after `evercli plugin install openclaw`, because OpenClaw's plugin loader owns that step — see §3.2.
- **Do not** instruct a Claude **Desktop** / Codex / Cursor / Hermes / Devin / opencode user to run `evercli plugin install claude-code` or `claude plugin install everme`. Those commands target Claude Code (the CLI) and either no-op or fail on the other hosts. The correct command is `evercli plugin install <their-host>` — see §3.4 for the per-host notes.
- **Do not** run `evercli plugin install manus` or invent a local install path for Manus — it does not exist. Manus is a hosted MCP agent registered entirely through the EverMe web page; send the user to `https://everme.evermind.ai/register-remote-agent?platform=manus&name=<name>` per §3.5, and never fabricate the hosted MCP URL or token yourself.
- **Do not** look for or suggest `evercli plugin register`. It was retired in V1 — every supported host now installs via `evercli plugin install <host>`, no manual paste, no one-shot token. Re-running `evercli plugin install` on an already-installed host rotates the token transparently (server-side upsert on `account_id + platform + machine_fingerprint`).

---

## 9 · Reference

**Plugin distribution channels** (see §3 for full retrieval-channel table):

- npm package (CLI wrapper): <https://www.npmjs.com/package/@everme/cli>
- npm package (Agent SDK): <https://www.npmjs.com/package/@everme/agent-sdk>
- npm package (Generic MCP server): <https://www.npmjs.com/package/@everme/memory-mcp>
- npm package (Claude Code plugin): <https://www.npmjs.com/package/@everme/claude-code>
- npm package (Kimi Code plugin): <https://www.npmjs.com/package/@everme/kimicode>
- **clawhub package (OpenClaw plugin)**: `clawhub:@everme/openclaw` — resolved by the OpenClaw CLI, not the npm registry. Source mirror at <https://www.npmjs.com/package/@everme/openclaw> is for reference only.
- GitHub Releases (CLI binary downloads): <https://github.com/EverMind-AI/EverMe/releases>

**EverMe endpoints (Beta):**

- Web dashboard: <https://everme.evermind.ai>
- **Registered agents view**: <https://everme.evermind.ai/agents> — authoritative source for "is my install actually live"
- API gateway (default): <https://api.everme.evermind.ai>
