mnemos-capture 1.5.0 → 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 CHANGED
@@ -98,7 +98,7 @@ https://xkg.xmu.sh/api/mcp
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`). `npx` still uses the package name `mnemos-capture`. An MCP server already registered as `xmu` or `mnemos` keeps working.
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
 
package/dist/cli/hooks.js CHANGED
@@ -4,13 +4,27 @@ import { join } from "path";
4
4
  import { execSync } from "child_process";
5
5
  const HOSTED_URL = "https://xkg.xmu.sh/api/mcp";
6
6
  const CLAUDE_SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
7
- // Matches both legacy ("mnemos-capture inbox-check") and modern
8
- // ("mnemos-capture@latest inbox-check") hook command forms.
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.includes("mnemos-capture") && cmd.includes("inbox-check");
20
+ return isOurHook(cmd, "inbox-check");
11
21
  }
12
22
  function isXkgPreToolHook(cmd) {
13
- return cmd.includes("mnemos-capture") && cmd.includes("vault-check");
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 legacy hooks that don't use @latest so they always stay fresh.
103
+ // silently migrate hooks that pin a version or use the old package name.
90
104
  if (existingCmd && opts.skipIfExists) {
91
- const alreadyLatest = existingCmd.includes("mnemos-capture@latest");
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 mnemos-capture@latest inbox-check --key ${apiKey} --briefing`
99
- : `npx -y mnemos-capture@latest inbox-check --key ${apiKey}`;
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.includes("mnemos-capture@latest"))
153
+ if (isCurrentHook(existingCmd))
141
154
  return;
142
155
  }
143
- const command = `npx -y mnemos-capture@latest vault-check --key ${apiKey}`;
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
@@ -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 mnemos-capture setup-hooks --key YOUR_API_KEY [--briefing] [--vault]");
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 mnemos-capture@latest serve-mcp --key YOUR_API_KEY");
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 mnemos-capture@latest … Same CLI, via the published package
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 mnemos-capture
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 mnemos-capture@latest serve-mcp --key YOUR_API_KEY
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 mnemos-capture setup-hooks --key YOUR_API_KEY --briefing
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 mnemos-capture setup-hooks --key YOUR_API_KEY --vault
128
+ npx @xmu-labs/xkg setup-hooks --key YOUR_API_KEY --vault
129
129
  `);
130
130
  }
131
131
  main().catch((err) => {
@@ -1,5 +1,5 @@
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 mnemos-capture serve-mcp --key <api-key>
2
+ // Used by Claude Code: claude mcp add xkg -- npx @xmu-labs/xkg serve-mcp --key <api-key>
3
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;
@@ -73,7 +73,7 @@ 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 mnemos-capture@latest serve-mcp --key <your-api-key>\n\n");
76
+ process.stderr.write("Usage: npx -y @xmu-labs/xkg@latest serve-mcp --key <your-api-key>\n\n");
77
77
  process.stderr.write("Get your API key at: https://xkg.xmu.sh/onboard\n\n");
78
78
  process.exit(1);
79
79
  }
@@ -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 mnemos-capture@latest` and proxy
5
- // stdio. An XKG_UPGRADED=1 env var (MNEMOS_UPGRADED=1 from releases before
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
- export function getCurrentVersion() {
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
- const pkg = JSON.parse(readFileSync(join(here, "../../package.json"), "utf-8"));
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 "0.0.0";
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(NPM_REGISTRY, { signal: AbortSignal.timeout(CHECK_TIMEOUT_MS) });
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 mnemos-capture@latest`
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", `mnemos-capture@${latest}`, ...process.argv.slice(2)], {
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.5.0",
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": "./dist/cli/index.js",
8
- "xkg": "./dist/cli/index.js",
9
- "xmu": "./dist/cli/index.js"
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.133.0",
51
- "@vercel/postgres": "^0.10.0",
52
- "next": "^16.3.5",
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.3.5",
63
+ "eslint-config-next": "^16.4.2",
64
64
  "postcss": "^8.5.3",
65
- "tailwindcss": "^3.4.17",
65
+ "tailwindcss": "^4.3.3",
66
66
  "typescript": "^6.0.3",
67
67
  "vitest": "^5.0.1"
68
68
  },