memtrace 0.3.87 → 0.3.90
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 +4 -5
- package/bin/memtrace.js +1 -1
- package/installer/dist/transformers/claude.js +4 -3
- package/installer/dist/transformers/cursor.js +2 -1
- package/installer/dist/transformers/shared.d.ts +1 -3
- package/installer/dist/transformers/shared.js +7 -1
- package/package.json +6 -6
- package/uninstall.js +108 -2
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ All four systems run on the same machine, same mempalace checkout, same 1,000 qu
|
|
|
61
61
|
|
|
62
62
|
| Tool | Coverage | Acc@1 | Acc@5 | Acc@10 | Avg lat | Tokens |
|
|
63
63
|
|:-----|---------:|------:|------:|-------:|--------:|-------:|
|
|
64
|
-
| **Memtrace** (
|
|
64
|
+
| **Memtrace** (MemDB) | **100.0%** | **96.7%** | **100.0%** | **100.0%** | **9.16 ms** | 195 |
|
|
65
65
|
| ChromaDB (all-MiniLM-L6-v2) | 100.0% | 62.3% | 86.1% | 87.9% | 58.5 ms | 1,937 |
|
|
66
66
|
| GitNexus (eval-server) | 99.5% | 27.1% | 89.7% | 89.9% | 191.2 ms | 213 |
|
|
67
67
|
| CodeGrapherContext (CLI) | 67.2% | 6.4% | 66.4% | 66.7% | 1627.2 ms | 221 |
|
|
@@ -117,7 +117,7 @@ GitNexus and CodeGrapherContext both build AST-based code graphs with structural
|
|
|
117
117
|
|
|
118
118
|
All numbers from [the fair benchmark](https://github.com/syncable-dev/memtrace-public/tree/main/benchmarks/fair) on the same machine, same mempalace checkout, same 1,000 queries. Ground truth is extracted by Python's stdlib `ast` — not from any tool's index — so no system is advantaged in the dataset itself.
|
|
119
119
|
|
|
120
|
-
The latency difference is primarily Rust vs. interpreted runtimes, and
|
|
120
|
+
The latency difference is primarily Rust vs. interpreted runtimes, and MemDB's embedded native graph engine (in-process Node/Edge storage, bi-temporal predicates resolved at the storage layer, vector + lexical indexes co-located) vs. HTTP/embedding pipelines. The feature difference is temporal memory and API topology — dimensions Memtrace adds on top of the shared AST-graph foundation.
|
|
121
121
|
|
|
122
122
|
</details>
|
|
123
123
|
|
|
@@ -248,7 +248,7 @@ For manual setup:
|
|
|
248
248
|
```bash
|
|
249
249
|
claude plugin marketplace add https://github.com/syncable-dev/memtrace-public.git
|
|
250
250
|
claude plugin install memtrace-skills@memtrace --scope user
|
|
251
|
-
claude mcp add memtrace -- memtrace mcp
|
|
251
|
+
claude mcp add memtrace -- memtrace mcp
|
|
252
252
|
```
|
|
253
253
|
|
|
254
254
|
### Cursor
|
|
@@ -299,8 +299,7 @@ For Cline, Roo Code, or any client that only needs MCP tools, add this server ma
|
|
|
299
299
|
"mcpServers": {
|
|
300
300
|
"memtrace": {
|
|
301
301
|
"command": "memtrace",
|
|
302
|
-
"args": ["mcp"]
|
|
303
|
-
"env": { "MEMTRACE_ARCADEDB_BOLT_URL": "bolt://localhost:7687" }
|
|
302
|
+
"args": ["mcp"]
|
|
304
303
|
}
|
|
305
304
|
}
|
|
306
305
|
}
|
package/bin/memtrace.js
CHANGED
|
@@ -262,7 +262,7 @@ async function maybePromptForUpgrade(command) {
|
|
|
262
262
|
["install", "-g", "memtrace@latest"],
|
|
263
263
|
spawnOptionsForPlatform(process.platform, {
|
|
264
264
|
stdio: "inherit",
|
|
265
|
-
env: process.env,
|
|
265
|
+
env: { ...process.env, MEMTRACE_INSTALL_PARENT: "1" },
|
|
266
266
|
}),
|
|
267
267
|
);
|
|
268
268
|
if (installResult.status !== 0) {
|
|
@@ -3,6 +3,7 @@ import path from 'path';
|
|
|
3
3
|
import os from 'os';
|
|
4
4
|
import { execCommand, commandExists } from '../utils.js';
|
|
5
5
|
import { safeReadJson, writeJsonAtomic } from '../fs-safe.js';
|
|
6
|
+
import { MEMTRACE_MCP_ENV } from './shared.js';
|
|
6
7
|
const PLUGIN_NAME = 'memtrace-skills';
|
|
7
8
|
const MARKETPLACE_NAME = 'memtrace';
|
|
8
9
|
const MARKETPLACE_REPO = 'syncable-dev/memtrace-public';
|
|
@@ -33,7 +34,7 @@ async function tryMcpAddJson(memtraceBinary) {
|
|
|
33
34
|
const config = JSON.stringify({
|
|
34
35
|
command: memtraceBinary,
|
|
35
36
|
args: ['mcp'],
|
|
36
|
-
env:
|
|
37
|
+
env: MEMTRACE_MCP_ENV,
|
|
37
38
|
});
|
|
38
39
|
// Shell-quote the JSON. Use single quotes; escape any embedded single quote.
|
|
39
40
|
const escaped = config.replace(/'/g, `'\\''`);
|
|
@@ -166,7 +167,7 @@ export function registerMcpInSettingsAt(settingsPath, memtraceBinary) {
|
|
|
166
167
|
settings.mcpServers['memtrace'] = {
|
|
167
168
|
command: memtraceBinary,
|
|
168
169
|
args: ['mcp'],
|
|
169
|
-
env:
|
|
170
|
+
env: MEMTRACE_MCP_ENV,
|
|
170
171
|
};
|
|
171
172
|
writeJsonAtomic(settingsPath, settings);
|
|
172
173
|
return { registered: true };
|
|
@@ -418,7 +419,7 @@ function writeClaudeLocalMcp(mcpPath, binary) {
|
|
|
418
419
|
cfg.mcpServers['memtrace'] = {
|
|
419
420
|
command: binary,
|
|
420
421
|
args: ['mcp'],
|
|
421
|
-
env:
|
|
422
|
+
env: MEMTRACE_MCP_ENV,
|
|
422
423
|
};
|
|
423
424
|
writeJsonAtomic(mcpPath, cfg);
|
|
424
425
|
return true;
|
|
@@ -2,6 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import os from 'os';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { safeReadJson, writeJsonAtomic } from '../fs-safe.js';
|
|
5
|
+
import { MEMTRACE_MCP_ENV } from './shared.js';
|
|
5
6
|
function skillsRoot(ctx) {
|
|
6
7
|
const base = ctx.scope === 'global' ? os.homedir() : ctx.cwd;
|
|
7
8
|
return path.join(base, '.cursor', 'skills');
|
|
@@ -30,7 +31,7 @@ export function registerCursorMcpAt(mcpFile, binary) {
|
|
|
30
31
|
cfg.mcpServers['memtrace'] = {
|
|
31
32
|
command: binary,
|
|
32
33
|
args: ['mcp'],
|
|
33
|
-
env:
|
|
34
|
+
env: MEMTRACE_MCP_ENV,
|
|
34
35
|
};
|
|
35
36
|
writeJsonAtomic(mcpFile, cfg);
|
|
36
37
|
return { registered: true };
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Skill } from '../skills.js';
|
|
2
2
|
export declare const MCP_SERVER_NAME = "memtrace";
|
|
3
|
-
export declare const MEMTRACE_MCP_ENV:
|
|
4
|
-
MEMTRACE_ARCADEDB_BOLT_URL: string;
|
|
5
|
-
};
|
|
3
|
+
export declare const MEMTRACE_MCP_ENV: Record<string, string>;
|
|
6
4
|
export declare function skillName(skill: Skill): string;
|
|
7
5
|
export declare function skillMarkdown(skill: Skill, extraFrontmatter?: Record<string, string>): string;
|
|
8
6
|
export declare function writeSkills(skills: Skill[], rootDir: string, extraFrontmatter?: Record<string, string>): number;
|
|
@@ -2,7 +2,13 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { safeReadJson, writeJsonAtomic } from '../fs-safe.js';
|
|
4
4
|
export const MCP_SERVER_NAME = 'memtrace';
|
|
5
|
-
|
|
5
|
+
// Phase 3 (ArcadeDB removal): the binary uses an embedded MemDB by default and
|
|
6
|
+
// reads MEMTRACE_MEMDB_MODE / workspace anchors directly. No env vars are
|
|
7
|
+
// required at MCP-registration time. Preserved as an empty constant so any
|
|
8
|
+
// future env-var plumbing (e.g. RUST_LOG, MEMTRACE_DATA_DIR overrides) has
|
|
9
|
+
// one place to land. The corresponding upgrade migration in install.js strips
|
|
10
|
+
// any legacy MEMTRACE_ARCADEDB_* keys from existing MCP entries on upgrade.
|
|
11
|
+
export const MEMTRACE_MCP_ENV = {};
|
|
6
12
|
export function skillName(skill) {
|
|
7
13
|
return skill.filename.replace(/\.md$/, '');
|
|
8
14
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memtrace",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.90",
|
|
4
4
|
"description": "Code intelligence graph — MCP server + AI agent skills + visualization UI",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
"fs-extra": "^11.0.0"
|
|
40
40
|
},
|
|
41
41
|
"optionalDependencies": {
|
|
42
|
-
"@memtrace/darwin-arm64": "0.3.
|
|
43
|
-
"@memtrace/linux-x64": "0.3.
|
|
44
|
-
"@memtrace/win32-x64": "0.3.
|
|
45
|
-
"@memtrace/linux-x64-noavx2": "0.3.
|
|
46
|
-
"@memtrace/win32-x64-noavx2": "0.3.
|
|
42
|
+
"@memtrace/darwin-arm64": "0.3.90",
|
|
43
|
+
"@memtrace/linux-x64": "0.3.90",
|
|
44
|
+
"@memtrace/win32-x64": "0.3.90",
|
|
45
|
+
"@memtrace/linux-x64-noavx2": "0.3.90",
|
|
46
|
+
"@memtrace/win32-x64-noavx2": "0.3.90"
|
|
47
47
|
},
|
|
48
48
|
"engines": {
|
|
49
49
|
"node": ">=18"
|
package/uninstall.js
CHANGED
|
@@ -223,6 +223,28 @@ function removeMemtraceHomeDir(home = os.homedir()) {
|
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
+
function isUpgradeLifecycle(env = process.env) {
|
|
227
|
+
if (env.MEMTRACE_INSTALL_PARENT === "1") {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// npm can run an installed package's preuninstall lifecycle while replacing
|
|
232
|
+
// it during `npm install -g memtrace@latest`. That is an upgrade, not a user
|
|
233
|
+
// data purge. Explicit `npm uninstall -g memtrace` reports npm_command as
|
|
234
|
+
// "uninstall"; data purge still requires MEMTRACE_PURGE_DATA=1.
|
|
235
|
+
if (env.npm_lifecycle_event !== "preuninstall") {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
return ["install", "update", "upgrade"].includes(env.npm_command);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function shouldPurgeMemtraceHomeDir(env = process.env) {
|
|
242
|
+
if (isUpgradeLifecycle(env)) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
return env.MEMTRACE_PURGE_DATA === "1" || env.MEMTRACE_UNINSTALL_PURGE_DATA === "1";
|
|
246
|
+
}
|
|
247
|
+
|
|
226
248
|
// ── Try Claude CLI uninstall ────────────────────────────────────────────────
|
|
227
249
|
|
|
228
250
|
function tryClaudeCliUninstall() {
|
|
@@ -272,7 +294,85 @@ function legacyCleanup(options = {}) {
|
|
|
272
294
|
removeClaudeIntegration(home);
|
|
273
295
|
}
|
|
274
296
|
|
|
297
|
+
function killRunningMemtraceProcesses(env = process.env) {
|
|
298
|
+
// npm's atomic global install on macOS / Linux works by renaming the
|
|
299
|
+
// existing `node_modules/memtrace` directory aside (to a `.memtrace-XXXX`
|
|
300
|
+
// tempname) before extracting the new tarball. If any memtrace process
|
|
301
|
+
// is still running — a long-lived daemon from `memtrace start`, an MCP
|
|
302
|
+
// server an agent left attached, the file watcher — the binary on disk
|
|
303
|
+
// is mmap'd into that process and the rename fails with ENOTEMPTY,
|
|
304
|
+
// leaving both the old dir AND a partially-renamed temp dir on disk.
|
|
305
|
+
// The user then has to manually rm both and retry. We can prevent that
|
|
306
|
+
// by killing memtrace processes BEFORE npm tries the rename — which is
|
|
307
|
+
// exactly what the preuninstall hook (this script) runs.
|
|
308
|
+
//
|
|
309
|
+
// Self-upgrade case: `memtrace install` sets MEMTRACE_INSTALL_PARENT=1
|
|
310
|
+
// before spawning npm, so the running memtrace binary is OUR PARENT.
|
|
311
|
+
// Killing it would abort the npm install we're a child of. Skip in
|
|
312
|
+
// that path — the parent will exit cleanly after its npm child returns
|
|
313
|
+
// and the rename will succeed on its way out.
|
|
314
|
+
if (env.MEMTRACE_INSTALL_PARENT === "1") {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const tryKill = (cmd, args) => {
|
|
319
|
+
try {
|
|
320
|
+
spawnSync(cmd, args, { stdio: "ignore" });
|
|
321
|
+
} catch {
|
|
322
|
+
// taskkill / pkill missing from PATH is rare but possible inside
|
|
323
|
+
// pared-down containers or locked-down enterprise images. We don't
|
|
324
|
+
// want to abort the user's install because a process-killer isn't
|
|
325
|
+
// installed — fall through and let npm's rename try its luck.
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
if (process.platform === "win32") {
|
|
330
|
+
// /F = force terminate
|
|
331
|
+
// /T = also kill child processes (file watchers, embed-worker children
|
|
332
|
+
// spawned by `memtrace start`, MCP server's notify-rs threads)
|
|
333
|
+
// /IM = match by image name; covers every launcher because the npm
|
|
334
|
+
// shim execs the same `memtrace.exe` binary regardless of
|
|
335
|
+
// `start` / `mcp` / `daemon` argv.
|
|
336
|
+
tryKill("taskkill", ["/F", "/T", "/IM", "memtrace.exe"]);
|
|
337
|
+
// Defensive: some Windows installs end up with a `node.exe` running
|
|
338
|
+
// `memtrace.js` (the npm shim) that hasn't yet exec'd the platform
|
|
339
|
+
// binary. Kill any node process whose command line references our
|
|
340
|
+
// shim path via PowerShell — wrapped so a missing PS install (rare
|
|
341
|
+
// on modern Windows but possible on Server Core) doesn't abort.
|
|
342
|
+
tryKill("powershell", [
|
|
343
|
+
"-NoProfile",
|
|
344
|
+
"-NonInteractive",
|
|
345
|
+
"-Command",
|
|
346
|
+
"Get-CimInstance Win32_Process -Filter \"Name='node.exe'\" | " +
|
|
347
|
+
"Where-Object { $_.CommandLine -like '*memtrace*\\bin\\memtrace.js*' } | " +
|
|
348
|
+
"ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }",
|
|
349
|
+
]);
|
|
350
|
+
} else {
|
|
351
|
+
// Three patterns cover every launcher shape the binary exposes.
|
|
352
|
+
// `pkill -f` matches against the full command line, so `memtrace mcp`
|
|
353
|
+
// catches both the npm-shim invocation AND the platform binary it
|
|
354
|
+
// exec'd into. Missing-process exit (1) is ignored via stdio: ignore.
|
|
355
|
+
tryKill("pkill", ["-9", "-f", "memtrace mcp"]);
|
|
356
|
+
tryKill("pkill", ["-9", "-f", "memtrace start"]);
|
|
357
|
+
tryKill("pkill", ["-9", "-f", "memtrace daemon"]);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Settle window: SIGKILL / taskkill is synchronous but the OS needs a
|
|
361
|
+
// tick to tear down mmap'd page tables and release directory entries.
|
|
362
|
+
// - macOS / Linux: 200ms is enough on every machine tested; the vnode
|
|
363
|
+
// reference usually drops within ~50ms after TASK_INACTIVE.
|
|
364
|
+
// - Windows: longer hold because Windows Defender, Search Indexer, and
|
|
365
|
+
// any OneDrive sync agent each take a file-handle reference when the
|
|
366
|
+
// binary exits. 750ms is empirically enough to clear those — well
|
|
367
|
+
// under any human-noticeable install delay.
|
|
368
|
+
const settleMs = process.platform === "win32" ? 750 : 200;
|
|
369
|
+
const until = Date.now() + settleMs;
|
|
370
|
+
// eslint-disable-next-line no-empty
|
|
371
|
+
while (Date.now() < until) {}
|
|
372
|
+
}
|
|
373
|
+
|
|
275
374
|
function run() {
|
|
375
|
+
killRunningMemtraceProcesses();
|
|
276
376
|
console.log("memtrace: cleaning up...");
|
|
277
377
|
|
|
278
378
|
// Try delegating to the compiled installer (handles ALL agents via registry)
|
|
@@ -293,9 +393,12 @@ function run() {
|
|
|
293
393
|
legacyCleanup();
|
|
294
394
|
}
|
|
295
395
|
|
|
296
|
-
|
|
297
|
-
|
|
396
|
+
if (isUpgradeLifecycle()) {
|
|
397
|
+
console.log("memtrace: preserving ~/.memtrace/ during upgrade");
|
|
398
|
+
} else if (shouldPurgeMemtraceHomeDir() && removeMemtraceHomeDir()) {
|
|
298
399
|
console.log("memtrace: removed ~/.memtrace/");
|
|
400
|
+
} else {
|
|
401
|
+
console.log("memtrace: preserving ~/.memtrace/ user data");
|
|
299
402
|
}
|
|
300
403
|
|
|
301
404
|
console.log("memtrace: uninstall complete");
|
|
@@ -319,6 +422,9 @@ module.exports = {
|
|
|
319
422
|
removeMarketplaceCaches,
|
|
320
423
|
removeInstalledPluginMetadata,
|
|
321
424
|
removeMemtraceHomeDir,
|
|
425
|
+
isUpgradeLifecycle,
|
|
426
|
+
shouldPurgeMemtraceHomeDir,
|
|
427
|
+
killRunningMemtraceProcesses,
|
|
322
428
|
removeClaudeIntegration,
|
|
323
429
|
legacyCleanup,
|
|
324
430
|
};
|