context-vault 2.4.1 → 2.4.2

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/bin/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * context-mcp CLI — Unified entry point
4
+ * context-vault CLI — Unified entry point
5
5
  *
6
6
  * Usage:
7
- * context-mcp setup Interactive MCP installer
8
- * context-mcp ui [--port 3141] Launch web dashboard
9
- * context-mcp reindex Rebuild search index
10
- * context-mcp status Show vault diagnostics
7
+ * context-vault setup Interactive MCP installer
8
+ * context-vault ui [--port 3141] Launch web dashboard
9
+ * context-vault reindex Rebuild search index
10
+ * context-vault status Show vault diagnostics
11
11
  */
12
12
 
13
13
  import { createInterface } from "node:readline";
@@ -23,6 +23,7 @@ import { join, resolve, dirname } from "node:path";
23
23
  import { homedir, platform } from "node:os";
24
24
  import { execSync, fork } from "node:child_process";
25
25
  import { fileURLToPath } from "node:url";
26
+ import { createServer as createNetServer } from "node:net";
26
27
 
27
28
  const __filename = fileURLToPath(import.meta.url);
28
29
  const __dirname = dirname(__filename);
@@ -105,19 +106,27 @@ function vscodeDataDir() {
105
106
 
106
107
  // ─── Tool Detection ──────────────────────────────────────────────────────────
107
108
 
109
+ function commandExists(bin) {
110
+ try {
111
+ const cmd = PLATFORM === "win32" ? `where ${bin}` : `which ${bin}`;
112
+ execSync(cmd, { stdio: "pipe" });
113
+ return true;
114
+ } catch {
115
+ return false;
116
+ }
117
+ }
118
+
108
119
  const TOOLS = [
109
120
  {
110
121
  id: "claude-code",
111
122
  name: "Claude Code",
112
- detect: () => {
113
- try {
114
- const cmd = PLATFORM === "win32" ? "where claude" : "which claude";
115
- execSync(cmd, { stdio: "pipe" });
116
- return true;
117
- } catch {
118
- return false;
119
- }
120
- },
123
+ detect: () => commandExists("claude"),
124
+ configType: "cli",
125
+ },
126
+ {
127
+ id: "codex",
128
+ name: "Codex",
129
+ detect: () => commandExists("codex"),
121
130
  configType: "cli",
122
131
  },
123
132
  {
@@ -144,6 +153,14 @@ const TOOLS = [
144
153
  configPath: join(HOME, ".codeium", "windsurf", "mcp_config.json"),
145
154
  configKey: "mcpServers",
146
155
  },
156
+ {
157
+ id: "antigravity",
158
+ name: "Antigravity",
159
+ detect: () => existsSync(join(HOME, ".gemini", "antigravity")),
160
+ configType: "json",
161
+ configPath: join(HOME, ".gemini", "antigravity", "mcp_config.json"),
162
+ configKey: "mcpServers",
163
+ },
147
164
  {
148
165
  id: "cline",
149
166
  name: "Cline (VS Code)",
@@ -168,10 +185,11 @@ function showHelp() {
168
185
  ${dim("Persistent memory for AI agents")}
169
186
 
170
187
  ${bold("Usage:")}
171
- context-mcp <command> [options]
188
+ context-vault <command> [options]
172
189
 
173
190
  ${bold("Commands:")}
174
191
  ${cyan("setup")} Interactive MCP server installer
192
+ ${cyan("connect")} --key cv_... Connect AI tools to hosted vault
175
193
  ${cyan("serve")} Start the MCP server (used by AI clients)
176
194
  ${cyan("ui")} [--port 3141] Launch web dashboard
177
195
  ${cyan("reindex")} Rebuild search index from knowledge files
@@ -242,7 +260,7 @@ async function runSetup() {
242
260
  }
243
261
 
244
262
  let selected;
245
- console.log(bold(" Which tools should context-mcp connect to?\n"));
263
+ console.log(bold(" Which tools should context-vault connect to?\n"));
246
264
  for (let i = 0; i < detected.length; i++) {
247
265
  console.log(` ${i + 1}) ${detected[i].name}`);
248
266
  }
@@ -272,7 +290,9 @@ async function runSetup() {
272
290
  console.log(`\n ${dim("[2/2]")}${bold(" Configuring tools...\n")}`);
273
291
  for (const tool of selected) {
274
292
  try {
275
- if (tool.configType === "cli") {
293
+ if (tool.configType === "cli" && tool.id === "codex") {
294
+ await configureCodex(tool, customVaultDir);
295
+ } else if (tool.configType === "cli") {
276
296
  await configureClaude(tool, customVaultDir);
277
297
  } else {
278
298
  configureJsonTool(tool, customVaultDir);
@@ -314,8 +334,8 @@ async function runSetup() {
314
334
  if (isInstalledPackage()) {
315
335
  console.log(` ${dim("{")}
316
336
  ${dim('"mcpServers": {')}
317
- ${dim('"context-mcp": {')}
318
- ${dim('"command": "context-mcp",')}
337
+ ${dim('"context-vault": {')}
338
+ ${dim('"command": "context-vault",')}
319
339
  ${dim(`"args": ["serve", "--vault-dir", "/path/to/vault"]`)}
320
340
  ${dim("}")}
321
341
  ${dim("}")}
@@ -323,7 +343,7 @@ async function runSetup() {
323
343
  } else {
324
344
  console.log(` ${dim("{")}
325
345
  ${dim('"mcpServers": {')}
326
- ${dim('"context-mcp": {')}
346
+ ${dim('"context-vault": {')}
327
347
  ${dim('"command": "node",')}
328
348
  ${dim(`"args": ["${SERVER_PATH}", "--vault-dir", "/path/to/vault"]`)}
329
349
  ${dim("}")}
@@ -338,7 +358,7 @@ async function runSetup() {
338
358
  if (isNonInteractive) {
339
359
  selected = detected;
340
360
  } else {
341
- console.log(bold(" Which tools should context-mcp connect to?\n"));
361
+ console.log(bold(" Which tools should context-vault connect to?\n"));
342
362
  for (let i = 0; i < detected.length; i++) {
343
363
  console.log(` ${i + 1}) ${detected[i].name}`);
344
364
  }
@@ -405,15 +425,30 @@ async function runSetup() {
405
425
  writeFileSync(configPath, JSON.stringify(vaultConfig, null, 2) + "\n");
406
426
  console.log(`\n ${green("+")} Wrote ${configPath}`);
407
427
 
408
- // Pre-download embedding model
428
+ // Pre-download embedding model with spinner
409
429
  console.log(`\n ${dim("[3/5]")}${bold(" Downloading embedding model...")}`);
410
430
  console.log(dim(" all-MiniLM-L6-v2 (~22MB, one-time download)\n"));
411
- try {
412
- const { embed } = await import("@context-vault/core/index/embed");
413
- await embed("warmup");
414
- console.log(` ${green("+")} Embedding model ready`);
415
- } catch (e) {
416
- console.log(` ${yellow("!")} Model download failed — will retry on first use`);
431
+ {
432
+ const spinnerFrames = ["⠋", "⠙", "⠹", "", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
433
+ let frame = 0;
434
+ const start = Date.now();
435
+ const spinner = setInterval(() => {
436
+ const elapsed = ((Date.now() - start) / 1000).toFixed(0);
437
+ process.stdout.write(`\r ${spinnerFrames[frame++ % spinnerFrames.length]} Downloading... ${dim(`${elapsed}s`)}`);
438
+ }, 100);
439
+
440
+ try {
441
+ const { embed } = await import("@context-vault/core/index/embed");
442
+ await embed("warmup");
443
+
444
+ clearInterval(spinner);
445
+ process.stdout.write(`\r ${green("+")} Embedding model ready \n`);
446
+ } catch (e) {
447
+ clearInterval(spinner);
448
+ process.stdout.write(`\r ${yellow("!")} Model download failed: ${e.message} \n`);
449
+ console.log(dim(` Retry: context-vault setup`));
450
+ console.log(dim(` Semantic search disabled — full-text search still works.`));
451
+ }
417
452
  }
418
453
 
419
454
  // Clean up legacy project-root config.json if it exists
@@ -433,7 +468,9 @@ async function runSetup() {
433
468
 
434
469
  for (const tool of selected) {
435
470
  try {
436
- if (tool.configType === "cli") {
471
+ if (tool.configType === "cli" && tool.id === "codex") {
472
+ await configureCodex(tool, customVaultDir);
473
+ } else if (tool.configType === "cli") {
437
474
  await configureClaude(tool, customVaultDir);
438
475
  } else {
439
476
  configureJsonTool(tool, customVaultDir);
@@ -490,9 +527,9 @@ async function runSetup() {
490
527
  ` "Show my vault status"`,
491
528
  ``,
492
529
  ` ${bold("CLI Commands:")}`,
493
- ` context-mcp status Show vault health`,
494
- ` context-mcp ui Launch web dashboard`,
495
- ` context-mcp update Check for updates`,
530
+ ` context-vault status Show vault health`,
531
+ ` context-vault ui Launch web dashboard`,
532
+ ` context-vault update Check for updates`,
496
533
  ];
497
534
  const innerWidth = Math.max(...boxLines.map((l) => l.length)) + 2;
498
535
  const pad = (s) => s + " ".repeat(Math.max(0, innerWidth - s.length));
@@ -509,6 +546,7 @@ async function configureClaude(tool, vaultDir) {
509
546
  const env = { ...process.env };
510
547
  delete env.CLAUDECODE;
511
548
 
549
+ // Clean up old name
512
550
  try {
513
551
  execSync("claude mcp remove context-mcp -s user", { stdio: "pipe", env });
514
552
  } catch {}
@@ -517,20 +555,57 @@ async function configureClaude(tool, vaultDir) {
517
555
  execSync("claude mcp remove context-vault -s user", { stdio: "pipe", env });
518
556
  } catch {}
519
557
 
520
- if (isInstalledPackage()) {
521
- const cmdArgs = ["serve"];
522
- if (vaultDir) cmdArgs.push("--vault-dir", `"${vaultDir}"`);
523
- execSync(
524
- `claude mcp add -s user context-mcp -- context-mcp ${cmdArgs.join(" ")}`,
525
- { stdio: "pipe", env }
526
- );
527
- } else {
528
- const cmdArgs = [`"${SERVER_PATH}"`];
529
- if (vaultDir) cmdArgs.push("--vault-dir", `"${vaultDir}"`);
530
- execSync(
531
- `claude mcp add -s user context-mcp -- node ${cmdArgs.join(" ")}`,
532
- { stdio: "pipe", env }
533
- );
558
+ try {
559
+ if (isInstalledPackage()) {
560
+ const cmdArgs = ["serve"];
561
+ if (vaultDir) cmdArgs.push("--vault-dir", `"${vaultDir}"`);
562
+ execSync(
563
+ `claude mcp add -s user context-vault -- context-vault ${cmdArgs.join(" ")}`,
564
+ { stdio: "pipe", env }
565
+ );
566
+ } else {
567
+ const cmdArgs = [`"${SERVER_PATH}"`];
568
+ if (vaultDir) cmdArgs.push("--vault-dir", `"${vaultDir}"`);
569
+ execSync(
570
+ `claude mcp add -s user context-vault -- node ${cmdArgs.join(" ")}`,
571
+ { stdio: "pipe", env }
572
+ );
573
+ }
574
+ } catch (e) {
575
+ const stderr = e.stderr?.toString().trim();
576
+ throw new Error(stderr || e.message);
577
+ }
578
+ }
579
+
580
+ async function configureCodex(tool, vaultDir) {
581
+ // Clean up old name
582
+ try {
583
+ execSync("codex mcp remove context-mcp", { stdio: "pipe" });
584
+ } catch {}
585
+
586
+ try {
587
+ execSync("codex mcp remove context-vault", { stdio: "pipe" });
588
+ } catch {}
589
+
590
+ try {
591
+ if (isInstalledPackage()) {
592
+ const cmdArgs = ["serve"];
593
+ if (vaultDir) cmdArgs.push("--vault-dir", `"${vaultDir}"`);
594
+ execSync(
595
+ `codex mcp add context-vault -- context-vault ${cmdArgs.join(" ")}`,
596
+ { stdio: "pipe" }
597
+ );
598
+ } else {
599
+ const cmdArgs = [`"${SERVER_PATH}"`];
600
+ if (vaultDir) cmdArgs.push("--vault-dir", `"${vaultDir}"`);
601
+ execSync(
602
+ `codex mcp add context-vault -- node ${cmdArgs.join(" ")}`,
603
+ { stdio: "pipe" }
604
+ );
605
+ }
606
+ } catch (e) {
607
+ const stderr = e.stderr?.toString().trim();
608
+ throw new Error(stderr || e.message);
534
609
  }
535
610
  }
536
611
 
@@ -559,19 +634,20 @@ function configureJsonTool(tool, vaultDir) {
559
634
  config[tool.configKey] = {};
560
635
  }
561
636
 
562
- delete config[tool.configKey]["context-vault"];
637
+ // Clean up old "context-mcp" key
638
+ delete config[tool.configKey]["context-mcp"];
563
639
 
564
640
  if (isInstalledPackage()) {
565
641
  const serverArgs = ["serve"];
566
642
  if (vaultDir) serverArgs.push("--vault-dir", vaultDir);
567
- config[tool.configKey]["context-mcp"] = {
568
- command: "context-mcp",
643
+ config[tool.configKey]["context-vault"] = {
644
+ command: "context-vault",
569
645
  args: serverArgs,
570
646
  };
571
647
  } else {
572
648
  const serverArgs = [SERVER_PATH];
573
649
  if (vaultDir) serverArgs.push("--vault-dir", vaultDir);
574
- config[tool.configKey]["context-mcp"] = {
650
+ config[tool.configKey]["context-vault"] = {
575
651
  command: "node",
576
652
  args: serverArgs,
577
653
  };
@@ -595,7 +671,7 @@ function createSeedEntries(vaultDir) {
595
671
  writeFileSync(insightPath, `---
596
672
  id: ${id1}
597
673
  tags: ["getting-started", "vault"]
598
- source: context-mcp-setup
674
+ source: context-vault-setup
599
675
  created: ${now}
600
676
  ---
601
677
  Welcome to your context vault! This is a seed entry created during setup.
@@ -625,7 +701,7 @@ ${insightPath}
625
701
  writeFileSync(decisionPath, `---
626
702
  id: ${id2}
627
703
  tags: ["example", "architecture"]
628
- source: context-mcp-setup
704
+ source: context-vault-setup
629
705
  created: ${now}
630
706
  ---
631
707
  Example decision: Use local-first data storage (SQLite + files) over cloud databases.
@@ -647,18 +723,222 @@ This is an example entry showing the decision format. Feel free to delete it.
647
723
  return created;
648
724
  }
649
725
 
726
+ // ─── Connect Command ─────────────────────────────────────────────────────────
727
+
728
+ async function runConnect() {
729
+ const apiKey = getFlag("--key");
730
+ const hostedUrl = getFlag("--url") || "https://www.context-vault.com";
731
+
732
+ if (!apiKey) {
733
+ console.log(`\n ${bold("context-vault connect")}\n`);
734
+ console.log(` Connect your AI tools to a hosted Context Vault.\n`);
735
+ console.log(` Usage:`);
736
+ console.log(` context-vault connect --key cv_...\n`);
737
+ console.log(` Options:`);
738
+ console.log(` --key <key> API key (required)`);
739
+ console.log(` --url <url> Hosted server URL (default: https://www.context-vault.com)`);
740
+ console.log();
741
+ return;
742
+ }
743
+
744
+ console.log();
745
+ console.log(` ${bold("◇ context-vault")} ${dim("connect")}`);
746
+ console.log();
747
+
748
+ // Detect tools
749
+ console.log(dim(` [1/2]`) + bold(" Detecting tools...\n"));
750
+ const detected = [];
751
+ for (const tool of TOOLS) {
752
+ const found = tool.detect();
753
+ if (found) {
754
+ detected.push(tool);
755
+ console.log(` ${green("+")} ${tool.name}`);
756
+ } else {
757
+ console.log(` ${dim("-")} ${dim(tool.name)} ${dim("(not found)")}`);
758
+ }
759
+ }
760
+ console.log();
761
+
762
+ if (detected.length === 0) {
763
+ console.log(yellow(" No supported tools detected."));
764
+ console.log(`\n Add this to your tool's MCP config manually:\n`);
765
+ console.log(dim(` ${JSON.stringify({
766
+ mcpServers: {
767
+ "context-vault": {
768
+ url: `${hostedUrl}/mcp`,
769
+ headers: { Authorization: `Bearer ${apiKey}` },
770
+ },
771
+ },
772
+ }, null, 2).split("\n").join("\n ")}`));
773
+ console.log();
774
+ return;
775
+ }
776
+
777
+ // Select tools
778
+ let selected;
779
+ if (isNonInteractive) {
780
+ selected = detected;
781
+ } else {
782
+ console.log(bold(" Which tools should connect to your hosted vault?\n"));
783
+ for (let i = 0; i < detected.length; i++) {
784
+ console.log(` ${i + 1}) ${detected[i].name}`);
785
+ }
786
+ console.log();
787
+ const answer = await prompt(
788
+ ` Select (${dim("1,2,3")} or ${dim('"all"')}):`,
789
+ "all"
790
+ );
791
+ if (answer === "all" || answer === "") {
792
+ selected = detected;
793
+ } else {
794
+ const nums = answer.split(/[,\s]+/).map((n) => parseInt(n, 10) - 1).filter((n) => n >= 0 && n < detected.length);
795
+ selected = nums.map((n) => detected[n]);
796
+ if (selected.length === 0) selected = detected;
797
+ }
798
+ }
799
+
800
+ // Configure each tool with hosted MCP endpoint
801
+ console.log(`\n ${dim("[2/2]")}${bold(" Configuring tools...\n")}`);
802
+ for (const tool of selected) {
803
+ try {
804
+ if (tool.configType === "cli" && tool.id === "codex") {
805
+ configureCodexHosted(apiKey, hostedUrl);
806
+ } else if (tool.configType === "cli") {
807
+ configureClaudeHosted(apiKey, hostedUrl);
808
+ } else {
809
+ configureJsonToolHosted(tool, apiKey, hostedUrl);
810
+ }
811
+ console.log(` ${green("+")} ${tool.name} — configured`);
812
+ } catch (e) {
813
+ console.log(` ${red("x")} ${tool.name} — ${e.message}`);
814
+ }
815
+ }
816
+
817
+ console.log();
818
+ console.log(green(" ✓ Connected! Your AI tools can now access your hosted vault."));
819
+ console.log(dim(` Endpoint: ${hostedUrl}/mcp`));
820
+ console.log();
821
+ }
822
+
823
+ function configureClaudeHosted(apiKey, hostedUrl) {
824
+ const env = { ...process.env };
825
+ delete env.CLAUDECODE;
826
+
827
+ try { execSync("claude mcp remove context-mcp -s user", { stdio: "pipe", env }); } catch {}
828
+ try { execSync("claude mcp remove context-vault -s user", { stdio: "pipe", env }); } catch {}
829
+
830
+ try {
831
+ execSync(
832
+ `claude mcp add -s user --transport http context-vault ${hostedUrl}/mcp`,
833
+ { stdio: "pipe", env }
834
+ );
835
+ } catch (e) {
836
+ const stderr = e.stderr?.toString().trim();
837
+ throw new Error(stderr || e.message);
838
+ }
839
+ }
840
+
841
+ function configureCodexHosted(apiKey, hostedUrl) {
842
+ try { execSync("codex mcp remove context-mcp", { stdio: "pipe" }); } catch {}
843
+ try { execSync("codex mcp remove context-vault", { stdio: "pipe" }); } catch {}
844
+
845
+ try {
846
+ execSync(
847
+ `codex mcp add --transport http context-vault ${hostedUrl}/mcp`,
848
+ { stdio: "pipe" }
849
+ );
850
+ } catch (e) {
851
+ const stderr = e.stderr?.toString().trim();
852
+ throw new Error(stderr || e.message);
853
+ }
854
+ }
855
+
856
+ function configureJsonToolHosted(tool, apiKey, hostedUrl) {
857
+ const configPath = tool.configPath;
858
+ const configDir = dirname(configPath);
859
+
860
+ if (!existsSync(configDir)) {
861
+ mkdirSync(configDir, { recursive: true });
862
+ }
863
+
864
+ let config = {};
865
+ if (existsSync(configPath)) {
866
+ const raw = readFileSync(configPath, "utf-8");
867
+ try {
868
+ config = JSON.parse(raw);
869
+ } catch {
870
+ const bakPath = configPath + ".bak";
871
+ copyFileSync(configPath, bakPath);
872
+ config = {};
873
+ }
874
+ }
875
+
876
+ if (!config[tool.configKey]) {
877
+ config[tool.configKey] = {};
878
+ }
879
+
880
+ // Clean up old "context-mcp" key
881
+ delete config[tool.configKey]["context-mcp"];
882
+
883
+ config[tool.configKey]["context-vault"] = {
884
+ url: `${hostedUrl}/mcp`,
885
+ headers: {
886
+ Authorization: `Bearer ${apiKey}`,
887
+ },
888
+ };
889
+
890
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
891
+ }
892
+
650
893
  // ─── UI Command ──────────────────────────────────────────────────────────────
651
894
 
652
895
  function runUi() {
653
- const serveScript = resolve(ROOT, "ui", "serve.js");
654
- if (!existsSync(serveScript)) {
655
- console.error(red("Error: ui/serve.js not found."));
896
+ const appDist = resolve(ROOT, "..", "app", "dist");
897
+ if (!existsSync(appDist) || !existsSync(join(appDist, "index.html"))) {
898
+ console.error(red("Web dashboard not found."));
899
+ console.error(dim(" From repo: npm run build --workspace=packages/app"));
900
+ console.error(dim(" Then run: context-vault ui"));
901
+ process.exit(1);
902
+ }
903
+
904
+ const port = parseInt(getFlag("--port") || "3141", 10);
905
+ const localServer = join(ROOT, "scripts", "local-server.js");
906
+ if (!existsSync(localServer)) {
907
+ console.error(red("Local server not found."));
656
908
  process.exit(1);
657
909
  }
658
910
 
659
- const uiArgs = args.slice(1);
660
- const child = fork(serveScript, uiArgs, { stdio: "inherit" });
911
+ // Probe the port before forking
912
+ const probe = createNetServer();
913
+ probe.once("error", (e) => {
914
+ if (e.code === "EADDRINUSE") {
915
+ console.error(red(` Port ${port} is already in use.`));
916
+ console.error(` Try: ${cyan(`context-vault ui --port ${port + 1}`)}`);
917
+ process.exit(1);
918
+ }
919
+ // Other error — let the fork handle it
920
+ probe.close();
921
+ launchServer(port, localServer);
922
+ });
923
+ probe.listen(port, () => {
924
+ probe.close(() => {
925
+ launchServer(port, localServer);
926
+ });
927
+ });
928
+ }
929
+
930
+ function launchServer(port, localServer) {
931
+ const child = fork(localServer, [`--port=${port}`], { stdio: "inherit" });
661
932
  child.on("exit", (code) => process.exit(code ?? 0));
933
+
934
+ // Open browser after a short delay
935
+ setTimeout(() => {
936
+ try {
937
+ const url = `http://localhost:${port}`;
938
+ const open = PLATFORM === "darwin" ? "open" : PLATFORM === "win32" ? "start" : "xdg-open";
939
+ execSync(`${open} ${url}`, { stdio: "ignore" });
940
+ } catch {}
941
+ }, 1500);
662
942
  }
663
943
 
664
944
  // ─── Reindex Command ─────────────────────────────────────────────────────────
@@ -676,7 +956,7 @@ async function runReindex() {
676
956
  console.error(
677
957
  red(`Vault directory not found: ${config.vaultDir}`)
678
958
  );
679
- console.error("Run " + cyan("context-mcp setup") + " to configure.");
959
+ console.error("Run " + cyan("context-vault setup") + " to configure.");
680
960
  process.exit(1);
681
961
  }
682
962
 
@@ -764,7 +1044,7 @@ async function runStatus() {
764
1044
  if (status.stalePaths) {
765
1045
  console.log();
766
1046
  console.log(yellow(" Stale paths detected in DB."));
767
- console.log(` Run ${cyan("context-mcp reindex")} to update.`);
1047
+ console.log(` Run ${cyan("context-vault reindex")} to update.`);
768
1048
  }
769
1049
  console.log();
770
1050
  }
@@ -820,23 +1100,36 @@ async function runUninstall() {
820
1100
  console.log(` ${bold("◇ context-vault")} ${dim("uninstall")}`);
821
1101
  console.log();
822
1102
 
823
- // Remove from Claude Code
1103
+ // Remove from Claude Code (both old and new names)
824
1104
  try {
825
1105
  const env = { ...process.env };
826
1106
  delete env.CLAUDECODE;
827
- execSync("claude mcp remove context-mcp -s user", { stdio: "pipe", env });
1107
+ try { execSync("claude mcp remove context-mcp -s user", { stdio: "pipe", env }); } catch {}
1108
+ execSync("claude mcp remove context-vault -s user", { stdio: "pipe", env });
828
1109
  console.log(` ${green("+")} Removed from Claude Code`);
829
1110
  } catch {
830
1111
  console.log(` ${dim("-")} Claude Code — not configured or not installed`);
831
1112
  }
832
1113
 
833
- // Remove from JSON-configured tools
1114
+ // Remove from Codex (both old and new names)
1115
+ try {
1116
+ try { execSync("codex mcp remove context-mcp", { stdio: "pipe" }); } catch {}
1117
+ execSync("codex mcp remove context-vault", { stdio: "pipe" });
1118
+ console.log(` ${green("+")} Removed from Codex`);
1119
+ } catch {
1120
+ console.log(` ${dim("-")} Codex — not configured or not installed`);
1121
+ }
1122
+
1123
+ // Remove from JSON-configured tools (both old and new keys)
834
1124
  for (const tool of TOOLS.filter((t) => t.configType === "json")) {
835
1125
  if (!existsSync(tool.configPath)) continue;
836
1126
  try {
837
1127
  const config = JSON.parse(readFileSync(tool.configPath, "utf-8"));
838
- if (config[tool.configKey]?.["context-mcp"]) {
1128
+ const hadOld = !!config[tool.configKey]?.["context-mcp"];
1129
+ const hadNew = !!config[tool.configKey]?.["context-vault"];
1130
+ if (hadOld || hadNew) {
839
1131
  delete config[tool.configKey]["context-mcp"];
1132
+ delete config[tool.configKey]["context-vault"];
840
1133
  writeFileSync(tool.configPath, JSON.stringify(config, null, 2) + "\n");
841
1134
  console.log(` ${green("+")} Removed from ${tool.name}`);
842
1135
  }
@@ -875,10 +1168,10 @@ async function runMigrate() {
875
1168
  : null;
876
1169
 
877
1170
  if (!direction) {
878
- console.log(`\n ${bold("context-mcp migrate")}\n`);
1171
+ console.log(`\n ${bold("context-vault migrate")}\n`);
879
1172
  console.log(` Usage:`);
880
- console.log(` context-mcp migrate --to-hosted Upload local vault to hosted service`);
881
- console.log(` context-mcp migrate --to-local Download hosted vault to local files`);
1173
+ console.log(` context-vault migrate --to-hosted Upload local vault to hosted service`);
1174
+ console.log(` context-vault migrate --to-local Download hosted vault to local files`);
882
1175
  console.log(`\n Options:`);
883
1176
  console.log(` --url <url> Hosted server URL (default: https://vault.contextvault.dev)`);
884
1177
  console.log(` --key <key> API key (cv_...)`);
@@ -936,7 +1229,7 @@ async function runMigrate() {
936
1229
  if (results.failed > 0) {
937
1230
  console.log(` ${red("-")} ${results.failed} failed`);
938
1231
  }
939
- console.log(dim("\n Run `context-mcp reindex` to rebuild the search index."));
1232
+ console.log(dim("\n Run `context-vault reindex` to rebuild the search index."));
940
1233
  }
941
1234
  console.log();
942
1235
  }
@@ -964,6 +1257,9 @@ async function main() {
964
1257
  case "setup":
965
1258
  await runSetup();
966
1259
  break;
1260
+ case "connect":
1261
+ await runConnect();
1262
+ break;
967
1263
  case "serve":
968
1264
  await runServe();
969
1265
  break;
@@ -972,7 +1268,7 @@ async function main() {
972
1268
  break;
973
1269
  case "import":
974
1270
  case "export":
975
- console.log(`Import/export removed. Add .md files to vault/ and run \`context-mcp reindex\`.`);
1271
+ console.log(`Import/export removed. Add .md files to vault/ and run \`context-vault reindex\`.`);
976
1272
  break;
977
1273
  case "reindex":
978
1274
  await runReindex();
@@ -991,7 +1287,7 @@ async function main() {
991
1287
  break;
992
1288
  default:
993
1289
  console.error(red(`Unknown command: ${command}`));
994
- console.error(`Run ${cyan("context-mcp --help")} for usage.`);
1290
+ console.error(`Run ${cyan("context-vault --help")} for usage.`);
995
1291
  process.exit(1);
996
1292
  }
997
1293
  }