@prom.codes/memory-mcp 0.14.0 → 0.15.1

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.
Files changed (3) hide show
  1. package/README.md +16 -5
  2. package/dist/bin.js +109 -53
  3. package/package.json +12 -2
package/README.md CHANGED
@@ -55,11 +55,22 @@ work, is a newer version published?). Secrets are rejected on every write.
55
55
  Your memories never leave your machine (only short query/record text
56
56
  transits when embeddings are enabled).
57
57
 
58
- ## Native modules
58
+ ## Native modules — no install script needed
59
59
 
60
- Uses `better-sqlite3` (native). Prebuilt binaries are fetched automatically on
61
- common platforms (macOS x64/arm64, Linux x64/arm64, Windows x64) no compiler
62
- needed. On an unsupported platform/Node ABI, install C/C++ build tools so the
63
- module can compile (Windows: VS Build Tools). Requires Node 20.10.
60
+ Uses `better-sqlite3` (native), but **nothing is built on your machine and no
61
+ install script runs**. The addon ships prebuilt in a platform package
62
+ (`@prom.codes/native-<platform>`) listed as an optional dependency: npm picks
63
+ the one matching your `os`/`cpu`/`libc` and installs it by copying files. So a
64
+ hardened npm needs no special handling — `ignore-scripts=true` (a sensible
65
+ policy, and npm v12's default) has nothing left to suppress:
66
+ ```bash
67
+ npm install -g @prom.codes/memory-mcp
68
+ ```
69
+
70
+ Prebuilt for macOS / Linux (glibc + musl) / Windows on x64 + arm64, Node 22, 24,
71
+ 25 and 26. **Requires Node ≥ 22** — upstream `better-sqlite3` publishes no
72
+ prebuild for Node 20's ABI. On an unshipped combination the install still
73
+ succeeds and falls back to building from source, which needs install scripts
74
+ allowed (`--allow-scripts=better-sqlite3`) and C/C++ build tools.
64
75
 
65
76
  Docs: https://prom.codes/docs/mcp/memory
package/dist/bin.js CHANGED
@@ -40,12 +40,8 @@ import { homedir } from "node:os";
40
40
  import { join } from "node:path";
41
41
  import { fileURLToPath } from "node:url";
42
42
  var UPGRADE_BASE = "npm install -g @prom.codes/context-mcp @prom.codes/memory-mcp @prom.codes/saver";
43
- var NATIVE_BUILD_PACKAGES = "better-sqlite3,tree-sitter";
44
- function upgradeCommandFor(npmMajor) {
45
- if (npmMajor !== null && npmMajor >= 12) {
46
- return `${UPGRADE_BASE} --allow-scripts=${NATIVE_BUILD_PACKAGES}`;
47
- }
48
- return `${UPGRADE_BASE} --ignore-scripts=false --foreground-scripts`;
43
+ function upgradeCommandFor(_npmMajor) {
44
+ return UPGRADE_BASE;
49
45
  }
50
46
  var UPGRADE_COMMAND = upgradeCommandFor(null);
51
47
  var npmMajorPromise;
@@ -209,15 +205,15 @@ async function checkForUpdate(options) {
209
205
  const file = cachePath(cacheDir, name);
210
206
  const now = Date.now();
211
207
  if (!force) {
212
- const cached = await readCache(file);
213
- if (cached !== null && now - cached.checkedAt < cacheTtlMs && !cachedLatestIsStale(cached.latest, version)) {
214
- const updateAvailable2 = cached.latest !== null && isNewerVersion(cached.latest, version);
208
+ const cached2 = await readCache(file);
209
+ if (cached2 !== null && now - cached2.checkedAt < cacheTtlMs && !cachedLatestIsStale(cached2.latest, version)) {
210
+ const updateAvailable2 = cached2.latest !== null && isNewerVersion(cached2.latest, version);
215
211
  if (updateAvailable2)
216
- notify(log, name, version, cached.latest);
217
- await syncAvailabilityMarker(cacheDir, name, version, cached.latest, updateAvailable2);
212
+ notify(log, name, version, cached2.latest);
213
+ await syncAvailabilityMarker(cacheDir, name, version, cached2.latest, updateAvailable2);
218
214
  return {
219
215
  ...base,
220
- latest: cached.latest,
216
+ latest: cached2.latest,
221
217
  checked: false,
222
218
  updateAvailable: updateAvailable2,
223
219
  reason: "throttled"
@@ -239,14 +235,14 @@ async function checkForUpdate(options) {
239
235
  async function getLatestVersion(name, options = {}) {
240
236
  const { env = process.env, fetch: fetchImpl = globalThis.fetch, cacheDir = join(homedir(), ".prometheus"), cacheTtlMs = DEFAULT_TTL_MS, timeoutMs = DEFAULT_TIMEOUT_MS, minVersion } = options;
241
237
  const file = cachePath(cacheDir, name);
242
- const cached = await readCache(file);
238
+ const cached2 = await readCache(file);
243
239
  const now = Date.now();
244
- const stale = cachedLatestIsStale(cached?.latest ?? null, minVersion);
245
- if (cached !== null && cached.latest !== null && now - cached.checkedAt < cacheTtlMs && !stale) {
246
- return cached.latest;
240
+ const stale = cachedLatestIsStale(cached2?.latest ?? null, minVersion);
241
+ if (cached2 !== null && cached2.latest !== null && now - cached2.checkedAt < cacheTtlMs && !stale) {
242
+ return cached2.latest;
247
243
  }
248
244
  if (OPT_OUT_RE.test(env.PROMETHEUS_NO_UPDATE_CHECK ?? "") || typeof fetchImpl !== "function") {
249
- return stale ? null : cached?.latest ?? null;
245
+ return stale ? null : cached2?.latest ?? null;
250
246
  }
251
247
  const latest = await fetchLatest(name, fetchImpl, timeoutMs);
252
248
  if (latest !== null) {
@@ -254,7 +250,7 @@ async function getLatestVersion(name, options = {}) {
254
250
  await writeCache(file, { checkedAt: now, latest });
255
251
  return latest;
256
252
  }
257
- return stale ? null : cached?.latest ?? null;
253
+ return stale ? null : cached2?.latest ?? null;
258
254
  }
259
255
  function notify(log, name, current, latest) {
260
256
  log(`${name}: a newer version (${latest}) is available \u2014 you are on ${current}. npx users get it automatically on the next restart; for a global install run \`npm update -g ${name}\`. (Set PROMETHEUS_NO_UPDATE_CHECK=1 to silence.)
@@ -426,10 +422,58 @@ function createIdleWatchdog(options) {
426
422
  };
427
423
  }
428
424
 
425
+ // ../shared/dist/native-binding.js
426
+ import { createRequire } from "node:module";
427
+ import { dirname as dirname2, join as join4 } from "node:path";
428
+ import { existsSync } from "node:fs";
429
+ var require_ = createRequire(import.meta.url);
430
+ function isMusl() {
431
+ try {
432
+ const report = process.report?.getReport();
433
+ const header = typeof report === "object" && report !== null ? report : {};
434
+ return header.header?.glibcVersionRuntime === void 0;
435
+ } catch {
436
+ return false;
437
+ }
438
+ }
439
+ function platformToken(platform = process.platform, arch = process.arch, musl = platform === "linux" && isMusl()) {
440
+ const os = platform === "linux" && musl ? "linuxmusl" : platform;
441
+ return `${os}-${arch}`;
442
+ }
443
+ function nativePackageName(token = platformToken()) {
444
+ return `@prom.codes/native-${token}`;
445
+ }
446
+ function addonFileName(abi = process.versions.modules) {
447
+ return `better_sqlite3/node-v${abi}.node`;
448
+ }
449
+ var cached;
450
+ function resolveNativeBinding() {
451
+ if (cached !== void 0)
452
+ return cached ?? void 0;
453
+ cached = null;
454
+ const override = process.env.PROMETHEUS_SQLITE_NATIVE_BINDING?.trim();
455
+ if (override) {
456
+ cached = existsSync(override) ? override : null;
457
+ return cached ?? void 0;
458
+ }
459
+ try {
460
+ const manifest = require_.resolve(`${nativePackageName()}/package.json`);
461
+ const candidate = join4(dirname2(manifest), addonFileName());
462
+ cached = existsSync(candidate) ? candidate : null;
463
+ } catch {
464
+ cached = null;
465
+ }
466
+ return cached ?? void 0;
467
+ }
468
+ function nativeBindingOption() {
469
+ const p = resolveNativeBinding();
470
+ return p ? { nativeBinding: p } : {};
471
+ }
472
+
429
473
  // dist/composition.js
430
474
  import { createHash } from "node:crypto";
431
475
  import { homedir as homedir5 } from "node:os";
432
- import { basename, join as join6, resolve as resolve2 } from "node:path";
476
+ import { basename, join as join7, resolve as resolve2 } from "node:path";
433
477
 
434
478
  // ../embeddings-openai-compat/dist/index.js
435
479
  var DEFAULT_BATCH = 96;
@@ -1763,7 +1807,7 @@ var OpenAICompatRewriter = class {
1763
1807
  // dist/sqlite.js
1764
1808
  import { randomUUID } from "node:crypto";
1765
1809
  import { mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, rmSync as rmSync2 } from "node:fs";
1766
- import { dirname as dirname3, join as join5 } from "node:path";
1810
+ import { dirname as dirname4, join as join6 } from "node:path";
1767
1811
  import Database from "better-sqlite3";
1768
1812
 
1769
1813
  // dist/security.js
@@ -1810,9 +1854,9 @@ function assertNoSecrets(text) {
1810
1854
  }
1811
1855
 
1812
1856
  // dist/recorder.js
1813
- import { copyFileSync, existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
1857
+ import { copyFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
1814
1858
  import { homedir as homedir4 } from "node:os";
1815
- import { dirname as dirname2, join as join4 } from "node:path";
1859
+ import { dirname as dirname3, join as join5 } from "node:path";
1816
1860
  var SPOOL_VERSION = 1;
1817
1861
  var SECRET_PATTERN_SOURCES = [
1818
1862
  "sk-proj-[A-Za-z0-9_-]{20,}",
@@ -1840,8 +1884,8 @@ var REDACT_RE = new RegExp(`(${SECRET_PATTERN_SOURCES.join(")|(")})`, "gi");
1840
1884
  var EVENT_CAP_BYTES = 4 * 1024;
1841
1885
  var SPOOL_CAP_BYTES = 4 * 1024 * 1024;
1842
1886
  function recorderRoot(env = process.env) {
1843
- const base = env.PROMETHEUS_DIR && env.PROMETHEUS_DIR !== "" ? env.PROMETHEUS_DIR : join4(homedir4(), ".prometheus");
1844
- return join4(base, "recorder");
1887
+ const base = env.PROMETHEUS_DIR && env.PROMETHEUS_DIR !== "" ? env.PROMETHEUS_DIR : join5(homedir4(), ".prometheus");
1888
+ return join5(base, "recorder");
1845
1889
  }
1846
1890
  function sanitizeSegment(s) {
1847
1891
  return s.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 128) || "_";
@@ -2001,20 +2045,20 @@ function resolveSettingsPath(opts) {
2001
2045
  return opts.settingsPathOverride;
2002
2046
  const root = opts.projectRoot ?? process.cwd();
2003
2047
  if (opts.scope === "project")
2004
- return join4(root, ".claude", "settings.json");
2048
+ return join5(root, ".claude", "settings.json");
2005
2049
  if (opts.scope === "project-local")
2006
- return join4(root, ".claude", "settings.local.json");
2007
- return join4(homedir4(), ".claude", "settings.json");
2050
+ return join5(root, ".claude", "settings.local.json");
2051
+ return join5(homedir4(), ".claude", "settings.json");
2008
2052
  }
2009
2053
  function resolveHookPath(opts) {
2010
- const dir = opts.hookDirOverride ?? join4(homedir4(), ".prometheus", "hooks");
2011
- return join4(dir, RECORDER_HOOK_FILENAME);
2054
+ const dir = opts.hookDirOverride ?? join5(homedir4(), ".prometheus", "hooks");
2055
+ return join5(dir, RECORDER_HOOK_FILENAME);
2012
2056
  }
2013
2057
  function ownsEntry(entry) {
2014
2058
  return Array.isArray(entry.hooks) && entry.hooks.some((h) => typeof h?.command === "string" && h.command.includes(RECORDER_HOOK_FILENAME));
2015
2059
  }
2016
2060
  function readSettings(settingsPath) {
2017
- if (!existsSync(settingsPath))
2061
+ if (!existsSync2(settingsPath))
2018
2062
  return {};
2019
2063
  const raw = readFileSync2(settingsPath, "utf8").replace(/^/, "");
2020
2064
  if (raw.trim() === "")
@@ -2026,7 +2070,7 @@ function readSettings(settingsPath) {
2026
2070
  return parsed;
2027
2071
  }
2028
2072
  function backupSettings(settingsPath) {
2029
- if (!existsSync(settingsPath))
2073
+ if (!existsSync2(settingsPath))
2030
2074
  return null;
2031
2075
  const d = /* @__PURE__ */ new Date();
2032
2076
  const p = (n) => String(n).padStart(2, "0");
@@ -2054,7 +2098,7 @@ function recorderStatus(opts = {}) {
2054
2098
  scope: opts.scope ?? "user",
2055
2099
  events: installedEvents,
2056
2100
  settingsPath,
2057
- hookScriptPresent: existsSync(hookPath)
2101
+ hookScriptPresent: existsSync2(hookPath)
2058
2102
  };
2059
2103
  }
2060
2104
  function applyRecorderHooks(opts = {}) {
@@ -2076,7 +2120,7 @@ function applyRecorderHooks(opts = {}) {
2076
2120
  }
2077
2121
  }
2078
2122
  if (!opts.uninstall) {
2079
- mkdirSync2(dirname2(hookPath), { recursive: true });
2123
+ mkdirSync2(dirname3(hookPath), { recursive: true });
2080
2124
  writeFileSync2(hookPath, RECORDER_HOOK_SCRIPT, "utf8");
2081
2125
  for (const ev of RECORDER_EVENTS) {
2082
2126
  const matcher = ev === "PostToolUse" ? "*" : "";
@@ -2088,7 +2132,7 @@ function applyRecorderHooks(opts = {}) {
2088
2132
  }
2089
2133
  if (settings.hooks && Object.keys(settings.hooks).length === 0)
2090
2134
  delete settings.hooks;
2091
- mkdirSync2(dirname2(settingsPath), { recursive: true });
2135
+ mkdirSync2(dirname3(settingsPath), { recursive: true });
2092
2136
  writeFileSync2(settingsPath, `${JSON.stringify(settings, null, 2)}
2093
2137
  `, "utf8");
2094
2138
  JSON.parse(readFileSync2(settingsPath, "utf8"));
@@ -2539,9 +2583,9 @@ var SqliteMemoryBackend = class {
2539
2583
  closed = false;
2540
2584
  constructor(dbPath, opts = {}) {
2541
2585
  if (dbPath !== ":memory:") {
2542
- mkdirSync3(dirname3(dbPath), { recursive: true });
2586
+ mkdirSync3(dirname4(dbPath), { recursive: true });
2543
2587
  }
2544
- this.db = new Database(dbPath);
2588
+ this.db = new Database(dbPath, { ...nativeBindingOption() });
2545
2589
  this.db.pragma("journal_mode = WAL");
2546
2590
  this.db.pragma("synchronous = NORMAL");
2547
2591
  this.db.exec(SCHEMA);
@@ -2987,7 +3031,7 @@ ${h.record.value}`
2987
3031
  * spool never aborts the sweep. Returns roll-up counts.
2988
3032
  */
2989
3033
  async ingestSpoolDir(projectId, env = process.env) {
2990
- const dir = join5(recorderRoot(env), sanitizeSegment(projectId));
3034
+ const dir = join6(recorderRoot(env), sanitizeSegment(projectId));
2991
3035
  let sessions = 0;
2992
3036
  let events = 0;
2993
3037
  let deletedSpools = 0;
@@ -2998,7 +3042,7 @@ ${h.record.value}`
2998
3042
  return { sessions: 0, events: 0, deletedSpools: 0 };
2999
3043
  }
3000
3044
  for (const file of files) {
3001
- const full = join5(dir, file);
3045
+ const full = join6(dir, file);
3002
3046
  try {
3003
3047
  const raw = readFileSync3(full, "utf8");
3004
3048
  const parsed = parseSpool(raw);
@@ -3171,7 +3215,7 @@ function projectIdFor(workspaceRoot) {
3171
3215
  return createHash("sha256").update(abs).digest("hex").slice(0, 16);
3172
3216
  }
3173
3217
  function defaultMemoryDbPath() {
3174
- return join6(homedir5(), ".prometheus", "memory.db");
3218
+ return join7(homedir5(), ".prometheus", "memory.db");
3175
3219
  }
3176
3220
  function intEnv(env, name, def) {
3177
3221
  const raw = env[name];
@@ -3764,9 +3808,9 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3764
3808
  import { z } from "zod";
3765
3809
 
3766
3810
  // dist/setup.js
3767
- import { existsSync as existsSync2, readFileSync as readFileSync4 } from "node:fs";
3811
+ import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
3768
3812
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
3769
- import { dirname as dirname4, join as join8 } from "node:path";
3813
+ import { dirname as dirname5, join as join9 } from "node:path";
3770
3814
  var MEMORY_RUNTIMES = [
3771
3815
  "claude-code",
3772
3816
  "cursor",
@@ -3810,13 +3854,13 @@ alwaysApply: true
3810
3854
  var TARGETS = {
3811
3855
  "claude-code": { relPath: "CLAUDE.md", mode: "block", detect: "CLAUDE.md" },
3812
3856
  cursor: {
3813
- relPath: join8(".cursor", "rules", "prometheus-memory.mdc"),
3857
+ relPath: join9(".cursor", "rules", "prometheus-memory.mdc"),
3814
3858
  mode: "file",
3815
3859
  fileContent: CURSOR_FRONTMATTER + withMarkers(RULE_BLOCK) + "\n",
3816
3860
  detect: ".cursor"
3817
3861
  },
3818
3862
  augment: {
3819
- relPath: join8(".augment", "rules", "prometheus-memory.md"),
3863
+ relPath: join9(".augment", "rules", "prometheus-memory.md"),
3820
3864
  mode: "file",
3821
3865
  fileContent: withMarkers(RULE_BLOCK) + "\n",
3822
3866
  detect: ".augment"
@@ -3824,16 +3868,16 @@ var TARGETS = {
3824
3868
  agents: { relPath: "AGENTS.md", mode: "block", detect: "AGENTS.md" }
3825
3869
  };
3826
3870
  function detectRuntimes(workspaceRoot) {
3827
- const found = MEMORY_RUNTIMES.filter((rt) => existsSync2(join8(workspaceRoot, TARGETS[rt].detect)));
3871
+ const found = MEMORY_RUNTIMES.filter((rt) => existsSync3(join9(workspaceRoot, TARGETS[rt].detect)));
3828
3872
  return found.length > 0 ? found : ["agents"];
3829
3873
  }
3830
3874
  function existingRuntimes(workspaceRoot) {
3831
- return MEMORY_RUNTIMES.filter((rt) => existsSync2(join8(workspaceRoot, TARGETS[rt].detect)));
3875
+ return MEMORY_RUNTIMES.filter((rt) => existsSync3(join9(workspaceRoot, TARGETS[rt].detect)));
3832
3876
  }
3833
3877
  function installedRuntimes(workspaceRoot) {
3834
3878
  return MEMORY_RUNTIMES.filter((rt) => {
3835
- const p = join8(workspaceRoot, TARGETS[rt].relPath);
3836
- if (!existsSync2(p))
3879
+ const p = join9(workspaceRoot, TARGETS[rt].relPath);
3880
+ if (!existsSync3(p))
3837
3881
  return false;
3838
3882
  try {
3839
3883
  return readFileSync4(p, "utf-8").includes(BLOCK_START);
@@ -3861,14 +3905,14 @@ function upsertBlock(existing, block) {
3861
3905
  }
3862
3906
  async function installRuntime(workspaceRoot, runtime) {
3863
3907
  const target = TARGETS[runtime];
3864
- const absPath = join8(workspaceRoot, target.relPath);
3865
- const exists = existsSync2(absPath);
3908
+ const absPath = join9(workspaceRoot, target.relPath);
3909
+ const exists = existsSync3(absPath);
3866
3910
  const before = exists ? await readFile3(absPath, "utf-8") : "";
3867
3911
  const after = target.mode === "file" ? target.fileContent : upsertBlock(before, RULE_BLOCK);
3868
3912
  if (exists && before === after) {
3869
3913
  return { runtime, path: absPath, action: "unchanged" };
3870
3914
  }
3871
- await mkdir3(dirname4(absPath), { recursive: true });
3915
+ await mkdir3(dirname5(absPath), { recursive: true });
3872
3916
  await writeFile3(absPath, after, "utf-8");
3873
3917
  return { runtime, path: absPath, action: exists ? "updated" : "created" };
3874
3918
  }
@@ -4389,7 +4433,7 @@ ${f.value}`);
4389
4433
  embeddingsError = err instanceof Error ? err.message : String(err);
4390
4434
  }
4391
4435
  }
4392
- const update = await buildUpdateStatus("@prom.codes/memory-mcp", "0.14.0", { isDevBuild: false });
4436
+ const update = await buildUpdateStatus("@prom.codes/memory-mcp", "0.15.1", { isDevBuild: false });
4393
4437
  let recorder;
4394
4438
  try {
4395
4439
  const scopes = ["project-local", "project", "user"];
@@ -4471,7 +4515,7 @@ ${f.value}`);
4471
4515
  // dist/server.js
4472
4516
  var SERVER_IDENTITY = {
4473
4517
  name: "prometheus-memory-mcp",
4474
- version: "0.14.0",
4518
+ version: "0.15.1",
4475
4519
  title: "prom.codes Memory"
4476
4520
  };
4477
4521
  var SERVER_INSTRUCTIONS = "Persistent agent memory for this workspace \u2014 USE IT PROACTIVELY; the user will not tell you to. Protocol:\n1. ONE-TIME: if this workspace has no Prometheus memory rule yet, call memory_setup now (idempotent) so the protocol is installed into the runtime rule files and survives future sessions. (The server also auto-installs it on startup when a project rule file already exists \u2014 memory_setup covers the rest.)\n2. SESSION START: before any non-trivial task, call memory_read to recall facts, decisions and procedures from earlier sessions.\n3. DURING WORK: when the user states a durable preference, decision, correction or project fact, store it with memory_write (semantic for facts, procedural for how-tos) \u2014 without being asked.\n4. LOOK-UP: use memory_search for keyword recall when memory_read is not specific enough.\n5. SESSION END: consolidate what was learned with memory_capture.\nCall memory_status anytime to check what is stored and whether the rule is installed. Never store secrets, API keys or credentials \u2014 such writes are rejected.";
@@ -4480,7 +4524,19 @@ var SERVER_INSTRUCTIONS = "Persistent agent memory for this workspace \u2014 USE
4480
4524
  function looksLikeMissingNativeBinding(msg) {
4481
4525
  return /bindings file|better_sqlite3\.node|could not locate the bindings|node_module_version|was compiled against a different|invalid elf|\.node['"\s]/i.test(msg);
4482
4526
  }
4483
- var NATIVE_BINDING_HINT = '\nThis looks like the native `better-sqlite3` module failed to load \u2014 the\ninstall script that builds it was skipped, so the binary was never produced.\nOn npm v12+ install scripts are opt-in by default; on older npm it\'s usually\n`ignore-scripts=true` hardening. Install globally, allowing the native build,\nthen point Claude Code at the built binary instead of npx:\n npm v12+: npm install -g @prom.codes/memory-mcp --allow-scripts=better-sqlite3\n npm \u2264 11: npm install -g @prom.codes/memory-mcp --ignore-scripts=false --foreground-scripts\n claude mcp add memory -- node "$(npm root -g)/@prom.codes/memory-mcp/dist/bin.js"\nDocs: https://prom.codes/docs/guides/troubleshooting#could-not-locate-the-bindings-file\n';
4527
+ var NATIVE_BINDING_HINT = `
4528
+ The native SQLite module failed to load. Since 0.15.0 the addon ships
4529
+ prebuilt in a platform package (no install script runs), so this almost always
4530
+ means we ship no build for THIS platform + Node combination:
4531
+ you are on ${process.platform}-${process.arch}, Node ${process.versions.node} (ABI v${process.versions.modules})
4532
+ shipped: win32/darwin/linux (glibc+musl) x x64/arm64, on Node 22, 24, 25, 26
4533
+ Most likely fix \u2014 use a supported Node (22+); Node 20 has no prebuilt addon
4534
+ upstream and must compile from source. To build from source instead, allow the
4535
+ install scripts:
4536
+ npm install -g @prom.codes/memory-mcp --allow-scripts=better-sqlite3 # npm v12+
4537
+ npm install -g @prom.codes/memory-mcp --ignore-scripts=false --foreground-scripts # npm <= 11
4538
+ Docs: https://prom.codes/docs/guides/troubleshooting#could-not-locate-the-bindings-file
4539
+ `;
4484
4540
  async function main() {
4485
4541
  const env = process.env;
4486
4542
  const explicitRoot = (env.PROMETHEUS_WORKSPACE_ROOT ?? "").trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prom.codes/memory-mcp",
3
- "version": "0.14.0",
3
+ "version": "0.15.1",
4
4
  "description": "prom.codes Memory — persistent, local-first agent memory as an MCP server.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,7 +10,7 @@
10
10
  "dist"
11
11
  ],
12
12
  "engines": {
13
- "node": ">=20.10"
13
+ "node": ">=22"
14
14
  },
15
15
  "license": "UNLICENSED",
16
16
  "homepage": "https://prom.codes",
@@ -28,5 +28,15 @@
28
28
  "@modelcontextprotocol/sdk": "^1.29.0",
29
29
  "better-sqlite3": "^12.10.0",
30
30
  "zod": "^4.4.3"
31
+ },
32
+ "optionalDependencies": {
33
+ "@prom.codes/native-darwin-arm64": "0.19.0",
34
+ "@prom.codes/native-darwin-x64": "0.19.0",
35
+ "@prom.codes/native-linux-arm64": "0.19.0",
36
+ "@prom.codes/native-linux-x64": "0.19.0",
37
+ "@prom.codes/native-linuxmusl-arm64": "0.19.0",
38
+ "@prom.codes/native-linuxmusl-x64": "0.19.0",
39
+ "@prom.codes/native-win32-arm64": "0.19.0",
40
+ "@prom.codes/native-win32-x64": "0.19.0"
31
41
  }
32
42
  }