mnemos-capture 1.3.0 → 1.4.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 +36 -36
- package/dist/cli/config.js +25 -16
- package/dist/cli/hooks.js +4 -4
- package/dist/cli/index.js +17 -17
- package/dist/cli/kos.js +6 -6
- package/dist/cli/mcp-server.js +8 -8
- package/dist/cli/version-check.js +1 -1
- package/package.json +13 -11
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<a href="https://mnemos-capture.vercel.app">
|
|
4
4
|
<picture>
|
|
5
5
|
<source media="(prefers-color-scheme: dark)" srcset="public/mnemos-hero-dark.gif">
|
|
6
|
-
<img src="public/mnemos-hero-light.gif" width="160" height="160" alt="
|
|
6
|
+
<img src="public/mnemos-hero-light.gif" width="160" height="160" alt="xkg">
|
|
7
7
|
</picture>
|
|
8
8
|
</a>
|
|
9
9
|
<br>
|
|
@@ -15,15 +15,15 @@
|
|
|
15
15
|
</p>
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## xkg
|
|
19
19
|
|
|
20
20
|
Humans are constantly exposed to useful knowledge, domain expertise, and external input. But there is no bridge between what humans know and what their AI workers know and do.
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
xkg is the knowledge graph for AI workers that bridges human knowledge into context they can use.
|
|
23
23
|
|
|
24
24
|
## Table of Contents
|
|
25
25
|
|
|
26
|
-
- [
|
|
26
|
+
- [xkg](#xkg)
|
|
27
27
|
- [How it works](#how-it-works)
|
|
28
28
|
- [Start here](#start-here)
|
|
29
29
|
- [Connect your AI workers](#connect-your-ai-workers)
|
|
@@ -48,12 +48,12 @@ Xmu is the knowledge graph for AI workers that bridges human knowledge into cont
|
|
|
48
48
|
|
|
49
49
|
## How it works
|
|
50
50
|
|
|
51
|
-
You find useful stuff, you capture through the web app, then
|
|
51
|
+
You find useful stuff, you capture through the web app, then xkg connects it into a knowledge graph, and makes it available to the AI workers you already use.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
xkg will continuously compound that knowledge over time — keeping AI workers' context up to date as human knowledge evolves.
|
|
54
54
|
|
|
55
55
|
> [!IMPORTANT]
|
|
56
|
-
> We are migrating from **mnemos** to **
|
|
56
|
+
> We are migrating from **mnemos** / **Xmu** to **xkg**. The app URL, this GitHub repo, and the npm package still say `mnemos-capture`. Sorry for the inconvenience.
|
|
57
57
|
|
|
58
58
|
## Start here
|
|
59
59
|
|
|
@@ -63,12 +63,12 @@ You do not need a terminal to start.
|
|
|
63
63
|
|
|
64
64
|
Open **[mnemos-capture.vercel.app](https://mnemos-capture.vercel.app)** and sign in with GitHub.
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
xkg will:
|
|
67
67
|
|
|
68
68
|
1. Create a **private** GitHub repo for your knowledge (you can opt to make it public)
|
|
69
69
|
2. Ask for your LLM provider API key — Anthropic, OpenAI, or Google. Your key, your cost.
|
|
70
70
|
3. Let you set a PIN (6+ characters) for quick unlock on this device
|
|
71
|
-
4. Show your **
|
|
71
|
+
4. Show your **xkg API key** once — save it if you want to connect an AI worker
|
|
72
72
|
|
|
73
73
|
That's the whole setup. No repo to clone. No database. No CLI required.
|
|
74
74
|
|
|
@@ -76,7 +76,7 @@ That's the whole setup. No repo to clone. No database. No CLI required.
|
|
|
76
76
|
|
|
77
77
|
In the app, paste a URL, a note, a doc excerpt, a transcript, or an idea, then hit **Capture**.
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
xkg extracts the **core idea**, **key takeaways**, **where to apply it**, and the **capture type**, then commits Markdown to your GitHub repo.
|
|
80
80
|
|
|
81
81
|
On a phone: open the app → **Share → Add to Home Screen**. It runs like a native app.
|
|
82
82
|
|
|
@@ -86,7 +86,7 @@ Skip this if you only want the app today. When you're ready, pick your tool unde
|
|
|
86
86
|
|
|
87
87
|
## Connect your AI workers
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
xkg is LLM-agnostic. Any worker that speaks MCP can use the same knowledge.
|
|
90
90
|
|
|
91
91
|
Two primitives:
|
|
92
92
|
|
|
@@ -98,13 +98,13 @@ https://mnemos-capture.vercel.app/api/mcp
|
|
|
98
98
|
npx -y mnemos-capture@latest serve-mcp --key YOUR_API_KEY
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
The CLI binary is **`
|
|
101
|
+
The CLI binary is **`xkg`** (also `xmu` and `mnemos-capture`). `npx` still uses the package name `mnemos-capture`. An MCP server already registered as `xmu` or `mnemos` keeps working.
|
|
102
102
|
|
|
103
|
-
**On the web** — paste the URL (no terminal). **In the terminal** — run the command. Finish
|
|
103
|
+
**On the web** — paste the URL (no terminal). **In the terminal** — run the command. Finish xkg onboarding first, then ask: *list my inbox* or *brief me*.
|
|
104
104
|
|
|
105
105
|
### On the web
|
|
106
106
|
|
|
107
|
-
Name the connector `
|
|
107
|
+
Name the connector `xkg`, paste `https://mnemos-capture.vercel.app/api/mcp`, sign in with GitHub when asked.
|
|
108
108
|
|
|
109
109
|
#### Claude
|
|
110
110
|
|
|
@@ -113,7 +113,7 @@ Name the connector `Xmu`, paste `https://mnemos-capture.vercel.app/api/mcp`, sig
|
|
|
113
113
|
#### ChatGPT
|
|
114
114
|
|
|
115
115
|
1. Settings → Plugins → Browse plugins
|
|
116
|
-
2. Name it
|
|
116
|
+
2. Name it xkg
|
|
117
117
|
3. Paste `https://mnemos-capture.vercel.app/api/mcp`
|
|
118
118
|
4. Sign in with GitHub when asked
|
|
119
119
|
|
|
@@ -138,7 +138,7 @@ Add this to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (all projects):
|
|
|
138
138
|
```json
|
|
139
139
|
{
|
|
140
140
|
"mcpServers": {
|
|
141
|
-
"
|
|
141
|
+
"xkg": {
|
|
142
142
|
"command": "npx",
|
|
143
143
|
"args": ["-y", "mnemos-capture@latest", "serve-mcp", "--key", "YOUR_API_KEY"]
|
|
144
144
|
}
|
|
@@ -155,7 +155,7 @@ Add this to `.vscode/mcp.json`:
|
|
|
155
155
|
```json
|
|
156
156
|
{
|
|
157
157
|
"servers": {
|
|
158
|
-
"
|
|
158
|
+
"xkg": {
|
|
159
159
|
"command": "npx",
|
|
160
160
|
"args": ["-y", "mnemos-capture@latest", "serve-mcp", "--key", "YOUR_API_KEY"]
|
|
161
161
|
}
|
|
@@ -170,7 +170,7 @@ GitHub Copilot Chat in VS Code uses the same file.
|
|
|
170
170
|
Codex CLI — add this to `~/.codex/config.toml`:
|
|
171
171
|
|
|
172
172
|
```toml
|
|
173
|
-
[mcp_servers.
|
|
173
|
+
[mcp_servers.xkg]
|
|
174
174
|
command = "npx"
|
|
175
175
|
args = ["-y", "mnemos-capture@latest", "serve-mcp", "--key", "YOUR_API_KEY"]
|
|
176
176
|
```
|
|
@@ -180,19 +180,19 @@ Codex App: Settings → MCP → add the same `npx` command.
|
|
|
180
180
|
#### Gemini CLI
|
|
181
181
|
|
|
182
182
|
```bash
|
|
183
|
-
gemini mcp add
|
|
183
|
+
gemini mcp add xkg npx -y mnemos-capture@latest serve-mcp --key YOUR_API_KEY
|
|
184
184
|
```
|
|
185
185
|
|
|
186
186
|
#### Claude Code
|
|
187
187
|
|
|
188
188
|
```bash
|
|
189
|
-
claude mcp add
|
|
189
|
+
claude mcp add xkg -- npx -y mnemos-capture@latest serve-mcp --key YOUR_API_KEY
|
|
190
190
|
```
|
|
191
191
|
|
|
192
192
|
Or the URL, no API key:
|
|
193
193
|
|
|
194
194
|
```bash
|
|
195
|
-
claude mcp add --transport http
|
|
195
|
+
claude mcp add --transport http xkg https://mnemos-capture.vercel.app/api/mcp
|
|
196
196
|
```
|
|
197
197
|
|
|
198
198
|
Optional session hooks (MCP works without them):
|
|
@@ -210,7 +210,7 @@ Settings → Developer → Edit Config. Add the same `npx` block to `claude_desk
|
|
|
210
210
|
```json
|
|
211
211
|
{
|
|
212
212
|
"mcpServers": {
|
|
213
|
-
"
|
|
213
|
+
"xkg": {
|
|
214
214
|
"command": "npx",
|
|
215
215
|
"args": ["-y", "mnemos-capture@latest", "serve-mcp", "--key", "YOUR_API_KEY"]
|
|
216
216
|
}
|
|
@@ -225,7 +225,7 @@ If the tool can launch a local process, register the same `npx` command. If it h
|
|
|
225
225
|
```json
|
|
226
226
|
{
|
|
227
227
|
"mcpServers": {
|
|
228
|
-
"
|
|
228
|
+
"xkg": {
|
|
229
229
|
"command": "npx",
|
|
230
230
|
"args": ["-y", "mnemos-capture@latest", "serve-mcp", "--key", "YOUR_API_KEY"]
|
|
231
231
|
}
|
|
@@ -233,7 +233,7 @@ If the tool can launch a local process, register the same `npx` command. If it h
|
|
|
233
233
|
}
|
|
234
234
|
```
|
|
235
235
|
|
|
236
|
-
No MCP support yet? Capture in the [
|
|
236
|
+
No MCP support yet? Capture in the [xkg app](https://mnemos-capture.vercel.app) and connect later.
|
|
237
237
|
|
|
238
238
|
## Workflow
|
|
239
239
|
|
|
@@ -241,7 +241,7 @@ No MCP support yet? Capture in the [Xmu app](https://mnemos-capture.vercel.app)
|
|
|
241
241
|
<img src="public/flow-workflow.svg" width="720" alt="Docs and notes → Capture → GitHub Markdown → Brief → Plan → Execute → Mark applied" />
|
|
242
242
|
</p>
|
|
243
243
|
|
|
244
|
-
1. **Capture** — Paste anything text-based: papers, docs, posts, GitHub repos, notes, decisions, ideas, transcripts.
|
|
244
|
+
1. **Capture** — Paste anything text-based: papers, docs, posts, GitHub repos, notes, decisions, ideas, transcripts. xkg detects a URL, a short note, or longer text. No manual tagging.
|
|
245
245
|
|
|
246
246
|
From a connected worker:
|
|
247
247
|
|
|
@@ -249,7 +249,7 @@ No MCP support yet? Capture in the [Xmu app](https://mnemos-capture.vercel.app)
|
|
|
249
249
|
capture "The Mom Test: don't ask if your idea is good. Ask about the person's real behavior, current workflow, and past spending."
|
|
250
250
|
```
|
|
251
251
|
|
|
252
|
-
2. **Brief** — At the start of a work session, ask your worker for a briefing.
|
|
252
|
+
2. **Brief** — At the start of a work session, ask your worker for a briefing. xkg looks at your project (branch, recent commits, `CLAUDE.md`, repo context) and ranks captures that could help now: **why** it matters, **what** applying it could achieve, **where** it could land. You decide what to apply.
|
|
253
253
|
|
|
254
254
|
3. **Plan** — Select the captures you want and ask your worker to call `generate_plan`. Each plan is Markdown: codebase mapping, implementation steps with effort tiers (`simple`, `complex`, `architectural`), and a verification checklist.
|
|
255
255
|
|
|
@@ -328,7 +328,7 @@ You don't have to memorize these. Ask in plain language: "save this", "what do I
|
|
|
328
328
|
|
|
329
329
|
## CLI
|
|
330
330
|
|
|
331
|
-
No global install required. The binary is **`
|
|
331
|
+
No global install required. The binary is **`xkg`** (also `xmu` and `mnemos-capture`). Via npx:
|
|
332
332
|
|
|
333
333
|
```bash
|
|
334
334
|
npx -y mnemos-capture@latest <command>
|
|
@@ -349,18 +349,18 @@ npx -y mnemos-capture@latest <command>
|
|
|
349
349
|
|
|
350
350
|
Captures live as structured Markdown in **your** GitHub repository. Private by default.
|
|
351
351
|
|
|
352
|
-
- **No lock-in** — clone it, move it, delete
|
|
352
|
+
- **No lock-in** — clone it, move it, delete xkg, keep the files
|
|
353
353
|
- **No proprietary format** — every capture is a readable `.md` file
|
|
354
354
|
- **No training on your data** — captures are sent only to the LLM provider you chose, with the key you supplied, to extract the insight you asked for
|
|
355
355
|
- **Any tool can read it** — anything that reads Git or speaks MCP
|
|
356
356
|
- **BYOK** — your provider, your key, your cost
|
|
357
|
-
- **Never commit your
|
|
357
|
+
- **Never commit your xkg API key** to source control
|
|
358
358
|
|
|
359
|
-
### What
|
|
359
|
+
### What xkg stores, and where
|
|
360
360
|
|
|
361
361
|
The whole point of this repo being public is that you can check these claims rather than trust them.
|
|
362
362
|
|
|
363
|
-
**Your captures are never stored by
|
|
363
|
+
**Your captures are never stored by xkg.** They are written straight to your own GitHub repo as Markdown (`src/lib/github.ts`). There is no captures table. Delete the app and your knowledge is untouched.
|
|
364
364
|
|
|
365
365
|
**The database holds only account plumbing** (`src/lib/db.ts`):
|
|
366
366
|
|
|
@@ -389,7 +389,7 @@ No analytics, no telemetry, no third-party tracking.
|
|
|
389
389
|
| --- | --- |
|
|
390
390
|
| GitHub token | Encrypted at rest (AES-256-GCM). Uses the `repo` scope, required to read and write a **private** knowledge hub |
|
|
391
391
|
| Your LLM API key | Encrypted at rest (AES-256-GCM) |
|
|
392
|
-
| Your MCP API key | Hashed — never recoverable, not even by
|
|
392
|
+
| Your MCP API key | Hashed — never recoverable, not even by xkg |
|
|
393
393
|
| Your PIN | Salted scrypt hash |
|
|
394
394
|
|
|
395
395
|
Your MCP key is shown exactly once. If you lose it, generate a new one.
|
|
@@ -400,7 +400,7 @@ Your MCP key is shown exactly once. If you lose it, generate a new one.
|
|
|
400
400
|
|
|
401
401
|
## Cost
|
|
402
402
|
|
|
403
|
-
|
|
403
|
+
xkg is BYOK. You bring your own API key. xkg never charges you for inference.
|
|
404
404
|
|
|
405
405
|
Extraction runs on a fast, low-cost model (Claude Haiku 4.5 by default):
|
|
406
406
|
|
|
@@ -417,7 +417,7 @@ Briefing, planning, and synthesis only run when you ask for them.
|
|
|
417
417
|
- **Learning Graph** — Applied work feeds the next brief. The graph compounds.
|
|
418
418
|
- **Knowledge Graph for Teams** — One graph the team and their AI workers share and compound.
|
|
419
419
|
- **Chrome extension** — Capture from the page you are on, without leaving the browser.
|
|
420
|
-
- **Voice memo** — Speak it.
|
|
420
|
+
- **Voice memo** — Speak it. xkg turns it into a capture.
|
|
421
421
|
|
|
422
422
|
Working on the code? See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
423
423
|
|
|
@@ -425,11 +425,11 @@ Working on the code? See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
|
425
425
|
|
|
426
426
|
[MIT License](./LICENSE)
|
|
427
427
|
|
|
428
|
-
If you use
|
|
428
|
+
If you use xkg in published work:
|
|
429
429
|
|
|
430
430
|
```bibtex
|
|
431
431
|
@misc{2026mnemos,
|
|
432
|
-
title = {
|
|
432
|
+
title = {xkg: A Knowledge Graph for AI workers},
|
|
433
433
|
author = {Sofia Padron Valdez},
|
|
434
434
|
year = 2026,
|
|
435
435
|
journal = {GitHub repository},
|
package/dist/cli/config.js
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* optional API key, in ~/.
|
|
2
|
+
* xkg CLI config — stores which AI assistant kos should drive, and an
|
|
3
|
+
* optional API key, in ~/.xkg/config.json.
|
|
4
|
+
* Falls back to ~/.xmu/config.json then ~/.mnemos/config.json.
|
|
4
5
|
*/
|
|
5
6
|
import { homedir } from "os";
|
|
6
7
|
import { join } from "path";
|
|
7
8
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
9
|
+
function xkgDir() {
|
|
10
|
+
return join(homedir(), ".xkg");
|
|
11
|
+
}
|
|
8
12
|
function xmuDir() {
|
|
9
13
|
return join(homedir(), ".xmu");
|
|
10
14
|
}
|
|
11
|
-
function
|
|
15
|
+
function mnemosDir() {
|
|
12
16
|
return join(homedir(), ".mnemos");
|
|
13
17
|
}
|
|
18
|
+
function xkgPath() {
|
|
19
|
+
return join(xkgDir(), "config.json");
|
|
20
|
+
}
|
|
14
21
|
function xmuPath() {
|
|
15
22
|
return join(xmuDir(), "config.json");
|
|
16
23
|
}
|
|
17
|
-
function
|
|
18
|
-
return join(
|
|
24
|
+
function mnemosPath() {
|
|
25
|
+
return join(mnemosDir(), "config.json");
|
|
19
26
|
}
|
|
20
|
-
/** Path we currently read from:
|
|
27
|
+
/** Path we currently read from: xkg, then xmu, then mnemos. */
|
|
21
28
|
function readPath() {
|
|
29
|
+
if (existsSync(xkgPath()))
|
|
30
|
+
return xkgPath();
|
|
22
31
|
if (existsSync(xmuPath()))
|
|
23
32
|
return xmuPath();
|
|
24
|
-
if (existsSync(
|
|
25
|
-
return
|
|
26
|
-
return
|
|
33
|
+
if (existsSync(mnemosPath()))
|
|
34
|
+
return mnemosPath();
|
|
35
|
+
return xkgPath();
|
|
27
36
|
}
|
|
28
37
|
const ALLOWED_FIELDS = ["agent", "key"];
|
|
29
38
|
export function readConfig() {
|
|
@@ -38,10 +47,10 @@ export function readConfig() {
|
|
|
38
47
|
}
|
|
39
48
|
}
|
|
40
49
|
export function writeConfig(cfg) {
|
|
41
|
-
const dir =
|
|
50
|
+
const dir = xkgDir();
|
|
42
51
|
if (!existsSync(dir))
|
|
43
52
|
mkdirSync(dir, { recursive: true });
|
|
44
|
-
writeFileSync(
|
|
53
|
+
writeFileSync(xkgPath(), JSON.stringify(cfg, null, 2) + "\n");
|
|
45
54
|
}
|
|
46
55
|
export function setConfigField(field, value) {
|
|
47
56
|
if (!ALLOWED_FIELDS.includes(field)) {
|
|
@@ -51,21 +60,21 @@ export function setConfigField(field, value) {
|
|
|
51
60
|
cfg[field] = value;
|
|
52
61
|
writeConfig(cfg);
|
|
53
62
|
}
|
|
54
|
-
/** Route `
|
|
63
|
+
/** Route `xkg config <set|get> ...`. */
|
|
55
64
|
export function runConfigCommand(args) {
|
|
56
65
|
const action = args[0];
|
|
57
66
|
if (action === "set") {
|
|
58
67
|
const field = args[1];
|
|
59
68
|
const value = args.slice(2).join(" ");
|
|
60
69
|
if (!field || !value) {
|
|
61
|
-
console.error("Usage:
|
|
62
|
-
console.error(' e.g.
|
|
70
|
+
console.error("Usage: xkg config set <field> <value>");
|
|
71
|
+
console.error(' e.g. xkg config set agent "claude -p"');
|
|
63
72
|
process.exit(1);
|
|
64
73
|
}
|
|
65
74
|
try {
|
|
66
75
|
setConfigField(field, value);
|
|
67
76
|
console.log(`Set ${field} = ${value}`);
|
|
68
|
-
console.log(`Saved to ${
|
|
77
|
+
console.log(`Saved to ${xkgPath()}`);
|
|
69
78
|
}
|
|
70
79
|
catch (err) {
|
|
71
80
|
console.error(err instanceof Error ? err.message : String(err));
|
|
@@ -84,6 +93,6 @@ export function runConfigCommand(args) {
|
|
|
84
93
|
}
|
|
85
94
|
return;
|
|
86
95
|
}
|
|
87
|
-
console.error("Usage:
|
|
96
|
+
console.error("Usage: xkg config set|get <field> [value]");
|
|
88
97
|
process.exit(1);
|
|
89
98
|
}
|
package/dist/cli/hooks.js
CHANGED
|
@@ -108,7 +108,7 @@ export function setupHooks(apiKey, opts = {}) {
|
|
|
108
108
|
settings.hooks = { ...hooks, SessionStart: filtered };
|
|
109
109
|
writeSettings(settings);
|
|
110
110
|
if (!opts.silent) {
|
|
111
|
-
console.log("
|
|
111
|
+
console.log("xkg inbox hook installed.");
|
|
112
112
|
console.log(`Location: ${CLAUDE_SETTINGS_PATH}`);
|
|
113
113
|
if (opts.briefing) {
|
|
114
114
|
console.log("At the start of each Claude Code session you'll see a full project briefing.");
|
|
@@ -151,7 +151,7 @@ export function setupPreToolHook(apiKey, opts = {}) {
|
|
|
151
151
|
settings.hooks = { ...hooks, PreToolCall: filtered };
|
|
152
152
|
writeSettings(settings);
|
|
153
153
|
if (!opts.silent) {
|
|
154
|
-
console.log("
|
|
154
|
+
console.log("xkg vault hook installed (PreToolCall).");
|
|
155
155
|
console.log("Your knowledge vault will surface relevant captures as you edit files.");
|
|
156
156
|
}
|
|
157
157
|
}
|
|
@@ -279,7 +279,7 @@ export async function inboxCheck(apiKey, opts = {}) {
|
|
|
279
279
|
process.stdout.write(displayText + "\n");
|
|
280
280
|
if (applyNow.length > 0) {
|
|
281
281
|
const filenames = applyNow.map((s) => `'${s.filename}'`).join(", ");
|
|
282
|
-
process.stdout.write(`\n---\
|
|
282
|
+
process.stdout.write(`\n---\nxkg: ${applyNow.length} insight${applyNow.length === 1 ? "" : "s"} ready to apply now.\n` +
|
|
283
283
|
`Run generate_plan with selected_captures: [${filenames}] to get a full implementation plan.\n`);
|
|
284
284
|
}
|
|
285
285
|
return;
|
|
@@ -294,7 +294,7 @@ export async function inboxCheck(apiKey, opts = {}) {
|
|
|
294
294
|
return;
|
|
295
295
|
const count = parseInt(match[1], 10);
|
|
296
296
|
if (count > 0) {
|
|
297
|
-
process.stdout.write(`
|
|
297
|
+
process.stdout.write(`xkg: ${count} capture${count === 1 ? "" : "s"} in inbox — run list_inbox to review\n`);
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
300
|
catch {
|
package/dist/cli/index.js
CHANGED
|
@@ -52,7 +52,7 @@ async function main() {
|
|
|
52
52
|
const keyIdx = args.indexOf("--key");
|
|
53
53
|
const apiKey = keyIdx !== -1 ? args[keyIdx + 1] : readConfig().key;
|
|
54
54
|
if (!apiKey) {
|
|
55
|
-
console.error("No API key. Pass --key YOUR_KEY or store it:
|
|
55
|
+
console.error("No API key. Pass --key YOUR_KEY or store it: xkg config set key YOUR_KEY");
|
|
56
56
|
process.exit(1);
|
|
57
57
|
}
|
|
58
58
|
const planIdx = args.indexOf("--plan");
|
|
@@ -62,13 +62,13 @@ async function main() {
|
|
|
62
62
|
}
|
|
63
63
|
// Default: open the hosted app
|
|
64
64
|
console.log("");
|
|
65
|
-
console.log("
|
|
65
|
+
console.log(" xkg — A knowledge graph for your AI workers\n");
|
|
66
66
|
console.log(` Open ${HOSTED_URL} to start capturing.`);
|
|
67
67
|
console.log("");
|
|
68
68
|
console.log(" First time? Sign in with GitHub — setup takes 30 seconds.");
|
|
69
69
|
console.log("");
|
|
70
70
|
console.log(" Connect an AI worker:");
|
|
71
|
-
console.log(" claude mcp add
|
|
71
|
+
console.log(" claude mcp add xkg -- npx -y mnemos-capture@latest serve-mcp --key YOUR_API_KEY");
|
|
72
72
|
console.log("");
|
|
73
73
|
// Try to open the URL in the default browser
|
|
74
74
|
const { exec } = await import("child_process");
|
|
@@ -77,18 +77,18 @@ async function main() {
|
|
|
77
77
|
}
|
|
78
78
|
function printHelp() {
|
|
79
79
|
console.log(`
|
|
80
|
-
|
|
80
|
+
xkg — A knowledge graph for your AI workers
|
|
81
81
|
|
|
82
82
|
Usage:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
83
|
+
xkg Open xkg in your browser
|
|
84
|
+
xkg serve-mcp --key KEY Start the MCP server for your AI worker
|
|
85
|
+
xkg setup-hooks --key KEY Install inbox count hook (fast)
|
|
86
|
+
xkg setup-hooks --key KEY --briefing Install full briefing hook (uses LLM)
|
|
87
|
+
xkg setup-hooks --key KEY --vault Install vault hook (PreToolCall)
|
|
88
|
+
xkg setup-hooks --key KEY --briefing --vault Install both hooks
|
|
89
|
+
xkg config set agent "claude -p" Set which AI worker kos drives
|
|
90
|
+
xkg kos --key KEY [--plan FILE] Implement a plan in an isolated worktree
|
|
91
|
+
xkg help Show this help
|
|
92
92
|
|
|
93
93
|
npx -y mnemos-capture@latest … Same CLI, via the published package
|
|
94
94
|
|
|
@@ -100,10 +100,10 @@ function printHelp() {
|
|
|
100
100
|
curate — Validate URLs and flag stale captures
|
|
101
101
|
|
|
102
102
|
kos — implement plans with your own AI worker (model-agnostic):
|
|
103
|
-
1. Tell
|
|
104
|
-
|
|
103
|
+
1. Tell xkg which assistant to drive (once):
|
|
104
|
+
xkg config set agent "claude -p" # or "codex exec", "aider --yes --message"
|
|
105
105
|
2. Generate a plan via the generate_plan MCP tool.
|
|
106
|
-
3. Run:
|
|
106
|
+
3. Run: xkg kos --key YOUR_KEY
|
|
107
107
|
kos creates an isolated git worktree, hands the plan to your assistant,
|
|
108
108
|
and reports the branch + the plan's Verification Checklist when done.
|
|
109
109
|
|
|
@@ -114,7 +114,7 @@ function printHelp() {
|
|
|
114
114
|
4. Start capturing!
|
|
115
115
|
|
|
116
116
|
Connect to Claude Code:
|
|
117
|
-
claude mcp add
|
|
117
|
+
claude mcp add xkg -- npx -y mnemos-capture@latest serve-mcp --key YOUR_API_KEY
|
|
118
118
|
|
|
119
119
|
The @latest tag ensures every Claude Code session uses the most recent
|
|
120
120
|
published version. serve-mcp also self-upgrades on startup as a safety net
|
package/dist/cli/kos.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* kos — mnemos' Knowledge Operations orchestrator.
|
|
3
3
|
*
|
|
4
|
-
* Drives whatever AI assistant the user configured (`
|
|
4
|
+
* Drives whatever AI assistant the user configured (`xkg config set agent ...`)
|
|
5
5
|
* to implement a generated plan in an isolated git worktree. mnemos owns the
|
|
6
6
|
* harness-independent parts: fetching the plan, the worktree, and reporting the
|
|
7
7
|
* Verification Checklist. The assistant is a black box — model-agnostic by design.
|
|
@@ -54,10 +54,10 @@ function run(cmd, cwd) {
|
|
|
54
54
|
export async function kos(apiKey, opts = {}) {
|
|
55
55
|
const cfg = readConfig();
|
|
56
56
|
if (!cfg.agent) {
|
|
57
|
-
console.error("No agent configured. Tell
|
|
58
|
-
console.error('
|
|
59
|
-
console.error('
|
|
60
|
-
console.error('
|
|
57
|
+
console.error("No agent configured. Tell xkg which AI worker to drive:\n");
|
|
58
|
+
console.error(' xkg config set agent "claude -p" # Claude Code');
|
|
59
|
+
console.error(' xkg config set agent "codex exec" # Codex');
|
|
60
|
+
console.error(' xkg config set agent "aider --yes --message" # Aider');
|
|
61
61
|
process.exit(1);
|
|
62
62
|
}
|
|
63
63
|
// 1. Resolve the plan — explicit filename, or the newest saved plan
|
|
@@ -77,7 +77,7 @@ export async function kos(apiKey, opts = {}) {
|
|
|
77
77
|
repoRoot = run("git rev-parse --show-toplevel");
|
|
78
78
|
}
|
|
79
79
|
catch {
|
|
80
|
-
console.error("
|
|
80
|
+
console.error("xkg kos must be run inside a git repository.");
|
|
81
81
|
process.exit(1);
|
|
82
82
|
return;
|
|
83
83
|
}
|
package/dist/cli/mcp-server.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// MCP server that runs locally via stdio and proxies to the hosted
|
|
2
|
-
// Used by Claude Code: claude mcp add
|
|
1
|
+
// MCP server that runs locally via stdio and proxies to the hosted API.
|
|
2
|
+
// Used by Claude Code: claude mcp add xkg -- npx mnemos-capture serve-mcp --key <api-key>
|
|
3
3
|
const DEFAULT_HOSTED_URL = "https://mnemos-capture.vercel.app/api/mcp";
|
|
4
4
|
/** Override for pointing the proxy at a local instance during development. */
|
|
5
|
-
const HOSTED_URL = process.env.XMU_API_URL ?? process.env.MNEMOS_API_URL ?? DEFAULT_HOSTED_URL;
|
|
5
|
+
const HOSTED_URL = process.env.XKG_API_URL ?? process.env.XMU_API_URL ?? process.env.MNEMOS_API_URL ?? DEFAULT_HOSTED_URL;
|
|
6
6
|
function sendMessage(msg) {
|
|
7
7
|
process.stdout.write(`${JSON.stringify(msg)}\n`);
|
|
8
8
|
}
|
|
@@ -25,7 +25,7 @@ async function proxyToHosted(apiKey, msg) {
|
|
|
25
25
|
}
|
|
26
26
|
catch (err) {
|
|
27
27
|
const detail = err instanceof Error ? err.message : "unknown error";
|
|
28
|
-
rpcError(msg.id, `Could not reach
|
|
28
|
+
rpcError(msg.id, `Could not reach xkg at ${HOSTED_URL}: ${detail}`);
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
31
|
const body = await res.text().catch(() => "");
|
|
@@ -51,14 +51,14 @@ export function interpretResponse(status, contentType, body) {
|
|
|
51
51
|
if (!type.includes("application/json")) {
|
|
52
52
|
const snippet = body.trim().slice(0, 200).replace(/\s+/g, " ");
|
|
53
53
|
return {
|
|
54
|
-
error: `
|
|
54
|
+
error: `xkg returned a non-JSON response (HTTP ${status}${type ? `, ${type}` : ""})${snippet ? `: ${snippet}` : ""}`,
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
try {
|
|
58
58
|
return { data: JSON.parse(body) };
|
|
59
59
|
}
|
|
60
60
|
catch {
|
|
61
|
-
return { error: `
|
|
61
|
+
return { error: `xkg returned malformed JSON (HTTP ${status}).` };
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
/** Track a proxied request so shutdown can await it. */
|
|
@@ -72,7 +72,7 @@ export async function serveMcp() {
|
|
|
72
72
|
const keyIdx = args.indexOf("--key");
|
|
73
73
|
const apiKey = keyIdx !== -1 ? args[keyIdx + 1] : undefined;
|
|
74
74
|
if (!apiKey) {
|
|
75
|
-
process.stderr.write("\
|
|
75
|
+
process.stderr.write("\nxkg MCP server requires an API key.\n");
|
|
76
76
|
process.stderr.write("Usage: npx -y mnemos-capture@latest serve-mcp --key <your-api-key>\n\n");
|
|
77
77
|
process.stderr.write("Get your API key at: https://mnemos-capture.vercel.app/onboard\n\n");
|
|
78
78
|
process.exit(1);
|
|
@@ -97,7 +97,7 @@ export async function serveMcp() {
|
|
|
97
97
|
catch {
|
|
98
98
|
// Non-fatal — hook setup should never block the MCP server from starting
|
|
99
99
|
}
|
|
100
|
-
process.stderr.write("
|
|
100
|
+
process.stderr.write("xkg MCP server starting (proxying to hosted instance)...\n");
|
|
101
101
|
let buffer = "";
|
|
102
102
|
process.stdin.setEncoding("utf-8");
|
|
103
103
|
process.stdin.on("data", (chunk) => {
|
|
@@ -59,7 +59,7 @@ export async function maybeSelfUpgrade() {
|
|
|
59
59
|
const latest = await getLatestVersion();
|
|
60
60
|
if (!latest || !isNewer(latest, current))
|
|
61
61
|
return false;
|
|
62
|
-
process.stderr.write(`
|
|
62
|
+
process.stderr.write(`xkg: upgrading to v${latest} (was v${current})...\n`);
|
|
63
63
|
const child = spawn("npx", ["-y", `mnemos-capture@${latest}`, ...process.argv.slice(2)], {
|
|
64
64
|
stdio: "inherit",
|
|
65
65
|
env: { ...process.env, MNEMOS_UPGRADED: "1" },
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mnemos-capture",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "xkg — Turn what you discover into context your AI workers can use. Capture once, then brief, plan, and execute with any MCP-compatible tool.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mnemos-capture": "./dist/cli/index.js",
|
|
8
|
+
"xkg": "./dist/cli/index.js",
|
|
8
9
|
"xmu": "./dist/cli/index.js"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
},
|
|
22
23
|
"keywords": [
|
|
23
24
|
"ai",
|
|
25
|
+
"xkg",
|
|
24
26
|
"xmu",
|
|
25
27
|
"knowledge",
|
|
26
28
|
"capture",
|
|
@@ -45,24 +47,24 @@
|
|
|
45
47
|
"README.md"
|
|
46
48
|
],
|
|
47
49
|
"dependencies": {
|
|
48
|
-
"@anthropic-ai/sdk": "^0.
|
|
50
|
+
"@anthropic-ai/sdk": "^0.127.0",
|
|
49
51
|
"@vercel/postgres": "^0.10.0",
|
|
50
|
-
"next": "^16.
|
|
51
|
-
"react": "^19.
|
|
52
|
-
"react-dom": "^19.
|
|
52
|
+
"next": "^16.3.5",
|
|
53
|
+
"react": "^19.3.0",
|
|
54
|
+
"react-dom": "^19.3.0"
|
|
53
55
|
},
|
|
54
56
|
"devDependencies": {
|
|
55
57
|
"@playwright/test": "^1.62.1",
|
|
56
58
|
"@types/node": "^26",
|
|
57
|
-
"@types/react": "^19.
|
|
58
|
-
"@types/react-dom": "^19.
|
|
59
|
-
"autoprefixer": "^10.
|
|
59
|
+
"@types/react": "^19.3.0",
|
|
60
|
+
"@types/react-dom": "^19.3.0",
|
|
61
|
+
"autoprefixer": "^10.6.1",
|
|
60
62
|
"eslint": "^9.39.5",
|
|
61
|
-
"eslint-config-next": "^16.3.
|
|
63
|
+
"eslint-config-next": "^16.3.5",
|
|
62
64
|
"postcss": "^8.5.3",
|
|
63
65
|
"tailwindcss": "^3.4.17",
|
|
64
66
|
"typescript": "^6.0.3",
|
|
65
|
-
"vitest": "^
|
|
67
|
+
"vitest": "^5.0.1"
|
|
66
68
|
},
|
|
67
69
|
"engines": {
|
|
68
70
|
"node": ">=20.9"
|