@yugabytedb/meko-mcp 2.0.0 → 2.2.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 +183 -33
- package/assets/hooks-handlers/codex-session-end.sh +13 -0
- package/assets/hooks-handlers/cursor-session-start.sh +19 -1
- package/assets/hooks-handlers/lib/capture-notices.js +321 -0
- package/assets/hooks-handlers/lib/capture-state.js +2079 -0
- package/assets/hooks-handlers/lib/capture-status-cli.js +82 -0
- package/assets/hooks-handlers/lib/capture.js +1653 -225
- package/assets/hooks-handlers/lib/checkpoint-timer.js +455 -50
- package/assets/hooks-handlers/lib/kiro-handler.js +738 -0
- package/assets/hooks-handlers/lib/terminal-handoff.js +418 -0
- package/assets/hooks-handlers/session-end.sh +3 -24
- package/assets/hooks-handlers/session-start.sh +8 -1
- package/assets/hooks-handlers/test_checkpoint_timer.sh +162 -0
- package/assets/scripts/meko-statusline.sh +41 -1
- package/assets/scripts/package-desktop-skill.sh +32 -1
- package/assets/skills/meko-mcp-tools/SKILL.md +90 -137
- package/assets/skills/meko-mcp-tools/references/_sections.md +3 -5
- package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +31 -28
- package/assets/skills/meko-mcp-tools/references/tools-conversation-dedup.md +5 -7
- package/assets/skills/meko-mcp-tools/references/tools-conversation-reasoning.md +50 -0
- package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +69 -49
- package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +6 -6
- package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +29 -5
- package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +29 -92
- package/assets/skills/meko-mcp-tools/references/tools-overview.md +42 -40
- package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +1 -2
- package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +18 -11
- package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +10 -9
- package/assets/skills/meko-mcp-tools-desktop/SKILL.md +51 -44
- package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +6 -6
- package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +2 -2
- package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +34 -25
- package/assets/skills/meko-mcp-tools-desktop/references/tools-conversation-reasoning.md +50 -0
- package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +63 -37
- package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +4 -4
- package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +19 -22
- package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +42 -40
- package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +1 -2
- package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +3 -17
- package/assets/skills/meko-select-datapack-desktop/SKILL.md +31 -21
- package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +8 -8
- package/assets/skills/meko-select-datapack-desktop/references/role-display-future.md +41 -0
- package/assets/skills/meko-select-datapack-desktop/references/troubleshooting.md +1 -1
- package/bin/create-meko-setup.mjs +93 -16
- package/lib/capture-status.mjs +67 -0
- package/lib/clients/aliases.mjs +5 -0
- package/lib/clients/claude-code.mjs +8 -4
- package/lib/clients/claude-desktop.mjs +133 -4
- package/lib/clients/codex.mjs +29 -11
- package/lib/clients/common.mjs +2 -0
- package/lib/clients/cursor.mjs +7 -2
- package/lib/clients/index.mjs +2 -0
- package/lib/clients/kiro.mjs +705 -0
- package/lib/config.mjs +90 -0
- package/lib/detect.mjs +7 -2
- package/lib/installer.mjs +1 -0
- package/lib/migrate/adapters/codex.mjs +490 -0
- package/lib/migrate/id.mjs +28 -3
- package/lib/migrate/orchestrator.mjs +34 -7
- package/lib/migrate.mjs +4 -2
- package/lib/prompt.mjs +17 -2
- package/lib/url-selection.mjs +55 -0
- package/package.json +4 -4
- package/assets/skills/meko-mcp-tools/references/tools-scope-permissions.md +0 -71
- package/assets/skills/meko-mcp-tools-desktop/references/tools-scope-permissions.md +0 -71
|
@@ -3,15 +3,15 @@ name: meko-select-datapack-desktop
|
|
|
3
3
|
description: >-
|
|
4
4
|
Lists the user's Meko datapacks, shows authorization, supports search and
|
|
5
5
|
pagination, and pins one as the active datapack on Claude Desktop. Triggers
|
|
6
|
-
when the user says things like "switch datapack", "use datapack
|
|
7
|
-
"list my datapacks", "which datapack am I on", "pin
|
|
6
|
+
when the user says things like "switch datapack", "use the Acme datapack",
|
|
7
|
+
"list my datapacks", "which datapack am I on", "pin Acme", or any request
|
|
8
8
|
to change or inspect the active datapack. Persistence is via memory_add
|
|
9
9
|
(Desktop has no SessionStart hook), so the pin survives across sessions
|
|
10
10
|
until the user clears it.
|
|
11
11
|
license: MIT
|
|
12
12
|
metadata:
|
|
13
13
|
author: Meko
|
|
14
|
-
version: "1.1
|
|
14
|
+
version: "1.2.1"
|
|
15
15
|
tags: meko, datapack, selection, project, claude-desktop, desktop
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -42,10 +42,10 @@ Trigger immediately on any of these signals:
|
|
|
42
42
|
|
|
43
43
|
## On every Meko-touching turn (not just when this skill triggers)
|
|
44
44
|
|
|
45
|
-
Before issuing a Meko MCP write tool call (memory_add,
|
|
45
|
+
Before issuing a Meko MCP write tool call (memory_add, conversation_add_message, artifact_put, etc.), if you don't already know the active pin from this turn's earlier work:
|
|
46
46
|
|
|
47
47
|
```
|
|
48
|
-
memory_search(
|
|
48
|
+
memory_search(
|
|
49
49
|
query="meko_active_datapack",
|
|
50
50
|
agent_id="claude_desktop",
|
|
51
51
|
conversation_id="<this conversation's id>",
|
|
@@ -61,7 +61,7 @@ This is once per turn, not once per call. Cache within the turn.
|
|
|
61
61
|
### 1. List
|
|
62
62
|
|
|
63
63
|
Use a **temporary** conversation for browsing only. Call
|
|
64
|
-
`conversation_create(
|
|
64
|
+
`conversation_create(agent_id="claude_desktop", title="Claude
|
|
65
65
|
Desktop datapack selection")` and use its returned ID for the read-only
|
|
66
66
|
`datapack_list` below and for the pin `memory_add`/`memory_update` in step 4.
|
|
67
67
|
|
|
@@ -72,13 +72,20 @@ must flow through a *new* conversation created in the selected datapack — see
|
|
|
72
72
|
step 5.
|
|
73
73
|
|
|
74
74
|
```
|
|
75
|
-
datapack_list(
|
|
75
|
+
datapack_list(conversation_id="<this conversation's id>")
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
The response is an array; the fields you'll use are `datapack_id`,
|
|
79
|
-
`datapack_name`, `created_at`, and `
|
|
79
|
+
`datapack_name`, `created_at`, `account_id`, and `grant`.
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
`grant` is the caller's actual authorization on the datapack — one of
|
|
82
|
+
`"owner"`, `"maintainer"`, `"contributor"`, `"viewer"`. Display it verbatim in
|
|
83
|
+
the Role column. Do not hardcode "Owner", do not invent or normalize the value
|
|
84
|
+
(render `"maintainer"` as `maintainer`, not `Maintainer`). The deployed
|
|
85
|
+
response is the source of truth — see `references/role-display-future.md` for
|
|
86
|
+
the taxonomy.
|
|
87
|
+
|
|
88
|
+
If the response has zero entries, tell the user: *"You don't have any datapacks yet. Run `datapack_create(name='<name>')` to make one, or visit the Meko Cloud console."* Stop here.
|
|
82
89
|
|
|
83
90
|
If the response has exactly **one** entry, **auto-select it**. Print: *"Only one datapack: `<name>`. Auto-selecting. Run `meko-select-datapack-desktop` again with `clear` to unset."* Skip the table; jump to step 4 (persist) and step 5 (confirm).
|
|
84
91
|
|
|
@@ -89,19 +96,22 @@ For 2+ datapacks, render a numbered table. **Page size 10.** Default sort: `crea
|
|
|
89
96
|
```
|
|
90
97
|
Your datapacks (showing 1-10 of 14):
|
|
91
98
|
|
|
92
|
-
# Name Role
|
|
93
|
-
1 meko-local-setup
|
|
94
|
-
2 meko_default_datapack
|
|
95
|
-
3
|
|
99
|
+
# Name Role Created Status Active?
|
|
100
|
+
1 meko-local-setup owner 2026-04-30 ready ← (pinned)
|
|
101
|
+
2 meko_default_datapack owner 2026-04-30 ready
|
|
102
|
+
3 team-onboarding maintainer 2026-04-08 ready
|
|
103
|
+
4 q2-roadmap viewer 2026-03-22 ready
|
|
96
104
|
…
|
|
97
105
|
|
|
98
106
|
Reply with: a number (1-10) to pin · a substring to search · `next` / `prev` to page
|
|
99
107
|
· `clear` to unset · `cancel` to leave the current pin alone
|
|
100
|
-
|
|
101
|
-
Note: Role is hardcoded to "Owner" today. Shared / Viewer / Contributor /
|
|
102
|
-
Maintainer roles are pending upstream backend work — see references/role-display-future.md.
|
|
103
108
|
```
|
|
104
109
|
|
|
110
|
+
The **Role** column shows each datapack's `grant` value verbatim (`owner`,
|
|
111
|
+
`maintainer`, `contributor`, `viewer`). Never hardcode "Owner" — shared
|
|
112
|
+
datapacks legitimately carry other grants, and misreporting them (e.g. showing
|
|
113
|
+
a `maintainer` grant as "Owner") misleads the user about their own access.
|
|
114
|
+
|
|
105
115
|
Mark the currently-pinned row with `← (pinned)` based on the `memory_search` result (if any).
|
|
106
116
|
|
|
107
117
|
### 3. Parse the user's reply
|
|
@@ -118,7 +128,7 @@ Mark the currently-pinned row with `← (pinned)` based on the `memory_search`
|
|
|
118
128
|
**On first pin (no existing pin memory):**
|
|
119
129
|
|
|
120
130
|
```
|
|
121
|
-
memory_add(
|
|
131
|
+
memory_add(
|
|
122
132
|
text="meko_active_datapack=<uuid> name=<name> selected_at=<iso8601>",
|
|
123
133
|
agent_id="claude_desktop",
|
|
124
134
|
conversation_id="<this conversation's id>",
|
|
@@ -130,7 +140,7 @@ Verify the write with `memory_search` (the standard Meko verify-after-write rule
|
|
|
130
140
|
**On switch (existing pin memory found):**
|
|
131
141
|
|
|
132
142
|
```
|
|
133
|
-
memory_update(
|
|
143
|
+
memory_update(
|
|
134
144
|
memory_id="<existing pin id>",
|
|
135
145
|
text="meko_active_datapack=<new uuid> name=<new name> selected_at=<iso8601>",
|
|
136
146
|
agent_id="claude_desktop",
|
|
@@ -142,7 +152,7 @@ Always update — never `memory_add` a second pin. Two pin memories will produce
|
|
|
142
152
|
**On clear:**
|
|
143
153
|
|
|
144
154
|
```
|
|
145
|
-
memory_delete_by_id(
|
|
155
|
+
memory_delete_by_id(
|
|
146
156
|
memory_id="<existing pin id>",
|
|
147
157
|
agent_id="claude_desktop",
|
|
148
158
|
conversation_id="<this conversation's id>")
|
|
@@ -153,7 +163,7 @@ If `memory_search` returned no pin, there's nothing to delete — print *"No pin
|
|
|
153
163
|
**Conversation transition after a clear (same rule as a switch).** The pin memory is now gone, but the session's current conversation still physically lives in the datapack that was pinned when it was created — a conversation cannot move to the default. You must pick exactly one of these; do not mix them:
|
|
154
164
|
|
|
155
165
|
- **Option A — keep capturing to the current conversation this session.** It stays in its original (now-unpinned) datapack, so you must keep passing that **same old `datapack_id`** on its `conversation_add_message` calls — do NOT switch it to the default (that would fail). The clear only affects *new* sessions. Disclose: *"Pin cleared. This chat keeps saving to `<old datapack name>`; new chats will use the default datapack."*
|
|
156
|
-
- **Option B — start default-datapack capture immediately.** Create a **new** conversation with no `datapack_id` (`conversation_create(
|
|
166
|
+
- **Option B — start default-datapack capture immediately.** Create a **new** conversation with no `datapack_id` (`conversation_create(agent_id="claude_desktop")`) and post all subsequent turns there. Stop posting to the old conversation. Disclose: *"Pin cleared. Started a new chat context saving to the default datapack."*
|
|
157
167
|
|
|
158
168
|
Default to Option A (least disruptive) unless the user wants the switch to take effect right now. Either way, never send `datapack_id=default` to the pre-existing pinned conversation.
|
|
159
169
|
|
|
@@ -173,7 +183,7 @@ right `datapack_id` flows through automatically.
|
|
|
173
183
|
**Then start a fresh conversation for capture in the selected datapack.** The
|
|
174
184
|
temporary selection conversation from step 1 belongs to the datapack that was
|
|
175
185
|
active when it was created and cannot be moved. For subsequent capture this
|
|
176
|
-
session, call `conversation_create(
|
|
186
|
+
session, call `conversation_create(agent_id="claude_desktop",
|
|
177
187
|
datapack_id="<the newly pinned uuid>", title="<topic>")` and post turns
|
|
178
188
|
(`conversation_add_message`) to *that* conversation with the same
|
|
179
189
|
`datapack_id`. Do not keep posting to the selection conversation — doing so
|
|
@@ -11,12 +11,12 @@ Concrete transcripts of the four flows the skill supports on Claude Desktop.
|
|
|
11
11
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", limit=1)
|
|
12
12
|
[empty]
|
|
13
13
|
|
|
14
|
-
> datapack_list(
|
|
14
|
+
> datapack_list(conversation_id="<conv-id>")
|
|
15
15
|
[14 entries returned, filtering by "prod-research"]
|
|
16
16
|
|
|
17
17
|
One match: `prod-research`. Pinning.
|
|
18
18
|
|
|
19
|
-
> memory_add(
|
|
19
|
+
> memory_add(
|
|
20
20
|
text="meko_active_datapack=8b1c…f4a2 name=prod-research selected_at=2026-05-25T18:42:00Z",
|
|
21
21
|
agent_id="claude_desktop",
|
|
22
22
|
conversation_id="<conv-id>",
|
|
@@ -44,12 +44,12 @@ datapack_id flows through automatically.
|
|
|
44
44
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", limit=1)
|
|
45
45
|
[returns id=mem_abc123, text="meko_active_datapack=8b1c…f4a2 name=prod-research …"]
|
|
46
46
|
|
|
47
|
-
> datapack_list(
|
|
47
|
+
> datapack_list(conversation_id="<conv-id>")
|
|
48
48
|
[14 entries returned, filtering by "q2-roadmap-deck"]
|
|
49
49
|
|
|
50
50
|
One match: `q2-roadmap-deck`. Switching pin.
|
|
51
51
|
|
|
52
|
-
> memory_update(
|
|
52
|
+
> memory_update(
|
|
53
53
|
memory_id="mem_abc123",
|
|
54
54
|
text="meko_active_datapack=4c2e…a991 name=q2-roadmap-deck selected_at=2026-05-25T19:05:00Z",
|
|
55
55
|
agent_id="claude_desktop",
|
|
@@ -69,12 +69,12 @@ The `memory_update` is critical here — using `memory_add` again would create a
|
|
|
69
69
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", limit=1)
|
|
70
70
|
[empty]
|
|
71
71
|
|
|
72
|
-
> datapack_list(
|
|
72
|
+
> datapack_list(conversation_id="<conv-id>")
|
|
73
73
|
[1 entry returned]
|
|
74
74
|
|
|
75
75
|
Only one datapack: `meko-local-setup`. Auto-selecting.
|
|
76
76
|
|
|
77
|
-
> memory_add(
|
|
77
|
+
> memory_add(
|
|
78
78
|
text="meko_active_datapack=a17d…cc91 name=meko-local-setup selected_at=…",
|
|
79
79
|
agent_id="claude_desktop",
|
|
80
80
|
conversation_id="<conv-id>",
|
|
@@ -93,7 +93,7 @@ Pinned datapack `meko-local-setup` (`a17d…cc91`). Run this skill again with
|
|
|
93
93
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", limit=1)
|
|
94
94
|
[returns id=mem_abc123]
|
|
95
95
|
|
|
96
|
-
> memory_delete_by_id(
|
|
96
|
+
> memory_delete_by_id(
|
|
97
97
|
memory_id="mem_abc123",
|
|
98
98
|
agent_id="claude_desktop",
|
|
99
99
|
conversation_id="<conv-id>")
|
|
@@ -114,7 +114,7 @@ This isn't a user-triggered flow — it's the per-turn lookup the skill teaches
|
|
|
114
114
|
|
|
115
115
|
# Extract UUID after "meko_active_datapack=" → 8b1c…f4a2
|
|
116
116
|
|
|
117
|
-
> memory_add(
|
|
117
|
+
> memory_add(text="…", datapack_id="8b1c…f4a2",
|
|
118
118
|
agent_id="claude_desktop", conversation_id="<conv-id>")
|
|
119
119
|
```
|
|
120
120
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Role display — current state
|
|
2
|
+
|
|
3
|
+
## Today: render `grant` verbatim
|
|
4
|
+
|
|
5
|
+
The deployed Meko `GET /datapacks` response includes a `grant` field on every datapack. Possible values (per maintainer guidance, 2026-05-26):
|
|
6
|
+
|
|
7
|
+
- `"owner"` — datapacks the caller created.
|
|
8
|
+
- `"maintainer"` — write access to a shared datapack including memories AND collective learnings/knowledge.
|
|
9
|
+
- `"contributor"` — write access to a shared datapack: can generate own memories. (Cannot promote / publish collective learnings — that's the maintainer's job.)
|
|
10
|
+
- `"viewer"` — read-only on a shared datapack.
|
|
11
|
+
|
|
12
|
+
Use the field directly in the **Role** column:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
# Name Role Created Active?
|
|
16
|
+
1 prod-research owner 2026-04-12 ← (pinned)
|
|
17
|
+
2 team-onboarding contributor 2026-04-08
|
|
18
|
+
3 q2-roadmap viewer 2026-03-22
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Do not invent values, do not normalize the casing, do not display `"Owner"` if the field says `"owner"`. The deployed schema is the source of truth.
|
|
22
|
+
|
|
23
|
+
Note that the upstream Go source (the `Datapack` struct in `api_server/internal/models/models.go` of the `meko` API-server repo) does NOT declare `grant` — the deployed server enriches the response beyond what the public Go code lists. Don't rely on the public struct for the wire schema; trust the actual response.
|
|
24
|
+
|
|
25
|
+
## Other fields the live response includes
|
|
26
|
+
|
|
27
|
+
Beyond the columns the skill renders by default, `datapack_list` returns counts that may be useful in some flows:
|
|
28
|
+
|
|
29
|
+
- `memory_count` — total memories the caller has under this datapack (per `(user_id, agent_id)` scoping).
|
|
30
|
+
- `knowledge_count` — knowledge-base entries on the datapack.
|
|
31
|
+
- `learnings_count` — promoted-to-shared memories on the datapack.
|
|
32
|
+
|
|
33
|
+
These aren't in the spec column set. Don't add them silently. If the user asks for counts, render them on request — and read the numbers from the live response, never invent them.
|
|
34
|
+
|
|
35
|
+
## Sharing UI vs API state
|
|
36
|
+
|
|
37
|
+
The Cloud console "Share <datapack>" page (`meko_ui/src/features/datapacks/pages/DatapackSharePage.tsx`) shows interactive controls with "Coming Soon" overlays on a few specific actions (e.g. invite-by-email link sharing, transfer-ownership). Those overlays mean *those specific UI affordances* aren't shipped — NOT that the underlying `grant`/sharing model is absent. Contributor/maintainer/viewer grants are functional in the data layer today; only the user-facing self-serve invite flow is gated.
|
|
38
|
+
|
|
39
|
+
## Why the skill ships without Mine / Shared / All filter tabs
|
|
40
|
+
|
|
41
|
+
The tagged pin memory (re-read via `memory_search` before each Meko write) delivers the user's actual ask ("don't make me remember a UUID"). Filter tabs are useful when the response is genuinely mixed-grant; for users with only owner-grant rows they're decorative. We add tabs when there's evidence users with mixed-grant responses want them.
|
|
@@ -40,7 +40,7 @@ The user has zero datapacks. Print:
|
|
|
40
40
|
```
|
|
41
41
|
You don't have any datapacks yet. Create one with:
|
|
42
42
|
|
|
43
|
-
datapack_create(
|
|
43
|
+
datapack_create(name="<your-datapack-name>")
|
|
44
44
|
|
|
45
45
|
Or visit the Meko Cloud console (Datapacks → New datapack).
|
|
46
46
|
```
|
|
@@ -7,12 +7,18 @@ import { dirname, join } from 'node:path';
|
|
|
7
7
|
|
|
8
8
|
import { install, uninstall } from '../lib/installer.mjs';
|
|
9
9
|
import { askChoice, askMultiChoice, askText, askSecret, askYesNo, close as closePrompts } from '../lib/prompt.mjs';
|
|
10
|
-
import { banner, error, dim, info } from '../lib/logger.mjs';
|
|
11
|
-
import {
|
|
10
|
+
import { banner, error, dim, info, warn } from '../lib/logger.mjs';
|
|
11
|
+
import {
|
|
12
|
+
isPackagedInstall,
|
|
13
|
+
MEKO_PRODUCTION_CONSOLE_URL,
|
|
14
|
+
selfInvocation,
|
|
15
|
+
} from '../lib/clients/common.mjs';
|
|
12
16
|
import { getClientAdapters } from '../lib/clients/index.mjs';
|
|
17
|
+
import { resolveSuggestedMcpUrl } from '../lib/url-selection.mjs';
|
|
13
18
|
import { parseClientList } from '../lib/clients/aliases.mjs';
|
|
14
19
|
import { startMigration, runChildMigration, readStatus, stopMigration } from '../lib/migrate.mjs';
|
|
15
20
|
import { checkLatest } from '../lib/version-check.mjs';
|
|
21
|
+
import { runCaptureStatus } from '../lib/capture-status.mjs';
|
|
16
22
|
|
|
17
23
|
// ---------------------------------------------------------------------------
|
|
18
24
|
// Flag definitions
|
|
@@ -39,6 +45,10 @@ const options = {
|
|
|
39
45
|
help: { type: 'boolean', short: 'h', default: false },
|
|
40
46
|
version: { type: 'boolean', short: 'v', default: false },
|
|
41
47
|
|
|
48
|
+
// --- Capture health (Capture V2 Workstream D) ---
|
|
49
|
+
'capture-status': { type: 'boolean', default: false },
|
|
50
|
+
json: { type: 'boolean', default: false },
|
|
51
|
+
|
|
42
52
|
// --- Migrate subcommand ---
|
|
43
53
|
migrate: { type: 'boolean', default: false },
|
|
44
54
|
'migrate-status': { type: 'boolean', default: false },
|
|
@@ -65,11 +75,11 @@ function readVersion() {
|
|
|
65
75
|
return pkg.version;
|
|
66
76
|
}
|
|
67
77
|
|
|
68
|
-
const ALL_CLIENTS = ['claude-code', 'claude-desktop', 'cursor', 'codex'];
|
|
78
|
+
const ALL_CLIENTS = ['claude-code', 'claude-desktop', 'cursor', 'codex', 'kiro'];
|
|
69
79
|
|
|
70
80
|
function printHelp() {
|
|
71
81
|
const text = `
|
|
72
|
-
Meko Setup for Claude
|
|
82
|
+
Meko Setup for Claude Code, Claude Desktop, Cursor, Codex, and Kiro
|
|
73
83
|
|
|
74
84
|
Install and configure Meko MCP Server in one command.
|
|
75
85
|
|
|
@@ -81,7 +91,7 @@ Examples:
|
|
|
81
91
|
create-meko-setup
|
|
82
92
|
|
|
83
93
|
# Cloud Meko for Claude Code (non-interactive):
|
|
84
|
-
create-meko-setup --url https://
|
|
94
|
+
create-meko-setup --url https://mcp.mekodata.ai/mcp --api-key "$MEKO_API_KEY" --yes
|
|
85
95
|
|
|
86
96
|
# Local Meko with Cursor config:
|
|
87
97
|
create-meko-setup --client cursor --local --scope project --yes
|
|
@@ -95,16 +105,24 @@ Examples:
|
|
|
95
105
|
# Install for OpenAI Codex (CLI + Desktop App share the same config):
|
|
96
106
|
create-meko-setup --client codex --yes
|
|
97
107
|
|
|
108
|
+
# Install for Kiro (IDE and kiro-cli share the same config):
|
|
109
|
+
create-meko-setup --client kiro --yes
|
|
110
|
+
|
|
98
111
|
# Local Meko (docker-compose stack, Claude Code):
|
|
99
112
|
create-meko-setup --local --yes
|
|
100
113
|
|
|
101
114
|
Options:
|
|
102
|
-
--client <list> Target clients: one or more of claude-code, claude-desktop, cursor, codex.
|
|
103
|
-
"claude" is accepted as an alias for claude-code
|
|
115
|
+
--client <list> Target clients: one or more of claude-code, claude-desktop, cursor, codex, kiro.
|
|
116
|
+
"claude" is accepted as an alias for claude-code;
|
|
117
|
+
"kiro-cli" and "kiro-ide" for kiro.
|
|
104
118
|
Comma-separated, or "all" to target every supported client (default: claude-code)
|
|
105
119
|
codex covers BOTH the OpenAI Codex CLI and the Codex Desktop App
|
|
106
120
|
(they share ~/.codex/config.toml).
|
|
107
|
-
|
|
121
|
+
kiro covers BOTH the Kiro IDE and kiro-cli. It installs
|
|
122
|
+
inline CLI 2.x and standalone CLI 3.x/IDE capture hooks;
|
|
123
|
+
untrusted IDE workspaces and non-managed CLI agents fall
|
|
124
|
+
back to agent-driven persistence.
|
|
125
|
+
--url <url> MCP server URL (from cloud.mekodata.ai > Datapacks > Connect)
|
|
108
126
|
--api-key <key> API key for Cloud Meko authentication
|
|
109
127
|
--local Use local Meko at http://localhost:8000/mcp
|
|
110
128
|
--scope <scope> Config scope: user or project (default: user)
|
|
@@ -129,6 +147,14 @@ Options:
|
|
|
129
147
|
-h, --help Show this help message
|
|
130
148
|
-v, --version Show version
|
|
131
149
|
|
|
150
|
+
Capture health (durable outbox / recovery):
|
|
151
|
+
--capture-status Report aggregate conversation-capture health from
|
|
152
|
+
~/.claude/meko-capture (or MEKO_WATERMARK_DIR).
|
|
153
|
+
Exit 0 = healthy|catching_up, 2 = degraded_retrying,
|
|
154
|
+
3 = blocked_action_required.
|
|
155
|
+
--json With --capture-status, print machine-readable JSON
|
|
156
|
+
matching the capture-health cache shape.
|
|
157
|
+
|
|
132
158
|
Migrate existing conversations and memories into Meko:
|
|
133
159
|
--migrate Start a detached migration of existing Claude Code
|
|
134
160
|
and Cursor conversations + CLAUDE.md memories.
|
|
@@ -262,6 +288,20 @@ async function main() {
|
|
|
262
288
|
process.exit(0);
|
|
263
289
|
}
|
|
264
290
|
|
|
291
|
+
// --capture-status — aggregate outbox health (Capture V2). Combine with
|
|
292
|
+
// --json for machine-readable output. Exit codes: 0 healthy|catching_up,
|
|
293
|
+
// 2 degraded_retrying, 3 blocked_action_required.
|
|
294
|
+
if (flags['capture-status']) {
|
|
295
|
+
const out = runCaptureStatus({ json: Boolean(flags.json) });
|
|
296
|
+
if (out.stdout) process.stdout.write(out.stdout);
|
|
297
|
+
if (out.stderr) process.stderr.write(out.stderr);
|
|
298
|
+
process.exit(out.code);
|
|
299
|
+
}
|
|
300
|
+
if (flags.json) {
|
|
301
|
+
error('--json requires --capture-status');
|
|
302
|
+
process.exit(1);
|
|
303
|
+
}
|
|
304
|
+
|
|
265
305
|
// --check-updates — synchronous probe of the npm registry. Never fails:
|
|
266
306
|
// network errors produce "status: network error (<message>)" and exit 0.
|
|
267
307
|
if (flags['check-updates']) {
|
|
@@ -437,6 +477,7 @@ async function main() {
|
|
|
437
477
|
'claude-desktop': 'Claude Desktop',
|
|
438
478
|
cursor: 'Cursor',
|
|
439
479
|
codex: 'OpenAI Codex (CLI + App)',
|
|
480
|
+
kiro: 'Kiro (IDE + kiro-cli)',
|
|
440
481
|
}[id];
|
|
441
482
|
return {
|
|
442
483
|
label: id,
|
|
@@ -465,6 +506,28 @@ async function main() {
|
|
|
465
506
|
}
|
|
466
507
|
}
|
|
467
508
|
|
|
509
|
+
let suggestedUrl = null;
|
|
510
|
+
if (!url && !flags.local) {
|
|
511
|
+
suggestedUrl = resolveSuggestedMcpUrl({
|
|
512
|
+
adapters: getClientAdapters(),
|
|
513
|
+
clients,
|
|
514
|
+
name: flags.name,
|
|
515
|
+
scope: flags.scope,
|
|
516
|
+
projectRoot,
|
|
517
|
+
});
|
|
518
|
+
if (flags.yes) {
|
|
519
|
+
if (suggestedUrl.source === 'conflict') {
|
|
520
|
+
const conflicts = suggestedUrl.existingUrls.map((existingUrl) => `\n - ${existingUrl}`).join('');
|
|
521
|
+
error(
|
|
522
|
+
`Selected clients have different existing Meko URLs:${conflicts}\n` +
|
|
523
|
+
'Pass --url explicitly to choose which endpoint to install.',
|
|
524
|
+
);
|
|
525
|
+
process.exit(1);
|
|
526
|
+
}
|
|
527
|
+
url = suggestedUrl.url;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
468
531
|
// Interactive mode: URL not provided and not auto-accepting defaults
|
|
469
532
|
if (!url && !flags.yes) {
|
|
470
533
|
banner('Meko Setup');
|
|
@@ -475,7 +538,7 @@ async function main() {
|
|
|
475
538
|
// When only Cloud is available, skip the prompt entirely — asking to
|
|
476
539
|
// pick between one option is pointless UX.
|
|
477
540
|
const connectionOptions = [
|
|
478
|
-
{ label: 'Cloud Meko', description: 'Hosted at
|
|
541
|
+
{ label: 'Cloud Meko', description: 'Hosted at mekodata.ai (requires an API key)' },
|
|
479
542
|
];
|
|
480
543
|
if (!isPackagedInstall()) {
|
|
481
544
|
connectionOptions.push({
|
|
@@ -490,7 +553,19 @@ async function main() {
|
|
|
490
553
|
|
|
491
554
|
if (connectionType === 'Cloud Meko') {
|
|
492
555
|
// Step 2 — MCP URL
|
|
493
|
-
|
|
556
|
+
if (suggestedUrl?.source === 'existing') {
|
|
557
|
+
dim(`Using the existing Meko endpoint as the default: ${suggestedUrl.url}`);
|
|
558
|
+
} else if (suggestedUrl?.source === 'conflict') {
|
|
559
|
+
const conflicts = suggestedUrl.existingUrls.map((existingUrl) => `\n - ${existingUrl}`).join('');
|
|
560
|
+
warn(
|
|
561
|
+
`Selected clients use different Meko endpoints:${conflicts}\n` +
|
|
562
|
+
'Enter the endpoint to use for this install.',
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
url = await askText(
|
|
566
|
+
`MCP server URL (from ${MEKO_PRODUCTION_CONSOLE_URL} > Datapacks > Connect):`,
|
|
567
|
+
suggestedUrl?.url ?? undefined,
|
|
568
|
+
);
|
|
494
569
|
|
|
495
570
|
// Step 3 — API key. Normalize: terminal paste can drag in trailing
|
|
496
571
|
// whitespace/CR or accidental surrounding quotes, all of which would
|
|
@@ -503,12 +578,14 @@ async function main() {
|
|
|
503
578
|
}
|
|
504
579
|
|
|
505
580
|
// Step 4 — skills
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
581
|
+
if (!skipSkills) {
|
|
582
|
+
const installSkills = await askYesNo(
|
|
583
|
+
'Install Meko agent skills plugin? (behavioral guides for MCP tools)',
|
|
584
|
+
true,
|
|
585
|
+
);
|
|
586
|
+
if (!installSkills) {
|
|
587
|
+
skipSkills = true;
|
|
588
|
+
}
|
|
512
589
|
}
|
|
513
590
|
|
|
514
591
|
// Step 5 — statusline (Claude Code only). --no-statusline / --statusline
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* capture-status.mjs — Installer helper that invokes capture-status-cli.js.
|
|
3
|
+
*
|
|
4
|
+
* Resolves the CLI next to bundled/source hooks (same root as capture.js).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { spawnSync } from "node:child_process";
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { dirname, join, resolve } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
|
|
12
|
+
import { resolveHooksRoot } from "./clients/common.mjs";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Absolute path to capture-status-cli.js under the active asset root.
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
export function resolveCaptureStatusCli() {
|
|
19
|
+
// Prefer the stable source-tree path in a checkout. Bundle tests create and
|
|
20
|
+
// remove installer/assets concurrently, so probing that transient directory
|
|
21
|
+
// first can race between existsSync and spawnSync. Published packages do not
|
|
22
|
+
// contain the repository skills tree and therefore fall back to assets.
|
|
23
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
const sourceCli = resolve(
|
|
25
|
+
here,
|
|
26
|
+
"..",
|
|
27
|
+
"..",
|
|
28
|
+
"skills",
|
|
29
|
+
"hooks-handlers",
|
|
30
|
+
"lib",
|
|
31
|
+
"capture-status-cli.js",
|
|
32
|
+
);
|
|
33
|
+
if (existsSync(sourceCli)) return sourceCli;
|
|
34
|
+
return join(resolveHooksRoot(), "lib", "capture-status-cli.js");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Run the capture-status CLI and return its result.
|
|
39
|
+
*
|
|
40
|
+
* @param {{ json?: boolean, env?: NodeJS.ProcessEnv }} [opts]
|
|
41
|
+
* @returns {{ code: number, stdout: string, stderr: string, cliPath: string }}
|
|
42
|
+
*/
|
|
43
|
+
export function runCaptureStatus(opts = {}) {
|
|
44
|
+
const cliPath = resolveCaptureStatusCli();
|
|
45
|
+
if (!existsSync(cliPath)) {
|
|
46
|
+
return {
|
|
47
|
+
code: 1,
|
|
48
|
+
stdout: "",
|
|
49
|
+
stderr: `capture-status CLI not found at ${cliPath}`,
|
|
50
|
+
cliPath,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const args = [cliPath];
|
|
54
|
+
if (opts.json) args.push("--json");
|
|
55
|
+
const result = spawnSync(process.execPath, args, {
|
|
56
|
+
encoding: "utf8",
|
|
57
|
+
env: opts.env ? { ...process.env, ...opts.env } : process.env,
|
|
58
|
+
});
|
|
59
|
+
const code =
|
|
60
|
+
typeof result.status === "number" && result.status >= 0 ? result.status : 1;
|
|
61
|
+
return {
|
|
62
|
+
code,
|
|
63
|
+
stdout: result.stdout || "",
|
|
64
|
+
stderr: result.stderr || "",
|
|
65
|
+
cliPath,
|
|
66
|
+
};
|
|
67
|
+
}
|
package/lib/clients/aliases.mjs
CHANGED
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
// import it without booting the bin entry point.
|
|
4
4
|
export const CLIENT_ALIASES = Object.freeze({
|
|
5
5
|
claude: "claude-code",
|
|
6
|
+
// The Kiro IDE and `kiro-cli` share one adapter: same mcp.json paths, same
|
|
7
|
+
// skills directories. Users reach for whichever name matches the surface
|
|
8
|
+
// they're installing for, so both resolve to the single `kiro` adapter.
|
|
9
|
+
"kiro-cli": "kiro",
|
|
10
|
+
"kiro-ide": "kiro",
|
|
6
11
|
});
|
|
7
12
|
|
|
8
13
|
/**
|
|
@@ -288,13 +288,17 @@ export function createClaudeCodeAdapter(options = {}) {
|
|
|
288
288
|
// leaving the marketplace.json missing. Full clone is small
|
|
289
289
|
// (~few MB, mostly markdown) and is the only way that reliably
|
|
290
290
|
// succeeds today.
|
|
291
|
-
// Marketplace source is normally the
|
|
291
|
+
// Marketplace source is normally the public generated skills repo. Use
|
|
292
|
+
// an explicit HTTPS URL: GitHub's owner/repo shorthand makes Claude Code
|
|
293
|
+
// clone over SSH, which fails for users without GitHub SSH credentials.
|
|
294
|
+
// A dev/e2e
|
|
292
295
|
// override lets a test install the plugin from a LOCAL working-tree
|
|
293
296
|
// checkout (a directory path) so unreleased skill changes can be
|
|
294
|
-
// exercised end-to-end before they
|
|
295
|
-
//
|
|
297
|
+
// exercised end-to-end before they are published to `yugabyte/meko-skills`.
|
|
298
|
+
// Only set MEKO_PLUGIN_MARKETPLACE_SOURCE in tests.
|
|
296
299
|
const marketplaceSource =
|
|
297
|
-
process.env.MEKO_PLUGIN_MARKETPLACE_SOURCE
|
|
300
|
+
process.env.MEKO_PLUGIN_MARKETPLACE_SOURCE
|
|
301
|
+
|| "https://github.com/yugabyte/meko-skills.git";
|
|
298
302
|
const marketplaceCmd =
|
|
299
303
|
`claude plugin marketplace add ${shellQuote(marketplaceSource)} --scope ${shellQuote(scope)}`;
|
|
300
304
|
// `claude plugin list` dropped --scope in CLI 2.1.x; it prints all
|