eminiar 0.10.1 → 0.11.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/dist/cli.js CHANGED
@@ -23221,6 +23221,24 @@ var init_storage = __esm({
23221
23221
  }
23222
23222
  });
23223
23223
 
23224
+ // src/hooks/cursor.ts
23225
+ import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
23226
+ import { homedir as homedir3 } from "os";
23227
+ import { join as join10 } from "path";
23228
+ function cursorDir() {
23229
+ return process.env.CURSOR_CONFIG_DIR || join10(homedir3(), ".cursor");
23230
+ }
23231
+ var PENDING_TTL_MS;
23232
+ var init_cursor = __esm({
23233
+ "src/hooks/cursor.ts"() {
23234
+ "use strict";
23235
+ init_esm_shims();
23236
+ init_context();
23237
+ init_paths();
23238
+ PENDING_TTL_MS = 10 * 6e4;
23239
+ }
23240
+ });
23241
+
23224
23242
  // src/install/shell.ts
23225
23243
  import { spawnSync } from "child_process";
23226
23244
  import { createInterface } from "readline";
@@ -23269,194 +23287,20 @@ var init_shell = __esm({
23269
23287
  }
23270
23288
  });
23271
23289
 
23272
- // src/install/materialize.ts
23273
- import { existsSync as existsSync7, mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync as readFileSync6, rmSync as rmSync2 } from "fs";
23274
- import { join as join10 } from "path";
23275
- function stableRoot() {
23276
- return join10(paths().plugin, "node_modules", "eminiar");
23277
- }
23278
- function stableVersion() {
23279
- try {
23280
- return JSON.parse(readFileSync6(join10(stableRoot(), "package.json"), "utf8")).version;
23281
- } catch {
23282
- return void 0;
23283
- }
23284
- }
23285
- function materialize(spec, force = false) {
23286
- const prefix = paths().plugin;
23287
- mkdirSync5(prefix, { recursive: true });
23288
- const root = stableRoot();
23289
- const here = pluginRoot();
23290
- if (!force && !spec && here === root) return { root, fromSpec: "self" };
23291
- if (!force && !spec && stableVersion() === version2() && existsSync7(join10(root, "dist", "server.js"))) {
23292
- log.ok(`stable copy already at v${version2()} (${root})`);
23293
- return { root, fromSpec: `pack:${here}` };
23294
- }
23295
- let target = spec;
23296
- if (!target) {
23297
- if (!existsSync7(join10(here, "dist", "server.js"))) {
23298
- throw new Error(`${here} has no dist/ \u2014 run \`npm run build\` first`);
23299
- }
23300
- const dest = paths().tmp;
23301
- mkdirSync5(dest, { recursive: true });
23302
- const pack = run(
23303
- npmCli(),
23304
- ["pack", "--ignore-scripts", "--pack-destination", dest, "--silent"],
23305
- { cwd: here }
23306
- );
23307
- if (!pack.ok) throw new Error(`npm pack failed: ${pack.stderr || pack.stdout}`);
23308
- const tarball = pack.stdout.trim().split("\n").pop();
23309
- target = join10(dest, tarball);
23310
- }
23311
- const install2 = run(
23312
- npmCli(),
23313
- [
23314
- "install",
23315
- "--prefix",
23316
- prefix,
23317
- "--omit=dev",
23318
- "--no-audit",
23319
- "--no-fund",
23320
- "--loglevel=error",
23321
- target
23322
- ],
23323
- {
23324
- env: { ...process.env, npm_config_update_notifier: "false" }
23325
- }
23326
- );
23327
- if (!install2.ok) throw new Error(`npm install failed: ${install2.stderr || install2.stdout}`);
23328
- if (!spec && target.endsWith(".tgz")) rmSync2(target, { force: true });
23329
- for (const must of [
23330
- "dist/server.js",
23331
- "dist/hook.js",
23332
- "bin/em-hook",
23333
- ".claude-plugin/plugin.json",
23334
- "hooks/hooks.json"
23335
- ]) {
23336
- if (!existsSync7(join10(root, must))) throw new Error(`stable copy is missing ${must}`);
23337
- }
23338
- log.ok(
23339
- `installed v${stableVersion()} into ${root} (${readdirSync3(join10(prefix, "node_modules")).length} packages)`
23340
- );
23341
- return { root, fromSpec: spec ?? `pack:${here}` };
23342
- }
23343
- function nativeCheck(node2, root) {
23344
- const script = `
23345
- const { createRequire } = require("node:module");
23346
- const req = createRequire(${JSON.stringify(join10(root, "package.json"))});
23347
- const out = [];
23348
- for (const m of ["better-sqlite3", "sqlite-vec", "web-tree-sitter", "@huggingface/transformers"]) {
23349
- try { const x = req(m); if (m === "better-sqlite3") { const db = new x(":memory:"); req("sqlite-vec").load(db); db.close(); } }
23350
- catch (e) { out.push(m + ": " + (e && e.message ? e.message.split("\\n")[0] : e)); }
23351
- }
23352
- process.stdout.write(JSON.stringify(out));
23353
- `;
23354
- const r = run(node2, ["-e", script], { cwd: root });
23355
- if (!r.ok) return [`native check could not run: ${r.stderr.trim().split("\n").pop()}`];
23356
- try {
23357
- return JSON.parse(r.stdout);
23358
- } catch {
23359
- return [`native check returned garbage: ${r.stdout.slice(0, 200)}`];
23360
- }
23361
- }
23362
- function rebuildNative(root) {
23363
- const r = run(
23364
- npmCli(),
23365
- ["rebuild", "better-sqlite3", "--prefix", paths().plugin, "--loglevel=error"],
23366
- { cwd: root }
23367
- );
23368
- return r.ok;
23369
- }
23370
- function downloadModel(node2, root, model2) {
23371
- const script = `
23372
- (async () => {
23373
- const tf = await import("@huggingface/transformers");
23374
- tf.env.cacheDir = ${JSON.stringify(paths().models)};
23375
- const p = await tf.pipeline("feature-extraction", ${JSON.stringify(model2)}, { dtype: "q8", device: "cpu" });
23376
- const r = await p(["warm up"], { pooling: "cls", normalize: true });
23377
- process.stdout.write(String(r.tolist()[0].length));
23378
- })().catch((e) => { process.stderr.write(String(e && e.message || e)); process.exit(1); });
23379
- `;
23380
- const r = run(node2, ["--input-type=module", "-e", script], { cwd: root });
23381
- return r.ok ? void 0 : r.stderr.trim().split("\n").pop();
23382
- }
23383
- var init_materialize = __esm({
23384
- "src/install/materialize.ts"() {
23385
- "use strict";
23386
- init_esm_shims();
23387
- init_paths();
23388
- init_version();
23389
- init_shell();
23390
- }
23391
- });
23392
-
23393
- // src/install/node-resolve.ts
23394
- import { accessSync as accessSync3, constants as constants3, existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
23395
- import { join as join11 } from "path";
23396
- function versionOf(bin) {
23397
- const r = run(bin, ["-p", "process.versions.node"]);
23398
- return r.ok ? r.stdout.trim() : void 0;
23399
- }
23400
- function nodeOk(version3) {
23401
- const [maj = 0, min = 0] = version3.split(".").map(Number);
23402
- return maj > 22 || maj === 22 && min >= 12;
23403
- }
23404
- function pinNode(explicit) {
23405
- const candidate = explicit ?? process.execPath;
23406
- accessSync3(candidate, constants3.X_OK);
23407
- const version3 = versionOf(candidate);
23408
- if (!version3) throw new Error(`${candidate} does not look like a node binary`);
23409
- if (!nodeOk(version3))
23410
- throw new Error(`node ${version3} at ${candidate} is too old; need >= 22.12`);
23411
- writeFileSync4(ensureDirs().nodePathFile, candidate);
23412
- return { path: candidate, version: version3 };
23413
- }
23414
- function pinnedNode() {
23415
- try {
23416
- const path3 = readFileSync7(ensureDirs().nodePathFile, "utf8").trim();
23417
- const version3 = versionOf(path3);
23418
- return version3 ? { path: path3, version: version3 } : void 0;
23419
- } catch {
23420
- return void 0;
23421
- }
23422
- }
23423
- function pinRoot(root) {
23424
- if (!existsSync8(join11(root, "dist", "server.js")))
23425
- throw new Error(`${root} has no dist/server.js; cannot pin it as the stable root`);
23426
- writeFileSync4(ensureDirs().rootPathFile, root);
23427
- return root;
23428
- }
23429
- function pinnedRoot() {
23430
- try {
23431
- const root = readFileSync7(ensureDirs().rootPathFile, "utf8").trim();
23432
- return root && existsSync8(join11(root, "dist", "server.js")) ? root : void 0;
23433
- } catch {
23434
- return void 0;
23435
- }
23436
- }
23437
- var init_node_resolve = __esm({
23438
- "src/install/node-resolve.ts"() {
23439
- "use strict";
23440
- init_esm_shims();
23441
- init_paths();
23442
- init_shell();
23443
- }
23444
- });
23445
-
23446
23290
  // src/install/register.ts
23447
23291
  import { createHash as createHash2 } from "crypto";
23448
- import { cpSync, existsSync as existsSync9, mkdirSync as mkdirSync6, readdirSync as readdirSync4, readFileSync as readFileSync8, rmSync as rmSync3 } from "fs";
23449
- import { join as join12 } from "path";
23292
+ import { cpSync, existsSync as existsSync8, mkdirSync as mkdirSync6, readdirSync as readdirSync3, readFileSync as readFileSync7, rmSync as rmSync3 } from "fs";
23293
+ import { join as join11 } from "path";
23450
23294
  function fileHash(file3) {
23451
23295
  try {
23452
- return createHash2("sha1").update(readFileSync8(file3)).digest("hex");
23296
+ return createHash2("sha1").update(readFileSync7(file3)).digest("hex");
23453
23297
  } catch {
23454
23298
  return void 0;
23455
23299
  }
23456
23300
  }
23457
23301
  function probeServer(root) {
23458
- const bin = join12(root, "bin", "em-server");
23459
- if (!existsSync9(bin)) return "bin/em-server is missing";
23302
+ const bin = join11(root, "bin", "em-server");
23303
+ if (!existsSync8(bin)) return "bin/em-server is missing";
23460
23304
  const r = run(bin, ["--probe"], { timeoutMs: 2e4 });
23461
23305
  if (r.ok && / ok /.test(r.stdout)) return void 0;
23462
23306
  const lines = (r.stderr || r.stdout).trim().split("\n").filter(Boolean);
@@ -23466,11 +23310,11 @@ function probeServer(root) {
23466
23310
  function pluginCacheStale(stable) {
23467
23311
  const cache3 = pluginInstallPath("eminiar@eminiar");
23468
23312
  if (!cache3 || cache3 === stable) return void 0;
23469
- if (!existsSync9(cache3)) return `${cache3} is missing`;
23313
+ if (!existsSync8(cache3)) return `${cache3} is missing`;
23470
23314
  for (const rel of CACHE_FINGERPRINT) {
23471
- if (fileHash(join12(cache3, rel)) !== fileHash(join12(stable, rel))) return `${rel} differs`;
23315
+ if (fileHash(join11(cache3, rel)) !== fileHash(join11(stable, rel))) return `${rel} differs`;
23472
23316
  }
23473
- if (existsSync9(join12(cache3, ".mcp.json")) && !existsSync9(join12(stable, ".mcp.json")))
23317
+ if (existsSync8(join11(cache3, ".mcp.json")) && !existsSync8(join11(stable, ".mcp.json")))
23474
23318
  return ".mcp.json is present in the cache but not in the stable copy";
23475
23319
  const probe3 = probeServer(cache3);
23476
23320
  if (probe3) return `cached copy ${probe3}`;
@@ -23527,7 +23371,7 @@ function isOurs(cmd2, stable) {
23527
23371
  function registerSettings(stable) {
23528
23372
  const settings = readJson2(settingsPath());
23529
23373
  const hooks = settings.hooks ?? {};
23530
- const hookCmd = `"${join12(stable, "bin", "em-hook")}"`;
23374
+ const hookCmd = `"${join11(stable, "bin", "em-hook")}"`;
23531
23375
  for (const ev2 of HOOK_EVENTS) {
23532
23376
  const list2 = hooks[ev2] ?? [];
23533
23377
  const filtered = list2.filter(
@@ -23548,17 +23392,17 @@ function registerSettings(stable) {
23548
23392
  const servers = cj.mcpServers ?? {};
23549
23393
  servers.eminiar = {
23550
23394
  type: "stdio",
23551
- command: join12(stable, "bin", "em-server"),
23395
+ command: join11(stable, "bin", "em-server"),
23552
23396
  args: [],
23553
23397
  env: { EMINIAR_PLUGIN_ROOT: stable }
23554
23398
  };
23555
23399
  cj.mcpServers = servers;
23556
23400
  writeJsonWithBackup(claudeJsonPath(), cj);
23557
23401
  const skills = [];
23558
- const skillsDir = join12(settingsPath(), "..", "skills");
23402
+ const skillsDir = join11(settingsPath(), "..", "skills");
23559
23403
  mkdirSync6(skillsDir, { recursive: true });
23560
- for (const name of readdirSync4(join12(stable, "skills"))) {
23561
- cpSync(join12(stable, "skills", name), join12(skillsDir, name), { recursive: true });
23404
+ for (const name of readdirSync3(join11(stable, "skills"))) {
23405
+ cpSync(join11(stable, "skills", name), join11(skillsDir, name), { recursive: true });
23562
23406
  skills.push(name);
23563
23407
  }
23564
23408
  return { hookEvents: HOOK_EVENTS, mcpServer: true, skills };
@@ -23589,8 +23433,8 @@ function unregisterSettings(stable, wrote) {
23589
23433
  }
23590
23434
  }
23591
23435
  for (const name of wrote.skills ?? []) {
23592
- const dir = join12(settingsPath(), "..", "skills", name);
23593
- if (existsSync9(dir)) rmSync3(dir, { recursive: true, force: true });
23436
+ const dir = join11(settingsPath(), "..", "skills", name);
23437
+ if (existsSync8(dir)) rmSync3(dir, { recursive: true, force: true });
23594
23438
  }
23595
23439
  }
23596
23440
  function setStatusline(stable) {
@@ -23604,7 +23448,7 @@ function setStatusline(stable) {
23604
23448
  }
23605
23449
  settings.statusLine = {
23606
23450
  type: "command",
23607
- command: `"${join12(stable, "bin", "eminiar")}" statusline`
23451
+ command: `"${join11(stable, "bin", "eminiar")}" statusline`
23608
23452
  };
23609
23453
  writeJsonWithBackup(settingsPath(), settings);
23610
23454
  return true;
@@ -23646,14 +23490,304 @@ var init_register = __esm({
23646
23490
  }
23647
23491
  });
23648
23492
 
23493
+ // src/install/cursor.ts
23494
+ import { cpSync as cpSync2, existsSync as existsSync9, mkdirSync as mkdirSync7, readdirSync as readdirSync4, readFileSync as readFileSync8, rmSync as rmSync4 } from "fs";
23495
+ import { join as join12 } from "path";
23496
+ function cursorPresent() {
23497
+ return existsSync9(cursorDir()) || existsSync9("/Applications/Cursor.app") || !!findOnPath("cursor") || !!findOnPath("cursor-agent");
23498
+ }
23499
+ function cursorHookCommand(stable) {
23500
+ return `"${join12(stable, "bin", "em-hook")}" --client cursor`;
23501
+ }
23502
+ function registerCursor(stable) {
23503
+ const cfg = readJson2(cursorHooksPath());
23504
+ if (typeof cfg.version !== "number") cfg.version = 1;
23505
+ const hooks = cfg.hooks ?? {};
23506
+ const command = cursorHookCommand(stable);
23507
+ for (const ev2 of CURSOR_HOOK_EVENTS) {
23508
+ const list2 = (Array.isArray(hooks[ev2]) ? hooks[ev2] : []).filter(
23509
+ (h) => !isOurs(h.command, stable)
23510
+ );
23511
+ const entry = { command, timeout: TIMEOUTS[ev2] ?? 5 };
23512
+ if (ev2 === "preToolUse") entry.matcher = CURSOR_PRE_TOOL_MATCHER;
23513
+ list2.push(entry);
23514
+ hooks[ev2] = list2;
23515
+ }
23516
+ cfg.hooks = hooks;
23517
+ writeJsonWithBackup(cursorHooksPath(), cfg);
23518
+ const mcp = readJson2(cursorMcpPath());
23519
+ const servers = mcp.mcpServers ?? {};
23520
+ servers.eminiar = {
23521
+ command: join12(stable, "bin", "em-server"),
23522
+ args: [],
23523
+ env: { EMINIAR_PLUGIN_ROOT: stable }
23524
+ };
23525
+ mcp.mcpServers = servers;
23526
+ writeJsonWithBackup(cursorMcpPath(), mcp);
23527
+ const skills = [];
23528
+ const src = join12(stable, "skills");
23529
+ if (existsSync9(src)) {
23530
+ mkdirSync7(cursorSkillsDir(), { recursive: true });
23531
+ for (const name of readdirSync4(src)) {
23532
+ cpSync2(join12(src, name), join12(cursorSkillsDir(), name), { recursive: true });
23533
+ skills.push(name);
23534
+ }
23535
+ }
23536
+ return { hookEvents: [...CURSOR_HOOK_EVENTS], mcpServer: true, skills };
23537
+ }
23538
+ function unregisterCursor(stable, wrote) {
23539
+ if (!wrote) return;
23540
+ if (wrote.hookEvents.length && existsSync9(cursorHooksPath())) {
23541
+ const cfg = readJson2(cursorHooksPath());
23542
+ const hooks = cfg.hooks ?? {};
23543
+ for (const ev2 of wrote.hookEvents) {
23544
+ if (!Array.isArray(hooks[ev2])) continue;
23545
+ const kept = hooks[ev2].filter((h) => !isOurs(h.command, stable));
23546
+ if (kept.length) hooks[ev2] = kept;
23547
+ else delete hooks[ev2];
23548
+ }
23549
+ cfg.hooks = hooks;
23550
+ writeJsonWithBackup(cursorHooksPath(), cfg);
23551
+ }
23552
+ if (wrote.mcpServer && existsSync9(cursorMcpPath())) {
23553
+ const mcp = readJson2(cursorMcpPath());
23554
+ const servers = mcp.mcpServers;
23555
+ if (servers?.eminiar && isOurs(servers.eminiar.command, stable)) {
23556
+ delete servers.eminiar;
23557
+ writeJsonWithBackup(cursorMcpPath(), mcp);
23558
+ }
23559
+ }
23560
+ for (const name of wrote.skills) {
23561
+ const dir = join12(cursorSkillsDir(), name);
23562
+ if (existsSync9(dir)) rmSync4(dir, { recursive: true, force: true });
23563
+ }
23564
+ }
23565
+ function cursorStatus() {
23566
+ const read2 = (f) => existsSync9(f) ? readFileSync8(f, "utf8") : "";
23567
+ const hooksRaw = read2(cursorHooksPath());
23568
+ let events = [];
23569
+ try {
23570
+ const cfg = hooksRaw ? JSON.parse(hooksRaw) : {};
23571
+ const hooks = cfg.hooks ?? {};
23572
+ events = Object.keys(hooks).filter(
23573
+ (ev2) => Array.isArray(hooks[ev2]) && hooks[ev2].some(
23574
+ (h) => typeof h.command === "string" && h.command.includes("em-hook")
23575
+ )
23576
+ );
23577
+ } catch {
23578
+ }
23579
+ return { hooks: events.length > 0, mcp: read2(cursorMcpPath()).includes("em-server"), events };
23580
+ }
23581
+ var cursorHooksPath, cursorMcpPath, cursorSkillsDir, CURSOR_HOOK_EVENTS, CURSOR_PRE_TOOL_MATCHER, TIMEOUTS;
23582
+ var init_cursor2 = __esm({
23583
+ "src/install/cursor.ts"() {
23584
+ "use strict";
23585
+ init_esm_shims();
23586
+ init_cursor();
23587
+ init_languages();
23588
+ init_claude_config();
23589
+ init_register();
23590
+ cursorHooksPath = () => join12(cursorDir(), "hooks.json");
23591
+ cursorMcpPath = () => join12(cursorDir(), "mcp.json");
23592
+ cursorSkillsDir = () => join12(cursorDir(), "skills");
23593
+ CURSOR_HOOK_EVENTS = [
23594
+ "sessionStart",
23595
+ "beforeSubmitPrompt",
23596
+ "preToolUse",
23597
+ "postToolUse",
23598
+ "postToolUseFailure",
23599
+ "subagentStop",
23600
+ "preCompact",
23601
+ "afterAgentResponse",
23602
+ "sessionEnd"
23603
+ ];
23604
+ CURSOR_PRE_TOOL_MATCHER = "Shell|Read|Write|Edit|Grep|Glob|WebFetch|WebSearch|Task";
23605
+ TIMEOUTS = { sessionStart: 10, preCompact: 15, postToolUse: 10 };
23606
+ }
23607
+ });
23608
+
23609
+ // src/install/materialize.ts
23610
+ import { existsSync as existsSync10, mkdirSync as mkdirSync8, readdirSync as readdirSync5, readFileSync as readFileSync9, rmSync as rmSync5 } from "fs";
23611
+ import { join as join13 } from "path";
23612
+ function stableRoot() {
23613
+ return join13(paths().plugin, "node_modules", "eminiar");
23614
+ }
23615
+ function stableVersion() {
23616
+ try {
23617
+ return JSON.parse(readFileSync9(join13(stableRoot(), "package.json"), "utf8")).version;
23618
+ } catch {
23619
+ return void 0;
23620
+ }
23621
+ }
23622
+ function materialize(spec, force = false) {
23623
+ const prefix = paths().plugin;
23624
+ mkdirSync8(prefix, { recursive: true });
23625
+ const root = stableRoot();
23626
+ const here = pluginRoot();
23627
+ if (!force && !spec && here === root) return { root, fromSpec: "self" };
23628
+ if (!force && !spec && stableVersion() === version2() && existsSync10(join13(root, "dist", "server.js"))) {
23629
+ log.ok(`stable copy already at v${version2()} (${root})`);
23630
+ return { root, fromSpec: `pack:${here}` };
23631
+ }
23632
+ let target = spec;
23633
+ if (!target) {
23634
+ if (!existsSync10(join13(here, "dist", "server.js"))) {
23635
+ throw new Error(`${here} has no dist/ \u2014 run \`npm run build\` first`);
23636
+ }
23637
+ const dest = paths().tmp;
23638
+ mkdirSync8(dest, { recursive: true });
23639
+ const pack = run(
23640
+ npmCli(),
23641
+ ["pack", "--ignore-scripts", "--pack-destination", dest, "--silent"],
23642
+ { cwd: here }
23643
+ );
23644
+ if (!pack.ok) throw new Error(`npm pack failed: ${pack.stderr || pack.stdout}`);
23645
+ const tarball = pack.stdout.trim().split("\n").pop();
23646
+ target = join13(dest, tarball);
23647
+ }
23648
+ const install2 = run(
23649
+ npmCli(),
23650
+ [
23651
+ "install",
23652
+ "--prefix",
23653
+ prefix,
23654
+ "--omit=dev",
23655
+ "--no-audit",
23656
+ "--no-fund",
23657
+ "--loglevel=error",
23658
+ target
23659
+ ],
23660
+ {
23661
+ env: { ...process.env, npm_config_update_notifier: "false" }
23662
+ }
23663
+ );
23664
+ if (!install2.ok) throw new Error(`npm install failed: ${install2.stderr || install2.stdout}`);
23665
+ if (!spec && target.endsWith(".tgz")) rmSync5(target, { force: true });
23666
+ for (const must of [
23667
+ "dist/server.js",
23668
+ "dist/hook.js",
23669
+ "bin/em-hook",
23670
+ ".claude-plugin/plugin.json",
23671
+ "hooks/hooks.json"
23672
+ ]) {
23673
+ if (!existsSync10(join13(root, must))) throw new Error(`stable copy is missing ${must}`);
23674
+ }
23675
+ log.ok(
23676
+ `installed v${stableVersion()} into ${root} (${readdirSync5(join13(prefix, "node_modules")).length} packages)`
23677
+ );
23678
+ return { root, fromSpec: spec ?? `pack:${here}` };
23679
+ }
23680
+ function nativeCheck(node2, root) {
23681
+ const script = `
23682
+ const { createRequire } = require("node:module");
23683
+ const req = createRequire(${JSON.stringify(join13(root, "package.json"))});
23684
+ const out = [];
23685
+ for (const m of ["better-sqlite3", "sqlite-vec", "web-tree-sitter", "@huggingface/transformers"]) {
23686
+ try { const x = req(m); if (m === "better-sqlite3") { const db = new x(":memory:"); req("sqlite-vec").load(db); db.close(); } }
23687
+ catch (e) { out.push(m + ": " + (e && e.message ? e.message.split("\\n")[0] : e)); }
23688
+ }
23689
+ process.stdout.write(JSON.stringify(out));
23690
+ `;
23691
+ const r = run(node2, ["-e", script], { cwd: root });
23692
+ if (!r.ok) return [`native check could not run: ${r.stderr.trim().split("\n").pop()}`];
23693
+ try {
23694
+ return JSON.parse(r.stdout);
23695
+ } catch {
23696
+ return [`native check returned garbage: ${r.stdout.slice(0, 200)}`];
23697
+ }
23698
+ }
23699
+ function rebuildNative(root) {
23700
+ const r = run(
23701
+ npmCli(),
23702
+ ["rebuild", "better-sqlite3", "--prefix", paths().plugin, "--loglevel=error"],
23703
+ { cwd: root }
23704
+ );
23705
+ return r.ok;
23706
+ }
23707
+ function downloadModel(node2, root, model2) {
23708
+ const script = `
23709
+ (async () => {
23710
+ const tf = await import("@huggingface/transformers");
23711
+ tf.env.cacheDir = ${JSON.stringify(paths().models)};
23712
+ const p = await tf.pipeline("feature-extraction", ${JSON.stringify(model2)}, { dtype: "q8", device: "cpu" });
23713
+ const r = await p(["warm up"], { pooling: "cls", normalize: true });
23714
+ process.stdout.write(String(r.tolist()[0].length));
23715
+ })().catch((e) => { process.stderr.write(String(e && e.message || e)); process.exit(1); });
23716
+ `;
23717
+ const r = run(node2, ["--input-type=module", "-e", script], { cwd: root });
23718
+ return r.ok ? void 0 : r.stderr.trim().split("\n").pop();
23719
+ }
23720
+ var init_materialize = __esm({
23721
+ "src/install/materialize.ts"() {
23722
+ "use strict";
23723
+ init_esm_shims();
23724
+ init_paths();
23725
+ init_version();
23726
+ init_shell();
23727
+ }
23728
+ });
23729
+
23730
+ // src/install/node-resolve.ts
23731
+ import { accessSync as accessSync3, constants as constants3, existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
23732
+ import { join as join14 } from "path";
23733
+ function versionOf(bin) {
23734
+ const r = run(bin, ["-p", "process.versions.node"]);
23735
+ return r.ok ? r.stdout.trim() : void 0;
23736
+ }
23737
+ function nodeOk(version3) {
23738
+ const [maj = 0, min = 0] = version3.split(".").map(Number);
23739
+ return maj > 22 || maj === 22 && min >= 12;
23740
+ }
23741
+ function pinNode(explicit) {
23742
+ const candidate = explicit ?? process.execPath;
23743
+ accessSync3(candidate, constants3.X_OK);
23744
+ const version3 = versionOf(candidate);
23745
+ if (!version3) throw new Error(`${candidate} does not look like a node binary`);
23746
+ if (!nodeOk(version3))
23747
+ throw new Error(`node ${version3} at ${candidate} is too old; need >= 22.12`);
23748
+ writeFileSync5(ensureDirs().nodePathFile, candidate);
23749
+ return { path: candidate, version: version3 };
23750
+ }
23751
+ function pinnedNode() {
23752
+ try {
23753
+ const path3 = readFileSync10(ensureDirs().nodePathFile, "utf8").trim();
23754
+ const version3 = versionOf(path3);
23755
+ return version3 ? { path: path3, version: version3 } : void 0;
23756
+ } catch {
23757
+ return void 0;
23758
+ }
23759
+ }
23760
+ function pinRoot(root) {
23761
+ if (!existsSync11(join14(root, "dist", "server.js")))
23762
+ throw new Error(`${root} has no dist/server.js; cannot pin it as the stable root`);
23763
+ writeFileSync5(ensureDirs().rootPathFile, root);
23764
+ return root;
23765
+ }
23766
+ function pinnedRoot() {
23767
+ try {
23768
+ const root = readFileSync10(ensureDirs().rootPathFile, "utf8").trim();
23769
+ return root && existsSync11(join14(root, "dist", "server.js")) ? root : void 0;
23770
+ } catch {
23771
+ return void 0;
23772
+ }
23773
+ }
23774
+ var init_node_resolve = __esm({
23775
+ "src/install/node-resolve.ts"() {
23776
+ "use strict";
23777
+ init_esm_shims();
23778
+ init_paths();
23779
+ init_shell();
23780
+ }
23781
+ });
23782
+
23649
23783
  // src/install/doctor.ts
23650
23784
  var doctor_exports = {};
23651
23785
  __export(doctor_exports, {
23652
23786
  fullDoctor: () => fullDoctor
23653
23787
  });
23654
23788
  import { spawn } from "child_process";
23655
- import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
23656
- import { join as join13 } from "path";
23789
+ import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
23790
+ import { join as join15 } from "path";
23657
23791
  function mcpHandshake(bin, ms = 15e3) {
23658
23792
  return new Promise((resolve9) => {
23659
23793
  const child = spawn(bin, [], { stdio: ["pipe", "pipe", "pipe"] });
@@ -23688,8 +23822,8 @@ function mcpHandshake(bin, ms = 15e3) {
23688
23822
  async function fullDoctor(opts = {}) {
23689
23823
  const rec = readInstallRecord();
23690
23824
  const stable = rec?.stableRoot ?? stableRoot();
23691
- const hasStable = existsSync10(join13(stable, "dist", "server.js"));
23692
- const bins = hasStable ? stable : join13(process.argv[1] ?? "", "..", "..");
23825
+ const hasStable = existsSync12(join15(stable, "dist", "server.js"));
23826
+ const bins = hasStable ? stable : join15(process.argv[1] ?? "", "..", "..");
23693
23827
  const fixed = [];
23694
23828
  if (opts.fix && hasStable) {
23695
23829
  try {
@@ -23714,7 +23848,7 @@ async function fullDoctor(opts = {}) {
23714
23848
  checks.push({
23715
23849
  name: "install",
23716
23850
  ok: !!rec,
23717
- detail: rec ? `v${rec.version} via ${rec.method} at ${rec.installedAt.slice(0, 10)} (${rec.stableRoot})` : "not installed (run `npx eminiar install`)"
23851
+ detail: rec ? `v${rec.version} via ${rec.method === "none" ? "cursor" : rec.method}${rec.wrote.cursor && rec.method !== "none" ? " + cursor" : ""} at ${rec.installedAt.slice(0, 10)} (${rec.stableRoot})` : "not installed (run `npx eminiar install`)"
23718
23852
  });
23719
23853
  const pinned = pinnedNode();
23720
23854
  checks.push({
@@ -23751,14 +23885,29 @@ async function fullDoctor(opts = {}) {
23751
23885
  detail: `${lines.join(" \xB7 ")}${drift}${liveOk ? "" : " \u2014 run `eminiar doctor --fix`, then `eminiar upgrade` if it still fails"}`
23752
23886
  });
23753
23887
  }
23754
- } else {
23755
- const s = existsSync10(join13(process.env.HOME ?? "", ".claude", "settings.json")) ? readFileSync9(join13(process.env.HOME ?? "", ".claude", "settings.json"), "utf8") : "";
23888
+ } else if (rec.method === "settings") {
23889
+ const s = existsSync12(join15(process.env.HOME ?? "", ".claude", "settings.json")) ? readFileSync11(join15(process.env.HOME ?? "", ".claude", "settings.json"), "utf8") : "";
23756
23890
  checks.push({
23757
23891
  name: "hooks in settings.json",
23758
23892
  ok: s.includes("em-hook"),
23759
23893
  detail: s.includes("em-hook") ? "present" : "missing"
23760
23894
  });
23761
23895
  }
23896
+ if (rec?.wrote.cursor || cursorPresent()) {
23897
+ const cs = cursorStatus();
23898
+ const registered = !!rec?.wrote.cursor;
23899
+ checks.push({
23900
+ name: "Cursor",
23901
+ ok: registered ? cs.hooks && cs.mcp : true,
23902
+ detail: registered ? `${cs.hooks ? `hooks on ${cs.events.length} events` : "hooks missing from ~/.cursor/hooks.json"} \xB7 ${cs.mcp ? "MCP server in ~/.cursor/mcp.json" : "MCP server missing from ~/.cursor/mcp.json"}${cs.hooks && cs.mcp ? "" : " \u2014 run `npx eminiar install --cursor`"}` : cs.hooks || cs.mcp ? "partly configured by hand; `npx eminiar install --cursor` completes and tracks it" : "installed but not registered; `npx eminiar install --cursor` adds hooks, MCP server and skills"
23903
+ });
23904
+ if (registered && rec?.method === "settings")
23905
+ checks.push({
23906
+ name: "Cursor third-party import",
23907
+ ok: false,
23908
+ detail: "Cursor also runs the Claude Code hooks in ~/.claude/settings.json (Settings \u2192 Agents \u2192 Third-Party Imports, on by default), so each event fires twice there; turn that setting off or reinstall Claude Code with `--method plugin`"
23909
+ });
23910
+ }
23762
23911
  const failed = needsAuthEntry();
23763
23912
  if (failed && opts.fix && clearNeedsAuthEntry()) fixed.push("cached launch failure cleared");
23764
23913
  const stillFailed = needsAuthEntry();
@@ -23769,8 +23918,8 @@ async function fullDoctor(opts = {}) {
23769
23918
  });
23770
23919
  if (opts.fix)
23771
23920
  checks.push({ name: "fix", ok: true, detail: fixed.join(", ") || "nothing to fix" });
23772
- const hookBin = join13(bins, "bin", "em-hook");
23773
- if (existsSync10(hookBin)) {
23921
+ const hookBin = join15(bins, "bin", "em-hook");
23922
+ if (existsSync12(hookBin)) {
23774
23923
  const r = run(hookBin, ["--selftest"], { env: { ...process.env } });
23775
23924
  checks.push({
23776
23925
  name: "hook self-test",
@@ -23778,8 +23927,8 @@ async function fullDoctor(opts = {}) {
23778
23927
  detail: r.ok ? r.stdout.trim() : r.stderr.trim().slice(-200) || "failed"
23779
23928
  });
23780
23929
  }
23781
- const serverBin = join13(bins, "bin", "em-server");
23782
- if (existsSync10(serverBin)) {
23930
+ const serverBin = join15(bins, "bin", "em-server");
23931
+ if (existsSync12(serverBin)) {
23783
23932
  const reply = await mcpHandshake(serverBin);
23784
23933
  checks.push({ name: "MCP handshake", ok: /^eminiar v|^ok$/.test(reply), detail: reply });
23785
23934
  }
@@ -23791,10 +23940,10 @@ async function fullDoctor(opts = {}) {
23791
23940
  ok: true,
23792
23941
  detail: `${ctx.root} \xB7 ${db.countDocuments()} docs \xB7 ${db.memoryCount()} memories \xB7 graph ${db.graphCounts().nodes} nodes`
23793
23942
  });
23794
- const cfgFile = join13(ctx.root, "eminiar.config.json");
23795
- if (existsSync10(cfgFile)) {
23943
+ const cfgFile = join15(ctx.root, "eminiar.config.json");
23944
+ if (existsSync12(cfgFile)) {
23796
23945
  try {
23797
- const parsed = ConfigSchema.safeParse(JSON.parse(readFileSync9(cfgFile, "utf8")));
23946
+ const parsed = ConfigSchema.safeParse(JSON.parse(readFileSync11(cfgFile, "utf8")));
23798
23947
  checks.push({
23799
23948
  name: "eminiar.config.json",
23800
23949
  ok: parsed.success,
@@ -23817,9 +23966,9 @@ async function fullDoctor(opts = {}) {
23817
23966
  ok: true,
23818
23967
  detail: live2.length ? `running for this project (pid ${live2.join(", ")})` : "none running for this project right now; enforce routing annotates instead of denying until one connects"
23819
23968
  });
23820
- const projectMcp = join13(ctx.root, ".mcp.json");
23821
- if (existsSync10(projectMcp)) {
23822
- const raw = readFileSync9(projectMcp, "utf8");
23969
+ const projectMcp = join15(ctx.root, ".mcp.json");
23970
+ if (existsSync12(projectMcp)) {
23971
+ const raw = readFileSync11(projectMcp, "utf8");
23823
23972
  const bad = raw.includes(`\${CLAUDE_PLUGIN_ROOT}`) && raw.includes("em-server");
23824
23973
  checks.push({
23825
23974
  name: "project .mcp.json",
@@ -23849,6 +23998,7 @@ var init_doctor2 = __esm({
23849
23998
  init_server_alive();
23850
23999
  init_storage();
23851
24000
  init_claude_config();
24001
+ init_cursor2();
23852
24002
  init_materialize();
23853
24003
  init_node_resolve();
23854
24004
  init_register();
@@ -23949,8 +24099,8 @@ __export(install_exports, {
23949
24099
  install: () => install,
23950
24100
  writeTeamFiles: () => writeTeamFiles
23951
24101
  });
23952
- import { existsSync as existsSync11, writeFileSync as writeFileSync5 } from "fs";
23953
- import { join as join14 } from "path";
24102
+ import { copyFileSync as copyFileSync2, existsSync as existsSync13, mkdirSync as mkdirSync9, writeFileSync as writeFileSync6 } from "fs";
24103
+ import { join as join16 } from "path";
23954
24104
  async function install(opts) {
23955
24105
  console.log(`eminiar v${version2()} installer`);
23956
24106
  log.step("node");
@@ -23980,8 +24130,8 @@ async function install(opts) {
23980
24130
  }
23981
24131
  log.step("data directory");
23982
24132
  const p = ensureDirs();
23983
- if (!existsSync11(p.configFile))
23984
- writeFileSync5(p.configFile, `${JSON.stringify(ConfigSchema.parse({}), null, 2)}
24133
+ if (!existsSync13(p.configFile))
24134
+ writeFileSync6(p.configFile, `${JSON.stringify(ConfigSchema.parse({}), null, 2)}
23985
24135
  `);
23986
24136
  globalDb();
23987
24137
  log.ok(p.home);
@@ -23991,18 +24141,23 @@ async function install(opts) {
23991
24141
  if (err) log.warn(`download failed (${err}); it will be retried lazily on first hybrid search`);
23992
24142
  else log.ok("ready");
23993
24143
  }
23994
- log.step("register with Claude Code");
23995
- const method = opts.method ?? (claudeCli() ? "plugin" : "settings");
24144
+ const claude = claudeCli();
24145
+ const wantClaude = !opts.cursor || !!claude || !!opts.method;
24146
+ const method = opts.method ?? (claude ? "plugin" : "settings");
24147
+ const targets = [wantClaude ? `Claude Code (${method} method)` : "", opts.cursor ? "Cursor" : ""].filter(Boolean).join(" and ");
24148
+ log.step(`register with ${targets}`);
24149
+ if (opts.cursor && !cursorPresent())
24150
+ log.warn(`${cursorDirHint()} not found; Cursor files are written anyway for its first launch`);
23996
24151
  if (!await confirm(
23997
- `Register eminiar with Claude Code using the ${method} method? This edits your user-level Claude config.`,
24152
+ `Register eminiar with ${targets}? This edits your user-level ${[wantClaude ? "Claude" : "", opts.cursor ? "Cursor" : ""].filter(Boolean).join(" and ")} config.`,
23998
24153
  !!opts.yes
23999
24154
  )) {
24000
24155
  log.warn("skipped registration; re-run with --yes or confirm interactively");
24001
24156
  return 1;
24002
24157
  }
24003
24158
  let wrote = {};
24004
- let usedMethod = method;
24005
- if (method === "plugin") {
24159
+ let usedMethod = wantClaude ? method : "none";
24160
+ if (usedMethod === "plugin") {
24006
24161
  const r = registerPlugin(stable);
24007
24162
  if (r.ok) {
24008
24163
  log.ok(r.detail);
@@ -24018,15 +24173,27 @@ async function install(opts) {
24018
24173
  "hooks written to ~/.claude/settings.json, MCP server to ~/.claude.json, skills to ~/.claude/skills"
24019
24174
  );
24020
24175
  }
24021
- if (needsAuthEntry() && clearNeedsAuthEntry())
24022
- log.ok("cleared Claude Code's cached connection failure for the plugin server");
24023
- const wantStatusline = opts.statusline ?? (!!opts.yes && !opts.team);
24024
- if (wantStatusline) {
24025
- if (setStatusline(stable)) {
24026
- wrote.statusline = true;
24027
- log.ok("statusLine set to `eminiar statusline`");
24176
+ if (wantClaude) {
24177
+ if (needsAuthEntry() && clearNeedsAuthEntry())
24178
+ log.ok("cleared Claude Code's cached connection failure for the plugin server");
24179
+ const wantStatusline = opts.statusline ?? (!!opts.yes && !opts.team);
24180
+ if (wantStatusline) {
24181
+ if (setStatusline(stable)) {
24182
+ wrote.statusline = true;
24183
+ log.ok("statusLine set to `eminiar statusline`");
24184
+ }
24028
24185
  }
24029
24186
  }
24187
+ if (opts.cursor) {
24188
+ wrote.cursor = registerCursor(stable);
24189
+ log.ok(
24190
+ `hooks written to ${cursorDirHint()}/hooks.json, MCP server to ${cursorDirHint()}/mcp.json, skills to ${cursorDirHint()}/skills`
24191
+ );
24192
+ if (usedMethod === "settings")
24193
+ log.warn(
24194
+ "Cursor also imports Claude Code hooks from ~/.claude/settings.json (Settings \u2192 Agents \u2192 Third-Party Imports); turn that off or each event fires twice in Cursor"
24195
+ );
24196
+ }
24030
24197
  writeInstallRecord({
24031
24198
  version: version2(),
24032
24199
  method: usedMethod,
@@ -24038,21 +24205,25 @@ async function install(opts) {
24038
24205
  });
24039
24206
  if (opts.team) {
24040
24207
  log.step("team defaults");
24041
- writeTeamFiles(resolveProjectRoot(), opts.marketplace);
24208
+ writeTeamFiles(resolveProjectRoot(), opts.marketplace, { cursor: !!opts.cursor, stable });
24042
24209
  }
24043
24210
  log.step("doctor");
24044
24211
  const checks = await fullDoctor();
24045
24212
  console.log(formatDoctor(checks));
24213
+ const restart = [wantClaude ? "Claude Code" : "", opts.cursor ? "Cursor" : ""].filter(Boolean).join(" and ");
24046
24214
  console.log(
24047
24215
  `
24048
- Restart Claude Code to load eminiar. Try /em-doctor, then em_execute with an intent.`
24216
+ Restart ${restart} to load eminiar. Try ${wantClaude ? "/em-doctor, then " : ""}em_execute with an intent.`
24049
24217
  );
24050
24218
  return checks.every((c) => c.ok) ? 0 : 1;
24051
24219
  }
24052
- function writeTeamFiles(root, marketplace) {
24053
- const cfg = join14(root, "eminiar.config.json");
24054
- if (!existsSync11(cfg)) {
24055
- writeFileSync5(
24220
+ function cursorDirHint() {
24221
+ return process.env.CURSOR_CONFIG_DIR || "~/.cursor";
24222
+ }
24223
+ function writeTeamFiles(root, marketplace, extra = {}) {
24224
+ const cfg = join16(root, "eminiar.config.json");
24225
+ if (!existsSync13(cfg)) {
24226
+ writeFileSync6(
24056
24227
  cfg,
24057
24228
  `${JSON.stringify(
24058
24229
  {
@@ -24082,7 +24253,7 @@ function writeTeamFiles(root, marketplace) {
24082
24253
  }
24083
24254
  if (marketplace) {
24084
24255
  const m = /^github:(.+)$/.exec(marketplace);
24085
- const file3 = join14(root, ".claude", "settings.json");
24256
+ const file3 = join16(root, ".claude", "settings.json");
24086
24257
  const settings = readJson2(file3);
24087
24258
  const known = settings.extraKnownMarketplaces ?? {};
24088
24259
  known.eminiar = m ? { source: { source: "github", repo: m[1] } } : { source: { source: "url", url: marketplace } };
@@ -24095,7 +24266,19 @@ function writeTeamFiles(root, marketplace) {
24095
24266
  `${file3}: marketplace + enabledPlugins added \u2014 teammates are prompted to install on next launch`
24096
24267
  );
24097
24268
  } else {
24098
- log.info("teammates: `npx eminiar install` (reads the committed eminiar.config.json)");
24269
+ log.info(
24270
+ `teammates: \`npx eminiar install${extra.cursor ? " --cursor" : ""}\` (reads the committed eminiar.config.json)`
24271
+ );
24272
+ }
24273
+ if (extra.cursor) {
24274
+ const src = join16(extra.stable ?? "", "rules", "eminiar.mdc");
24275
+ const dst = join16(root, ".cursor", "rules", "eminiar.mdc");
24276
+ if (existsSync13(dst)) log.ok(`${dst} already exists`);
24277
+ else if (existsSync13(src)) {
24278
+ mkdirSync9(join16(root, ".cursor", "rules"), { recursive: true });
24279
+ copyFileSync2(src, dst);
24280
+ log.ok(`wrote ${dst} \u2014 commit it`);
24281
+ }
24099
24282
  }
24100
24283
  }
24101
24284
  var init_install = __esm({
@@ -24109,6 +24292,7 @@ var init_install = __esm({
24109
24292
  init_global();
24110
24293
  init_version();
24111
24294
  init_claude_config();
24295
+ init_cursor2();
24112
24296
  init_doctor2();
24113
24297
  init_materialize();
24114
24298
  init_node_resolve();
@@ -24131,12 +24315,14 @@ async function upgrade() {
24131
24315
  const fromCheckout = rec.fromSpec.startsWith("pack:") || rec.fromSpec === "self";
24132
24316
  return install({
24133
24317
  yes: true,
24134
- method: rec.method,
24318
+ // "none" means Cursor-only last time; let install() decide again from what is present.
24319
+ method: rec.method === "none" ? void 0 : rec.method,
24135
24320
  noModel: false,
24136
24321
  spec: fromCheckout ? void 0 : "eminiar@latest",
24137
24322
  force: fromCheckout,
24138
24323
  node: rec.node,
24139
- statusline: !!rec.wrote.statusline
24324
+ statusline: !!rec.wrote.statusline,
24325
+ cursor: !!rec.wrote.cursor
24140
24326
  });
24141
24327
  }
24142
24328
  var init_upgrade = __esm({
@@ -24154,13 +24340,14 @@ var uninstall_exports = {};
24154
24340
  __export(uninstall_exports, {
24155
24341
  uninstall: () => uninstall
24156
24342
  });
24157
- import { existsSync as existsSync12, rmSync as rmSync4 } from "fs";
24343
+ import { existsSync as existsSync14, rmSync as rmSync6 } from "fs";
24158
24344
  async function uninstall(opts) {
24159
24345
  const rec = readInstallRecord();
24160
24346
  const p = paths();
24161
24347
  const plan = [
24162
24348
  rec?.method === "plugin" || !rec ? "claude plugin uninstall eminiar@eminiar + marketplace remove" : "",
24163
24349
  rec?.method === "settings" ? "remove eminiar hook entries from ~/.claude/settings.json, mcpServers.eminiar from ~/.claude.json, em-* skills" : "",
24350
+ rec?.wrote.cursor ? "remove eminiar hook entries from ~/.cursor/hooks.json, mcpServers.eminiar from ~/.cursor/mcp.json, em-* skills from ~/.cursor/skills" : "",
24164
24351
  rec?.wrote.statusline ? "clear the eminiar statusLine" : "",
24165
24352
  `delete ${p.plugin}`,
24166
24353
  opts.purgeData ? `delete ${p.home} (ALL indexes, memories, stats)` : `keep ${p.home} (indexes, memories, stats)`
@@ -24171,11 +24358,13 @@ async function uninstall(opts) {
24171
24358
  const stable = rec?.stableRoot ?? `${p.plugin}/node_modules/eminiar`;
24172
24359
  if (!rec || rec.method === "plugin") unregisterPlugin();
24173
24360
  if (rec?.method === "settings") unregisterSettings(stable, rec.wrote);
24361
+ if (rec?.wrote.cursor) unregisterCursor(stable, rec.wrote.cursor);
24174
24362
  if (rec?.wrote.statusline) clearStatusline(stable);
24175
- if (existsSync12(p.plugin)) rmSync4(p.plugin, { recursive: true, force: true });
24176
- if (opts.purgeData) rmSync4(p.home, { recursive: true, force: true });
24177
- else if (existsSync12(p.installFile)) rmSync4(p.installFile, { force: true });
24178
- log.ok("eminiar removed from Claude Code; restart it to finish");
24363
+ if (existsSync14(p.plugin)) rmSync6(p.plugin, { recursive: true, force: true });
24364
+ if (opts.purgeData) rmSync6(p.home, { recursive: true, force: true });
24365
+ else if (existsSync14(p.installFile)) rmSync6(p.installFile, { force: true });
24366
+ const from = [rec?.method !== "none" ? "Claude Code" : "", rec?.wrote.cursor ? "Cursor" : ""].filter(Boolean).join(" and ");
24367
+ log.ok(`eminiar removed from ${from || "Claude Code"}; restart it to finish`);
24179
24368
  return 0;
24180
24369
  }
24181
24370
  var init_uninstall = __esm({
@@ -24184,6 +24373,7 @@ var init_uninstall = __esm({
24184
24373
  init_esm_shims();
24185
24374
  init_paths();
24186
24375
  init_claude_config();
24376
+ init_cursor2();
24187
24377
  init_register();
24188
24378
  init_shell();
24189
24379
  }
@@ -30631,7 +30821,7 @@ __export(indexer_exports, {
30631
30821
  indexContent: () => indexContent,
30632
30822
  indexPath: () => indexPath
30633
30823
  });
30634
- import { readFileSync as readFileSync10, statSync } from "fs";
30824
+ import { readFileSync as readFileSync12, statSync } from "fs";
30635
30825
  import { relative, resolve as resolve2 } from "path";
30636
30826
  function indexContent(db, input2) {
30637
30827
  const kind = input2.kind ?? (input2.contentType === "code" ? "code" : input2.contentType === "json" ? "json" : void 0);
@@ -30713,7 +30903,7 @@ function indexPath(db, root, target, opts = {}) {
30713
30903
  summary.skipped.push({ path: rel, reason: `too large (${size} bytes)` });
30714
30904
  continue;
30715
30905
  }
30716
- const content = readFileSync10(file3, "utf8");
30906
+ const content = readFileSync12(file3, "utf8");
30717
30907
  if (content.includes("\0")) {
30718
30908
  summary.skipped.push({ path: rel, reason: "binary" });
30719
30909
  continue;
@@ -32328,8 +32518,8 @@ var init_routes = __esm({
32328
32518
  });
32329
32519
 
32330
32520
  // src/graph/languages/parser.ts
32331
- import { existsSync as existsSync13 } from "fs";
32332
- import { extname as extname2, join as join15 } from "path";
32521
+ import { existsSync as existsSync15 } from "fs";
32522
+ import { extname as extname2, join as join17 } from "path";
32333
32523
  function grammarFor(path3) {
32334
32524
  switch (extname2(path3).toLowerCase()) {
32335
32525
  case ".ts":
@@ -32362,8 +32552,8 @@ async function getParser(grammar) {
32362
32552
  }
32363
32553
  let lang = languages.get(grammar);
32364
32554
  if (!lang) {
32365
- const file3 = join15(pluginRoot(), "vendor", "grammars", `${grammar}.wasm`);
32366
- if (!existsSync13(file3)) throw new Error(`grammar missing: ${file3}`);
32555
+ const file3 = join17(pluginRoot(), "vendor", "grammars", `${grammar}.wasm`);
32556
+ if (!existsSync15(file3)) throw new Error(`grammar missing: ${file3}`);
32367
32557
  lang = await parserMod.Language.load(file3);
32368
32558
  languages.set(grammar, lang);
32369
32559
  }
@@ -32421,8 +32611,8 @@ var init_parser = __esm({
32421
32611
  });
32422
32612
 
32423
32613
  // src/graph/languages/go.ts
32424
- import { existsSync as existsSync14, readdirSync as readdirSync5, readFileSync as readFileSync11 } from "fs";
32425
- import { dirname as dirname4, join as join16, normalize, relative as relative2, resolve as resolve3 } from "path";
32614
+ import { existsSync as existsSync16, readdirSync as readdirSync6, readFileSync as readFileSync13 } from "fs";
32615
+ import { dirname as dirname4, join as join18, normalize, relative as relative2, resolve as resolve3 } from "path";
32426
32616
  function goModule(root, fromAbs) {
32427
32617
  let dir = dirname4(fromAbs);
32428
32618
  while (dir.startsWith(root)) {
@@ -32430,9 +32620,9 @@ function goModule(root, fromAbs) {
32430
32620
  if (hit !== void 0) {
32431
32621
  if (hit) return hit;
32432
32622
  } else {
32433
- const file3 = join16(dir, "go.mod");
32434
- if (existsSync14(file3)) {
32435
- const m = /^module\s+(\S+)/m.exec(readFileSync11(file3, "utf8"));
32623
+ const file3 = join18(dir, "go.mod");
32624
+ if (existsSync16(file3)) {
32625
+ const m = /^module\s+(\S+)/m.exec(readFileSync13(file3, "utf8"));
32436
32626
  const info = m ? { module: m[1], dir } : null;
32437
32627
  goModCache.set(dir, info);
32438
32628
  if (info) return info;
@@ -32449,11 +32639,11 @@ function resolveGoPackage(root, fromRel, importPath) {
32449
32639
  let dir;
32450
32640
  if (importPath === mod.module) dir = mod.dir;
32451
32641
  else if (importPath.startsWith(`${mod.module}/`))
32452
- dir = join16(mod.dir, importPath.slice(mod.module.length + 1));
32453
- if (!dir || !existsSync14(dir)) return [];
32642
+ dir = join18(mod.dir, importPath.slice(mod.module.length + 1));
32643
+ if (!dir || !existsSync16(dir)) return [];
32454
32644
  try {
32455
- return readdirSync5(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).sort().map(
32456
- (f) => normalize(relative2(root, join16(dir, f))).split("\\").join("/")
32645
+ return readdirSync6(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).sort().map(
32646
+ (f) => normalize(relative2(root, join18(dir, f))).split("\\").join("/")
32457
32647
  );
32458
32648
  } catch {
32459
32649
  return [];
@@ -32855,13 +33045,13 @@ var init_go = __esm({
32855
33045
  });
32856
33046
 
32857
33047
  // src/graph/languages/php.ts
32858
- import { readdirSync as readdirSync6, readFileSync as readFileSync12, statSync as statSync2 } from "fs";
32859
- import { dirname as dirname5, join as join17, normalize as normalize2, relative as relative3, resolve as resolve4 } from "path";
33048
+ import { readdirSync as readdirSync7, readFileSync as readFileSync14, statSync as statSync2 } from "fs";
33049
+ import { dirname as dirname5, join as join19, normalize as normalize2, relative as relative3, resolve as resolve4 } from "path";
32860
33050
  function readComposer(dir) {
32861
- const file3 = join17(dir, "composer.json");
33051
+ const file3 = join19(dir, "composer.json");
32862
33052
  if (!isFile(file3)) return null;
32863
33053
  try {
32864
- const json3 = JSON.parse(readFileSync12(file3, "utf8"));
33054
+ const json3 = JSON.parse(readFileSync14(file3, "utf8"));
32865
33055
  const info = { dir, psr4: [], psr0: [], classmap: [], files: [], require: [] };
32866
33056
  for (const key of ["autoload", "autoload-dev"]) {
32867
33057
  const section = json3[key];
@@ -32903,7 +33093,7 @@ function phpFilesUnder(abs, budget) {
32903
33093
  if (isFile(abs)) return abs.endsWith(".php") ? [abs] : [];
32904
33094
  let entries;
32905
33095
  try {
32906
- entries = readdirSync6(abs, { recursive: true, encoding: "utf8" });
33096
+ entries = readdirSync7(abs, { recursive: true, encoding: "utf8" });
32907
33097
  } catch {
32908
33098
  return [];
32909
33099
  }
@@ -32911,7 +33101,7 @@ function phpFilesUnder(abs, budget) {
32911
33101
  for (const e of entries) {
32912
33102
  if (budget.left <= 0) break;
32913
33103
  if (!e.endsWith(".php") || e.split(/[\\/]/).includes("vendor")) continue;
32914
- out.push(join17(abs, e));
33104
+ out.push(join19(abs, e));
32915
33105
  budget.left--;
32916
33106
  }
32917
33107
  return out;
@@ -32921,11 +33111,11 @@ function classmapClasses(root, auto) {
32921
33111
  const classes = /* @__PURE__ */ new Map();
32922
33112
  const budget = { left: CLASSMAP_MAX_FILES };
32923
33113
  for (const entry of auto.classmap) {
32924
- for (const f of phpFilesUnder(join17(auto.dir, entry), budget)) {
33114
+ for (const f of phpFilesUnder(join19(auto.dir, entry), budget)) {
32925
33115
  if (relative3(root, f).startsWith("..")) continue;
32926
33116
  let code;
32927
33117
  try {
32928
- code = readFileSync12(f, "utf8");
33118
+ code = readFileSync14(f, "utf8");
32929
33119
  } catch {
32930
33120
  continue;
32931
33121
  }
@@ -32945,11 +33135,11 @@ function autoloadedFunctions(root, auto) {
32945
33135
  if (auto.functions) return auto.functions;
32946
33136
  const functions = /* @__PURE__ */ new Map();
32947
33137
  for (const entry of auto.files) {
32948
- const f = join17(auto.dir, entry);
33138
+ const f = join19(auto.dir, entry);
32949
33139
  if (!isFile(f) || relative3(root, f).startsWith("..")) continue;
32950
33140
  let code;
32951
33141
  try {
32952
- code = readFileSync12(f, "utf8");
33142
+ code = readFileSync14(f, "utf8");
32953
33143
  } catch {
32954
33144
  continue;
32955
33145
  }
@@ -32969,14 +33159,14 @@ function resolvePhpClass(root, fromRel, fqcn) {
32969
33159
  for (const { prefix, dirs } of auto.psr4) {
32970
33160
  if (!name.startsWith(prefix)) continue;
32971
33161
  const rest2 = name.slice(prefix.length).split("\\");
32972
- for (const d of dirs) candidates2.push(join17(auto.dir, d, ...rest2));
33162
+ for (const d of dirs) candidates2.push(join19(auto.dir, d, ...rest2));
32973
33163
  }
32974
33164
  for (const { prefix, dirs } of auto.psr0) {
32975
33165
  if (!name.startsWith(prefix)) continue;
32976
33166
  const cut = name.lastIndexOf("\\");
32977
33167
  const ns = cut === -1 ? [] : name.slice(0, cut).split("\\");
32978
33168
  const cls = name.slice(cut + 1).split("_");
32979
- for (const d of dirs) candidates2.push(join17(auto.dir, d, ...ns, ...cls));
33169
+ for (const d of dirs) candidates2.push(join19(auto.dir, d, ...ns, ...cls));
32980
33170
  }
32981
33171
  } else {
32982
33172
  const parts = name.split("\\");
@@ -33213,7 +33403,7 @@ async function parsePhp(root, rel, code) {
33213
33403
  for (let i = left.includes("__FILE__") ? 1 : 0; i < Number(up[1] ?? 1); i++)
33214
33404
  base = dirname5(base);
33215
33405
  }
33216
- if (base && right !== void 0) candidates2.push(join17(base, right));
33406
+ if (base && right !== void 0) candidates2.push(join19(base, right));
33217
33407
  }
33218
33408
  const hit = candidates2.find((c) => isFile(c) && !relative3(root, c).startsWith(".."));
33219
33409
  if (!hit) continue;
@@ -33922,25 +34112,25 @@ var init_php = __esm({
33922
34112
  });
33923
34113
 
33924
34114
  // src/graph/languages/python.ts
33925
- import { existsSync as existsSync15, statSync as statSync3 } from "fs";
33926
- import { dirname as dirname6, join as join18, normalize as normalize3, relative as relative4, resolve as resolve5 } from "path";
34115
+ import { existsSync as existsSync17, statSync as statSync3 } from "fs";
34116
+ import { dirname as dirname6, join as join20, normalize as normalize3, relative as relative4, resolve as resolve5 } from "path";
33927
34117
  function resolvePython(root, fromRel, module, level) {
33928
34118
  const parts = module ? module.split(".") : [];
33929
34119
  const candidates2 = [];
33930
34120
  if (level > 0) {
33931
34121
  let base = dirname6(resolve5(root, fromRel));
33932
34122
  for (let i = 1; i < level; i++) base = dirname6(base);
33933
- candidates2.push(join18(base, ...parts));
34123
+ candidates2.push(join20(base, ...parts));
33934
34124
  } else {
33935
34125
  candidates2.push(resolve5(root, ...parts), resolve5(root, "src", ...parts));
33936
34126
  let dir = dirname6(resolve5(root, fromRel));
33937
34127
  while (dir.startsWith(root) && dir !== root) {
33938
- candidates2.push(join18(dir, ...parts));
34128
+ candidates2.push(join20(dir, ...parts));
33939
34129
  dir = dirname6(dir);
33940
34130
  }
33941
34131
  }
33942
34132
  for (const c of candidates2) {
33943
- for (const f of [`${c}.py`, join18(c, "__init__.py"), `${c}.pyi`]) {
34133
+ for (const f of [`${c}.py`, join20(c, "__init__.py"), `${c}.pyi`]) {
33944
34134
  if (isFile2(f) && !relative4(root, f).startsWith(".."))
33945
34135
  return normalize3(relative4(root, f)).split("\\").join("/");
33946
34136
  }
@@ -33979,7 +34169,7 @@ async function parsePython(root, rel, code) {
33979
34169
  walkRefs(stmt);
33980
34170
  }
33981
34171
  edges.push(...refs.edges());
33982
- if (!existsSync15(join18(root, rel))) {
34172
+ if (!existsSync17(join20(root, rel))) {
33983
34173
  }
33984
34174
  const errors = tree.rootNode.hasError ? tree.rootNode.descendantsOfType("ERROR").length : 0;
33985
34175
  fileNode.meta = {
@@ -34326,16 +34516,16 @@ var init_python = __esm({
34326
34516
  });
34327
34517
 
34328
34518
  // src/graph/resolve.ts
34329
- import { existsSync as existsSync16, readdirSync as readdirSync7, readFileSync as readFileSync13, statSync as statSync4 } from "fs";
34330
- import { dirname as dirname7, join as join19, normalize as normalize4, relative as relative5, resolve as resolve6 } from "path";
34519
+ import { existsSync as existsSync18, readdirSync as readdirSync8, readFileSync as readFileSync15, statSync as statSync4 } from "fs";
34520
+ import { dirname as dirname7, join as join21, normalize as normalize4, relative as relative5, resolve as resolve6 } from "path";
34331
34521
  function loadTsPaths(root) {
34332
34522
  const hit = tsPathsCache.get(root);
34333
34523
  if (hit !== void 0) return hit;
34334
34524
  let out = null;
34335
34525
  try {
34336
- const file3 = join19(root, "tsconfig.json");
34337
- if (existsSync16(file3)) {
34338
- const raw = readFileSync13(file3, "utf8").replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "").replace(/,(\s*[}\]])/g, "$1");
34526
+ const file3 = join21(root, "tsconfig.json");
34527
+ if (existsSync18(file3)) {
34528
+ const raw = readFileSync15(file3, "utf8").replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "").replace(/,(\s*[}\]])/g, "$1");
34339
34529
  const cfg = JSON.parse(raw);
34340
34530
  const co = cfg.compilerOptions ?? {};
34341
34531
  if (co.paths) {
@@ -34373,16 +34563,16 @@ function probe(abs) {
34373
34563
  if (tryFile(abs + ext)) return abs + ext;
34374
34564
  }
34375
34565
  for (const ext of EXTS) {
34376
- const idx = join19(abs, `index${ext}`);
34566
+ const idx = join21(abs, `index${ext}`);
34377
34567
  if (tryFile(idx)) return idx;
34378
34568
  }
34379
34569
  return void 0;
34380
34570
  }
34381
34571
  function readPackageJson(dir) {
34382
34572
  try {
34383
- const file3 = join19(dir, "package.json");
34384
- if (!existsSync16(file3)) return void 0;
34385
- return JSON.parse(readFileSync13(file3, "utf8"));
34573
+ const file3 = join21(dir, "package.json");
34574
+ if (!existsSync18(file3)) return void 0;
34575
+ return JSON.parse(readFileSync15(file3, "utf8"));
34386
34576
  } catch {
34387
34577
  return void 0;
34388
34578
  }
@@ -34398,9 +34588,9 @@ function loadWorkspaces(root) {
34398
34588
  if (Array.isArray(ws)) globs.push(...ws);
34399
34589
  else if (ws?.packages) globs.push(...ws.packages);
34400
34590
  try {
34401
- const yaml = join19(root, "pnpm-workspace.yaml");
34402
- if (existsSync16(yaml)) {
34403
- for (const m of readFileSync13(yaml, "utf8").matchAll(/^\s*-\s*['"]?([^'"\n#]+?)['"]?\s*$/gm))
34591
+ const yaml = join21(root, "pnpm-workspace.yaml");
34592
+ if (existsSync18(yaml)) {
34593
+ for (const m of readFileSync15(yaml, "utf8").matchAll(/^\s*-\s*['"]?([^'"\n#]+?)['"]?\s*$/gm))
34404
34594
  globs.push(m[1].trim());
34405
34595
  }
34406
34596
  } catch {
@@ -34413,8 +34603,8 @@ function loadWorkspaces(root) {
34413
34603
  else {
34414
34604
  const base = resolve6(root, g.slice(0, star));
34415
34605
  try {
34416
- for (const d of readdirSync7(base, { withFileTypes: true })) {
34417
- if (d.isDirectory()) dirs.push(join19(base, d.name));
34606
+ for (const d of readdirSync8(base, { withFileTypes: true })) {
34607
+ if (d.isDirectory()) dirs.push(join21(base, d.name));
34418
34608
  }
34419
34609
  } catch {
34420
34610
  }
@@ -35557,8 +35747,8 @@ var init_link = __esm({
35557
35747
  });
35558
35748
 
35559
35749
  // src/graph/reindex.ts
35560
- import { readFileSync as readFileSync14, statSync as statSync5 } from "fs";
35561
- import { join as join20 } from "path";
35750
+ import { readFileSync as readFileSync16, statSync as statSync5 } from "fs";
35751
+ import { join as join22 } from "path";
35562
35752
  function listCodeFiles(ctx) {
35563
35753
  return import_fast_glob2.default.sync(ctx.config.graph.include, {
35564
35754
  cwd: ctx.root,
@@ -35569,7 +35759,7 @@ function listCodeFiles(ctx) {
35569
35759
  });
35570
35760
  }
35571
35761
  async function indexOne(ctx, db, rel, force) {
35572
- const abs = join20(ctx.root, rel);
35762
+ const abs = join22(ctx.root, rel);
35573
35763
  const st = statSync5(abs);
35574
35764
  const backend = getCodeBackend(ctx);
35575
35765
  const language = backend.languageOf(rel) ?? null;
@@ -35589,7 +35779,7 @@ async function indexOne(ctx, db, rel, force) {
35589
35779
  }
35590
35780
  return "skipped";
35591
35781
  }
35592
- const code = readFileSync14(abs, "utf8");
35782
+ const code = readFileSync16(abs, "utf8");
35593
35783
  const hash2 = hashText(code);
35594
35784
  const prev = db.fileIndexGet(rel);
35595
35785
  if (!force && prev?.hash === hash2 && prev.status !== "skipped") return "unchanged";
@@ -35670,7 +35860,7 @@ async function reindexCode(ctx, db, opts = {}) {
35670
35860
  summary.unsupported++;
35671
35861
  if (db.fileIndexGet(rel)?.status === "unsupported") continue;
35672
35862
  try {
35673
- const st = statSync5(join20(ctx.root, rel));
35863
+ const st = statSync5(join22(ctx.root, rel));
35674
35864
  db.fileIndexSet({
35675
35865
  path: rel,
35676
35866
  hash: "",
@@ -35686,7 +35876,7 @@ async function reindexCode(ctx, db, opts = {}) {
35686
35876
  }
35687
35877
  for (const rel of targets) {
35688
35878
  try {
35689
- if (!statSafe(join20(ctx.root, rel))) {
35879
+ if (!statSafe(join22(ctx.root, rel))) {
35690
35880
  if (db.fileIndexGet(rel)) {
35691
35881
  removeOne(db, rel);
35692
35882
  summary.removed++;
@@ -35698,7 +35888,7 @@ async function reindexCode(ctx, db, opts = {}) {
35698
35888
  const error62 = err.message;
35699
35889
  summary.errors.push({ path: rel, error: error62 });
35700
35890
  try {
35701
- const st = statSync5(join20(ctx.root, rel));
35891
+ const st = statSync5(join22(ctx.root, rel));
35702
35892
  db.fileIndexSet({
35703
35893
  path: rel,
35704
35894
  hash: "",
@@ -35801,10 +35991,10 @@ function indexFreshness(ctx, db) {
35801
35991
  const dirty = [];
35802
35992
  for (const r of rows.slice(0, 400)) {
35803
35993
  try {
35804
- const abs = join20(ctx.root, r.path);
35994
+ const abs = join22(ctx.root, r.path);
35805
35995
  const st = statSync5(abs);
35806
35996
  if (r.mtime !== null && Math.abs(st.mtimeMs - r.mtime) < 1 && st.size === r.size) continue;
35807
- if (hashText(readFileSync14(abs, "utf8")) !== r.hash) dirty.push(r.path);
35997
+ if (hashText(readFileSync16(abs, "utf8")) !== r.hash) dirty.push(r.path);
35808
35998
  } catch {
35809
35999
  dirty.push(r.path);
35810
36000
  }
@@ -35838,10 +36028,10 @@ var init_reindex = __esm({
35838
36028
  });
35839
36029
 
35840
36030
  // src/session/current.ts
35841
- import { readFileSync as readFileSync15, statSync as statSync6, writeFileSync as writeFileSync6 } from "fs";
35842
- import { join as join21 } from "path";
36031
+ import { readFileSync as readFileSync17, statSync as statSync6, writeFileSync as writeFileSync7 } from "fs";
36032
+ import { join as join23 } from "path";
35843
36033
  function file2(ctx) {
35844
- return join21(projectDir(ctx.id), "current-session");
36034
+ return join23(projectDir(ctx.id), "current-session");
35845
36035
  }
35846
36036
  function getCurrentSession(ctx) {
35847
36037
  if (process.env.EMINIAR_SESSION_ID) return process.env.EMINIAR_SESSION_ID;
@@ -35853,7 +36043,7 @@ function getCurrentSession(ctx) {
35853
36043
  return "unknown";
35854
36044
  }
35855
36045
  if (cached4 && cached4.file === f && cached4.mtimeMs === mtimeMs) return cached4.id;
35856
- const id = readFileSync15(f, "utf8").trim() || "unknown";
36046
+ const id = readFileSync17(f, "utf8").trim() || "unknown";
35857
36047
  cached4 = { file: f, mtimeMs, id };
35858
36048
  return id;
35859
36049
  }
@@ -36024,15 +36214,15 @@ __export(store_exports, {
36024
36214
  write: () => write
36025
36215
  });
36026
36216
  import {
36027
- existsSync as existsSync17,
36028
- mkdirSync as mkdirSync7,
36029
- readFileSync as readFileSync16,
36217
+ existsSync as existsSync19,
36218
+ mkdirSync as mkdirSync10,
36219
+ readFileSync as readFileSync18,
36030
36220
  renameSync,
36031
36221
  statSync as statSync7,
36032
36222
  unlinkSync,
36033
- writeFileSync as writeFileSync7
36223
+ writeFileSync as writeFileSync8
36034
36224
  } from "fs";
36035
- import { dirname as dirname8, join as join22, relative as relative6, sep } from "path";
36225
+ import { dirname as dirname8, join as join24, relative as relative6, sep } from "path";
36036
36226
  function isStatus(s) {
36037
36227
  return typeof s === "string" && MEMORY_STATUSES.includes(s);
36038
36228
  }
@@ -36046,13 +36236,13 @@ function memoriesRel(ctx) {
36046
36236
  return ctx.config.memories.dir.replace(/^\.\//, "").replace(/\/+$/, "");
36047
36237
  }
36048
36238
  function memoriesDir(ctx) {
36049
- return join22(ctx.root, memoriesRel(ctx));
36239
+ return join24(ctx.root, memoriesRel(ctx));
36050
36240
  }
36051
36241
  function relOf(ctx, name) {
36052
36242
  return `${memoriesRel(ctx)}/${name}.md`;
36053
36243
  }
36054
36244
  function absOf(ctx, name) {
36055
- return join22(ctx.root, relOf(ctx, name));
36245
+ return join24(ctx.root, relOf(ctx, name));
36056
36246
  }
36057
36247
  function nameOfFile(ctx, abs) {
36058
36248
  const rel = relative6(memoriesDir(ctx), abs).split(sep).join("/");
@@ -36110,7 +36300,7 @@ function impliedFileLinks(root, body, skipPrefix) {
36110
36300
  if (!p || p.startsWith("..") || out.has(p) || skipPrefix && p.startsWith(`${skipPrefix}/`))
36111
36301
  continue;
36112
36302
  try {
36113
- if (statSync7(join22(root, p)).isFile()) out.add(p);
36303
+ if (statSync7(join24(root, p)).isFile()) out.add(p);
36114
36304
  } catch {
36115
36305
  }
36116
36306
  if (out.size >= 30) break;
@@ -36119,8 +36309,8 @@ function impliedFileLinks(root, body, skipPrefix) {
36119
36309
  }
36120
36310
  function writeMemoryFile(ctx, name, meta4, body) {
36121
36311
  const abs = absOf(ctx, name);
36122
- mkdirSync7(dirname8(abs), { recursive: true });
36123
- writeFileSync7(abs, serializeMemoryFile(meta4, `
36312
+ mkdirSync10(dirname8(abs), { recursive: true });
36313
+ writeFileSync8(abs, serializeMemoryFile(meta4, `
36124
36314
  ${body.trim()}
36125
36315
  `));
36126
36316
  }
@@ -36158,13 +36348,13 @@ function forgetInDb(db, name, rel) {
36158
36348
  function syncFile(ctx, db, name, opts = {}) {
36159
36349
  const abs = absOf(ctx, name);
36160
36350
  const rel = relOf(ctx, name);
36161
- if (!existsSync17(abs)) return void 0;
36351
+ if (!existsSync19(abs)) return void 0;
36162
36352
  let st = statSync7(abs);
36163
36353
  const row = db.memoryGetByName(name);
36164
36354
  const mtime = Math.floor(st.mtimeMs);
36165
36355
  if (!opts.force && row && row.file_mtime === mtime && row.file_size === st.size)
36166
36356
  return { changed: false, row };
36167
- let text3 = readFileSync16(abs, "utf8");
36357
+ let text3 = readFileSync18(abs, "utf8");
36168
36358
  let hash2 = hashText(text3);
36169
36359
  if (!opts.force && row && row.file_hash === hash2) {
36170
36360
  db.memoryUpsertByName({
@@ -36202,7 +36392,7 @@ function syncFile(ctx, db, name, opts = {}) {
36202
36392
  parsed.hadFrontmatter ? parsed.body : `
36203
36393
  ${parsed.body.replace(/^\s*\n/, "")}`
36204
36394
  );
36205
- writeFileSync7(abs, text3);
36395
+ writeFileSync8(abs, text3);
36206
36396
  st = statSync7(abs);
36207
36397
  hash2 = hashText(text3);
36208
36398
  }
@@ -36244,15 +36434,15 @@ tags: ${tags.join(", ")}` : ""}`,
36244
36434
  }
36245
36435
  function setMeta(ctx, db, name, patch) {
36246
36436
  const abs = absOf(ctx, name);
36247
- if (!existsSync17(abs)) return false;
36248
- const parsed = parseMemoryFile(readFileSync16(abs, "utf8"));
36437
+ if (!existsSync19(abs)) return false;
36438
+ const parsed = parseMemoryFile(readFileSync18(abs, "utf8"));
36249
36439
  const meta4 = { ...parsed.meta };
36250
36440
  for (const [k, v] of Object.entries(patch)) {
36251
36441
  if (v === void 0) delete meta4[k];
36252
36442
  else meta4[k] = v;
36253
36443
  }
36254
36444
  meta4.updated = (/* @__PURE__ */ new Date()).toISOString();
36255
- writeFileSync7(abs, serializeMemoryFile(meta4, parsed.body));
36445
+ writeFileSync8(abs, serializeMemoryFile(meta4, parsed.body));
36256
36446
  syncFile(ctx, db, name, { force: true });
36257
36447
  return true;
36258
36448
  }
@@ -36261,10 +36451,10 @@ function migrateLegacy(ctx, db) {
36261
36451
  for (const row of db.memoryLegacyRows()) {
36262
36452
  const kind = isKind(row.kind) ? row.kind : "note";
36263
36453
  const base = `${kind}/${slugify2(row.content)}`;
36264
- const taken = existsSync17(absOf(ctx, base)) || !!db.memoryGetByName(base);
36454
+ const taken = existsSync19(absOf(ctx, base)) || !!db.memoryGetByName(base);
36265
36455
  const name = taken ? `${base}-${row.id}` : base;
36266
36456
  const created = new Date(row.created_at).toISOString();
36267
- if (!existsSync17(absOf(ctx, name))) {
36457
+ if (!existsSync19(absOf(ctx, name))) {
36268
36458
  writeMemoryFile(
36269
36459
  ctx,
36270
36460
  name,
@@ -36289,7 +36479,7 @@ function reconcile(ctx, db) {
36289
36479
  const out = { files: 0, synced: 0, removed: 0, migrated: 0, skipped: [] };
36290
36480
  out.migrated = migrateLegacy(ctx, db);
36291
36481
  const dir = memoriesDir(ctx);
36292
- const files = existsSync17(dir) ? import_fast_glob3.default.sync("**/*.md", { cwd: dir, absolute: true, onlyFiles: true, dot: true }) : [];
36482
+ const files = existsSync19(dir) ? import_fast_glob3.default.sync("**/*.md", { cwd: dir, absolute: true, onlyFiles: true, dot: true }) : [];
36293
36483
  const seen = /* @__PURE__ */ new Set();
36294
36484
  for (const f of files) {
36295
36485
  const name = nameOfFile(ctx, f);
@@ -36317,7 +36507,7 @@ function write(ctx, db, input2) {
36317
36507
  );
36318
36508
  const abs = absOf(ctx, name);
36319
36509
  const prev = db.memoryGetByName(name);
36320
- const exists = !!prev || existsSync17(abs);
36510
+ const exists = !!prev || existsSync19(abs);
36321
36511
  if (exists && !input2.replace)
36322
36512
  throw new Error(
36323
36513
  `memory "${name}" already exists; pass replace: true to overwrite it, or em_memory {action: "edit"} to change part of it`
@@ -36326,7 +36516,7 @@ function write(ctx, db, input2) {
36326
36516
  let extra = {};
36327
36517
  if (exists) {
36328
36518
  try {
36329
- extra = parseMemoryFile(readFileSync16(abs, "utf8")).meta;
36519
+ extra = parseMemoryFile(readFileSync18(abs, "utf8")).meta;
36330
36520
  } catch {
36331
36521
  }
36332
36522
  }
@@ -36353,7 +36543,7 @@ function write(ctx, db, input2) {
36353
36543
  function read(ctx, db, name) {
36354
36544
  const synced = syncFile(ctx, db, name);
36355
36545
  if (!synced) return void 0;
36356
- const parsed = parseMemoryFile(readFileSync16(absOf(ctx, name), "utf8"));
36546
+ const parsed = parseMemoryFile(readFileSync18(absOf(ctx, name), "utf8"));
36357
36547
  return {
36358
36548
  name,
36359
36549
  kind: synced.row.kind,
@@ -36378,14 +36568,14 @@ function escapeRe(s) {
36378
36568
  }
36379
36569
  function edit(ctx, db, name, opts) {
36380
36570
  const abs = absOf(ctx, name);
36381
- if (!existsSync17(abs)) throw new Error(`memory "${name}" does not exist`);
36571
+ if (!existsSync19(abs)) throw new Error(`memory "${name}" does not exist`);
36382
36572
  syncFile(ctx, db, name);
36383
- const parsed = parseMemoryFile(readFileSync16(abs, "utf8"));
36573
+ const parsed = parseMemoryFile(readFileSync18(abs, "utf8"));
36384
36574
  const re = new RegExp(opts.regex ? opts.find : escapeRe(opts.find), "g");
36385
36575
  const count = (parsed.body.match(re) ?? []).length;
36386
36576
  if (!count) return 0;
36387
36577
  const body = parsed.body.replace(re, opts.replace);
36388
- writeFileSync7(
36578
+ writeFileSync8(
36389
36579
  abs,
36390
36580
  serializeMemoryFile({ ...parsed.meta, updated: (/* @__PURE__ */ new Date()).toISOString() }, body)
36391
36581
  );
@@ -36396,12 +36586,12 @@ function rename(ctx, db, from, to) {
36396
36586
  if (!isValidName(to)) throw new Error(`invalid memory name "${to}"`);
36397
36587
  const absFrom = absOf(ctx, from);
36398
36588
  const absTo = absOf(ctx, to);
36399
- if (!existsSync17(absFrom)) throw new Error(`memory "${from}" does not exist`);
36400
- if (existsSync17(absTo) || db.memoryGetByName(to)) throw new Error(`memory "${to}" already exists`);
36401
- mkdirSync7(dirname8(absTo), { recursive: true });
36589
+ if (!existsSync19(absFrom)) throw new Error(`memory "${from}" does not exist`);
36590
+ if (existsSync19(absTo) || db.memoryGetByName(to)) throw new Error(`memory "${to}" already exists`);
36591
+ mkdirSync10(dirname8(absTo), { recursive: true });
36402
36592
  renameSync(absFrom, absTo);
36403
- const parsed = parseMemoryFile(readFileSync16(absTo, "utf8"));
36404
- writeFileSync7(
36593
+ const parsed = parseMemoryFile(readFileSync18(absTo, "utf8"));
36594
+ writeFileSync8(
36405
36595
  absTo,
36406
36596
  serializeMemoryFile(
36407
36597
  { ...parsed.meta, name: to, updated: (/* @__PURE__ */ new Date()).toISOString() },
@@ -36415,11 +36605,11 @@ function rename(ctx, db, from, to) {
36415
36605
  for (const row of db.memoryList({ limit: 1e5 })) {
36416
36606
  if (!row.name || row.name === to) continue;
36417
36607
  const abs = absOf(ctx, row.name);
36418
- if (!existsSync17(abs)) continue;
36419
- const text3 = readFileSync16(abs, "utf8");
36608
+ if (!existsSync19(abs)) continue;
36609
+ const text3 = readFileSync18(abs, "utf8");
36420
36610
  if (!ref.test(text3)) continue;
36421
36611
  ref.lastIndex = 0;
36422
- writeFileSync7(abs, text3.replace(ref, `mem:${to}`));
36612
+ writeFileSync8(abs, text3.replace(ref, `mem:${to}`));
36423
36613
  syncFile(ctx, db, row.name, { force: true });
36424
36614
  refsUpdated++;
36425
36615
  }
@@ -36427,19 +36617,19 @@ function rename(ctx, db, from, to) {
36427
36617
  }
36428
36618
  function remove(ctx, db, name) {
36429
36619
  const abs = absOf(ctx, name);
36430
- const existed = existsSync17(abs) || !!db.memoryGetByName(name);
36431
- if (existsSync17(abs)) unlinkSync(abs);
36620
+ const existed = existsSync19(abs) || !!db.memoryGetByName(name);
36621
+ if (existsSync19(abs)) unlinkSync(abs);
36432
36622
  forgetInDb(db, name, relOf(ctx, name));
36433
36623
  return existed;
36434
36624
  }
36435
36625
  function gitignoreHint(ctx) {
36436
36626
  if (hinted.has(ctx.root)) return void 0;
36437
36627
  hinted.add(ctx.root);
36438
- const file3 = join22(ctx.root, ".gitignore");
36439
- if (!existsSync17(file3)) return void 0;
36628
+ const file3 = join24(ctx.root, ".gitignore");
36629
+ if (!existsSync19(file3)) return void 0;
36440
36630
  const dir = memoriesRel(ctx);
36441
36631
  const top2 = dir.split("/")[0];
36442
- const ignored = readFileSync16(file3, "utf8").split(/\r?\n/).map((l) => l.trim().replace(/^\//, "").replace(/\/$/, "")).some((l) => l === top2 || l === dir || l === `${top2}/**` || l === `${dir}/**`);
36632
+ const ignored = readFileSync18(file3, "utf8").split(/\r?\n/).map((l) => l.trim().replace(/^\//, "").replace(/\/$/, "")).some((l) => l === top2 || l === dir || l === `${top2}/**` || l === `${dir}/**`);
36443
36633
  return ignored ? `note: .gitignore ignores ${dir}, so memories stay local to this machine (remove that line to share them with the team)` : void 0;
36444
36634
  }
36445
36635
  var import_fast_glob3, MEMORY_KINDS, SEGMENT, NAME_RE, MEM_LINK_RE, PATH_RE, hinted;
@@ -37069,12 +37259,12 @@ var init_em_graph_changes = __esm({
37069
37259
  });
37070
37260
 
37071
37261
  // src/graph/architecture.ts
37072
- import { existsSync as existsSync18, readFileSync as readFileSync17 } from "fs";
37073
- import { join as join23 } from "path";
37262
+ import { existsSync as existsSync20, readFileSync as readFileSync19 } from "fs";
37263
+ import { join as join25 } from "path";
37074
37264
  function pkgJson(root) {
37075
37265
  try {
37076
- const f = join23(root, "package.json");
37077
- return existsSync18(f) ? JSON.parse(readFileSync17(f, "utf8")) : {};
37266
+ const f = join25(root, "package.json");
37267
+ return existsSync20(f) ? JSON.parse(readFileSync19(f, "utf8")) : {};
37078
37268
  } catch {
37079
37269
  return {};
37080
37270
  }
@@ -38426,8 +38616,8 @@ var init_catalog = __esm({
38426
38616
  });
38427
38617
 
38428
38618
  // src/docs/manifest.ts
38429
- import { existsSync as existsSync19, mkdirSync as mkdirSync8, readFileSync as readFileSync18, writeFileSync as writeFileSync8 } from "fs";
38430
- import { dirname as dirname9, join as join24 } from "path";
38619
+ import { existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync20, writeFileSync as writeFileSync9 } from "fs";
38620
+ import { dirname as dirname9, join as join26 } from "path";
38431
38621
  function docsTag(name) {
38432
38622
  return `${DOCS_PREFIX}${name}`;
38433
38623
  }
@@ -38442,7 +38632,7 @@ function slugify3(input2) {
38442
38632
  return (s || "source").slice(0, 64);
38443
38633
  }
38444
38634
  function manifestPathAt(root, rel = ".eminiar/docs.json") {
38445
- return join24(root, rel);
38635
+ return join26(root, rel);
38446
38636
  }
38447
38637
  function manifestPath(ctx) {
38448
38638
  return manifestPathAt(ctx.root, ctx.config.docs.manifest);
@@ -38470,9 +38660,9 @@ function normalize5(raw) {
38470
38660
  return { version: 1, sources: out };
38471
38661
  }
38472
38662
  function readManifestAt(file3) {
38473
- if (!existsSync19(file3)) return empty();
38663
+ if (!existsSync21(file3)) return empty();
38474
38664
  try {
38475
- return normalize5(JSON.parse(readFileSync18(file3, "utf8")));
38665
+ return normalize5(JSON.parse(readFileSync20(file3, "utf8")));
38476
38666
  } catch {
38477
38667
  return empty();
38478
38668
  }
@@ -38482,12 +38672,12 @@ function readManifest(ctx) {
38482
38672
  }
38483
38673
  function writeManifest(ctx, m) {
38484
38674
  const file3 = manifestPath(ctx);
38485
- mkdirSync8(dirname9(file3), { recursive: true });
38675
+ mkdirSync11(dirname9(file3), { recursive: true });
38486
38676
  const sorted = {
38487
38677
  version: 1,
38488
38678
  sources: [...m.sources].sort((a, b) => a.name.localeCompare(b.name))
38489
38679
  };
38490
- writeFileSync8(file3, `${JSON.stringify(sorted, null, 2)}
38680
+ writeFileSync9(file3, `${JSON.stringify(sorted, null, 2)}
38491
38681
  `);
38492
38682
  return file3;
38493
38683
  }
@@ -38583,11 +38773,11 @@ var init_manifest = __esm({
38583
38773
  });
38584
38774
 
38585
38775
  // src/docs/discover.ts
38586
- import { existsSync as existsSync20, readFileSync as readFileSync19, statSync as statSync8 } from "fs";
38587
- import { basename, join as join25, relative as relative7 } from "path";
38776
+ import { existsSync as existsSync22, readFileSync as readFileSync21, statSync as statSync8 } from "fs";
38777
+ import { basename, join as join27, relative as relative7 } from "path";
38588
38778
  function readText(file3) {
38589
38779
  try {
38590
- return readFileSync19(file3, "utf8");
38780
+ return readFileSync21(file3, "utf8");
38591
38781
  } catch {
38592
38782
  return void 0;
38593
38783
  }
@@ -38641,7 +38831,7 @@ function findProjects(root, opts) {
38641
38831
  const found = /* @__PURE__ */ new Set();
38642
38832
  for (const m of markers) {
38643
38833
  for (const f of glob(root, [`*/${m}`, `*/*/${m}`], 3)) {
38644
- const dir = join25(f, "..");
38834
+ const dir = join27(f, "..");
38645
38835
  const rel = relative7(root, dir);
38646
38836
  if (!rel || rel.split("/").some((p) => p.startsWith(".") || p === "node_modules")) continue;
38647
38837
  found.add(dir);
@@ -38650,7 +38840,7 @@ function findProjects(root, opts) {
38650
38840
  const max = opts.maxProjects ?? 40;
38651
38841
  const seenNames = /* @__PURE__ */ new Set();
38652
38842
  const nameOf = (dir) => {
38653
- const pkg = readJson3(join25(dir, "package.json"));
38843
+ const pkg = readJson3(join27(dir, "package.json"));
38654
38844
  return typeof pkg?.name === "string" ? pkg.name : void 0;
38655
38845
  };
38656
38846
  const rootName = nameOf(root);
@@ -38668,7 +38858,7 @@ function findProjects(root, opts) {
38668
38858
  return out;
38669
38859
  }
38670
38860
  function npmSignals(dir, includeDev, project) {
38671
- const pkg = readJson3(join25(dir, "package.json"));
38861
+ const pkg = readJson3(join27(dir, "package.json"));
38672
38862
  if (!pkg) return [];
38673
38863
  const sections = ["dependencies", ...includeDev ? ["devDependencies"] : []];
38674
38864
  const out = [];
@@ -38685,13 +38875,13 @@ function npmSignals(dir, includeDev, project) {
38685
38875
  }
38686
38876
  function pythonSignals(dir, project) {
38687
38877
  const out = [];
38688
- const py = readText(join25(dir, "pyproject.toml"));
38878
+ const py = readText(join27(dir, "pyproject.toml"));
38689
38879
  if (py) {
38690
38880
  const block = /dependencies\s*=\s*\[([\s\S]*?)\]/.exec(py)?.[1] ?? "";
38691
38881
  for (const m of block.matchAll(/["']([A-Za-z0-9_.-]+)/g))
38692
38882
  out.push({ kind: "pypi", key: m[1].toLowerCase(), project });
38693
38883
  }
38694
- const req = readText(join25(dir, "requirements.txt"));
38884
+ const req = readText(join27(dir, "requirements.txt"));
38695
38885
  if (req) {
38696
38886
  for (const line of req.split("\n")) {
38697
38887
  const name = /^\s*([A-Za-z0-9_.-]+)/.exec(line)?.[1];
@@ -38702,7 +38892,7 @@ function pythonSignals(dir, project) {
38702
38892
  return out;
38703
38893
  }
38704
38894
  function goSignals(dir, project) {
38705
- const mod = readText(join25(dir, "go.mod"));
38895
+ const mod = readText(join27(dir, "go.mod"));
38706
38896
  if (!mod) return [];
38707
38897
  const out = [];
38708
38898
  const block = /require\s*\(([\s\S]*?)\)/g;
@@ -38899,8 +39089,8 @@ function localCandidates(root, dir, project, isRegistered) {
38899
39089
  why: "project readme and top-level guides"
38900
39090
  });
38901
39091
  for (const d of ["docs", "doc", "documentation"]) {
38902
- const abs = join25(dir, d);
38903
- if (!existsSync20(abs)) continue;
39092
+ const abs = join27(dir, d);
39093
+ if (!existsSync22(abs)) continue;
38904
39094
  const files = glob(abs, ["**/*.md", "**/*.mdx", "**/*.rst", "**/*.txt"]).filter(
38905
39095
  (f) => !SKIP_EXT.has(f.slice(f.lastIndexOf(".")))
38906
39096
  );
@@ -38923,8 +39113,8 @@ function localCandidates(root, dir, project, isRegistered) {
38923
39113
  "docs/decisions",
38924
39114
  "decisions"
38925
39115
  ]) {
38926
- const abs = join25(dir, d);
38927
- if (!existsSync20(abs)) continue;
39116
+ const abs = join27(dir, d);
39117
+ if (!existsSync22(abs)) continue;
38928
39118
  if (out.some((c) => c.path && rel(abs).startsWith(`${c.path}/`))) break;
38929
39119
  const files = glob(abs, ["**/*.md"]);
38930
39120
  push({
@@ -39721,7 +39911,7 @@ var init_category = __esm({
39721
39911
  });
39722
39912
 
39723
39913
  // src/docs/graph.ts
39724
- import { existsSync as existsSync21, statSync as statSync9 } from "fs";
39914
+ import { existsSync as existsSync23, statSync as statSync9 } from "fs";
39725
39915
  import { dirname as dirname10, posix, relative as relative8, sep as sep2 } from "path";
39726
39916
  function manifestRel(ctx) {
39727
39917
  return relative8(ctx.root, manifestPath(ctx)).split(sep2).join("/");
@@ -39819,7 +40009,7 @@ function localDocPages(ctx, db) {
39819
40009
  }
39820
40010
  function stampOf(ctx, db) {
39821
40011
  const file3 = manifestPath(ctx);
39822
- const st = existsSync21(file3) ? statSync9(file3) : void 0;
40012
+ const st = existsSync23(file3) ? statSync9(file3) : void 0;
39823
40013
  const counts = db.graphNodeCounts();
39824
40014
  const syncs = readManifest(ctx).sources.map((s) => syncState(db, s.name)?.at ?? 0).join(",");
39825
40015
  return `${st ? `${Math.floor(st.mtimeMs)}:${st.size}` : "none"}|${counts.file ?? 0}|${counts.package ?? 0}|${syncs}`;
@@ -44386,14 +44576,14 @@ __export(ingest_exports, {
44386
44576
  usageEnabled: () => usageEnabled
44387
44577
  });
44388
44578
  import { createHash as createHash4 } from "crypto";
44389
- import { closeSync, existsSync as existsSync22, openSync, readdirSync as readdirSync8, readSync, statSync as statSync10 } from "fs";
44390
- import { homedir as homedir3 } from "os";
44391
- import { basename as basename2, dirname as dirname11, join as join26, resolve as resolve7, sep as sep3 } from "path";
44579
+ import { closeSync, existsSync as existsSync24, openSync, readdirSync as readdirSync9, readSync, statSync as statSync10 } from "fs";
44580
+ import { homedir as homedir4 } from "os";
44581
+ import { basename as basename2, dirname as dirname11, join as join28, resolve as resolve7, sep as sep3 } from "path";
44392
44582
  function isValidSessionId(id) {
44393
44583
  return SESSION_ID_RE.test(id);
44394
44584
  }
44395
44585
  function claudeDir2() {
44396
- return process.env.EMINIAR_CLAUDE_DIR || join26(homedir3(), ".claude");
44586
+ return process.env.EMINIAR_CLAUDE_DIR || join28(homedir4(), ".claude");
44397
44587
  }
44398
44588
  function insideDir(path3, dir) {
44399
44589
  const d = resolve7(dir);
@@ -44412,7 +44602,7 @@ function transcriptSlug(root) {
44412
44602
  return root.replace(/[^A-Za-z0-9]/g, "-");
44413
44603
  }
44414
44604
  function transcriptDirFor(root) {
44415
- return join26(claudeDir2(), "projects", transcriptSlug(root));
44605
+ return join28(claudeDir2(), "projects", transcriptSlug(root));
44416
44606
  }
44417
44607
  function usageEnabled(ctx) {
44418
44608
  return ctx.config.usage.enabled !== false;
@@ -44582,7 +44772,7 @@ function add(a, b) {
44582
44772
  }
44583
44773
  function listJsonl(dir) {
44584
44774
  try {
44585
- return readdirSync8(dir).filter((f) => f.endsWith(".jsonl")).map((f) => join26(dir, f));
44775
+ return readdirSync9(dir).filter((f) => f.endsWith(".jsonl")).map((f) => join28(dir, f));
44586
44776
  } catch {
44587
44777
  return [];
44588
44778
  }
@@ -44602,7 +44792,7 @@ function firstEntrySessionId(path3) {
44602
44792
  function sidechainFilesFor(db, dir, sessionId) {
44603
44793
  if (!isValidSessionId(sessionId)) return [];
44604
44794
  const inside = (p) => insideDir(p, dir) && p.endsWith(".jsonl");
44605
- const out = listJsonl(join26(dir, sessionId, "subagents")).filter(inside);
44795
+ const out = listJsonl(join28(dir, sessionId, "subagents")).filter(inside);
44606
44796
  for (const path3 of listJsonl(dir)) {
44607
44797
  if (!inside(path3) || !basename2(path3).startsWith("agent-")) continue;
44608
44798
  const known = db.transcriptFileGet(path3)?.session_id;
@@ -44646,11 +44836,11 @@ function ingestSession(db, root, sessionId, transcriptPath, opts = {}) {
44646
44836
  function ingestProject(db, root, opts = {}) {
44647
44837
  const dir = transcriptDirFor(root);
44648
44838
  const files = new Set(listJsonl(dir));
44649
- if (existsSync22(dir)) {
44839
+ if (existsSync24(dir)) {
44650
44840
  try {
44651
- for (const entry of readdirSync8(dir, { withFileTypes: true })) {
44841
+ for (const entry of readdirSync9(dir, { withFileTypes: true })) {
44652
44842
  if (entry.isDirectory())
44653
- for (const sub of listJsonl(join26(dir, entry.name, "subagents"))) files.add(sub);
44843
+ for (const sub of listJsonl(join28(dir, entry.name, "subagents"))) files.add(sub);
44654
44844
  }
44655
44845
  } catch {
44656
44846
  }
@@ -46004,14 +46194,14 @@ var init_em_search = __esm({
46004
46194
  });
46005
46195
 
46006
46196
  // src/ui/api.ts
46007
- import { existsSync as existsSync23, readdirSync as readdirSync9 } from "fs";
46008
- import { join as join27, relative as relative9 } from "path";
46197
+ import { existsSync as existsSync25, readdirSync as readdirSync10 } from "fs";
46198
+ import { join as join29, relative as relative9 } from "path";
46009
46199
  function listProjects() {
46010
46200
  const dir = paths().projects;
46011
46201
  const out = [];
46012
- for (const id of readdirSync9(dir, { withFileTypes: true })) {
46202
+ for (const id of readdirSync10(dir, { withFileTypes: true })) {
46013
46203
  if (!id.isDirectory()) continue;
46014
- const db = join27(dir, id.name, "eminiar.db");
46204
+ const db = join29(dir, id.name, "eminiar.db");
46015
46205
  try {
46016
46206
  const a = new SqliteAdapter(db, { vectors: false });
46017
46207
  out.push({ id: id.name, root: a.sessionLatest()?.project_root ?? null });
@@ -46037,8 +46227,8 @@ function statsPayload(ctx) {
46037
46227
  const db = getStorage(ctx);
46038
46228
  const sessionId = getCurrentSession(ctx);
46039
46229
  const g = globalDb();
46040
- const onboardingDir = join27(memoriesDir(ctx), "onboarding");
46041
- const onboarding = existsSync23(onboardingDir) ? readdirSync9(onboardingDir).filter((f) => f.endsWith(".md")).map((f) => f.slice(0, -3)) : [];
46230
+ const onboardingDir = join29(memoriesDir(ctx), "onboarding");
46231
+ const onboarding = existsSync25(onboardingDir) ? readdirSync10(onboardingDir).filter((f) => f.endsWith(".md")).map((f) => f.slice(0, -3)) : [];
46042
46232
  return {
46043
46233
  project: ctx.root,
46044
46234
  projectId: ctx.id,
@@ -46640,8 +46830,8 @@ var init_namepath = __esm({
46640
46830
  });
46641
46831
 
46642
46832
  // src/code/symbols.ts
46643
- import { existsSync as existsSync24, readFileSync as readFileSync20 } from "fs";
46644
- import { join as join28 } from "path";
46833
+ import { existsSync as existsSync26, readFileSync as readFileSync22 } from "fs";
46834
+ import { join as join30 } from "path";
46645
46835
  function isExported2(n) {
46646
46836
  if (!n.meta) return false;
46647
46837
  try {
@@ -46677,7 +46867,7 @@ var init_symbols2 = __esm({
46677
46867
  });
46678
46868
 
46679
46869
  // src/ui/graph-api.ts
46680
- import { readFileSync as readFileSync21, realpathSync as realpathSync2, statSync as statSync11 } from "fs";
46870
+ import { readFileSync as readFileSync23, realpathSync as realpathSync2, statSync as statSync11 } from "fs";
46681
46871
  import { relative as relative10, resolve as resolve8 } from "path";
46682
46872
  function metaOf2(row) {
46683
46873
  if (!row?.meta) return {};
@@ -46763,7 +46953,7 @@ function filePayload(ctx, rel) {
46763
46953
  }));
46764
46954
  if (st.size > MAX_CODE_BYTES)
46765
46955
  return { path: clean, tooLarge: true, size: st.size, status: row?.status ?? null, symbols };
46766
- const content = readFileSync21(real, "utf8");
46956
+ const content = readFileSync23(real, "utf8");
46767
46957
  return {
46768
46958
  path: clean,
46769
46959
  size: st.size,
@@ -47449,8 +47639,8 @@ var init_lineage = __esm({
47449
47639
  });
47450
47640
 
47451
47641
  // src/ui/history-graph-api.ts
47452
- import { existsSync as existsSync25 } from "fs";
47453
- import { join as join29 } from "path";
47642
+ import { existsSync as existsSync27 } from "fs";
47643
+ import { join as join31 } from "path";
47454
47644
  function parseList(raw) {
47455
47645
  if (!raw) return [];
47456
47646
  try {
@@ -47689,7 +47879,7 @@ function buildHistoryGraph(ctx, db, m, opts = {}) {
47689
47879
  path: p,
47690
47880
  line: null,
47691
47881
  root: id === focusId,
47692
- missing: existsSync25(join29(ctx.root, p)) ? void 0 : true,
47882
+ missing: existsSync27(join31(ctx.root, p)) ? void 0 : true,
47693
47883
  risk: h?.risk,
47694
47884
  fixes: h?.fixes
47695
47885
  });
@@ -48048,9 +48238,9 @@ __export(server_exports, {
48048
48238
  uiDir: () => uiDir
48049
48239
  });
48050
48240
  import { spawn as spawn2 } from "child_process";
48051
- import { existsSync as existsSync26, readFileSync as readFileSync22, statSync as statSync12 } from "fs";
48241
+ import { existsSync as existsSync28, readFileSync as readFileSync24, statSync as statSync12 } from "fs";
48052
48242
  import { createServer } from "http";
48053
- import { extname as extname3, join as join30, normalize as normalize6 } from "path";
48243
+ import { extname as extname3, join as join32, normalize as normalize6 } from "path";
48054
48244
  import { URL as URL2 } from "url";
48055
48245
  function json2(res, status, body) {
48056
48246
  res.writeHead(status, {
@@ -48072,7 +48262,7 @@ function strList(v) {
48072
48262
  return void 0;
48073
48263
  }
48074
48264
  function uiDir() {
48075
- return process.env.EMINIAR_UI_DIR || join30(pluginRoot(), "dist", "ui");
48265
+ return process.env.EMINIAR_UI_DIR || join32(pluginRoot(), "dist", "ui");
48076
48266
  }
48077
48267
  function originAllowed(req, port) {
48078
48268
  const host = req.headers.host ?? "";
@@ -48096,25 +48286,25 @@ function originAllowed(req, port) {
48096
48286
  function serveStatic(res, p) {
48097
48287
  const dir = uiDir();
48098
48288
  const rel = p === "/" ? "index.html" : p.replace(/^\/+/, "");
48099
- const file3 = normalize6(join30(dir, rel));
48289
+ const file3 = normalize6(join32(dir, rel));
48100
48290
  if (!file3.startsWith(normalize6(dir))) return false;
48101
- if (!existsSync26(file3) || !statSync12(file3).isFile()) return false;
48291
+ if (!existsSync28(file3) || !statSync12(file3).isFile()) return false;
48102
48292
  const type = MIME[extname3(file3).toLowerCase()] ?? "application/octet-stream";
48103
48293
  if (rel === "index.html") {
48104
48294
  const stamp = (name) => {
48105
48295
  try {
48106
- return `/${name}?v=${Math.floor(statSync12(join30(dir, name)).mtimeMs)}`;
48296
+ return `/${name}?v=${Math.floor(statSync12(join32(dir, name)).mtimeMs)}`;
48107
48297
  } catch {
48108
48298
  return `/${name}`;
48109
48299
  }
48110
48300
  };
48111
- const html = readFileSync22(file3, "utf8").replace('"/app.global.js"', `"${stamp("app.global.js")}"`).replace('"/styles.css"', `"${stamp("styles.css")}"`);
48301
+ const html = readFileSync24(file3, "utf8").replace('"/app.global.js"', `"${stamp("app.global.js")}"`).replace('"/styles.css"', `"${stamp("styles.css")}"`);
48112
48302
  res.writeHead(200, { "content-type": type, "cache-control": "no-store" });
48113
48303
  res.end(html);
48114
48304
  return true;
48115
48305
  }
48116
48306
  res.writeHead(200, { "content-type": type, "cache-control": "no-cache" });
48117
- res.end(readFileSync22(file3));
48307
+ res.end(readFileSync24(file3));
48118
48308
  return true;
48119
48309
  }
48120
48310
  async function serve(opts) {
@@ -48553,7 +48743,7 @@ __export(statusline_exports, {
48553
48743
  renderStatusline: () => renderStatusline,
48554
48744
  usageSegments: () => usageSegments
48555
48745
  });
48556
- import { existsSync as existsSync27, readFileSync as readFileSync23, writeFileSync as writeFileSync9 } from "fs";
48746
+ import { existsSync as existsSync29, readFileSync as readFileSync25, writeFileSync as writeFileSync10 } from "fs";
48557
48747
  function epochMs(v) {
48558
48748
  if (typeof v === "number" && Number.isFinite(v)) return v < 1e12 ? v * 1e3 : v;
48559
48749
  if (typeof v === "string") {
@@ -48615,8 +48805,8 @@ function renderStatusline(raw) {
48615
48805
  const key = cacheKey(input2);
48616
48806
  const cache3 = paths().statuslineCache;
48617
48807
  try {
48618
- if (existsSync27(cache3)) {
48619
- const c = JSON.parse(readFileSync23(cache3, "utf8"));
48808
+ if (existsSync29(cache3)) {
48809
+ const c = JSON.parse(readFileSync25(cache3, "utf8"));
48620
48810
  if (Date.now() - c.at < CACHE_TTL_MS && c.key === key) return c.line;
48621
48811
  }
48622
48812
  } catch {
@@ -48647,7 +48837,7 @@ function renderStatusline(raw) {
48647
48837
  line = `eminiar \xB7 unavailable (${err.message.slice(0, 40)})`;
48648
48838
  }
48649
48839
  try {
48650
- writeFileSync9(cache3, JSON.stringify({ at: Date.now(), line, key }));
48840
+ writeFileSync10(cache3, JSON.stringify({ at: Date.now(), line, key }));
48651
48841
  } catch {
48652
48842
  }
48653
48843
  return line;
@@ -48681,9 +48871,11 @@ var USAGE = `eminiar v${version2()} \u2014 local-first context, memory & knowled
48681
48871
  Usage: eminiar <command> [options]
48682
48872
 
48683
48873
  Setup
48684
- install [--no-model] [--method plugin|settings] [--team] [--yes] [--force] Install into Claude Code
48874
+ install [--no-model] [--method plugin|settings] [--cursor] [--team] [--yes] [--force]
48875
+ Install into Claude Code; --cursor also registers with Cursor
48876
+ (hooks, MCP server, skills under ~/.cursor)
48685
48877
  upgrade Update to the latest version and re-register
48686
- uninstall [--purge-data] Remove from Claude Code (data kept unless --purge-data)
48878
+ uninstall [--purge-data] Remove from Claude Code and Cursor (data kept unless --purge-data)
48687
48879
  doctor [--json] [--fix] Check installation health; --fix re-pins node/root and clears
48688
48880
  Claude Code's cached launch failure
48689
48881
  replace-context-mode [--yes] Remove the context-mode plugin after parity sign-off
@@ -48711,7 +48903,7 @@ Use
48711
48903
  ui [--port 7331] [--no-open] Web dashboard: stats, memories, graph, search, sessions, actions
48712
48904
  (alias: serve)
48713
48905
  statusline Claude Code statusLine command (reads JSON on stdin)
48714
- hook [--event E] Run the hook handler manually (reads JSON on stdin)
48906
+ hook [--event E] [--client claude|cursor] Run the hook handler manually (reads JSON on stdin)
48715
48907
  version | help
48716
48908
  `;
48717
48909
  function text2(r) {
@@ -48741,6 +48933,7 @@ var commands = {
48741
48933
  node: { type: "string" },
48742
48934
  yes: { type: "boolean" },
48743
48935
  statusline: { type: "boolean" },
48936
+ cursor: { type: "boolean" },
48744
48937
  force: { type: "boolean" }
48745
48938
  },
48746
48939
  strict: false
@@ -48748,6 +48941,7 @@ var commands = {
48748
48941
  const { install: install2 } = await Promise.resolve().then(() => (init_install(), install_exports));
48749
48942
  return install2({
48750
48943
  force: !!values.force,
48944
+ cursor: !!values.cursor,
48751
48945
  noModel: !!values["no-model"],
48752
48946
  method: values.method === "settings" ? "settings" : values.method === "plugin" ? "plugin" : void 0,
48753
48947
  team: !!values.team,