mnemos-capture 1.4.1 → 1.6.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 +9 -9
- package/dist/cli/hooks.js +25 -12
- package/dist/cli/index.js +8 -8
- package/dist/cli/mcp-server.js +4 -4
- package/dist/cli/version-check.js +26 -13
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<br>
|
|
3
|
-
<a href="https://
|
|
3
|
+
<a href="https://xkg.xmu.sh">
|
|
4
4
|
<picture>
|
|
5
5
|
<source media="(prefers-color-scheme: dark)" srcset="public/xkg-hero-dark.gif">
|
|
6
6
|
<img src="public/xkg-hero-light.gif" width="160" height="160" alt="xkg">
|
|
@@ -53,7 +53,7 @@ You find useful stuff, you capture through the web app, then xkg connects it int
|
|
|
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** / **Xmu** to **xkg**. The
|
|
56
|
+
> We are migrating from **mnemos** / **Xmu** to **xkg**. The app now lives at [xkg.xmu.sh](https://xkg.xmu.sh) and the code at [xmu-labs/xkg](https://github.com/xmu-labs/xkg). Connectors set up with `mnemos-capture.vercel.app` keep working. The npm package still says `mnemos-capture`. Sorry for the inconvenience.
|
|
57
57
|
|
|
58
58
|
## Start here
|
|
59
59
|
|
|
@@ -61,7 +61,7 @@ You do not need a terminal to start.
|
|
|
61
61
|
|
|
62
62
|
### 1. Create your account
|
|
63
63
|
|
|
64
|
-
Open **[
|
|
64
|
+
Open **[xkg.xmu.sh](https://xkg.xmu.sh)** and sign in with GitHub.
|
|
65
65
|
|
|
66
66
|
xkg will:
|
|
67
67
|
|
|
@@ -91,20 +91,20 @@ xkg is LLM-agnostic. Any worker that speaks MCP can use the same knowledge.
|
|
|
91
91
|
Two primitives:
|
|
92
92
|
|
|
93
93
|
```text
|
|
94
|
-
https://
|
|
94
|
+
https://xkg.xmu.sh/api/mcp
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
```bash
|
|
98
98
|
npx -y mnemos-capture@latest serve-mcp --key YOUR_API_KEY
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
The CLI binary is **`xkg`** (also `xmu` and `mnemos-capture`).
|
|
101
|
+
The CLI binary is **`xkg`** (also `xmu` and `mnemos-capture`). An MCP server already registered as `xmu` or `mnemos`, or set up with `mnemos-capture@latest`, keeps working.
|
|
102
102
|
|
|
103
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 `xkg`, paste `https://
|
|
107
|
+
Name the connector `xkg`, paste `https://xkg.xmu.sh/api/mcp`, sign in with GitHub when asked.
|
|
108
108
|
|
|
109
109
|
#### Claude
|
|
110
110
|
|
|
@@ -114,7 +114,7 @@ Name the connector `xkg`, paste `https://mnemos-capture.vercel.app/api/mcp`, sig
|
|
|
114
114
|
|
|
115
115
|
1. Settings → Plugins → Browse plugins
|
|
116
116
|
2. Name it xkg
|
|
117
|
-
3. Paste `https://
|
|
117
|
+
3. Paste `https://xkg.xmu.sh/api/mcp`
|
|
118
118
|
4. Sign in with GitHub when asked
|
|
119
119
|
|
|
120
120
|
#### Grok
|
|
@@ -192,7 +192,7 @@ claude mcp add xkg -- npx -y mnemos-capture@latest serve-mcp --key YOUR_API_KEY
|
|
|
192
192
|
Or the URL, no API key:
|
|
193
193
|
|
|
194
194
|
```bash
|
|
195
|
-
claude mcp add --transport http xkg https://
|
|
195
|
+
claude mcp add --transport http xkg https://xkg.xmu.sh/api/mcp
|
|
196
196
|
```
|
|
197
197
|
|
|
198
198
|
Optional session hooks (MCP works without them):
|
|
@@ -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 [xkg app](https://
|
|
236
|
+
No MCP support yet? Capture in the [xkg app](https://xkg.xmu.sh) and connect later.
|
|
237
237
|
|
|
238
238
|
## Workflow
|
|
239
239
|
|
package/dist/cli/hooks.js
CHANGED
|
@@ -2,15 +2,29 @@ import { homedir, tmpdir } from "os";
|
|
|
2
2
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
import { execSync } from "child_process";
|
|
5
|
-
const HOSTED_URL = "https://
|
|
5
|
+
const HOSTED_URL = "https://xkg.xmu.sh/api/mcp";
|
|
6
6
|
const CLAUDE_SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
/** The npm package new hooks run. Releases also publish it as `mnemos-capture`. */
|
|
8
|
+
const PACKAGE = "@xmu-labs/xkg";
|
|
9
|
+
/**
|
|
10
|
+
* Matches hooks this CLI installed under either package name, with or without
|
|
11
|
+
* a version: `npx -y @xmu-labs/xkg@latest inbox-check`,
|
|
12
|
+
* `npx -y mnemos-capture@latest inbox-check`, and the legacy
|
|
13
|
+
* `npx mnemos-capture inbox-check`.
|
|
14
|
+
*/
|
|
15
|
+
function isOurHook(cmd, subcommand) {
|
|
16
|
+
// The package must be a whole shell word: `my-xkg` or `@acme/xkg` is someone else's.
|
|
17
|
+
return new RegExp(`(?:^|\\s)(?:${PACKAGE}|mnemos-capture)(?:@[\\w.-]+)?\\s+${subcommand}\\b`).test(cmd);
|
|
18
|
+
}
|
|
9
19
|
function isXkgHook(cmd) {
|
|
10
|
-
return cmd
|
|
20
|
+
return isOurHook(cmd, "inbox-check");
|
|
11
21
|
}
|
|
12
22
|
function isXkgPreToolHook(cmd) {
|
|
13
|
-
return cmd
|
|
23
|
+
return isOurHook(cmd, "vault-check");
|
|
24
|
+
}
|
|
25
|
+
/** True when a hook already runs the current package at @latest — nothing to migrate. */
|
|
26
|
+
function isCurrentHook(cmd) {
|
|
27
|
+
return cmd.includes(`npx -y ${PACKAGE}@latest `);
|
|
14
28
|
}
|
|
15
29
|
function readSettings() {
|
|
16
30
|
if (!existsSync(CLAUDE_SETTINGS_PATH))
|
|
@@ -86,17 +100,16 @@ export function setupHooks(apiKey, opts = {}) {
|
|
|
86
100
|
break;
|
|
87
101
|
}
|
|
88
102
|
// skipIfExists (serve-mcp auto-install): preserve user-configured hooks but
|
|
89
|
-
// silently migrate
|
|
103
|
+
// silently migrate hooks that pin a version or use the old package name.
|
|
90
104
|
if (existingCmd && opts.skipIfExists) {
|
|
91
|
-
|
|
92
|
-
if (alreadyLatest)
|
|
105
|
+
if (isCurrentHook(existingCmd))
|
|
93
106
|
return;
|
|
94
107
|
// Migration: preserve the existing --briefing flag when upgrading to @latest
|
|
95
108
|
opts = { ...opts, briefing: existingCmd.includes("--briefing") };
|
|
96
109
|
}
|
|
97
110
|
const command = opts.briefing
|
|
98
|
-
? `npx -y
|
|
99
|
-
: `npx -y
|
|
111
|
+
? `npx -y ${PACKAGE}@latest inbox-check --key ${apiKey} --briefing`
|
|
112
|
+
: `npx -y ${PACKAGE}@latest inbox-check --key ${apiKey}`;
|
|
100
113
|
// Remove any existing xkg inbox-check hook (handles key rotation too)
|
|
101
114
|
const filtered = sessionStart
|
|
102
115
|
.map((group) => ({
|
|
@@ -137,10 +150,10 @@ export function setupPreToolHook(apiKey, opts = {}) {
|
|
|
137
150
|
break;
|
|
138
151
|
}
|
|
139
152
|
if (existingCmd && opts.skipIfExists) {
|
|
140
|
-
if (existingCmd
|
|
153
|
+
if (isCurrentHook(existingCmd))
|
|
141
154
|
return;
|
|
142
155
|
}
|
|
143
|
-
const command = `npx -y
|
|
156
|
+
const command = `npx -y ${PACKAGE}@latest vault-check --key ${apiKey}`;
|
|
144
157
|
const filtered = preToolCall
|
|
145
158
|
.map((group) => ({
|
|
146
159
|
...group,
|
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const HOSTED_URL = "https://
|
|
2
|
+
const HOSTED_URL = "https://xkg.xmu.sh";
|
|
3
3
|
async function main() {
|
|
4
4
|
const args = process.argv.slice(2);
|
|
5
5
|
const command = args[0];
|
|
@@ -17,7 +17,7 @@ async function main() {
|
|
|
17
17
|
const keyIdx = args.indexOf("--key");
|
|
18
18
|
const apiKey = keyIdx !== -1 ? args[keyIdx + 1] : undefined;
|
|
19
19
|
if (!apiKey) {
|
|
20
|
-
console.error("Usage: npx
|
|
20
|
+
console.error("Usage: npx @xmu-labs/xkg setup-hooks --key YOUR_API_KEY [--briefing] [--vault]");
|
|
21
21
|
process.exit(1);
|
|
22
22
|
}
|
|
23
23
|
setupHooks(apiKey, { briefing: args.includes("--briefing"), vault: args.includes("--vault") });
|
|
@@ -68,7 +68,7 @@ async function main() {
|
|
|
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 xkg -- npx -y
|
|
71
|
+
console.log(" claude mcp add xkg -- npx -y @xmu-labs/xkg@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");
|
|
@@ -90,7 +90,7 @@ function printHelp() {
|
|
|
90
90
|
xkg kos --key KEY [--plan FILE] Implement a plan in an isolated worktree
|
|
91
91
|
xkg help Show this help
|
|
92
92
|
|
|
93
|
-
npx -y
|
|
93
|
+
npx -y @xmu-labs/xkg@latest … Same CLI, via the published package
|
|
94
94
|
|
|
95
95
|
MCP tools (via your AI worker):
|
|
96
96
|
briefing — Session-start briefing with ranked insights to apply
|
|
@@ -108,13 +108,13 @@ function printHelp() {
|
|
|
108
108
|
and reports the branch + the plan's Verification Checklist when done.
|
|
109
109
|
|
|
110
110
|
Get started:
|
|
111
|
-
1. Run: npx
|
|
111
|
+
1. Run: npx @xmu-labs/xkg
|
|
112
112
|
2. Sign in with GitHub (creates your knowledge repo automatically)
|
|
113
113
|
3. Set a PIN for quick mobile access
|
|
114
114
|
4. Start capturing!
|
|
115
115
|
|
|
116
116
|
Connect to Claude Code:
|
|
117
|
-
claude mcp add xkg -- npx -y
|
|
117
|
+
claude mcp add xkg -- npx -y @xmu-labs/xkg@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
|
|
@@ -122,10 +122,10 @@ function printHelp() {
|
|
|
122
122
|
|
|
123
123
|
The hook is installed automatically when you start the MCP server.
|
|
124
124
|
To upgrade to a full project briefing at session start:
|
|
125
|
-
npx
|
|
125
|
+
npx @xmu-labs/xkg setup-hooks --key YOUR_API_KEY --briefing
|
|
126
126
|
|
|
127
127
|
To enable the vault (surfaces captures as you edit files — opt-in):
|
|
128
|
-
npx
|
|
128
|
+
npx @xmu-labs/xkg setup-hooks --key YOUR_API_KEY --vault
|
|
129
129
|
`);
|
|
130
130
|
}
|
|
131
131
|
main().catch((err) => {
|
package/dist/cli/mcp-server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// MCP server that runs locally via stdio and proxies to the hosted API.
|
|
2
|
-
// Used by Claude Code: claude mcp add xkg -- npx
|
|
3
|
-
const DEFAULT_HOSTED_URL = "https://
|
|
2
|
+
// Used by Claude Code: claude mcp add xkg -- npx @xmu-labs/xkg serve-mcp --key <api-key>
|
|
3
|
+
const DEFAULT_HOSTED_URL = "https://xkg.xmu.sh/api/mcp";
|
|
4
4
|
/** Override for pointing the proxy at a local instance during development. */
|
|
5
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) {
|
|
@@ -73,8 +73,8 @@ export async function serveMcp() {
|
|
|
73
73
|
const apiKey = keyIdx !== -1 ? args[keyIdx + 1] : undefined;
|
|
74
74
|
if (!apiKey) {
|
|
75
75
|
process.stderr.write("\nxkg MCP server requires an API key.\n");
|
|
76
|
-
process.stderr.write("Usage: npx -y
|
|
77
|
-
process.stderr.write("Get your API key at: https://
|
|
76
|
+
process.stderr.write("Usage: npx -y @xmu-labs/xkg@latest serve-mcp --key <your-api-key>\n\n");
|
|
77
|
+
process.stderr.write("Get your API key at: https://xkg.xmu.sh/onboard\n\n");
|
|
78
78
|
process.exit(1);
|
|
79
79
|
}
|
|
80
80
|
// Self-upgrade: if a newer version exists on npm, respawn via npx @latest.
|
|
@@ -1,26 +1,36 @@
|
|
|
1
1
|
// Self-update enforcement: ensures users always run the latest xkg CLI.
|
|
2
2
|
//
|
|
3
3
|
// Strategy: on serve-mcp startup, query npm for the latest published version.
|
|
4
|
-
// If behind, respawn the process via `npx -y
|
|
5
|
-
//
|
|
4
|
+
// If behind, respawn the process via `npx -y <name>@<latest>` and proxy stdio.
|
|
5
|
+
// <name> is the package this copy was installed as: every release is published
|
|
6
|
+
// as both `@xmu-labs/xkg` and `mnemos-capture`, so each install updates under its own
|
|
7
|
+
// name. An XKG_UPGRADED=1 env var (MNEMOS_UPGRADED=1 from releases before
|
|
6
8
|
// 1.4.1) prevents infinite recursion.
|
|
7
9
|
import { readFileSync } from "fs";
|
|
8
10
|
import { fileURLToPath } from "url";
|
|
9
11
|
import { dirname, join } from "path";
|
|
10
12
|
import { spawn } from "child_process";
|
|
11
|
-
const NPM_REGISTRY = "https://registry.npmjs.org/mnemos-capture/latest";
|
|
12
13
|
const CHECK_TIMEOUT_MS = 2000;
|
|
13
|
-
|
|
14
|
+
/** The names releases are published under; anything else falls back to the first. */
|
|
15
|
+
export const PACKAGE_NAMES = ["@xmu-labs/xkg", "mnemos-capture"];
|
|
16
|
+
function readOwnPackage() {
|
|
14
17
|
try {
|
|
15
18
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
16
19
|
// dist/cli/version-check.js → ../../package.json
|
|
17
|
-
|
|
18
|
-
return pkg.version ?? "0.0.0";
|
|
20
|
+
return JSON.parse(readFileSync(join(here, "../../package.json"), "utf-8"));
|
|
19
21
|
}
|
|
20
22
|
catch {
|
|
21
|
-
return
|
|
23
|
+
return {};
|
|
22
24
|
}
|
|
23
25
|
}
|
|
26
|
+
export function getCurrentVersion() {
|
|
27
|
+
return readOwnPackage().version ?? "0.0.0";
|
|
28
|
+
}
|
|
29
|
+
/** The npm name this copy was installed as, so updates come from the same name. */
|
|
30
|
+
export function getPackageName() {
|
|
31
|
+
const name = readOwnPackage().name;
|
|
32
|
+
return PACKAGE_NAMES.includes(name ?? "") ? name : PACKAGE_NAMES[0];
|
|
33
|
+
}
|
|
24
34
|
export function isNewer(latest, current) {
|
|
25
35
|
const l = latest.split(".").map((n) => parseInt(n, 10) || 0);
|
|
26
36
|
const c = current.split(".").map((n) => parseInt(n, 10) || 0);
|
|
@@ -34,9 +44,11 @@ export function isNewer(latest, current) {
|
|
|
34
44
|
}
|
|
35
45
|
return false;
|
|
36
46
|
}
|
|
37
|
-
async function getLatestVersion() {
|
|
47
|
+
async function getLatestVersion(name) {
|
|
38
48
|
try {
|
|
39
|
-
const res = await fetch(
|
|
49
|
+
const res = await fetch(`https://registry.npmjs.org/${name}/latest`, {
|
|
50
|
+
signal: AbortSignal.timeout(CHECK_TIMEOUT_MS),
|
|
51
|
+
});
|
|
40
52
|
if (!res.ok)
|
|
41
53
|
return null;
|
|
42
54
|
const data = (await res.json());
|
|
@@ -47,8 +59,8 @@ async function getLatestVersion() {
|
|
|
47
59
|
}
|
|
48
60
|
}
|
|
49
61
|
/**
|
|
50
|
-
* If a newer version exists on npm, respawn via `npx -y
|
|
51
|
-
* with the original argv, piping stdio. Returns true if the caller should stop
|
|
62
|
+
* If a newer version exists on npm, respawn via `npx -y <name>@<latest>` under
|
|
63
|
+
* the name this copy was installed as, with the original argv, piping stdio. Returns true if the caller should stop
|
|
52
64
|
* (because the child is taking over). Returns false otherwise — caller should
|
|
53
65
|
* continue with normal startup.
|
|
54
66
|
*/
|
|
@@ -57,12 +69,13 @@ export async function maybeSelfUpgrade() {
|
|
|
57
69
|
// releases set MNEMOS_UPGRADED, and may be the parent that spawned this one.
|
|
58
70
|
if (process.env.XKG_UPGRADED === "1" || process.env.MNEMOS_UPGRADED === "1")
|
|
59
71
|
return false;
|
|
72
|
+
const name = getPackageName();
|
|
60
73
|
const current = getCurrentVersion();
|
|
61
|
-
const latest = await getLatestVersion();
|
|
74
|
+
const latest = await getLatestVersion(name);
|
|
62
75
|
if (!latest || !isNewer(latest, current))
|
|
63
76
|
return false;
|
|
64
77
|
process.stderr.write(`xkg: upgrading to v${latest} (was v${current})...\n`);
|
|
65
|
-
const child = spawn("npx", ["-y",
|
|
78
|
+
const child = spawn("npx", ["-y", `${name}@${latest}`, ...process.argv.slice(2)], {
|
|
66
79
|
stdio: "inherit",
|
|
67
80
|
env: { ...process.env, XKG_UPGRADED: "1" },
|
|
68
81
|
});
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mnemos-capture",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
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
|
-
"mnemos-capture": "
|
|
8
|
-
"xkg": "
|
|
9
|
-
"xmu": "
|
|
7
|
+
"mnemos-capture": "dist/cli/index.js",
|
|
8
|
+
"xkg": "dist/cli/index.js",
|
|
9
|
+
"xmu": "dist/cli/index.js"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"dev": "next dev",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"repository": {
|
|
40
40
|
"type": "git",
|
|
41
|
-
"url": "https://github.com/xmu-labs/xkg.git"
|
|
41
|
+
"url": "git+https://github.com/xmu-labs/xkg.git"
|
|
42
42
|
},
|
|
43
43
|
"homepage": "https://github.com/xmu-labs/xkg",
|
|
44
44
|
"files": [
|
|
@@ -47,22 +47,22 @@
|
|
|
47
47
|
"README.md"
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@anthropic-ai/sdk": "^0.
|
|
51
|
-
"@
|
|
52
|
-
"next": "^16.
|
|
50
|
+
"@anthropic-ai/sdk": "^0.135.0",
|
|
51
|
+
"@neondatabase/serverless": "^1.2.0",
|
|
52
|
+
"next": "^16.4.2",
|
|
53
53
|
"react": "^19.3.0",
|
|
54
54
|
"react-dom": "^19.3.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@playwright/test": "^1.62.1",
|
|
58
|
+
"@tailwindcss/postcss": "^4.3.3",
|
|
58
59
|
"@types/node": "^26",
|
|
59
60
|
"@types/react": "^19.3.0",
|
|
60
61
|
"@types/react-dom": "^19.3.0",
|
|
61
|
-
"autoprefixer": "^10.6.1",
|
|
62
62
|
"eslint": "^9.39.5",
|
|
63
|
-
"eslint-config-next": "^16.
|
|
63
|
+
"eslint-config-next": "^16.4.2",
|
|
64
64
|
"postcss": "^8.5.3",
|
|
65
|
-
"tailwindcss": "^3.
|
|
65
|
+
"tailwindcss": "^4.3.3",
|
|
66
66
|
"typescript": "^6.0.3",
|
|
67
67
|
"vitest": "^5.0.1"
|
|
68
68
|
},
|