@yugabytedb/meko-mcp 2.2.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -61
- package/assets/hooks-handlers/lib/capture-cleanup-cli.js +2134 -0
- package/assets/hooks-handlers/lib/capture-notices.js +224 -14
- package/assets/hooks-handlers/lib/capture-state.js +206 -1
- package/assets/hooks-handlers/lib/capture-status-cli.js +6 -2
- package/assets/hooks-handlers/lib/capture.js +1364 -139
- package/assets/hooks-handlers/lib/checkpoint-timer.js +445 -18
- package/assets/hooks-handlers/lib/journal-bridge.js +218 -0
- package/assets/hooks-handlers/lib/kiro-handler.js +26 -4
- package/assets/hooks-handlers/lib/opencode-handler.js +643 -0
- package/assets/hooks-handlers/lib/opencode-normalizer.js +145 -0
- package/assets/hooks-handlers/lib/terminal-handoff.js +10 -1
- package/assets/opencode-plugin/meko.js +213 -0
- package/assets/scripts/meko-statusline.sh +102 -19
- package/assets/skills/meko-mcp-tools/SKILL.md +59 -16
- package/assets/skills/meko-mcp-tools/references/_sections.md +2 -2
- package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +15 -7
- package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +275 -19
- package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +7 -4
- package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +39 -11
- package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +10 -6
- package/assets/skills/meko-mcp-tools/references/tools-overview.md +44 -29
- package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +79 -14
- package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +47 -1
- package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +6 -39
- package/assets/skills/meko-mcp-tools-desktop/SKILL.md +57 -21
- package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +4 -4
- package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +1 -1
- package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +8 -6
- package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +284 -38
- package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +32 -10
- package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +16 -12
- package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +46 -31
- package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +79 -14
- package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +69 -1
- package/assets/skills/meko-select-datapack-desktop/SKILL.md +93 -14
- package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +44 -12
- package/assets/skills/meko-select-datapack-desktop/references/role-display-future.md +14 -10
- package/assets/skills/meko-select-datapack-desktop/references/troubleshooting.md +17 -5
- package/bin/create-meko-setup.mjs +186 -30
- package/lib/autofix.mjs +100 -0
- package/lib/browser-login.mjs +495 -0
- package/lib/capture-cleanup.mjs +63 -0
- package/lib/clients/claude-code.mjs +1 -0
- package/lib/clients/codex.mjs +80 -35
- package/lib/clients/common.mjs +7 -0
- package/lib/clients/index.mjs +2 -0
- package/lib/clients/kiro.mjs +5 -5
- package/lib/clients/opencode.mjs +537 -0
- package/lib/config.mjs +68 -1
- package/lib/installer.mjs +18 -2
- package/lib/migrate/adapters/claude-code.mjs +11 -2
- package/lib/migrate/adapters/codex.mjs +9 -2
- package/lib/migrate/adapters/memory-md.mjs +27 -8
- package/lib/migrate/adapters/opencode.mjs +148 -0
- package/lib/migrate/claude-parser.mjs +153 -9
- package/lib/migrate/datapack.mjs +254 -16
- package/lib/migrate/id.mjs +195 -13
- package/lib/migrate/mcp-client.mjs +59 -1
- package/lib/migrate/opencode-normalizer.mjs +132 -0
- package/lib/migrate/orchestrator.mjs +294 -78
- package/lib/migrate/progress.mjs +239 -5
- package/lib/migrate/registry.mjs +72 -0
- package/lib/migrate.mjs +97 -9
- package/lib/validate.mjs +111 -22
- package/package.json +5 -5
- package/scripts/bundle-assets.mjs +4 -0
package/README.md
CHANGED
|
@@ -1,24 +1,43 @@
|
|
|
1
1
|
# Meko Setup Installer
|
|
2
2
|
|
|
3
|
-
A zero-dependency Node.js CLI that configures [Meko MCP Server](https://mekodata.netlify.app/) for Claude Code, Claude Desktop, Cursor, OpenAI Codex
|
|
3
|
+
A zero-dependency Node.js CLI that configures [Meko MCP Server](https://mekodata.netlify.app/) for Claude Code, Claude Desktop, Cursor, OpenAI Codex, Kiro, and OpenCode in one command. It registers MCP server settings, configures hook/runtime environment where supported, installs skills support, and validates the setup.
|
|
4
4
|
|
|
5
5
|
Reduces manual setup to a single command.
|
|
6
6
|
|
|
7
7
|
## What this installer authenticates with
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
Every client the installer configures authenticates with a Meko API key. Each
|
|
10
|
+
one sends `Authorization: Bearer <your-api-key>` on the wire, plus the
|
|
11
11
|
`User-Agent` the Cloud WAF requires. Most adapters store the header value in
|
|
12
12
|
client config. Codex stores `bearer_token_env_var = "MEKO_API_KEY"` and resolves
|
|
13
13
|
the key from its runtime environment; Claude Desktop passes the same variable
|
|
14
|
-
through `mcp-remote` header interpolation.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
through `mcp-remote` header interpolation. Capture hooks use the same key.
|
|
15
|
+
|
|
16
|
+
You don't need to have a key already. The installer gets one in this order:
|
|
17
|
+
|
|
18
|
+
1. `--api-key <key>`.
|
|
19
|
+
2. The `MEKO_API_KEY` environment variable.
|
|
20
|
+
3. **Browser sign-in (the default).** The installer opens the Meko sign-in page,
|
|
21
|
+
and after you sign in it creates a key named `Meko installer (<host>)
|
|
22
|
+
<timestamp>`. It uses the MCP server's OAuth flow with a `localhost`
|
|
23
|
+
callback, then calls the server's `POST /api-keys`. The OAuth session is
|
|
24
|
+
discarded; only the key is kept.
|
|
25
|
+
|
|
26
|
+
Sign in with the same method you use for the Meko console. If the browser
|
|
27
|
+
signs in as a user with no Meko account (for example Google here, email and
|
|
28
|
+
password in the console), the server refuses to create a key, and the
|
|
29
|
+
installer tells you how to retry or fall back to `--api-key`.
|
|
30
|
+
|
|
31
|
+
The new key counts toward your 10 active keys and expires after 365 days. You
|
|
32
|
+
can revoke it at cloud.mekodata.ai > **Settings > API Keys**. Use `--no-browser`
|
|
33
|
+
to print the sign-in URL instead of opening a browser, for example over SSH.
|
|
34
|
+
Runs with no terminal attached (CI, scripts, redirected stdin) skip sign-in and
|
|
35
|
+
require a key, with or without `--yes`.
|
|
36
|
+
|
|
37
|
+
Separately, some clients can run their own browser **OAuth** flow against Cloud
|
|
38
|
+
Meko, configured in the client's own UI with no API key. The installer doesn't
|
|
39
|
+
set that up. Don't configure both against the same client; see [Two
|
|
40
|
+
authentication modes](../README.md#two-authentication-modes--pick-one-dont-mix-them).
|
|
22
41
|
|
|
23
42
|
**Note:** The server accepts the key only as `Authorization: Bearer …` on the
|
|
24
43
|
wire. An `API_KEY` or `MEKO_API_KEY` environment variable does nothing unless
|
|
@@ -48,7 +67,7 @@ Claude Desktop has two install paths: a one-click `.mcpb` Desktop Extension down
|
|
|
48
67
|
npx @yugabytedb/meko-mcp
|
|
49
68
|
```
|
|
50
69
|
|
|
51
|
-
The installer walks you through connection type
|
|
70
|
+
The installer walks you through connection type and URL, signs you in through your browser to create an API key (unless you pass `--api-key` or set `$MEKO_API_KEY`), then asks about skills.
|
|
52
71
|
|
|
53
72
|
**Local one-liner (docker-compose stack already running):**
|
|
54
73
|
|
|
@@ -62,6 +81,16 @@ npx @yugabytedb/meko-mcp --local --yes
|
|
|
62
81
|
npx @yugabytedb/meko-mcp --client cursor --local --scope project --yes
|
|
63
82
|
```
|
|
64
83
|
|
|
84
|
+
**OpenCode CLI/TUI 1.18.x install:**
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx @yugabytedb/meko-mcp --client opencode --scope user --yes
|
|
88
|
+
# Project-scoped plugin, runtime, and skill:
|
|
89
|
+
npx @yugabytedb/meko-mcp --client opencode --scope project --yes
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Restart OpenCode after either install.
|
|
93
|
+
|
|
65
94
|
**Claude Desktop install:**
|
|
66
95
|
|
|
67
96
|
Claude Desktop has two install paths — pick based on whether you want the agent skill (the behavioral guide that teaches the agent *when* to call Meko tools — how to capture turns via per-turn `conversation_add_message` posting so the server can extract memories, and when the narrow explicit `memory_add` cases apply):
|
|
@@ -78,7 +107,7 @@ You can also combine both: install via `.mcpb` for the MCP wiring, then run Opti
|
|
|
78
107
|
|
|
79
108
|
**Option A — Desktop Extension (`.mcpb`), one-click:**
|
|
80
109
|
|
|
81
|
-
1. Download `meko-<version>.mcpb` from the [GitHub Releases page](https://github.com/yugabyte/meko-mcp-server/releases) (e.g. `meko-
|
|
110
|
+
1. Download `meko-<version>.mcpb` from the [GitHub Releases page](https://github.com/yugabyte/meko-mcp-server/releases) (e.g. `meko-2.5.0.mcpb`). From 2.5.0, the `.mcpb`, the npm installer, and the public plugin share one version number.
|
|
82
111
|
2. Open **Claude Desktop > Settings > Extensions > Install from file** and select the file (or drag the file onto that pane).
|
|
83
112
|
3. When prompted, paste your Meko MCP URL and API key.
|
|
84
113
|
4. Quit and relaunch Claude Desktop.
|
|
@@ -120,13 +149,19 @@ Re-run the installer to refresh the bundles when skill content updates; you'll n
|
|
|
120
149
|
# Target two clients in one run:
|
|
121
150
|
npx @yugabytedb/meko-mcp --client claude-code,claude-desktop --local --yes
|
|
122
151
|
|
|
123
|
-
# Target every supported client
|
|
152
|
+
# Target every supported client:
|
|
124
153
|
npx @yugabytedb/meko-mcp --client all --local --yes
|
|
125
154
|
```
|
|
126
155
|
|
|
127
156
|
Each client is installed sequentially. A failure on one does not abort the others — the command exits with status 2 on partial success, 1 on total failure.
|
|
128
157
|
|
|
129
|
-
**
|
|
158
|
+
**Cloud Meko (signs in through your browser):**
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npx @yugabytedb/meko-mcp --url https://mcp.mekodata.ai/mcp --client claude-code
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**CI / non-interactive (Cloud Meko, existing API key):**
|
|
130
165
|
|
|
131
166
|
```bash
|
|
132
167
|
npx @yugabytedb/meko-mcp \
|
|
@@ -145,13 +180,13 @@ The installer performs up to 5 steps (some are skippable via flags):
|
|
|
145
180
|
| 2 | Set hook environment vars | Writes `MEKO_MCP_URL` and `MEKO_API_KEY` into `~/.claude/settings.json` under the `env` key. Also prunes any stale Meko hook entries in `settings.json.hooks` that point at a prior install path (e.g. a previous `npx` cache or homebrew-global copy) so only the current install's hooks fire. |
|
|
146
181
|
| 3 | Register public plugin marketplace | `claude plugin marketplace add https://github.com/yugabyte/meko-skills.git --scope user` |
|
|
147
182
|
| 4 | Install skills plugin | `claude plugin install meko-agent-skills --scope user` |
|
|
148
|
-
| 5 | Validate setup | Config check via `claude mcp list`, MCP `initialize` handshake, `tools/list` verification, and a canary `
|
|
183
|
+
| 5 | Validate setup | Config check via `claude mcp list`, MCP `initialize` handshake, `tools/list` verification, and a canary `datapack_search` call (`datapack_list` on older servers) |
|
|
149
184
|
|
|
150
185
|
### Post-install validation (canary)
|
|
151
186
|
|
|
152
|
-
Step 5 includes a **canary call** that invokes the read-only `
|
|
187
|
+
Step 5 includes a **canary call** that invokes the read-only `datapack_search(limit=1)` tool and asserts it returns at least one datapack. On a server whose `tools/list` has no `datapack_search`, it calls `datapack_list` instead and asserts a non-empty JSON array; `datapack_search` reads one page whatever the account size, where `datapack_list` reads the whole account. This proves the part of the stack that connectivity + `tools/list` don't cover: the API token authenticated as a real Meko identity, the tenant resolver found an account for it, and datapack routing wired up the user's actual workspace. A successful `tools/list` only proves the server speaks MCP — it says nothing about whether a Meko tool call would actually find the user's data.
|
|
153
188
|
|
|
154
|
-
The canary used to do a `memory_add` → `memory_get_by_id` → `memory_delete_by_id` round-trip, but mem0's LLM fact-extractor is non-deterministic for synthetic test text — for the same input it sometimes returned `results: []` (no facts extracted) while still adding graph relations, which the installer reported as "no memory id" and surfaced as a validation failure even when the server was healthy.
|
|
189
|
+
The canary used to do a `memory_add` → `memory_get_by_id` → `memory_delete_by_id` round-trip, but mem0's LLM fact-extractor is non-deterministic for synthetic test text — for the same input it sometimes returned `results: []` (no facts extracted) while still adding graph relations, which the installer reported as "no memory id" and surfaced as a validation failure even when the server was healthy. Both datapack tools are a single SQL read with no LLM in the path and return deterministically.
|
|
155
190
|
|
|
156
191
|
`--no-canary` skips the canary entirely. The `initialize` and `tools/list` checks still run. Use this when you've already proved the round-trip in a prior step (CI, pre-flight smoke).
|
|
157
192
|
|
|
@@ -173,7 +208,7 @@ The canary used to do a `memory_add` → `memory_get_by_id` → `memory_delete_b
|
|
|
173
208
|
- MCP config: `~/.codex/config.toml` (TOML; `[mcp_servers.<name>]` block).
|
|
174
209
|
- Skills path: `~/.agents/skills/meko-mcp-tools/` (the shared agent-skills convention).
|
|
175
210
|
- System prompt: `~/.codex/AGENTS.md` (a Meko-managed sentinel block is upserted; user content outside the fence is preserved).
|
|
176
|
-
- **Cloud auth (MCP server)**: Codex's TOML stores `bearer_token_env_var = "MEKO_API_KEY"` rather than the key itself. You must export `MEKO_API_KEY` in your shell before launching Codex. The installer offers (interactively, never with `--yes`) to append the export line to your shell rc (`~/.zshrc` / `~/.bashrc` / `~/.config/fish/config.fish`). On macOS, when
|
|
211
|
+
- **Cloud auth (MCP server)**: Codex's TOML stores `bearer_token_env_var = "MEKO_API_KEY"` rather than the key itself. You must export `MEKO_API_KEY` in your shell before launching Codex. The installer offers (interactively, never with `--yes`) to append the export line to your shell rc (`~/.zshrc` / `~/.bashrc` / `~/.config/fish/config.fish`). On macOS, when an API key is supplied, the installer offers to run `launchctl setenv MEKO_API_KEY ...` (default Yes) so GUI-launched Codex - the desktop app from Finder/Dock, or the CLI from Spotlight/Alfred/`open` - can authenticate in the current login session. The prompt calls out that `launchctl setenv` writes into the login-session env inherited by every subsequently GUI-launched process (visible via `launchctl getenv`, `ps e` on descendants, and crash reports); decline the offer if that exposure is not acceptable for the host and rely on shell rc instead.
|
|
177
212
|
- **Cloud WAF User-Agent** (cloud installs only): Cloud Meko sits behind a WAF that returns an HTML `403 Forbidden` for any HTTP request with no `User-Agent`. Codex's native MCP client sends none by default, so its `initialize` handshake would 403 and the `meko` server would fail to start with `MCP client for 'meko' failed to start ... HTTP 403`. `codex mcp add` exposes no header flag, so the installer writes a per-server header into `~/.codex/config.toml`:
|
|
178
213
|
```toml
|
|
179
214
|
[mcp_servers.meko]
|
|
@@ -191,6 +226,24 @@ The canary used to do a `memory_add` → `memory_get_by_id` → `memory_delete_b
|
|
|
191
226
|
- Managed CLI 2.x agent: `~/.kiro/agents/meko-default.json` or `.kiro/agents/meko-default.json`, with inline `agentSpawn`, `userPromptSubmit`, and `stop` hooks. The installer preserves the previous `chat.defaultAgent` before selecting it.
|
|
192
227
|
- Stable capture runtime: `~/.kiro/hooks/meko-hooks/hooks-handlers/` or the project equivalent. `kiro-hook-env.json` stores the endpoint and optional API key at mode 0600.
|
|
193
228
|
- Steering file: `~/.kiro/steering/meko.md` or `.kiro/steering/meko.md`. It follows hook capture when the session-start marker is present and falls back to agent-driven persistence only when hooks are disabled, untrusted, or a different CLI 2.x agent is selected. See [Kiro notes](#kiro-notes).
|
|
229
|
+
- **OpenCode CLI/TUI 1.18.x**
|
|
230
|
+
- User plugin: `$OPENCODE_CONFIG_DIR/plugins/meko.js` when set, otherwise `~/.config/opencode/plugins/meko.js`; project plugin: `<project>/.opencode/plugins/meko.js`.
|
|
231
|
+
- Stable runtime and private environment: `$OPENCODE_CONFIG_DIR/meko/` when set, otherwise `~/.config/opencode/meko/`, or `<project>/.opencode/meko/`. `opencode-hook-env.json` is mode 0600 and contains the MCP URL, API key, server name, User-Agent, hook client, stable Node executable, and watermark dir. Edits to this file reach the next capture attempt, including the retries of a running capture timer. Removing `MEKO_MCP_URL` or `MEKO_API_KEY` from the file, as `--uninstall` does, also removes it from a running timer's next attempt. Automatic capture uses the server-default datapack in this release. `--datapack` applies only to `--migrate`. OpenCode does not read `pin-<slug>.json` (no SessionStart, and `meko-select-datapack` is not installed).
|
|
232
|
+
- Skill: `$OPENCODE_CONFIG_DIR/skills/meko-mcp-tools/` when set, otherwise `~/.config/opencode/skills/meko-mcp-tools/`, or `<project>/.opencode/skills/meko-mcp-tools/`.
|
|
233
|
+
- The plugin mutates OpenCode's resolved configuration at runtime with a native remote MCP entry (`type: remote`, `enabled: true`, `oauth: false`). It does **not** edit `opencode.json` or `opencode.jsonc`; validation runs `opencode debug config` and verifies the resolved entry.
|
|
234
|
+
- Restart OpenCode after install. Reinstall upgrades installer-owned assets while preserving durable capture state and user-owned collisions.
|
|
235
|
+
|
|
236
|
+
### OpenCode CLI / TUI 1.18.x
|
|
237
|
+
|
|
238
|
+
OpenCode **1.18.x only** is supported in this release; 1.18.22 is the initial canary baseline. The installer rejects older releases and future minor/major versions until they are explicitly certified because OpenCode's plugin and MCP configuration APIs are evolving.
|
|
239
|
+
|
|
240
|
+
The installer-owned plugin listens to OpenCode's public `event({event})` hook. On `session.idle` and `session.error`, it fetches `session.get({path:{id}})` and `session.messages({path:{id}})`, strips the snapshot to visible text plus stable IDs/timestamps, and hands it to Capture v2. Duplicate completed turns are skipped by OpenCode message IDs. A `session.error` snapshot does not rewrite a completed turn and does not append a synthetic `u1:interrupted` user id. A failed handoff leaves a staged snapshot under the durable capture root for startup replay; structurally invalid snapshots are quarantined.
|
|
241
|
+
|
|
242
|
+
**Capture boundary:** one visible user message plus the first visible assistant message before the next user message becomes one Meko turn. Later assistant messages in the same turn are dropped. Multiple visible text parts on that first assistant retain order. Tool calls/results, reasoning, files, attachments, steps, snapshots, patches, text explicitly marked ignored or synthetic, and binary content are excluded. OpenCode compaction-summary exclusion is not certified because the 1.18.22 export shape has not been frozen in a real fixture. Active incomplete turns remain pending until a later snapshot completes them, a later user turn interrupts them, or the 30-minute settle deadline expires (every Capture v2 timer that shares the capture root uses that default; `MEKO_OPENCODE_SETTLE_MS` is a same-process test override). `session.error` holds a partial assistant as a tentative observation until OpenCode rewrites that assistant in place on idle, a later user turn interrupts, or that deadline expires. A later distinct user turn interrupts the prior pending user. Ownership is `opencode:<repo>`, derived at capture from the session directory (the plugin does not inject `agent_id`). Health is visible through `create-meko-setup --capture-status`.
|
|
243
|
+
|
|
244
|
+
**Migration:** `create-meko-setup --migrate` invokes only supported public CLI commands (`opencode session list --format json` and `opencode export <sessionID>`); it never reads OpenCode's SQLite database or internal storage. User scope is a cwd-backed superset that includes the active project. OpenCode 1.18.x lists root sessions only, so child sessions are not migrated. An unsupported OpenCode version is skipped without blocking Claude Code, Cursor, or Codex migration. The current durable root-session view is migrated, not a historical event log.
|
|
245
|
+
|
|
246
|
+
**Not supported yet:** OpenCode Desktop certification, V2 preview APIs/configuration, pre-1.18 or post-1.18 versions, GitHub agent/headless server/remote workspace/shared-session migration, parent-child tree reconstruction, tool/reasoning/file/attachment capture, and incremental streaming capture.
|
|
194
247
|
|
|
195
248
|
## CLI Reference
|
|
196
249
|
|
|
@@ -201,16 +254,17 @@ Usage:
|
|
|
201
254
|
|
|
202
255
|
| Flag | Description | Default |
|
|
203
256
|
|------|-------------|---------|
|
|
204
|
-
| `--client <list>` | Target client(s): one or more of `claude-code`, `claude-desktop`, `cursor`, `codex`, `kiro`. Comma-separated, or `all`. `codex` covers both the OpenAI Codex CLI and the Codex Desktop App (they share `~/.codex/config.toml`); `kiro` covers both the Kiro IDE and `kiro-cli` (they share `~/.kiro/settings/mcp.json`). Aliases: `claude` → `claude-code`, `kiro-cli` / `kiro-ide` → `kiro`. | `claude-code` |
|
|
257
|
+
| `--client <list>` | Target client(s): one or more of `claude-code`, `claude-desktop`, `cursor`, `codex`, `kiro`, `opencode`. Comma-separated, or `all`. `codex` covers both the OpenAI Codex CLI and the Codex Desktop App (they share `~/.codex/config.toml`); `kiro` covers both the Kiro IDE and `kiro-cli` (they share `~/.kiro/settings/mcp.json`). OpenCode is version-gated to CLI/TUI 1.18.x. Aliases: `claude` → `claude-code`, `kiro-cli` / `kiro-ide` → `kiro`. | `claude-code` |
|
|
205
258
|
| `--url <url>` | MCP server URL (from cloud.mekodata.ai > Datapacks > Connect) | Shared existing endpoint, otherwise production; conflicts prompt or require `--url` under `--yes` |
|
|
206
|
-
| `--api-key <key>` |
|
|
259
|
+
| `--api-key <key>` | Use an existing Cloud Meko API key instead of signing in. Without this flag, the installer falls back to `$MEKO_API_KEY`, then to browser sign-in, which creates a key. Fails hard when no TTY is attached, with or without `--yes`. | _(`$MEKO_API_KEY`, else browser sign-in)_ |
|
|
260
|
+
| `--no-browser` | Print the sign-in URL instead of opening a browser. | `false` |
|
|
207
261
|
| `--local` | Use local Meko at `http://localhost:8000/mcp` (no API key needed) | `false` |
|
|
208
262
|
| `--scope <scope>` | Config scope: `user` or `project` (`claude-desktop` uses user scope config) | `user` |
|
|
209
263
|
| `--name <name>` | MCP server name in config | `meko` |
|
|
210
264
|
| `--cursor-hook-mode <mode>` | Cursor hook strategy: `native` or `claude-compat` | `native` |
|
|
211
265
|
| `--skip-skills` | Skip plugin marketplace and skills installation (steps 3-4) | `false` |
|
|
212
266
|
| `--skip-validation` | Skip post-install validation (step 5) | `false` |
|
|
213
|
-
| `--no-canary` | Skip the canary `datapack_list` call. Basic connectivity + tools/list still run. | `false` |
|
|
267
|
+
| `--no-canary` | Skip the canary `datapack_search` / `datapack_list` call. Basic connectivity + tools/list still run. | `false` |
|
|
214
268
|
| `--dry-run` | Show what would be done without making changes | `false` |
|
|
215
269
|
| `--uninstall` | Remove Meko MCP server, skills, env vars, and marketplace entry | `false` |
|
|
216
270
|
| `--verbose` | Show detailed output (API keys are always redacted) | `false` |
|
|
@@ -223,13 +277,20 @@ Capture health flags (durable outbox / recovery — Capture V2):
|
|
|
223
277
|
| Flag | Description | Default |
|
|
224
278
|
|------|-------------|---------|
|
|
225
279
|
| `--capture-status` | Report aggregate conversation-capture health from `~/.claude/meko-capture` (or `MEKO_WATERMARK_DIR`). Exit `0` = healthy\|catching_up, `2` = degraded_retrying, `3` = blocked_action_required. | `false` |
|
|
226
|
-
| `--json` | With `--capture-status`, print machine-readable JSON matching the capture-health cache shape. | `false` |
|
|
280
|
+
| `--json` | With `--capture-status`, print machine-readable JSON matching the capture-health cache shape. Also accepted by `--capture-cleanup`. | `false` |
|
|
281
|
+
| `--no-autofix` | Turn off automatic capture repair. The capture timer otherwise runs `--capture-cleanup fix` every 30 minutes (`MEKO_AUTOFIX_INTERVAL`) when a session is stuck. Saved for every client; a reinstall keeps it. | `false` |
|
|
282
|
+
| `--autofix` | Turn automatic capture repair back on. | `false` |
|
|
283
|
+
| `--capture-cleanup <action>` | Inspect and clean up stuck capture on this machine. Actions: `status`, `fix`, `stop`, `resume`, `drain`, `discard`, `repair`. Start with `fix`. See [Clean up stuck capture](../OPERATIONS.md#clean-up-stuck-capture). Exit `0` = done, `1` = error, `2` = partly done. | |
|
|
284
|
+
| `--session <id>` | With `--capture-cleanup`, act on one session. Repeatable; a unique prefix of the ID is enough. A bare ID after the action works too: `--capture-cleanup drain c0acdeb2`. | |
|
|
285
|
+
| `--all` | With `--capture-cleanup`, act on every session. `drain` and `discard` need `--session` or `--all`. | `false` |
|
|
286
|
+
| `--max-exchanges <n>` | With `--capture-cleanup drain`, stop after sending this many exchanges in total. | `200` |
|
|
287
|
+
| `--pace-ms <n>` | With `--capture-cleanup drain`, wait this long between batches. | `1000` |
|
|
227
288
|
|
|
228
289
|
Migrate subcommand flags (see [Migrate Existing Data](#migrate-existing-data) below for details):
|
|
229
290
|
|
|
230
291
|
| Flag | Description | Default |
|
|
231
292
|
|------|-------------|---------|
|
|
232
|
-
| `--migrate` | Start a detached migration of existing Claude Code
|
|
293
|
+
| `--migrate` | Start a detached migration of existing Claude Code, Cursor, Codex, and OpenCode sessions plus `CLAUDE.md` memories into Meko. | `false` |
|
|
233
294
|
| `--with-migrate` | With `--yes`, kick off `--migrate` at the end of a successful install without prompting. CI-friendly. | `false` |
|
|
234
295
|
| `--migrate-status` | Print the status of the latest (or `--run-id`-specified) migration run. | `false` |
|
|
235
296
|
| `--migrate-stop` | Stop the running migration (SIGTERM, then SIGKILL after 2s). | `false` |
|
|
@@ -246,8 +307,9 @@ After installing Meko, `--migrate` seeds your new datapack with the conversation
|
|
|
246
307
|
|
|
247
308
|
| Source | Location | Becomes |
|
|
248
309
|
|---|---|---|
|
|
249
|
-
| Claude Code transcripts | `~/.claude/projects/<slug>/<uuid>.jsonl` | One Meko conversation (one Langfuse trace) per session; one paired user↔assistant turn per message pair. |
|
|
310
|
+
| Claude Code transcripts | `~/.claude/projects/<slug>/<uuid>.jsonl` | One Meko conversation (one Langfuse trace) per session; one paired user↔assistant turn per message pair. Skill bodies and task notifications join the `reasoning` of the turn they belong to, and a typed `/skill args` becomes that turn's input, as in live capture. |
|
|
250
311
|
| Cursor transcripts | `~/.cursor/projects/<name>/agent-transcripts/<uuid>/*.jsonl` | Same — one conversation per session, one paired turn per user↔assistant round. |
|
|
312
|
+
| OpenCode sessions | Public CLI: `opencode session list --format json`, then `opencode export <sessionID>` | One Meko conversation per root session with directory metadata; visible text only. |
|
|
251
313
|
| User-scope CLAUDE.md | `~/.claude/CLAUDE.md` | One memory per top-level `# ` section (`agent_id = "meko_agent"` — the cross-project common bucket — with `metadata.scope = "user"`). |
|
|
252
314
|
| Project-scope CLAUDE.md | `<projectCwd>/.claude/CLAUDE.md` | One memory per top-level `# ` section (`agent_id = "claude_code:<repo-basename>"`, `metadata.scope = "project"`, `metadata.cwd = <project path>`). |
|
|
253
315
|
| Indexed project memories | `~/.claude/projects/<slug>/memory/*.md` | One memory per file (`agent_id = "claude_code:<repo-basename>"`); YAML frontmatter (`name`, `description`, `type`) is preserved in metadata. |
|
|
@@ -256,12 +318,14 @@ Project `cwd` is derived by reading the `cwd` field from a real session file in
|
|
|
256
318
|
|
|
257
319
|
### What the migrator writes (MCP calls)
|
|
258
320
|
|
|
259
|
-
Per migrated Claude Code / Cursor session:
|
|
321
|
+
Per migrated Claude Code / Cursor / Codex session:
|
|
260
322
|
|
|
261
|
-
1. **`conversation_create`** — once per session. Captures `cwd`, `
|
|
323
|
+
1. **`conversation_create`** — once per session. Captures `cwd`, `startedAt`, and source agent (`claude-code`, `cursor`, or `codex`) in metadata. Returns the `conversation_id` used for subsequent calls. `gitBranch` is set only for Claude Code (its refs have a slug). Cursor and Codex send null.
|
|
262
324
|
2. **`conversation_add_message`** — once per paired user↔assistant turn. Carries `input`, `output`, and `reasoning` (thinking blocks + tool-use/tool-result summaries), plus a deterministic `seed` for server-side dedup. Fire-and-forget; Meko batches to Langfuse.
|
|
263
325
|
3. **`memory_add(messages=[{role,content},...])`** — once per paired turn. This invokes Meko's server-side Mem0 extractor (the same pipeline the demo chatbot uses at `chatbot.py:177-178`) so the migrator seeds structured memories, not just raw transcripts. Skipped entirely under `--no-extract`.
|
|
264
326
|
|
|
327
|
+
Per migrated OpenCode session: the same three calls, with two differences. `gitBranch` is always null because OpenCode refs have no slug. The adapter sets `reasoning` to `""`, and the orchestrator omits the field (`reasoning || undefined`), so the MCP call has no `reasoning` key.
|
|
328
|
+
|
|
265
329
|
Per CLAUDE.md / memory directory discovered:
|
|
266
330
|
|
|
267
331
|
4. **`conversation_create`** — one umbrella "memory-migration" conversation per agent (reused for all MD items under that agent, to satisfy Meko's `memory_add` requirement that memories be associated with a conversation).
|
|
@@ -273,6 +337,8 @@ So a real run exercises **both** the Langfuse observability surface (1 + 2) and
|
|
|
273
337
|
Dry run:
|
|
274
338
|
Claude Code sessions: 94
|
|
275
339
|
Cursor sessions: 10
|
|
340
|
+
Codex sessions: 3
|
|
341
|
+
OpenCode sessions: 4
|
|
276
342
|
Paired user↔asst turns: 887
|
|
277
343
|
Memory items (MD): 14
|
|
278
344
|
Planned MCP calls:
|
|
@@ -291,7 +357,7 @@ The Meko MCP server does **not** currently auto-extract memories on `conversatio
|
|
|
291
357
|
|
|
292
358
|
### Scope
|
|
293
359
|
|
|
294
|
-
- `--scope user` (default) — every
|
|
360
|
+
- `--scope user` (default) — every supported local session found by the registered migration adapters, plus `~/.claude/CLAUDE.md`, plus every per-project `.claude/CLAUDE.md` and indexed `memory/*.md` directory.
|
|
295
361
|
- `--scope project` — only sessions whose `cwd` equals `process.cwd()`, plus that one project's `.claude/CLAUDE.md` and memory directory.
|
|
296
362
|
|
|
297
363
|
### Running
|
|
@@ -322,32 +388,36 @@ create-meko-setup --migrate --scope user --no-extract
|
|
|
322
388
|
|
|
323
389
|
```
|
|
324
390
|
run-id: 20260429-000912-74dbe6
|
|
325
|
-
status: running (
|
|
391
|
+
status: running (running → succeeded | failed | cancelled; crashed is inferred)
|
|
326
392
|
scope: user
|
|
327
393
|
started: 2026-04-29T00:09:12.673Z
|
|
328
394
|
finished: (in progress)
|
|
329
|
-
|
|
395
|
+
heartbeat: 2026-04-29T00:14:02.118Z (refreshed while running; staleness implies crashed)
|
|
396
|
+
current: agent / a2f6a1d6-... / 7c1e0b44-... (<agent-id> / <source-session> / <message-id>)
|
|
330
397
|
sessions: 76 / 111 (processed / discovered)
|
|
331
398
|
messages: 674
|
|
332
399
|
memory pairs: 674 (memory_add from Mem0 extractor)
|
|
333
400
|
memory (MD): 0 (memory_add from CLAUDE.md / memory files)
|
|
334
401
|
warnings: 0 (non-fatal; run continues)
|
|
335
402
|
memory errs: 0 (failed memory_add calls; re-run with --force to retry)
|
|
403
|
+
auth skipped: 0 (calls dropped on a mid-run 401/403; re-run to retry them)
|
|
336
404
|
```
|
|
337
405
|
|
|
338
406
|
| Field | Meaning |
|
|
339
407
|
|---|---|
|
|
340
408
|
| `run-id` | Unique ID; also the directory name under `~/.meko/migrate/<run-id>/`. |
|
|
341
|
-
| `status` |
|
|
409
|
+
| `status` | `running` while the daemon is alive; `succeeded`, `failed`, or `cancelled` once it ends. A fifth value, `crashed`, is not stored: the status command reports it for a run whose daemon is gone (dead PID, or a heartbeat older than 30 s), which is what a `kill -9`, an OOM kill, or a reboot looks like. On `failed`, an `error:` line carries the reason. |
|
|
342
410
|
| `scope` | Matches the `--scope` flag used at start (`user` or `project`). |
|
|
343
|
-
| `started` / `finished` | UTC timestamps. `finished` shows `(in progress)` until a terminal state is reached. |
|
|
344
|
-
| `
|
|
411
|
+
| `started` / `finished` | UTC timestamps. `finished` shows `(in progress)` until a terminal state is reached, or `(never, daemon died)` for a crashed run. |
|
|
412
|
+
| `heartbeat` | Last time the daemon touched `progress.json`. Refreshed every 10 s while running. |
|
|
413
|
+
| `current` | Which source item is being replayed: `<agent-id> / <source-session-uuid> / <source-message-uuid>`, where `<agent-id>` is the owner such as `opencode:<repo>` or `claude_code:<repo>`. Becomes `-` once the run reaches a terminal state. |
|
|
345
414
|
| `sessions` | Conversation sessions processed / discovered across all adapters. Climbs during the run. |
|
|
346
415
|
| `messages` | Total messages replayed so far via `conversation_add_message`. |
|
|
347
416
|
| `memory pairs` | `memory_add` calls made via the Mem0 extractor path (messages-style input). Usually close to `messages` when the extractor is enabled. |
|
|
348
417
|
| `memory (MD)` | `memory_add` calls from `CLAUDE.md` / memory-file sources (plain-text input). |
|
|
349
418
|
| `warnings` | Non-fatal issues (skipped item, partial parse). Run keeps going. |
|
|
350
419
|
| `memory errs` | `memory_add` calls that failed. Non-zero means the memory extractor couldn't reach the server or rejected the payload — check the per-run log. Re-run with `--force` to retry only the failed items. |
|
|
420
|
+
| `auth skipped` | Calls dropped because the server returned 401/403 partway through the run, typically an expired token. The session that hit the 401/403 stops at that turn and is marked failed, and the run moves on to the next session. Each dropped call is recorded in `log.ndjson` as `message_skipped_auth`. Refresh the credential and re-run without `--force`: the run resumes each failed session from its last delivered turn. |
|
|
351
421
|
|
|
352
422
|
### Behavior around install
|
|
353
423
|
|
|
@@ -355,39 +425,49 @@ memory errs: 0 (failed memory_add calls; re-run with --force to
|
|
|
355
425
|
- **`--yes` without `--with-migrate`**: install succeeds silently and prints a one-line tip pointing at `create-meko-setup --migrate`. No migration is started.
|
|
356
426
|
- **`--yes --with-migrate`**: install succeeds, then the detached migration is started automatically. Progress via `--migrate-status`.
|
|
357
427
|
|
|
428
|
+
### Destination datapack
|
|
429
|
+
|
|
430
|
+
`--datapack <name|id>` picks the datapack the migration writes to; without it the migration uses `meko_default_datapack`, or the server's own default when that row isn't visible. The resolved destination is printed before the run starts.
|
|
431
|
+
|
|
432
|
+
- A name is looked up with `datapack_search(name=...)`, preferring a datapack you own over a shared one with the same name. A miss lists similar names.
|
|
433
|
+
- A UUID is looked up with `datapack_describe`, so any datapack the API key can open resolves, however many the account has.
|
|
434
|
+
- On a server whose `tools/list` has no `datapack_search`, both are matched against the `datapack_list` response instead.
|
|
435
|
+
|
|
358
436
|
### Idempotency, resume, and state
|
|
359
437
|
|
|
360
|
-
- Per-run logs: `~/.meko/migrate/<run-id>/log.ndjson` (one JSON object per line). `tail -f | jq .` is a reasonable debug loop.
|
|
438
|
+
- Per-run logs: `~/.meko/migrate/<run-id>/log.ndjson` (one JSON object per line). `tail -f | jq .` is a reasonable debug loop. This is the file the start banner points at, and the only one with run diagnostics in it.
|
|
439
|
+
- `~/.meko/migrate/<run-id>/stdout.log` is the daemon's redirected stdout/stderr. It is normally empty, because every diagnostic goes through the NDJSON logger instead. Non-empty means output escaped the logger: a stack trace from before it opened, or a native crash.
|
|
361
440
|
- Per-run progress snapshot: `~/.meko/migrate/<run-id>/progress.json` (what `--migrate-status` reads).
|
|
362
441
|
- Durable state: `~/.meko/migrate/state/<datapack-key>.json` tracks per-session checkpoints (`conversationId`, `messagesSent`, `lastUuid`, `status`) and per-memory content hashes, **scoped per destination datapack**. A re-run skips sessions marked `done` and memories whose body hash is unchanged. A partial session resumes from `lastUuid + 1`.
|
|
363
442
|
- **Per-datapack scoping**: the datapack key is the UUID segment of the MCP URL (`https://<uuid>.mcp.mekodev.com/mcp` → `<uuid>`), or a stable 16-char sha256 prefix for non-UUID URLs (e.g. `http://localhost:8000/mcp`). Switching datapacks produces completely independent state — migrating into a fresh datapack never falsely treats sessions as already-done just because an earlier run populated a different one. `--migrate-status` prints the `datapack:` key of the latest run so you can tell at a glance which state it belongs to.
|
|
364
443
|
- Back-compat for the legacy layout: migrations created before this change wrote to a single `~/.meko/migrate/state.json`. On the first run after upgrading, if `state/` is empty and `state.json` exists, the installer asks (or, under `--yes` / CI, silently accepts) "treat the legacy state as belonging to the current datapack" and copies `state.json` → `state/<current-key>.json`. The legacy file is kept on disk in case you roll back the installer.
|
|
365
444
|
- Server-side dedup: `conversation_add_message` gets a deterministic `seed = sha256(agentId + ":" + sessionUuid + ":" + messageUuid)` so partial-run overlap doesn't create duplicate messages.
|
|
366
445
|
- `--force` wipes the **current datapack's** resume state and re-issues every MCP call for it. Other datapacks' state files are untouched. If you only want to re-migrate into a new datapack, just point `--url` at the new one — no `--force` needed.
|
|
446
|
+
- `--force` doesn't remove messages that an older installer stored and this version no longer produces. Installers before 2.3.0 stored each Claude Code task notification as its own message, with the notification as input. 2.3.0 folds the notification and its reply into the turn it belongs to. After `--force`, that turn is sent again with the reply, but the old notification message stays, so the reply can appear twice. To get a clean copy, migrate into a new datapack instead.
|
|
367
447
|
|
|
368
448
|
### What does NOT get migrated (v1)
|
|
369
449
|
|
|
370
450
|
- Slash-command skills, hooks, and `.claude/settings.json` — those remain in Claude Code's own config; Meko has no equivalent tool.
|
|
371
|
-
- Knowledge-base documents — KB
|
|
372
|
-
- Transcripts from
|
|
451
|
+
- Knowledge-base documents — this migration doesn't re-upload old KB files; add them via `knowledgebase_upload_document` or the UI (Datapack → Actions → Add Knowledge) after migrating.
|
|
452
|
+
- Transcripts from unregistered coding agents (for example Aider, Continue.dev, or Windsurf).
|
|
373
453
|
- `user_id` is left null on every call (the server fills it from the API key). Multi-user routing is a follow-up.
|
|
374
454
|
|
|
375
455
|
## Client Compatibility Matrix
|
|
376
456
|
|
|
377
|
-
| Capability | Claude Code | Claude Desktop | Cursor | Codex (CLI + App) | Kiro (IDE + `kiro-cli`) |
|
|
378
|
-
|
|
379
|
-
| One-command install | Yes | Yes | Yes | Yes | Yes |
|
|
380
|
-
| MCP server registration | via `claude mcp add` | via `claude_desktop_config.json` merge using `mcp-remote` stdio bridge | via `.cursor/mcp.json` merge | via `codex mcp add` (CLI) or direct TOML write (App-only) | via `~/.kiro/settings/mcp.json` merge (native remote MCP) |
|
|
381
|
-
| Backup before config write | `.bak` on `~/.claude/settings.json` | `.bak` on `claude_desktop_config.json` | No `.bak` — additive JSON writes preserve unrelated MCP servers, hooks, and settings | `.bak` on `~/.codex/config.toml` and `~/.codex/AGENTS.md` | No `.bak` — the write is an additive merge that preserves other `mcpServers` entries |
|
|
382
|
-
| Automatic conversation capture | Yes (hooks) | **No** — see [issue #8](https://github.com/amiramm/meko-mcp-server/issues/8) | Yes (native hooks; first SessionStart may pause briefly while creating the Meko conversation) | Yes (hooks) — `SessionStart` / `PreCompact` / `SessionEnd` written to `~/.codex/hooks.json`; the AGENTS.md block provides fallback instructions when hooks are unavailable | Yes — inline CLI 2.x plus standalone CLI 3.x/IDE hooks share Capture v2 |
|
|
383
|
-
| Automatic memory persistence | Yes (hooks + skill) | Skill only (proactive `memory_add`) | Yes (hooks + skill) | Hooks + skill; AGENTS.md fallback when hooks are unavailable | Hooks + skill; conditional steering fallback when the hook marker is absent |
|
|
384
|
-
| Skill install | Plugin marketplace (automatic) | `.skill` bundle auto-built, user drags into app | Copy into `.cursor/skills` | Copy into `~/.agents/skills/meko-mcp-tools/` | Copy into `~/.kiro/skills/` (native Agent Skills format) |
|
|
385
|
-
| Uninstall | Full automatic | MCP entry removed; skill must be removed manually from app | MCP + hooks + skills cleaned up | MCP entry, skill dir, and AGENTS.md block all cleaned up | MCP entry plus installer-owned hooks, managed agent, private env, skills, and steering; pending outbox data is preserved |
|
|
386
|
-
| `agent_id` used by skill | `claude_code:<repo>` per project (via SessionStart hook); cross-project facts go to `meko_agent` | `claude_desktop` | `cursor:<repo>` per project (via Cursor hook); cross-project facts go to `meko_agent` | `codex:<repo>` per project (via SessionStart hook); cross-project facts go to `meko_agent` | `kiro:<repo>` per project via hook capture; cross-project facts go to `meko_agent` |
|
|
387
|
-
| Transport | HTTP only | HTTP (or stdio via hand-edited config) | HTTP only | HTTP (Codex's `bearer_token_env_var` model) | HTTP only |
|
|
388
|
-
| Auth model | inline `Authorization: Bearer ...` header | inline header via `mcp-remote` | inline header | MCP server: env-var name reference (`MEKO_API_KEY` exported in shell or via `launchctl setenv`). Hooks: key written to `~/.codex/meko-env.sh` at mode 0600; each hook command sources the file before bash (no env block in Codex's hooks schema; see [Security](#security)). | inline `Authorization: Bearer ...` header (never `mcp-remote` — see note below) |
|
|
389
|
-
| Project scope | Yes (`--scope project`) | No | Yes (`--scope project`) | No (warns and degrades to user scope) | Yes (`--scope project`) |
|
|
390
|
-
| Deferred to a follow-up | — | `.mcpb` Desktop Extension packaging — see [issue #7](https://github.com/amiramm/meko-mcp-server/issues/7) | — | — | Tool-call/hidden-reasoning capture (not exposed by Kiro hook events) |
|
|
457
|
+
| Capability | Claude Code | Claude Desktop | Cursor | Codex (CLI + App) | Kiro (IDE + `kiro-cli`) | OpenCode CLI/TUI 1.18.x |
|
|
458
|
+
|---|---|---|---|---|---|---|
|
|
459
|
+
| One-command install | Yes | Yes | Yes | Yes | Yes | Yes |
|
|
460
|
+
| MCP server registration | via `claude mcp add` | via `claude_desktop_config.json` merge using `mcp-remote` stdio bridge | via `.cursor/mcp.json` merge | via `codex mcp add` (CLI) or direct TOML write (App-only) | via `~/.kiro/settings/mcp.json` merge (native remote MCP) | Installer-owned plugin overlay; source config untouched |
|
|
461
|
+
| Backup before config write | `.bak` on `~/.claude/settings.json` | `.bak` on `claude_desktop_config.json` | No `.bak` — additive JSON writes preserve unrelated MCP servers, hooks, and settings | `.bak` on `~/.codex/config.toml` and `~/.codex/AGENTS.md` | No `.bak` — the write is an additive merge that preserves other `mcpServers` entries | No source-config write; plugin overlay is copied then renamed into place; runtime tree uses installStableTree |
|
|
462
|
+
| Automatic conversation capture | Yes (hooks) | **No** — see [issue #8](https://github.com/amiramm/meko-mcp-server/issues/8) | Yes (native hooks; first SessionStart may pause briefly while creating the Meko conversation) | Yes (hooks) — `SessionStart` / `PreCompact` / `SessionEnd` written to `~/.codex/hooks.json`; the AGENTS.md block provides fallback instructions when hooks are unavailable | Yes — inline CLI 2.x plus standalone CLI 3.x/IDE hooks share Capture v2 | Yes (`session.idle` / `session.error`, Capture v2; error is an observation, not an immediate interrupt) |
|
|
463
|
+
| Automatic memory persistence | Yes (hooks + skill) | Skill only (proactive `memory_add`) | Yes (hooks + skill) | Hooks + skill; AGENTS.md fallback when hooks are unavailable | Hooks + skill; conditional steering fallback when the hook marker is absent | Yes (capture + skill) |
|
|
464
|
+
| Skill install | Plugin marketplace (automatic) | `.skill` bundle auto-built, user drags into app | Copy into `.cursor/skills` | Copy into `~/.agents/skills/meko-mcp-tools/` | Copy into `~/.kiro/skills/` (native Agent Skills format) | Copy into scoped OpenCode `skills/` |
|
|
465
|
+
| Uninstall | Full automatic | MCP entry removed; skill must be removed manually from app | MCP + hooks + skills cleaned up | MCP entry, skill dir, and AGENTS.md block all cleaned up | MCP entry plus installer-owned hooks, managed agent, private env, skills, and steering; pending outbox data is preserved | Owned plugin/runtime/skill removed; env stays watermark-only; snapshots, journals, outboxes, and capture-root quarantine stay; #307-era invalid files stay in meko/snapshots/quarantine |
|
|
466
|
+
| `agent_id` used by skill | `claude_code:<repo>` per project (via SessionStart hook); cross-project facts go to `meko_agent` | `claude_desktop` | `cursor:<repo>` per project (via Cursor hook); cross-project facts go to `meko_agent` | `codex:<repo>` per project (via SessionStart hook); cross-project facts go to `meko_agent` | `kiro:<repo>` per project via hook capture; cross-project facts go to `meko_agent` | `opencode:<repo>` per project, derived at capture from the session directory (the plugin does not inject `agent_id`); cross-project facts go to `meko_agent` |
|
|
467
|
+
| Transport | HTTP only | HTTP (or stdio via hand-edited config) | HTTP only | HTTP (Codex's `bearer_token_env_var` model) | HTTP only | Native remote HTTP MCP |
|
|
468
|
+
| Auth model | inline `Authorization: Bearer ...` header | inline header via `mcp-remote` | inline header | MCP server: env-var name reference (`MEKO_API_KEY` exported in shell or via `launchctl setenv`). Hooks: key written to `~/.codex/meko-env.sh` at mode 0600; each hook command sources the file before bash (no env block in Codex's hooks schema; see [Security](#security)). | inline `Authorization: Bearer ...` header (never `mcp-remote` — see note below) | Authorization header supplied by the plugin from a mode-0600 private env file |
|
|
469
|
+
| Project scope | Yes (`--scope project`) | No | Yes (`--scope project`) | No (warns and degrades to user scope) | Yes (`--scope project`) | Yes (`--scope project`) |
|
|
470
|
+
| Deferred to a follow-up | — | `.mcpb` Desktop Extension packaging — see [issue #7](https://github.com/amiramm/meko-mcp-server/issues/7) | — | — | Tool-call/hidden-reasoning capture (not exposed by Kiro hook events) | Desktop/V2/headless certification; richer capture surfaces |
|
|
391
471
|
|
|
392
472
|
Cursor previously had a hybrid hook mode that also wrote Claude-compatible hooks into `~/.claude/settings.json`. If you used that mode and now see duplicate `claude_code:*` Meko instructions in Cursor, remove the old Meko hook entries from `~/.claude/settings.json` unless you still use them for Claude Code.
|
|
393
473
|
|
|
@@ -397,7 +477,10 @@ Cursor previously had a hybrid hook mode that also wrote Claude-compatible hooks
|
|
|
397
477
|
|
|
398
478
|
**Never use the `mcp-remote` bridge with Kiro.** Kiro speaks remote MCP natively, so the installer registers `{ url, headers }` directly.
|
|
399
479
|
|
|
400
|
-
What
|
|
480
|
+
What was measured against `https://mcp.mekodata.ai` before 2026-09-24. Production
|
|
481
|
+
now accepts loopback redirects on `/register`, `/authorize`, and `/token`, and a
|
|
482
|
+
2026-10-07 re-measure found DEV (`mcp.mekodev.com`) accepts them too ([#277](https://github.com/yugabyte/meko-mcp-server/issues/277)). The `mcp-remote` findings below still
|
|
483
|
+
apply, because an API key behind the bridge is never sent.
|
|
401
484
|
|
|
402
485
|
- `mcp-remote@0.1.38` reads no auth env var (its only `process.env` reference is `MCP_REMOTE_CONFIG_DIR`), so `MEKO_API_KEY` is never sent; headers come only from `--header`. It therefore connects unauthenticated and begins OAuth.
|
|
403
486
|
- Run directly, it fails at `registerClient` — the DCR POST — with `HTTP 403: Invalid OAuth error response … Raw body: <html>403 Forbidden</html>`. Its source builds `redirect_uri` as `http://${host}:${callbackPort}${callbackPath}`, defaulting to `localhost` and `/oauth/callback`.
|
|
@@ -413,7 +496,7 @@ Confirmed on `kiro-cli` 2.18.1 itself. Its DCR registration is:
|
|
|
413
496
|
|
|
414
497
|
so against Cloud Meko it fails with `Dynamic registration failed: Registration failed: HTTP 403 Forbidden`. Its first `POST /mcp` also goes out with **no `User-Agent`**, which trips a second HTML-403 rule independently. With Mode 1 headers and a valid `mko_tkn_…` key it connects and lists all 23 tools — no OAuth, no 403.
|
|
415
498
|
|
|
416
|
-
Both surfaces are verified against Cloud Meko with a real key. On the **Kiro IDE** (1.0.337), the installer's config produces `[meko] Connected` in its `Kiro - MCP Logs` output. On **`kiro-cli`** (2.18.1) the agent
|
|
499
|
+
Both surfaces are verified against Cloud Meko with a real key. On the **Kiro IDE** (1.0.337), the installer's config produces `[meko] Connected` in its `Kiro - MCP Logs` output. On **`kiro-cli`** (2.18.1) the agent enumerated all 23 tools the server had at the time; production now lists 42, including 14 `amp_*` tools. The steering file is confirmed to reach the model, not just disk: asked with tools disabled what its Meko steering requires, the agent answered that it must call `memory_add` when the user states a durable fact and that this "explicitly overrides the meko-mcp-tools skill", which assumes capture hooks are running.
|
|
417
500
|
|
|
418
501
|
One naming correction worth knowing, since it has caused confusion: **`Q DEV CLI` is not an OAuth client id.** It is the MCP `initialize` handshake's `clientInfo.name` (`"clientInfo":{"name":"Q DEV CLI","version":"1.0.0"}`); the string appears nowhere in the `kiro-cli` binary's OAuth path, and its actual DCR `client_name` is `kiro`. There is nothing named `Q DEV CLI` to allowlist. See [#277](https://github.com/yugabyte/meko-mcp-server/issues/277).
|
|
419
502
|
|
|
@@ -434,12 +517,12 @@ Uninstall removes only files carrying installer ownership markers: the three sta
|
|
|
434
517
|
| | Cloud Meko | Local Meko |
|
|
435
518
|
|---|-----------|-----------|
|
|
436
519
|
| **URL** | `https://mcp.mekodata.ai/mcp` (or the endpoint shown by cloud.mekodata.ai) | `http://localhost:8000/mcp` |
|
|
437
|
-
| **Authentication** |
|
|
520
|
+
| **Authentication** | Browser sign-in creates an API key, or pass `--api-key` / `$MEKO_API_KEY` | None |
|
|
438
521
|
| **MCP registration** | Includes `-H "Authorization: Bearer <key>"` header | No auth header |
|
|
439
522
|
| **Hook env vars** | Both `MEKO_MCP_URL` and `MEKO_API_KEY` written to settings | Only `MEKO_MCP_URL` written |
|
|
440
523
|
| **Infrastructure** | Hosted, no local setup needed | Requires `docker compose up -d` running the Meko stack |
|
|
441
524
|
| **Use case** | Production, team collaboration | Development, testing |
|
|
442
|
-
| **Flag** | `--url <url
|
|
525
|
+
| **Flag** | `--url <url>` (optionally `--api-key <key>`) | `--local` |
|
|
443
526
|
|
|
444
527
|
The installer auto-detects cloud vs local based on the URL: any URL containing `localhost` or `127.0.0.1` is treated as local (no API key required). All other URLs are cloud and require authentication.
|
|
445
528
|
|
|
@@ -461,6 +544,8 @@ The installer auto-detects cloud vs local based on the URL: any URL containing `
|
|
|
461
544
|
- **Kiro (IDE + `kiro-cli`)**
|
|
462
545
|
- API key header — stored in `~/.kiro/settings/mcp.json` (or `.kiro/settings/mcp.json` for project scope) under `mcpServers.<name>.headers.Authorization`. The adapter forces the file to **mode 0600** on registration and removal rewrites.
|
|
463
546
|
- Hook runtime — the endpoint and optional API key are also stored in `kiro-hook-env.json` at **mode 0600** so inline and standalone hooks can authenticate without putting the key in their command strings.
|
|
547
|
+
- **OpenCode**
|
|
548
|
+
- The plugin reads the API key from `$OPENCODE_CONFIG_DIR/meko/opencode-hook-env.json` when set, otherwise `~/.config/opencode/meko/opencode-hook-env.json` (user scope), or `.opencode/meko/opencode-hook-env.json` (project scope). The installer writes this file at **mode 0600** and never places the key in process arguments. Sanitized staged snapshots and Capture v2 journal/outbox files are also private; successfully handed-off snapshots are deleted, transient failures remain retryable, and malformed snapshots move to quarantine.
|
|
464
549
|
|
|
465
550
|
**How credentials are protected:**
|
|
466
551
|
|
|
@@ -505,10 +590,11 @@ Re-running the installer is idempotent but not inert. A re-run:
|
|
|
505
590
|
- Rewrites the Cursor skill directory and hooks config if `--client cursor` is targeted.
|
|
506
591
|
- Auto-updates the skills plugin if it's already installed (via `claude plugin update meko-agent-skills@meko-agent-skills`), otherwise installs it. See "Updating the skills plugin" below.
|
|
507
592
|
- Rebuilds the Claude Desktop `.skill` bundle if `--client claude-desktop` is targeted. You must re-drag the rebuilt bundle into Claude Desktop to pick up the new skill content.
|
|
593
|
+
- Replaces installer-owned OpenCode plugin/runtime/skill assets if `--client opencode` is targeted; restart OpenCode to load them. User-owned collisions are refused rather than overwritten.
|
|
508
594
|
|
|
509
595
|
### Updating the skills plugin (Claude Code)
|
|
510
596
|
|
|
511
|
-
The `meko-agent-skills` plugin is distributed via the Claude Code plugin marketplace
|
|
597
|
+
The `meko-agent-skills` plugin is distributed via the Claude Code plugin marketplace from yugabyte/meko-skills, not npm. It also carries the Claude Code capture hooks. From 2.5.0, the plugin, the installer, and the `.mcpb` share one version number. Re-running the installer now picks up the latest skill definitions automatically: it probes `claude plugin list` and, when the plugin is already present, calls
|
|
512
598
|
|
|
513
599
|
```bash
|
|
514
600
|
claude plugin update meko-agent-skills@meko-agent-skills --scope <scope>
|
|
@@ -607,6 +693,21 @@ Logs worth collecting before filing a bug:
|
|
|
607
693
|
- **Claude Code MCP log** (macOS) — `ls -lt ~/Library/Caches/claude-cli-nodejs/*/mcp-logs-meko/ 2>/dev/null` — most recent `*.txt` shows the registration attempt and any stderr from the spawned process.
|
|
608
694
|
- **Current config snippet** — `grep -A 20 '"meko"' ~/.claude.json` — confirms what state Claude Code was in when the install was attempted.
|
|
609
695
|
|
|
696
|
+
### OpenCode is unsupported or does not load Meko
|
|
697
|
+
|
|
698
|
+
OpenCode integration is gated to **1.18.x**. Check the exact binary that the installer sees:
|
|
699
|
+
|
|
700
|
+
```bash
|
|
701
|
+
which opencode
|
|
702
|
+
opencode --version
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
If the version is outside 1.18.x, upgrade or install a certified 1.18.x release before rerunning the installer. If the version is supported but installer validation does not report the remote `mcp.<name>` overlay (`mcp.meko` for the default name), confirm the selected scope and `--name`, check for a user-owned collision at the plugin path, rerun the installer, and restart OpenCode. User scope uses `$OPENCODE_CONFIG_DIR/plugins/meko.js` when the variable is set and `~/.config/opencode/plugins/meko.js` otherwise; project scope uses `.opencode/plugins/meko.js`. Do not print or share `opencode debug config`; its resolved headers may contain the API key.
|
|
706
|
+
|
|
707
|
+
For capture failures, run `create-meko-setup --capture-status --json`. The plugin captures only on `session.idle` or `session.error`, so an actively streaming turn is expected to remain pending. Retained staged snapshots indicate a retryable handoff failure and are replayed at startup; files moved to quarantine were invalid and require inspection. Uninstall leaves staged snapshots in the durable capture root. Do not delete Capture v2 journal/outbox data while diagnosing.
|
|
708
|
+
|
|
709
|
+
For migration failures, run `opencode session list --format json` and `opencode export <sessionID>` directly. One malformed export is isolated to that session. A malformed list records an OpenCode source warning while the other migration sources continue; dry-run output prints the warning.
|
|
710
|
+
|
|
610
711
|
### Connection refused
|
|
611
712
|
|
|
612
713
|
```
|
|
@@ -660,10 +761,11 @@ Three known causes:
|
|
|
660
761
|
- **No `User-Agent` header.** The WAF refuses any request without one. Add
|
|
661
762
|
`User-Agent: meko-mcp-installer/1.0`. The installer always does; hand-written
|
|
662
763
|
configs and some native MCP clients don't.
|
|
663
|
-
- **An OAuth callback on a loopback address.** The WAF
|
|
664
|
-
pointing at an internal host, so dynamic client
|
|
665
|
-
client that registers such a callback,
|
|
666
|
-
|
|
764
|
+
- **An OAuth callback on a loopback address (DEV, historically).** The DEV WAF
|
|
765
|
+
refused any `redirect_uri` pointing at an internal host, so dynamic client
|
|
766
|
+
registration failed there for any client that registers such a callback,
|
|
767
|
+
including IDEs. Production accepts these callbacks as of 2026-09-24, and a
|
|
768
|
+
2026-10-07 re-measure didn't reproduce the DEV block. Tracked in
|
|
667
769
|
[#277](https://github.com/yugabyte/meko-mcp-server/issues/277).
|
|
668
770
|
- **Message text that looks like a path.** Capture writes containing `../` or
|
|
669
771
|
absolute paths can trip a traversal rule. Tracked in
|
|
@@ -680,7 +782,7 @@ API-key checks:
|
|
|
680
782
|
- If using `$MEKO_API_KEY` env var, ensure it is exported in the current shell.
|
|
681
783
|
- Confirm the key environment matches the URL: PATs minted on `app.mekodev.com` only validate against `mcp.mekodev.com`; PATs minted on `cloud.mekodata.ai` only validate against `mcp.mekodata.ai`.
|
|
682
784
|
- The installer normalizes API keys (trims surrounding whitespace and a single matching pair of quotes) so a paste with a trailing newline or a literal `"…"` from a `.env` file is fine — but your raw shell variable might still be contaminated. Echo it (`echo "[$MEKO_API_KEY]"`) and check the brackets bracket the key tightly with no extra characters.
|
|
683
|
-
- Re-run the installer
|
|
785
|
+
- Re-run the installer in a terminal without `--api-key` and with `$MEKO_API_KEY` unset to sign in through the browser and create a new key, or pass a new key with `--api-key`.
|
|
684
786
|
|
|
685
787
|
### Plugin marketplace already registered
|
|
686
788
|
|
|
@@ -709,7 +811,7 @@ cp ~/.claude/settings.json.bak ~/.claude/settings.json
|
|
|
709
811
|
Missing core tools: memory_search, memory_get_by_id, conversation_create. Found 0 tool(s) total.
|
|
710
812
|
```
|
|
711
813
|
|
|
712
|
-
The MCP server responded but does not expose the expected tools (`memory_search`, `memory_get_by_id`, `conversation_create`, `datapack_list`). This usually means a server version mismatch. Update the MCP server or check which datapack is connected.
|
|
814
|
+
The MCP server responded but does not expose the expected tools (`memory_search`, `memory_get_by_id`, `conversation_create`, `datapack_list`). This usually means a server version mismatch. Update the MCP server or check which datapack is connected. The canary itself calls `datapack_search`, or `datapack_list` on a server without it (see [Post-install validation](#post-install-validation-canary) above).
|
|
713
815
|
|
|
714
816
|
### DNS lookup failed
|
|
715
817
|
|
|
@@ -772,6 +874,8 @@ This reverses installer-managed changes for the selected client:
|
|
|
772
874
|
|
|
773
875
|
Each step is safe if the component was already removed -- the uninstaller logs a warning and continues.
|
|
774
876
|
|
|
877
|
+
For OpenCode, uninstall removes installer-owned plugin, runtime, and skill assets. The private env stays with only `MEKO_WATERMARK_DIR` (API key stripped) so reinstall resumes the same capture root. Staged snapshots, journals, outboxes, and watermarks stay in the durable capture root. Quarantine of snapshots staged there lives next to those files. Invalid files from a leftover `#307` `meko/snapshots` tree stay in `meko/snapshots/quarantine`. Uninstall does not edit `opencode.json` / `opencode.jsonc` or remove user-owned collisions. There is no installer purge command. Do not delete the capture root: it is shared with Claude Code, Cursor, Codex, and Kiro, and also stores datapack pins. Do not delete OpenCode subdirectories on their own: each session also has a `<sessionId>.watermark.json` in that shared root, and it still points at the journal.
|
|
878
|
+
|
|
775
879
|
### Claude Desktop: which artifact, and why the UI can't remove it
|
|
776
880
|
|
|
777
881
|
Claude Desktop can be connected to Meko in two different ways, and they are removed differently:
|
|
@@ -795,6 +899,8 @@ node installer/bin/create-meko-setup.mjs --uninstall --verbose
|
|
|
795
899
|
|---|----------|-------|-----------------|
|
|
796
900
|
| M1 | Fresh local install | `node installer/bin/create-meko-setup.mjs --local --yes` with docker stack running | All 5 steps pass, validation shows 3 green checks |
|
|
797
901
|
| M2 | Fresh cloud install | Run interactively, provide Cloud Meko URL + API key | MCP registered with `Authorization: Bearer` header, env vars set, validation passes |
|
|
902
|
+
| M2b | Browser sign-in | In a terminal with `$MEKO_API_KEY` unset, run `--url https://mcp.mekodata.ai/mcp` without `--api-key` and sign in | A key is created through `POST /api-keys`; validation passes |
|
|
903
|
+
| M2c | No terminal, no key | Pipe stdin (or run under CI) with no `--api-key` and no `$MEKO_API_KEY` | Exits with "API key is required for Cloud Meko" |
|
|
798
904
|
| M3 | Existing config | Run installer when `meko` MCP is already registered | Prompts to overwrite; answering No keeps existing config |
|
|
799
905
|
| M4 | No claude CLI | Run on a machine without `claude` in PATH | Exits with error message and install link |
|
|
800
906
|
| M5 | Server unreachable | Install with `--skip-validation`, then re-run without it | Install succeeds; validation warns about connectivity |
|
|
@@ -806,6 +912,7 @@ node installer/bin/create-meko-setup.mjs --uninstall --verbose
|
|
|
806
912
|
| M11 | Invoke from repo root | `cd <repo> && node installer/bin/create-meko-setup.mjs --client cursor --local --scope user --dry-run --yes` | Dry-run succeeds; no path-resolution errors |
|
|
807
913
|
| M12 | Invoke from `installer/` | `cd <repo>/installer && node bin/create-meko-setup.mjs --client cursor --local --scope user --dry-run --yes` | Dry-run succeeds (note: `--scope project` gives different `.cursor/...` paths because project scope uses cwd — pick a fixed cwd or `--scope user` to compare byte-for-byte) |
|
|
808
914
|
| M13 | Clone-free via npm pack | `cd installer && npm pack` → `npm install -g ./yugabytedb-meko-mcp-*.tgz` → from a directory with **no repo clone**, run `create-meko-setup --client cursor --local --scope project --dry-run` | Succeeds; asset paths resolve under the globally-installed `node_modules/@yugabytedb/meko-mcp/assets/...` |
|
|
915
|
+
| M14 | OpenCode Tier-2 canary | Follow the OpenCode checklist in [`RELEASING.md`](../RELEASING.md#opencode-tier-2-canary) on certified 1.18.x | Packaged user/project install, tools visibility, automatic capture/recovery, migration, and uninstall all pass |
|
|
809
916
|
|
|
810
917
|
## Development
|
|
811
918
|
|