@memories.sh/cli 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +653 -359
  2. package/package.json +6 -1
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command21 } from "commander";
4
+ import { Command as Command22 } from "commander";
5
5
 
6
6
  // src/commands/init.ts
7
7
  import { Command } from "commander";
8
- import chalk from "chalk";
8
+ import chalk2 from "chalk";
9
9
 
10
10
  // src/lib/db.ts
11
11
  import { createClient } from "@libsql/client";
@@ -265,8 +265,8 @@ async function searchMemories(query, opts) {
265
265
  args: [ftsQuery, ...args]
266
266
  });
267
267
  return result.rows;
268
- } catch (error) {
269
- console.error("FTS search failed, falling back to LIKE:", error);
268
+ } catch (error2) {
269
+ console.error("FTS search failed, falling back to LIKE:", error2);
270
270
  return searchMemoriesLike(query, opts);
271
271
  }
272
272
  }
@@ -462,55 +462,181 @@ async function bulkForgetByIds(ids) {
462
462
  return ids.length;
463
463
  }
464
464
 
465
+ // src/lib/auth.ts
466
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, unlink } from "fs/promises";
467
+ import { existsSync as existsSync2 } from "fs";
468
+ import { join as join2 } from "path";
469
+ import { homedir as homedir2 } from "os";
470
+ var AUTH_DIR = join2(homedir2(), ".config", "memories");
471
+ var AUTH_FILE = join2(AUTH_DIR, "auth.json");
472
+ async function readAuth() {
473
+ if (!existsSync2(AUTH_FILE)) return null;
474
+ try {
475
+ const raw = await readFile2(AUTH_FILE, "utf-8");
476
+ return JSON.parse(raw);
477
+ } catch {
478
+ return null;
479
+ }
480
+ }
481
+ async function saveAuth(data) {
482
+ await mkdir2(AUTH_DIR, { recursive: true });
483
+ await writeFile2(AUTH_FILE, JSON.stringify(data, null, 2), {
484
+ encoding: "utf-8",
485
+ mode: 384
486
+ });
487
+ }
488
+ async function clearAuth() {
489
+ if (existsSync2(AUTH_FILE)) {
490
+ await unlink(AUTH_FILE);
491
+ }
492
+ }
493
+ function getApiClient(auth) {
494
+ return async function apiFetch(path, opts) {
495
+ const url = `${auth.apiUrl}${path}`;
496
+ return fetch(url, {
497
+ ...opts,
498
+ headers: {
499
+ ...opts?.headers,
500
+ Authorization: `Bearer ${auth.token}`,
501
+ "Content-Type": "application/json"
502
+ }
503
+ });
504
+ };
505
+ }
506
+
507
+ // src/lib/ui.ts
508
+ import chalk from "chalk";
509
+ import figlet from "figlet";
510
+ import gradient from "gradient-string";
511
+ import boxen from "boxen";
512
+ var memoriesGradient = gradient(["#a855f7", "#6366f1"]);
513
+ function banner() {
514
+ const text = figlet.textSync("memories", {
515
+ font: "Small",
516
+ horizontalLayout: "fitted"
517
+ });
518
+ console.log(memoriesGradient(text));
519
+ console.log(chalk.dim(" One memory, every AI tool\n"));
520
+ }
521
+ function success(message) {
522
+ console.log(chalk.green("\u2713") + " " + message);
523
+ }
524
+ function warn(message) {
525
+ console.log(chalk.yellow("\u26A0") + " " + message);
526
+ }
527
+ function error(message) {
528
+ console.log(chalk.red("\u2717") + " " + message);
529
+ }
530
+ function info(message) {
531
+ console.log(chalk.blue("\u2139") + " " + message);
532
+ }
533
+ function step(num, total, message) {
534
+ console.log(chalk.dim(`[${num}/${total}]`) + " " + message);
535
+ }
536
+ function dim(message) {
537
+ console.log(chalk.dim(" " + message));
538
+ }
539
+ function box(content, title) {
540
+ console.log(
541
+ boxen(content, {
542
+ padding: 1,
543
+ margin: { top: 1, bottom: 1, left: 0, right: 0 },
544
+ borderStyle: "round",
545
+ borderColor: "gray",
546
+ title,
547
+ titleAlignment: "left"
548
+ })
549
+ );
550
+ }
551
+ function nextSteps(steps) {
552
+ const content = steps.map((s) => chalk.dim("\u2192 ") + s).join("\n");
553
+ box(content, chalk.bold("Next steps"));
554
+ }
555
+ function proFeature(feature) {
556
+ console.log(
557
+ chalk.yellow("\u2B50") + " " + chalk.dim(`${feature} requires `) + chalk.bold("Pro") + chalk.dim(". Run ") + chalk.cyan("memories login") + chalk.dim(" to upgrade.")
558
+ );
559
+ }
560
+
465
561
  // src/commands/init.ts
466
562
  var initCommand = new Command("init").description("Initialize memories for the current project or globally").option("-g, --global", "Initialize global memories (user-wide)").option("-r, --rule <rule>", "Add an initial rule", (val, acc) => [...acc, val], []).action(async (opts) => {
467
563
  try {
564
+ banner();
565
+ step(1, 3, "Initializing database...");
468
566
  await getDb();
469
567
  const configDir = getConfigDir();
470
- if (opts.global) {
471
- console.log(chalk.green("\u2713") + " Initialized global memories");
472
- console.log(chalk.dim(` Database: ${configDir}/local.db`));
473
- } else {
568
+ dim(`Database: ${configDir}/local.db`);
569
+ step(2, 3, "Detecting scope...");
570
+ let useGlobal = opts.global;
571
+ if (!useGlobal) {
474
572
  const projectId = getProjectId();
475
573
  const gitRoot = getGitRoot();
476
574
  if (!projectId) {
477
- console.log(chalk.yellow("\u26A0") + " Not in a git repository.");
478
- console.log(chalk.dim(" Run from a git repo for project-scoped memories, or use --global"));
479
- return;
575
+ warn("Not in a git repository - using global scope");
576
+ dim("Global memories apply to all projects");
577
+ useGlobal = true;
578
+ } else {
579
+ success("Using project scope");
580
+ dim(`Project: ${projectId}`);
581
+ dim(`Root: ${gitRoot}`);
480
582
  }
481
- console.log(chalk.green("\u2713") + " Initialized project memories");
482
- console.log(chalk.dim(` Project: ${projectId}`));
483
- console.log(chalk.dim(` Root: ${gitRoot}`));
484
- console.log(chalk.dim(` Database: ${configDir}/local.db`));
583
+ }
584
+ if (useGlobal) {
585
+ success("Using global scope (applies to all projects)");
586
+ }
587
+ step(3, 3, "Checking account...");
588
+ const auth = await readAuth();
589
+ if (auth) {
590
+ success(`Logged in as ${chalk2.bold(auth.email)}`);
591
+ } else {
592
+ dim("Not logged in (local-only mode)");
593
+ dim("Run " + chalk2.cyan("memories login") + " for cloud sync");
485
594
  }
486
595
  if (opts.rule?.length) {
487
596
  console.log("");
488
- console.log(chalk.blue("Adding rules:"));
597
+ info("Adding initial rules...");
489
598
  for (const rule of opts.rule) {
490
599
  const memory = await addMemory(rule, {
491
600
  type: "rule",
492
- global: opts.global
601
+ global: useGlobal
493
602
  });
494
- console.log(chalk.dim(` ${memory.id}: ${rule}`));
603
+ dim(`${memory.id}: ${rule}`);
495
604
  }
496
605
  }
497
- console.log("");
498
- console.log(chalk.dim("Quick start:"));
499
- console.log(chalk.dim(` memories add "Your first memory"`));
500
- console.log(chalk.dim(` memories add --rule "Always use TypeScript strict mode"`));
501
- console.log(chalk.dim(` memories recall "what are my coding preferences"`));
502
- } catch (error) {
503
- console.error(chalk.red("\u2717") + " Failed to initialize:", error instanceof Error ? error.message : "Unknown error");
606
+ nextSteps([
607
+ `${chalk2.cyan("memories add")} ${chalk2.dim('"Your first memory"')}`,
608
+ `${chalk2.cyan("memories add --rule")} ${chalk2.dim('"Always use TypeScript"')}`,
609
+ `${chalk2.cyan("memories generate")} ${chalk2.dim("to create IDE rule files")}`,
610
+ `${chalk2.cyan("memories serve")} ${chalk2.dim("to start MCP server")}`
611
+ ]);
612
+ } catch (error2) {
613
+ error("Failed to initialize: " + (error2 instanceof Error ? error2.message : "Unknown error"));
504
614
  process.exit(1);
505
615
  }
506
616
  });
507
617
 
508
618
  // src/commands/add.ts
509
619
  import { Command as Command2 } from "commander";
510
- import chalk2 from "chalk";
620
+ import chalk3 from "chalk";
511
621
  var VALID_TYPES = ["rule", "decision", "fact", "note"];
512
622
  var addCommand = new Command2("add").description("Add a new memory").argument("<content>", "Memory content").option("-t, --tags <tags>", "Comma-separated tags").option("-g, --global", "Store as global memory (default: project-scoped if in git repo)").option("--type <type>", "Memory type: rule, decision, fact, note (default: note)").option("-r, --rule", "Shorthand for --type rule").option("-d, --decision", "Shorthand for --type decision").option("-f, --fact", "Shorthand for --type fact").action(async (content, opts) => {
513
623
  try {
624
+ const auth = await readAuth();
625
+ if (auth) {
626
+ try {
627
+ const apiFetch = getApiClient(auth);
628
+ const res = await apiFetch("/api/db/limits");
629
+ if (res.ok) {
630
+ const limits = await res.json();
631
+ if (limits.memoryLimit !== null && limits.memoryCount >= limits.memoryLimit) {
632
+ warn(`You've reached the free plan limit of ${limits.memoryLimit.toLocaleString()} memories.`);
633
+ proFeature("Unlimited memories");
634
+ process.exit(1);
635
+ }
636
+ }
637
+ } catch {
638
+ }
639
+ }
514
640
  const tags = opts.tags?.split(",").map((t) => t.trim());
515
641
  let type = "note";
516
642
  if (opts.rule) type = "rule";
@@ -518,24 +644,29 @@ var addCommand = new Command2("add").description("Add a new memory").argument("<
518
644
  else if (opts.fact) type = "fact";
519
645
  else if (opts.type) {
520
646
  if (!VALID_TYPES.includes(opts.type)) {
521
- console.error(chalk2.red("\u2717") + ` Invalid type "${opts.type}". Valid types: ${VALID_TYPES.join(", ")}`);
647
+ console.error(chalk3.red("\u2717") + ` Invalid type "${opts.type}". Valid types: ${VALID_TYPES.join(", ")}`);
522
648
  process.exit(1);
523
649
  }
524
650
  type = opts.type;
525
651
  }
526
652
  const memory = await addMemory(content, { tags, global: opts.global, type });
527
- const typeIcon = type === "rule" ? "\u{1F4CC}" : type === "decision" ? "\u{1F4A1}" : type === "fact" ? "\u{1F4CB}" : "\u{1F4DD}";
528
- const scopeInfo = memory.scope === "global" ? chalk2.dim("(global)") : chalk2.dim(`(project)`);
529
- console.log(chalk2.green("\u2713") + ` ${typeIcon} Stored ${type} ${chalk2.dim(memory.id)} ${scopeInfo}`);
530
- } catch (error) {
531
- console.error(chalk2.red("\u2717") + " Failed to add memory:", error instanceof Error ? error.message : "Unknown error");
653
+ const typeLabel = type === "rule" ? "Rule" : type === "decision" ? "Decision" : type === "fact" ? "Fact" : "Note";
654
+ const scopeInfo = memory.scope === "global" ? "global" : "project";
655
+ success(`Stored ${chalk3.bold(typeLabel.toLowerCase())} ${chalk3.dim(memory.id)}`);
656
+ dim(`Scope: ${scopeInfo}${tags?.length ? ` \u2022 Tags: ${tags.join(", ")}` : ""}`);
657
+ if (type === "rule") {
658
+ console.log("");
659
+ dim(`Run ${chalk3.cyan("memories generate")} to update your IDE rule files`);
660
+ }
661
+ } catch (error2) {
662
+ error("Failed to add memory: " + (error2 instanceof Error ? error2.message : "Unknown error"));
532
663
  process.exit(1);
533
664
  }
534
665
  });
535
666
 
536
667
  // src/commands/recall.ts
537
668
  import { Command as Command3 } from "commander";
538
- import chalk3 from "chalk";
669
+ import chalk4 from "chalk";
539
670
  var TYPE_ICONS = {
540
671
  rule: "\u{1F4CC}",
541
672
  decision: "\u{1F4A1}",
@@ -543,18 +674,18 @@ var TYPE_ICONS = {
543
674
  note: "\u{1F4DD}"
544
675
  };
545
676
  var TYPE_COLORS = {
546
- rule: chalk3.yellow,
547
- decision: chalk3.cyan,
548
- fact: chalk3.green,
549
- note: chalk3.white
677
+ rule: chalk4.yellow,
678
+ decision: chalk4.cyan,
679
+ fact: chalk4.green,
680
+ note: chalk4.white
550
681
  };
551
682
  function formatMemory(m, verbose) {
552
683
  const icon = TYPE_ICONS[m.type] || "\u{1F4DD}";
553
- const colorFn = TYPE_COLORS[m.type] || chalk3.white;
554
- const scope = m.scope === "global" ? chalk3.dim("G") : chalk3.dim("P");
555
- const tags = m.tags ? chalk3.dim(` [${m.tags}]`) : "";
684
+ const colorFn = TYPE_COLORS[m.type] || chalk4.white;
685
+ const scope = m.scope === "global" ? chalk4.dim("G") : chalk4.dim("P");
686
+ const tags = m.tags ? chalk4.dim(` [${m.tags}]`) : "";
556
687
  if (verbose) {
557
- return `${icon} ${scope} ${chalk3.dim(m.id)} ${colorFn(m.content)}${tags}`;
688
+ return `${icon} ${scope} ${chalk4.dim(m.id)} ${colorFn(m.content)}${tags}`;
558
689
  }
559
690
  return `${icon} ${colorFn(m.content)}`;
560
691
  }
@@ -568,11 +699,11 @@ var recallCommand = new Command3("recall").description("Recall context - get rul
568
699
  return;
569
700
  }
570
701
  if (rules2.length === 0) {
571
- console.log(chalk3.dim("No rules defined."));
572
- console.log(chalk3.dim('Add one with: memories add --rule "Your rule here"'));
702
+ console.log(chalk4.dim("No rules defined."));
703
+ console.log(chalk4.dim('Add one with: memories add --rule "Your rule here"'));
573
704
  return;
574
705
  }
575
- console.log(chalk3.bold("Rules:"));
706
+ console.log(chalk4.bold("Rules:"));
576
707
  for (const rule of rules2) {
577
708
  console.log(formatMemory(rule, opts.verbose ?? false));
578
709
  }
@@ -587,26 +718,26 @@ var recallCommand = new Command3("recall").description("Recall context - get rul
587
718
  return;
588
719
  }
589
720
  if (rules.length > 0) {
590
- console.log(chalk3.bold("Rules:"));
721
+ console.log(chalk4.bold("Rules:"));
591
722
  for (const rule of rules) {
592
723
  console.log(formatMemory(rule, opts.verbose ?? false));
593
724
  }
594
725
  console.log("");
595
726
  }
596
727
  if (memories.length > 0) {
597
- console.log(chalk3.bold(query ? `Relevant to "${query}":` : "Recent memories:"));
728
+ console.log(chalk4.bold(query ? `Relevant to "${query}":` : "Recent memories:"));
598
729
  for (const m of memories) {
599
730
  console.log(formatMemory(m, opts.verbose ?? false));
600
731
  }
601
732
  } else if (query) {
602
- console.log(chalk3.dim(`No memories found matching "${query}"`));
733
+ console.log(chalk4.dim(`No memories found matching "${query}"`));
603
734
  }
604
735
  if (rules.length === 0 && memories.length === 0) {
605
- console.log(chalk3.dim("No memories found."));
606
- console.log(chalk3.dim('Add some with: memories add "Your memory here"'));
736
+ console.log(chalk4.dim("No memories found."));
737
+ console.log(chalk4.dim('Add some with: memories add "Your memory here"'));
607
738
  }
608
- } catch (error) {
609
- console.error(chalk3.red("\u2717") + " Failed to recall:", error instanceof Error ? error.message : "Unknown error");
739
+ } catch (error2) {
740
+ console.error(chalk4.red("\u2717") + " Failed to recall:", error2 instanceof Error ? error2.message : "Unknown error");
610
741
  process.exit(1);
611
742
  }
612
743
  });
@@ -614,7 +745,7 @@ var recallCommand = new Command3("recall").description("Recall context - get rul
614
745
  // src/commands/prompt.ts
615
746
  import { Command as Command4 } from "commander";
616
747
  import { execFileSync } from "child_process";
617
- import chalk4 from "chalk";
748
+ import chalk5 from "chalk";
618
749
  var VALID_TYPES2 = ["rule", "decision", "fact", "note"];
619
750
  function formatMarkdown(sections) {
620
751
  return sections.map(({ title, memories }) => {
@@ -657,7 +788,7 @@ var promptCommand = new Command4("prompt").description("Output memories formatte
657
788
  try {
658
789
  const format = opts.format ?? "markdown";
659
790
  if (!["markdown", "xml", "plain"].includes(format)) {
660
- console.error(chalk4.red("\u2717") + ` Invalid format "${opts.format}". Use: markdown, xml, plain`);
791
+ console.error(chalk5.red("\u2717") + ` Invalid format "${opts.format}". Use: markdown, xml, plain`);
661
792
  process.exit(1);
662
793
  }
663
794
  const projectId = getProjectId() ?? void 0;
@@ -669,7 +800,7 @@ var promptCommand = new Command4("prompt").description("Output memories formatte
669
800
  for (const t of opts.include.split(",").map((s) => s.trim())) {
670
801
  const normalized = t.replace(/s$/, "");
671
802
  if (!VALID_TYPES2.includes(normalized)) {
672
- console.error(chalk4.red("\u2717") + ` Invalid type "${t}". Valid: decisions, facts, notes`);
803
+ console.error(chalk5.red("\u2717") + ` Invalid type "${t}". Valid: decisions, facts, notes`);
673
804
  process.exit(1);
674
805
  }
675
806
  if (normalized !== "rule") extraTypes.push(normalized);
@@ -698,7 +829,7 @@ var promptCommand = new Command4("prompt").description("Output memories formatte
698
829
  }
699
830
  if (sections.length === 0) {
700
831
  if (!opts.quiet) {
701
- console.error(chalk4.dim('No memories found. Add rules with: memories add --rule "Your rule"'));
832
+ console.error(chalk5.dim('No memories found. Add rules with: memories add --rule "Your rule"'));
702
833
  }
703
834
  return;
704
835
  }
@@ -718,26 +849,26 @@ var promptCommand = new Command4("prompt").description("Output memories formatte
718
849
  if (copied) {
719
850
  console.log(output);
720
851
  if (!opts.quiet) {
721
- console.error(chalk4.green("\u2713") + " Copied to clipboard");
852
+ console.error(chalk5.green("\u2713") + " Copied to clipboard");
722
853
  }
723
854
  } else {
724
855
  console.log(output);
725
856
  if (!opts.quiet) {
726
- console.error(chalk4.yellow("\u26A0") + " Could not copy to clipboard (unsupported platform)");
857
+ console.error(chalk5.yellow("\u26A0") + " Could not copy to clipboard (unsupported platform)");
727
858
  }
728
859
  }
729
860
  } else {
730
861
  console.log(output);
731
862
  }
732
- } catch (error) {
733
- console.error(chalk4.red("\u2717") + " Failed to generate prompt:", error instanceof Error ? error.message : "Unknown error");
863
+ } catch (error2) {
864
+ console.error(chalk5.red("\u2717") + " Failed to generate prompt:", error2 instanceof Error ? error2.message : "Unknown error");
734
865
  process.exit(1);
735
866
  }
736
867
  });
737
868
 
738
869
  // src/commands/search.ts
739
870
  import { Command as Command5 } from "commander";
740
- import chalk5 from "chalk";
871
+ import chalk6 from "chalk";
741
872
  var TYPE_ICONS2 = {
742
873
  rule: "\u{1F4CC}",
743
874
  decision: "\u{1F4A1}",
@@ -747,16 +878,16 @@ var TYPE_ICONS2 = {
747
878
  var VALID_TYPES3 = ["rule", "decision", "fact", "note"];
748
879
  function formatMemory2(m) {
749
880
  const icon = TYPE_ICONS2[m.type] || "\u{1F4DD}";
750
- const scope = m.scope === "global" ? chalk5.dim("G") : chalk5.dim("P");
751
- const tags = m.tags ? chalk5.dim(` [${m.tags}]`) : "";
752
- return `${icon} ${scope} ${chalk5.dim(m.id)} ${m.content}${tags}`;
881
+ const scope = m.scope === "global" ? chalk6.dim("G") : chalk6.dim("P");
882
+ const tags = m.tags ? chalk6.dim(` [${m.tags}]`) : "";
883
+ return `${icon} ${scope} ${chalk6.dim(m.id)} ${m.content}${tags}`;
753
884
  }
754
885
  var searchCommand = new Command5("search").description("Search memories using full-text search").argument("<query>", "Search query").option("-l, --limit <n>", "Max results", "20").option("--type <type>", "Filter by type: rule, decision, fact, note").option("-g, --global", "Search only global memories").option("--project-only", "Search only project memories (exclude global)").option("--json", "Output as JSON").action(async (query, opts) => {
755
886
  try {
756
887
  let types;
757
888
  if (opts.type) {
758
889
  if (!VALID_TYPES3.includes(opts.type)) {
759
- console.error(chalk5.red("\u2717") + ` Invalid type "${opts.type}". Valid types: ${VALID_TYPES3.join(", ")}`);
890
+ console.error(chalk6.red("\u2717") + ` Invalid type "${opts.type}". Valid types: ${VALID_TYPES3.join(", ")}`);
760
891
  process.exit(1);
761
892
  }
762
893
  types = [opts.type];
@@ -770,7 +901,7 @@ var searchCommand = new Command5("search").description("Search memories using fu
770
901
  includeGlobal = false;
771
902
  projectId = getProjectId() ?? void 0;
772
903
  if (!projectId) {
773
- console.log(chalk5.yellow("\u26A0") + " Not in a git repository. No project memories to search.");
904
+ console.log(chalk6.yellow("\u26A0") + " Not in a git repository. No project memories to search.");
774
905
  return;
775
906
  }
776
907
  }
@@ -786,30 +917,30 @@ var searchCommand = new Command5("search").description("Search memories using fu
786
917
  return;
787
918
  }
788
919
  if (memories.length === 0) {
789
- console.log(chalk5.dim(`No memories found matching "${query}"`));
920
+ console.log(chalk6.dim(`No memories found matching "${query}"`));
790
921
  return;
791
922
  }
792
- console.log(chalk5.bold(`Results for "${query}":`));
923
+ console.log(chalk6.bold(`Results for "${query}":`));
793
924
  console.log("");
794
925
  for (const m of memories) {
795
926
  console.log(formatMemory2(m));
796
927
  }
797
- console.log(chalk5.dim(`
928
+ console.log(chalk6.dim(`
798
929
  ${memories.length} results`));
799
- } catch (error) {
800
- console.error(chalk5.red("\u2717") + " Failed to search:", error instanceof Error ? error.message : "Unknown error");
930
+ } catch (error2) {
931
+ console.error(chalk6.red("\u2717") + " Failed to search:", error2 instanceof Error ? error2.message : "Unknown error");
801
932
  process.exit(1);
802
933
  }
803
934
  });
804
935
 
805
936
  // src/commands/list.ts
806
937
  import { Command as Command6 } from "commander";
807
- import chalk6 from "chalk";
938
+ import chalk7 from "chalk";
808
939
  var TYPE_COLORS2 = {
809
- rule: chalk6.blue,
810
- decision: chalk6.yellow,
811
- fact: chalk6.green,
812
- note: chalk6.dim
940
+ rule: chalk7.blue,
941
+ decision: chalk7.yellow,
942
+ fact: chalk7.green,
943
+ note: chalk7.dim
813
944
  };
814
945
  var TYPE_LABELS = {
815
946
  rule: "rule",
@@ -824,12 +955,12 @@ function truncate(str, max) {
824
955
  return str.slice(0, max - 1) + "\u2026";
825
956
  }
826
957
  function formatMemory3(m) {
827
- const typeColor = TYPE_COLORS2[m.type] ?? chalk6.dim;
958
+ const typeColor = TYPE_COLORS2[m.type] ?? chalk7.dim;
828
959
  const typeLabel = typeColor(TYPE_LABELS[m.type].padEnd(9));
829
- const scope = m.scope === "global" ? chalk6.magenta("G") : chalk6.cyan("P");
830
- const id = chalk6.dim(m.id);
960
+ const scope = m.scope === "global" ? chalk7.magenta("G") : chalk7.cyan("P");
961
+ const id = chalk7.dim(m.id);
831
962
  const content = truncate(m.content, MAX_CONTENT_WIDTH);
832
- const tags = m.tags ? chalk6.dim(` [${m.tags}]`) : "";
963
+ const tags = m.tags ? chalk7.dim(` [${m.tags}]`) : "";
833
964
  return ` ${scope} ${typeLabel} ${id} ${content}${tags}`;
834
965
  }
835
966
  var listCommand = new Command6("list").description("List memories").option("-l, --limit <n>", "Max results", "50").option("-t, --tags <tags>", "Filter by comma-separated tags").option("--type <type>", "Filter by type: rule, decision, fact, note").option("-g, --global", "Show only global memories").option("--project-only", "Show only project memories (exclude global)").option("--json", "Output as JSON").action(async (opts) => {
@@ -838,7 +969,7 @@ var listCommand = new Command6("list").description("List memories").option("-l,
838
969
  let types;
839
970
  if (opts.type) {
840
971
  if (!VALID_TYPES4.includes(opts.type)) {
841
- console.error(chalk6.red("\u2717") + ` Invalid type "${opts.type}". Valid types: ${VALID_TYPES4.join(", ")}`);
972
+ console.error(chalk7.red("\u2717") + ` Invalid type "${opts.type}". Valid types: ${VALID_TYPES4.join(", ")}`);
842
973
  process.exit(1);
843
974
  }
844
975
  types = [opts.type];
@@ -852,7 +983,7 @@ var listCommand = new Command6("list").description("List memories").option("-l,
852
983
  includeGlobal = false;
853
984
  projectId = getProjectId() ?? void 0;
854
985
  if (!projectId) {
855
- console.log(chalk6.yellow("\u26A0") + " Not in a git repository. No project memories to show.");
986
+ console.log(chalk7.yellow("\u26A0") + " Not in a git repository. No project memories to show.");
856
987
  return;
857
988
  }
858
989
  }
@@ -869,21 +1000,21 @@ var listCommand = new Command6("list").description("List memories").option("-l,
869
1000
  return;
870
1001
  }
871
1002
  if (memories.length === 0) {
872
- console.log(chalk6.dim("No memories found."));
1003
+ console.log(chalk7.dim("No memories found."));
873
1004
  return;
874
1005
  }
875
1006
  const currentProject = getProjectId();
876
1007
  if (currentProject && !opts.global) {
877
- console.log(chalk6.dim(` Project: ${currentProject}
1008
+ console.log(chalk7.dim(` Project: ${currentProject}
878
1009
  `));
879
1010
  }
880
1011
  for (const m of memories) {
881
1012
  console.log(formatMemory3(m));
882
1013
  }
883
- console.log(chalk6.dim(`
1014
+ console.log(chalk7.dim(`
884
1015
  ${memories.length} memories`));
885
- } catch (error) {
886
- console.error(chalk6.red("\u2717") + " Failed to list memories:", error instanceof Error ? error.message : "Unknown error");
1016
+ } catch (error2) {
1017
+ console.error(chalk7.red("\u2717") + " Failed to list memories:", error2 instanceof Error ? error2.message : "Unknown error");
887
1018
  process.exit(1);
888
1019
  }
889
1020
  });
@@ -891,7 +1022,7 @@ var listCommand = new Command6("list").description("List memories").option("-l,
891
1022
  // src/commands/forget.ts
892
1023
  import { Command as Command7 } from "commander";
893
1024
  import { createInterface } from "readline";
894
- import chalk7 from "chalk";
1025
+ import chalk8 from "chalk";
895
1026
  var VALID_TYPES5 = ["rule", "decision", "fact", "note"];
896
1027
  var TYPE_ICONS3 = {
897
1028
  rule: "\u{1F4CC}",
@@ -913,28 +1044,28 @@ var forgetCommand = new Command7("forget").description("Soft-delete memories by
913
1044
  if (id) {
914
1045
  const deleted = await forgetMemory(id);
915
1046
  if (deleted) {
916
- console.log(chalk7.green("\u2713") + ` Forgot memory ${chalk7.dim(id)}`);
1047
+ console.log(chalk8.green("\u2713") + ` Forgot memory ${chalk8.dim(id)}`);
917
1048
  } else {
918
- console.error(chalk7.red("\u2717") + ` Memory ${id} not found or already forgotten.`);
1049
+ console.error(chalk8.red("\u2717") + ` Memory ${id} not found or already forgotten.`);
919
1050
  process.exit(1);
920
1051
  }
921
1052
  return;
922
1053
  }
923
1054
  const hasBulkFilter = opts.type || opts.tag || opts.olderThan || opts.pattern || opts.all;
924
1055
  if (!hasBulkFilter) {
925
- console.error(chalk7.red("\u2717") + " Provide a memory ID or a bulk filter (--type, --tag, --older-than, --pattern, --all)");
1056
+ console.error(chalk8.red("\u2717") + " Provide a memory ID or a bulk filter (--type, --tag, --older-than, --pattern, --all)");
926
1057
  process.exit(1);
927
1058
  }
928
1059
  if (opts.all && (opts.type || opts.tag || opts.olderThan || opts.pattern)) {
929
- console.error(chalk7.red("\u2717") + " --all cannot be combined with other filters. Use --all alone to delete everything.");
1060
+ console.error(chalk8.red("\u2717") + " --all cannot be combined with other filters. Use --all alone to delete everything.");
930
1061
  process.exit(1);
931
1062
  }
932
1063
  if (opts.type && !VALID_TYPES5.includes(opts.type)) {
933
- console.error(chalk7.red("\u2717") + ` Invalid type "${opts.type}". Valid: ${VALID_TYPES5.join(", ")}`);
1064
+ console.error(chalk8.red("\u2717") + ` Invalid type "${opts.type}". Valid: ${VALID_TYPES5.join(", ")}`);
934
1065
  process.exit(1);
935
1066
  }
936
1067
  if (opts.olderThan && (isNaN(parseInt(opts.olderThan, 10)) || parseInt(opts.olderThan, 10) <= 0)) {
937
- console.error(chalk7.red("\u2717") + " --older-than must be a positive number of days");
1068
+ console.error(chalk8.red("\u2717") + " --older-than must be a positive number of days");
938
1069
  process.exit(1);
939
1070
  }
940
1071
  const filter = {
@@ -947,27 +1078,27 @@ var forgetCommand = new Command7("forget").description("Soft-delete memories by
947
1078
  };
948
1079
  const matches = await findMemoriesToForget(filter);
949
1080
  if (matches.length === 0) {
950
- console.log(chalk7.dim("No memories match the filter."));
1081
+ console.log(chalk8.dim("No memories match the filter."));
951
1082
  return;
952
1083
  }
953
- console.log(chalk7.bold(`${matches.length} memories will be forgotten:
1084
+ console.log(chalk8.bold(`${matches.length} memories will be forgotten:
954
1085
  `));
955
1086
  for (const m of matches.slice(0, 30)) {
956
1087
  const icon = TYPE_ICONS3[m.type] || "\u{1F4DD}";
957
- const scope = m.scope === "global" ? chalk7.dim("G") : chalk7.dim("P");
958
- console.log(` ${icon} ${scope} ${chalk7.dim(m.id)} ${m.content}`);
1088
+ const scope = m.scope === "global" ? chalk8.dim("G") : chalk8.dim("P");
1089
+ console.log(` ${icon} ${scope} ${chalk8.dim(m.id)} ${m.content}`);
959
1090
  }
960
1091
  if (matches.length > 30) {
961
- console.log(chalk7.dim(` ... and ${matches.length - 30} more`));
1092
+ console.log(chalk8.dim(` ... and ${matches.length - 30} more`));
962
1093
  }
963
1094
  console.log("");
964
1095
  if (opts.dryRun) {
965
- console.log(chalk7.yellow("Dry run") + " \u2014 no memories were deleted.");
1096
+ console.log(chalk8.yellow("Dry run") + " \u2014 no memories were deleted.");
966
1097
  return;
967
1098
  }
968
1099
  if (!opts.force) {
969
1100
  const proceed = await confirm(
970
- chalk7.yellow(`Forget ${matches.length} memories? This is a soft-delete. [y/N] `)
1101
+ chalk8.yellow(`Forget ${matches.length} memories? This is a soft-delete. [y/N] `)
971
1102
  );
972
1103
  if (!proceed) {
973
1104
  console.log("Cancelled.");
@@ -976,17 +1107,17 @@ var forgetCommand = new Command7("forget").description("Soft-delete memories by
976
1107
  }
977
1108
  const ids = matches.map((m) => m.id);
978
1109
  const count = await bulkForgetByIds(ids);
979
- console.log(chalk7.green("\u2713") + ` Forgot ${count} memories.`);
980
- } catch (error) {
981
- console.error(chalk7.red("\u2717") + " Failed to forget:", error instanceof Error ? error.message : "Unknown error");
1110
+ console.log(chalk8.green("\u2713") + ` Forgot ${count} memories.`);
1111
+ } catch (error2) {
1112
+ console.error(chalk8.red("\u2717") + " Failed to forget:", error2 instanceof Error ? error2.message : "Unknown error");
982
1113
  process.exit(1);
983
1114
  }
984
1115
  });
985
1116
 
986
1117
  // src/commands/export.ts
987
1118
  import { Command as Command8 } from "commander";
988
- import chalk8 from "chalk";
989
- import { writeFile as writeFile2 } from "fs/promises";
1119
+ import chalk9 from "chalk";
1120
+ import { writeFile as writeFile3 } from "fs/promises";
990
1121
  var exportCommand = new Command8("export").description("Export memories to JSON or YAML file").option("-o, --output <file>", "Output file path (default: stdout)").option("-f, --format <format>", "Output format: json, yaml (default: json)", "json").option("-g, --global", "Export only global memories").option("--project-only", "Export only project memories").option("--type <type>", "Filter by type: rule, decision, fact, note").action(async (opts) => {
991
1122
  try {
992
1123
  const projectId = getProjectId();
@@ -999,7 +1130,7 @@ var exportCommand = new Command8("export").description("Export memories to JSON
999
1130
  includeGlobal = false;
1000
1131
  queryProjectId = projectId ?? void 0;
1001
1132
  if (!queryProjectId) {
1002
- console.error(chalk8.red("\u2717") + " Not in a git repository. No project memories to export.");
1133
+ console.error(chalk9.red("\u2717") + " Not in a git repository. No project memories to export.");
1003
1134
  process.exit(1);
1004
1135
  }
1005
1136
  }
@@ -1033,24 +1164,24 @@ var exportCommand = new Command8("export").description("Export memories to JSON
1033
1164
  output = JSON.stringify(exportData, null, 2);
1034
1165
  }
1035
1166
  if (opts.output) {
1036
- await writeFile2(opts.output, output, "utf-8");
1037
- console.log(chalk8.green("\u2713") + ` Exported ${memories.length} memories to ${chalk8.dim(opts.output)}`);
1167
+ await writeFile3(opts.output, output, "utf-8");
1168
+ console.log(chalk9.green("\u2713") + ` Exported ${memories.length} memories to ${chalk9.dim(opts.output)}`);
1038
1169
  } else {
1039
1170
  console.log(output);
1040
1171
  }
1041
- } catch (error) {
1042
- console.error(chalk8.red("\u2717") + " Failed to export:", error instanceof Error ? error.message : "Unknown error");
1172
+ } catch (error2) {
1173
+ console.error(chalk9.red("\u2717") + " Failed to export:", error2 instanceof Error ? error2.message : "Unknown error");
1043
1174
  process.exit(1);
1044
1175
  }
1045
1176
  });
1046
1177
 
1047
1178
  // src/commands/import.ts
1048
1179
  import { Command as Command9 } from "commander";
1049
- import chalk9 from "chalk";
1050
- import { readFile as readFile2 } from "fs/promises";
1180
+ import chalk10 from "chalk";
1181
+ import { readFile as readFile3 } from "fs/promises";
1051
1182
  var importCommand = new Command9("import").description("Import memories from JSON or YAML file").argument("<file>", "Input file path").option("-f, --format <format>", "Input format: json, yaml (auto-detected from extension)").option("-g, --global", "Import all as global memories (override file scope)").option("--dry-run", "Show what would be imported without actually importing").action(async (file, opts) => {
1052
1183
  try {
1053
- const content = await readFile2(file, "utf-8");
1184
+ const content = await readFile3(file, "utf-8");
1054
1185
  let format = opts.format;
1055
1186
  if (!format) {
1056
1187
  if (file.endsWith(".yaml") || file.endsWith(".yml")) {
@@ -1067,7 +1198,7 @@ var importCommand = new Command9("import").description("Import memories from JSO
1067
1198
  data = JSON.parse(content);
1068
1199
  }
1069
1200
  if (!data || typeof data !== "object" || !("memories" in data) || !Array.isArray(data.memories)) {
1070
- console.error(chalk9.red("\u2717") + " Invalid import file: missing 'memories' array");
1201
+ console.error(chalk10.red("\u2717") + " Invalid import file: missing 'memories' array");
1071
1202
  process.exit(1);
1072
1203
  }
1073
1204
  const VALID_TYPES11 = ["rule", "decision", "fact", "note"];
@@ -1080,23 +1211,23 @@ var importCommand = new Command9("import").description("Import memories from JSO
1080
1211
  continue;
1081
1212
  }
1082
1213
  if (m.type && !VALID_TYPES11.includes(m.type)) {
1083
- console.error(chalk9.yellow("\u26A0") + ` Skipping memory with invalid type "${m.type}": ${m.content.slice(0, 50)}`);
1214
+ console.error(chalk10.yellow("\u26A0") + ` Skipping memory with invalid type "${m.type}": ${m.content.slice(0, 50)}`);
1084
1215
  skipped++;
1085
1216
  continue;
1086
1217
  }
1087
1218
  validMemories.push(m);
1088
1219
  }
1089
1220
  if (opts.dryRun) {
1090
- console.log(chalk9.blue("Dry run - would import:"));
1221
+ console.log(chalk10.blue("Dry run - would import:"));
1091
1222
  for (const m of validMemories) {
1092
1223
  const type = m.type || "note";
1093
1224
  const scope = opts.global ? "global" : m.scope || "project";
1094
1225
  const tags = m.tags?.length ? ` [${m.tags.join(", ")}]` : "";
1095
1226
  console.log(` ${type} (${scope}): ${m.content}${tags}`);
1096
1227
  }
1097
- console.log(chalk9.dim(`
1228
+ console.log(chalk10.dim(`
1098
1229
  ${validMemories.length} memories would be imported`));
1099
- if (skipped > 0) console.log(chalk9.dim(`${skipped} entries skipped (invalid)`));
1230
+ if (skipped > 0) console.log(chalk10.dim(`${skipped} entries skipped (invalid)`));
1100
1231
  return;
1101
1232
  }
1102
1233
  let imported = 0;
@@ -1109,20 +1240,20 @@ ${validMemories.length} memories would be imported`));
1109
1240
  global: opts.global || m.scope === "global"
1110
1241
  });
1111
1242
  imported++;
1112
- } catch (error) {
1113
- console.error(chalk9.yellow("\u26A0") + ` Failed to import: ${m.content.slice(0, 50)}...`);
1243
+ } catch (error2) {
1244
+ console.error(chalk10.yellow("\u26A0") + ` Failed to import: ${m.content.slice(0, 50)}...`);
1114
1245
  failed++;
1115
1246
  }
1116
1247
  }
1117
- console.log(chalk9.green("\u2713") + ` Imported ${imported} memories`);
1248
+ console.log(chalk10.green("\u2713") + ` Imported ${imported} memories`);
1118
1249
  if (failed > 0) {
1119
- console.log(chalk9.yellow("\u26A0") + ` ${failed} memories failed to import`);
1250
+ console.log(chalk10.yellow("\u26A0") + ` ${failed} memories failed to import`);
1120
1251
  }
1121
1252
  if (skipped > 0) {
1122
- console.log(chalk9.dim(`${skipped} entries skipped (invalid content or type)`));
1253
+ console.log(chalk10.dim(`${skipped} entries skipped (invalid content or type)`));
1123
1254
  }
1124
- } catch (error) {
1125
- console.error(chalk9.red("\u2717") + " Failed to import:", error instanceof Error ? error.message : "Unknown error");
1255
+ } catch (error2) {
1256
+ console.error(chalk10.red("\u2717") + " Failed to import:", error2 instanceof Error ? error2.message : "Unknown error");
1126
1257
  process.exit(1);
1127
1258
  }
1128
1259
  });
@@ -1131,17 +1262,17 @@ ${validMemories.length} memories would be imported`));
1131
1262
  import { Command as Command10 } from "commander";
1132
1263
 
1133
1264
  // src/lib/config.ts
1134
- import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir2 } from "fs/promises";
1135
- import { join as join2 } from "path";
1136
- import { existsSync as existsSync2 } from "fs";
1265
+ import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir3 } from "fs/promises";
1266
+ import { join as join3 } from "path";
1267
+ import { existsSync as existsSync3 } from "fs";
1137
1268
  import { parse, stringify } from "yaml";
1138
1269
  var AGENTS_DIR = ".agents";
1139
1270
  var CONFIG_FILE = "config.yaml";
1140
1271
  async function initConfig(dir) {
1141
- const agentsDir = join2(dir, AGENTS_DIR);
1142
- await mkdir2(agentsDir, { recursive: true });
1143
- const configPath = join2(agentsDir, CONFIG_FILE);
1144
- if (!existsSync2(configPath)) {
1272
+ const agentsDir = join3(dir, AGENTS_DIR);
1273
+ await mkdir3(agentsDir, { recursive: true });
1274
+ const configPath = join3(agentsDir, CONFIG_FILE);
1275
+ if (!existsSync3(configPath)) {
1145
1276
  const defaultConfig = {
1146
1277
  name: "my-project",
1147
1278
  description: "Agent memory configuration",
@@ -1151,14 +1282,14 @@ async function initConfig(dir) {
1151
1282
  store: "~/.config/memories/local.db"
1152
1283
  }
1153
1284
  };
1154
- await writeFile3(configPath, stringify(defaultConfig), "utf-8");
1285
+ await writeFile4(configPath, stringify(defaultConfig), "utf-8");
1155
1286
  }
1156
1287
  return configPath;
1157
1288
  }
1158
1289
  async function readConfig(dir) {
1159
- const configPath = join2(dir, AGENTS_DIR, CONFIG_FILE);
1160
- if (!existsSync2(configPath)) return null;
1161
- const raw = await readFile3(configPath, "utf-8");
1290
+ const configPath = join3(dir, AGENTS_DIR, CONFIG_FILE);
1291
+ if (!existsSync3(configPath)) return null;
1292
+ const raw = await readFile4(configPath, "utf-8");
1162
1293
  return parse(raw);
1163
1294
  }
1164
1295
 
@@ -1240,9 +1371,9 @@ ${projectRules.map((r) => `- ${r.content}`).join("\n")}`);
1240
1371
  return {
1241
1372
  contents: [{ uri: "memories://rules", mimeType: "text/markdown", text: parts.join("\n\n") }]
1242
1373
  };
1243
- } catch (error) {
1374
+ } catch (error2) {
1244
1375
  return {
1245
- contents: [{ uri: "memories://rules", mimeType: "text/markdown", text: `Error loading rules: ${error instanceof Error ? error.message : "Unknown error"}` }]
1376
+ contents: [{ uri: "memories://rules", mimeType: "text/markdown", text: `Error loading rules: ${error2 instanceof Error ? error2.message : "Unknown error"}` }]
1246
1377
  };
1247
1378
  }
1248
1379
  }
@@ -1268,9 +1399,9 @@ ${projectRules.map((r) => `- ${r.content}`).join("\n")}`);
1268
1399
 
1269
1400
  ${text}` }]
1270
1401
  };
1271
- } catch (error) {
1402
+ } catch (error2) {
1272
1403
  return {
1273
- contents: [{ uri: "memories://recent", mimeType: "text/markdown", text: `Error loading memories: ${error instanceof Error ? error.message : "Unknown error"}` }]
1404
+ contents: [{ uri: "memories://recent", mimeType: "text/markdown", text: `Error loading memories: ${error2 instanceof Error ? error2.message : "Unknown error"}` }]
1274
1405
  };
1275
1406
  }
1276
1407
  }
@@ -1297,9 +1428,9 @@ ${text}` }]
1297
1428
 
1298
1429
  ${text}` }]
1299
1430
  };
1300
- } catch (error) {
1431
+ } catch (error2) {
1301
1432
  return {
1302
- contents: [{ uri: uri.href, mimeType: "text/markdown", text: `Error loading project memories: ${error instanceof Error ? error.message : "Unknown error"}` }]
1433
+ contents: [{ uri: uri.href, mimeType: "text/markdown", text: `Error loading project memories: ${error2 instanceof Error ? error2.message : "Unknown error"}` }]
1303
1434
  };
1304
1435
  }
1305
1436
  }
@@ -1337,9 +1468,9 @@ Use this at the start of tasks to understand project conventions and recall past
1337
1468
  return {
1338
1469
  content: [{ type: "text", text: parts.join("\n\n") }]
1339
1470
  };
1340
- } catch (error) {
1471
+ } catch (error2) {
1341
1472
  return {
1342
- content: [{ type: "text", text: `Failed to get context: ${error instanceof Error ? error.message : "Unknown error"}` }],
1473
+ content: [{ type: "text", text: `Failed to get context: ${error2 instanceof Error ? error2.message : "Unknown error"}` }],
1343
1474
  isError: true
1344
1475
  };
1345
1476
  }
@@ -1376,9 +1507,9 @@ By default, memories are project-scoped when in a git repo. Use global: true for
1376
1507
  }
1377
1508
  ]
1378
1509
  };
1379
- } catch (error) {
1510
+ } catch (error2) {
1380
1511
  return {
1381
- content: [{ type: "text", text: `Failed to add memory: ${error instanceof Error ? error.message : "Unknown error"}` }],
1512
+ content: [{ type: "text", text: `Failed to add memory: ${error2 instanceof Error ? error2.message : "Unknown error"}` }],
1382
1513
  isError: true
1383
1514
  };
1384
1515
  }
@@ -1415,9 +1546,9 @@ ${formatted}`
1415
1546
  }
1416
1547
  ]
1417
1548
  };
1418
- } catch (error) {
1549
+ } catch (error2) {
1419
1550
  return {
1420
- content: [{ type: "text", text: `Failed to search memories: ${error instanceof Error ? error.message : "Unknown error"}` }],
1551
+ content: [{ type: "text", text: `Failed to search memories: ${error2 instanceof Error ? error2.message : "Unknown error"}` }],
1421
1552
  isError: true
1422
1553
  };
1423
1554
  }
@@ -1449,9 +1580,9 @@ ${projectRules.map((r) => `- ${r.content}`).join("\n")}`);
1449
1580
  return {
1450
1581
  content: [{ type: "text", text: parts.join("\n\n") }]
1451
1582
  };
1452
- } catch (error) {
1583
+ } catch (error2) {
1453
1584
  return {
1454
- content: [{ type: "text", text: `Failed to get rules: ${error instanceof Error ? error.message : "Unknown error"}` }],
1585
+ content: [{ type: "text", text: `Failed to get rules: ${error2 instanceof Error ? error2.message : "Unknown error"}` }],
1455
1586
  isError: true
1456
1587
  };
1457
1588
  }
@@ -1489,9 +1620,9 @@ ${formatted}`
1489
1620
  }
1490
1621
  ]
1491
1622
  };
1492
- } catch (error) {
1623
+ } catch (error2) {
1493
1624
  return {
1494
- content: [{ type: "text", text: `Failed to list memories: ${error instanceof Error ? error.message : "Unknown error"}` }],
1625
+ content: [{ type: "text", text: `Failed to list memories: ${error2 instanceof Error ? error2.message : "Unknown error"}` }],
1495
1626
  isError: true
1496
1627
  };
1497
1628
  }
@@ -1530,9 +1661,9 @@ Find the memory ID first with search_memories or list_memories.`,
1530
1661
  content: [{ type: "text", text: `Memory ${id} not found or already deleted.` }],
1531
1662
  isError: true
1532
1663
  };
1533
- } catch (error) {
1664
+ } catch (error2) {
1534
1665
  return {
1535
- content: [{ type: "text", text: `Failed to edit memory: ${error instanceof Error ? error.message : "Unknown error"}` }],
1666
+ content: [{ type: "text", text: `Failed to edit memory: ${error2 instanceof Error ? error2.message : "Unknown error"}` }],
1536
1667
  isError: true
1537
1668
  };
1538
1669
  }
@@ -1556,9 +1687,9 @@ Find the memory ID first with search_memories or list_memories.`,
1556
1687
  content: [{ type: "text", text: `Memory ${id} not found or already forgotten.` }],
1557
1688
  isError: true
1558
1689
  };
1559
- } catch (error) {
1690
+ } catch (error2) {
1560
1691
  return {
1561
- content: [{ type: "text", text: `Failed to forget memory: ${error instanceof Error ? error.message : "Unknown error"}` }],
1692
+ content: [{ type: "text", text: `Failed to forget memory: ${error2 instanceof Error ? error2.message : "Unknown error"}` }],
1562
1693
  isError: true
1563
1694
  };
1564
1695
  }
@@ -1581,6 +1712,7 @@ var serveCommand = new Command11("serve").description("Start the MCP server (std
1581
1712
 
1582
1713
  // src/commands/sync.ts
1583
1714
  import { Command as Command12 } from "commander";
1715
+ import ora from "ora";
1584
1716
 
1585
1717
  // src/lib/turso.ts
1586
1718
  import { nanoid as nanoid2 } from "nanoid";
@@ -1633,27 +1765,69 @@ async function createDatabaseToken(org, dbName) {
1633
1765
  }
1634
1766
 
1635
1767
  // src/commands/sync.ts
1636
- import { unlinkSync, existsSync as existsSync3 } from "fs";
1637
- import { join as join3 } from "path";
1638
- import { homedir as homedir2 } from "os";
1639
- var DB_PATH = join3(homedir2(), ".config", "memories", "local.db");
1768
+ import { unlinkSync, existsSync as existsSync4 } from "fs";
1769
+ import { join as join4 } from "path";
1770
+ import { homedir as homedir3 } from "os";
1771
+ var DB_PATH = join4(homedir3(), ".config", "memories", "local.db");
1640
1772
  var syncCommand = new Command12("sync").description(
1641
1773
  "Manage remote sync"
1642
1774
  );
1643
- syncCommand.command("enable").description("Provision a Turso database and enable sync").option("-o, --org <org>", "Turso organization", "webrenew").action(async (opts) => {
1775
+ syncCommand.command("enable").description("Provision a cloud database and enable sync").option("-o, --org <org>", "Turso organization", "webrenew").action(async (opts) => {
1644
1776
  const existing = await readSyncConfig();
1645
1777
  if (existing) {
1646
- console.log(`Sync already enabled: ${existing.syncUrl}`);
1647
- console.log('Run "memories sync push" to sync now.');
1778
+ info(`Sync already enabled`);
1779
+ dim(`Remote: ${existing.syncUrl}`);
1780
+ dim(`Run ${success} memories sync push to sync now.`);
1648
1781
  return;
1649
1782
  }
1650
- console.log(`Creating database in ${opts.org}...`);
1783
+ const auth = await readAuth();
1784
+ if (auth) {
1785
+ const spinner2 = ora("Fetching cloud database credentials...").start();
1786
+ try {
1787
+ const apiFetch = getApiClient(auth);
1788
+ const res = await apiFetch("/api/db/provision", { method: "POST" });
1789
+ if (res.ok) {
1790
+ const data = await res.json();
1791
+ const profileRes = await apiFetch("/api/db/credentials");
1792
+ if (profileRes.ok) {
1793
+ const creds = await profileRes.json();
1794
+ if (existsSync4(DB_PATH)) {
1795
+ resetDb();
1796
+ unlinkSync(DB_PATH);
1797
+ }
1798
+ await saveSyncConfig({
1799
+ syncUrl: creds.url,
1800
+ syncToken: creds.token,
1801
+ org: opts.org,
1802
+ dbName: creds.dbName
1803
+ });
1804
+ spinner2.text = "Waiting for database to be ready...";
1805
+ await new Promise((r) => setTimeout(r, 3e3));
1806
+ resetDb();
1807
+ await syncDb();
1808
+ spinner2.stop();
1809
+ success("Cloud sync enabled");
1810
+ dim(`Remote: ${data.url}`);
1811
+ dim(`Database: ${creds.dbName}`);
1812
+ return;
1813
+ }
1814
+ }
1815
+ spinner2.stop();
1816
+ } catch {
1817
+ spinner2.stop();
1818
+ warn("Could not fetch credentials from web, provisioning directly...");
1819
+ }
1820
+ } else {
1821
+ warn("Not logged in");
1822
+ proFeature("Cloud sync");
1823
+ return;
1824
+ }
1825
+ const spinner = ora(`Creating database in ${opts.org}...`).start();
1651
1826
  const db = await createDatabase(opts.org);
1652
- console.log(`Created database: ${db.name} (${db.hostname})`);
1653
- console.log("Generating auth token...");
1827
+ spinner.text = "Generating auth token...";
1654
1828
  const token = await createDatabaseToken(opts.org, db.name);
1655
1829
  const syncUrl = `libsql://${db.hostname}`;
1656
- if (existsSync3(DB_PATH)) {
1830
+ if (existsSync4(DB_PATH)) {
1657
1831
  resetDb();
1658
1832
  unlinkSync(DB_PATH);
1659
1833
  }
@@ -1663,40 +1837,48 @@ syncCommand.command("enable").description("Provision a Turso database and enable
1663
1837
  org: opts.org,
1664
1838
  dbName: db.name
1665
1839
  });
1666
- console.log("Waiting for database to be ready...");
1840
+ spinner.text = "Waiting for database to be ready...";
1667
1841
  await new Promise((r) => setTimeout(r, 3e3));
1668
1842
  resetDb();
1669
1843
  await syncDb();
1670
- console.log(`Sync enabled: ${syncUrl}`);
1844
+ spinner.stop();
1845
+ success("Cloud sync enabled");
1846
+ dim(`Remote: ${syncUrl}`);
1847
+ dim(`Database: ${db.name}`);
1671
1848
  });
1672
1849
  syncCommand.command("push").description("Push local changes to remote").action(async () => {
1673
1850
  const config = await readSyncConfig();
1674
1851
  if (!config) {
1675
- console.error('Sync not enabled. Run "memories sync enable" first.');
1852
+ error("Sync not enabled");
1853
+ dim(`Run ${"memories sync enable"} first, or ${"memories login"} to set up cloud sync.`);
1676
1854
  process.exitCode = 1;
1677
1855
  return;
1678
1856
  }
1857
+ const spinner = ora("Syncing to remote...").start();
1679
1858
  await syncDb();
1680
- console.log("Synced to remote.");
1859
+ spinner.stop();
1860
+ success("Synced to remote");
1681
1861
  });
1682
1862
  syncCommand.command("status").description("Show sync configuration").action(async () => {
1683
1863
  const config = await readSyncConfig();
1684
1864
  if (!config) {
1685
- console.log("Sync not enabled.");
1865
+ info("Sync not enabled (local-only mode)");
1866
+ dim(`Run ${"memories login"} to enable cloud sync.`);
1686
1867
  return;
1687
1868
  }
1688
- console.log(`Remote: ${config.syncUrl}`);
1689
- console.log(`Org: ${config.org}`);
1690
- console.log(`Database: ${config.dbName}`);
1869
+ success("Cloud sync enabled");
1870
+ dim(`Remote: ${config.syncUrl}`);
1871
+ dim(`Org: ${config.org}`);
1872
+ dim(`Database: ${config.dbName}`);
1691
1873
  });
1692
1874
 
1693
1875
  // src/commands/generate.ts
1694
1876
  import { Command as Command13 } from "commander";
1695
- import chalk10 from "chalk";
1696
- import { writeFile as writeFile4, readFile as readFile4, mkdir as mkdir3 } from "fs/promises";
1697
- import { existsSync as existsSync4, watch as fsWatch } from "fs";
1698
- import { dirname, resolve, join as join4 } from "path";
1699
- import { homedir as homedir3 } from "os";
1877
+ import chalk11 from "chalk";
1878
+ import { writeFile as writeFile5, readFile as readFile5, mkdir as mkdir4 } from "fs/promises";
1879
+ import { existsSync as existsSync5, watch as fsWatch } from "fs";
1880
+ import { dirname, resolve, join as join5 } from "path";
1881
+ import { homedir as homedir4 } from "os";
1700
1882
  import { checkbox } from "@inquirer/prompts";
1701
1883
  var MARKER = "Generated by memories.sh";
1702
1884
  var VALID_TYPES6 = ["rule", "decision", "fact", "note"];
@@ -1709,18 +1891,40 @@ function groupByType(memories) {
1709
1891
  const order = ["Rules", "Key Decisions", "Project Facts", "Notes"];
1710
1892
  return order.filter((t) => groups[t]?.length).map((title) => ({ title, memories: groups[title] }));
1711
1893
  }
1712
- function formatMemoriesAsMarkdown(memories) {
1894
+ var AGENT_INSTRUCTIONS = `## Memory Management
1895
+
1896
+ When you learn something important about this project, save it for future sessions.
1897
+
1898
+ **Via CLI:**
1899
+ - \`memories add "<decision>" --type decision\` \u2014 Architectural decisions
1900
+ - \`memories add "<convention>" --type rule\` \u2014 Coding conventions
1901
+ - \`memories add "<fact>" --type fact\` \u2014 Project facts
1902
+
1903
+ **Via MCP (if connected):**
1904
+ Use the \`add_memory\` tool with content and type parameters.
1905
+
1906
+ **When to save:**
1907
+ - Architectural decisions and their rationale
1908
+ - Project-specific patterns or conventions
1909
+ - Non-obvious setup, configuration, or gotchas
1910
+ - Tricky bugs and how they were resolved`;
1911
+ function formatMemoriesAsMarkdown(memories, includeAgentInstructions = true) {
1713
1912
  const sections = groupByType(memories);
1714
- if (sections.length === 0) return "";
1715
- return sections.map(({ title, memories: mems }) => {
1913
+ const memoriesContent = sections.length === 0 ? "" : sections.map(({ title, memories: mems }) => {
1716
1914
  const items = mems.map((m) => `- ${m.content}`).join("\n");
1717
1915
  return `## ${title}
1718
1916
 
1719
1917
  ${items}`;
1720
1918
  }).join("\n\n");
1919
+ if (includeAgentInstructions) {
1920
+ return memoriesContent ? `${memoriesContent}
1921
+
1922
+ ${AGENT_INSTRUCTIONS}` : AGENT_INSTRUCTIONS;
1923
+ }
1924
+ return memoriesContent;
1721
1925
  }
1722
1926
  function formatCursorMdc(memories) {
1723
- const body = formatMemoriesAsMarkdown(memories);
1927
+ const body = formatMemoriesAsMarkdown(memories, true);
1724
1928
  const frontmatter = [
1725
1929
  "---",
1726
1930
  "description: Project memories and rules from memories.sh",
@@ -1735,7 +1939,7 @@ function formatCursorMdc(memories) {
1735
1939
  ${body}`;
1736
1940
  }
1737
1941
  function formatWindsurf(memories) {
1738
- const full = formatMemoriesAsMarkdown(memories);
1942
+ const full = formatMemoriesAsMarkdown(memories, true);
1739
1943
  const LIMIT = 6e3;
1740
1944
  if (full.length <= LIMIT) return full;
1741
1945
  const truncated = full.slice(0, LIMIT);
@@ -1811,7 +2015,7 @@ function makeFooter() {
1811
2015
  }
1812
2016
  async function hasOurMarker(filePath) {
1813
2017
  try {
1814
- const content = await readFile4(filePath, "utf-8");
2018
+ const content = await readFile5(filePath, "utf-8");
1815
2019
  return content.includes(MARKER);
1816
2020
  } catch {
1817
2021
  return false;
@@ -1822,13 +2026,13 @@ async function checkGitignore(filePath) {
1822
2026
  if (TRACK_BY_DEFAULT.has(filePath)) return;
1823
2027
  const gitignorePath = resolve(".gitignore");
1824
2028
  try {
1825
- const content = existsSync4(gitignorePath) ? await readFile4(gitignorePath, "utf-8") : "";
2029
+ const content = existsSync5(gitignorePath) ? await readFile5(gitignorePath, "utf-8") : "";
1826
2030
  const lines = content.split("\n");
1827
2031
  const parentDir = filePath.split("/")[0];
1828
2032
  if (lines.some((l) => l.trim() === filePath || l.trim() === parentDir || l.trim() === `${parentDir}/`)) {
1829
2033
  return;
1830
2034
  }
1831
- console.log(chalk10.dim(` hint: add "${filePath}" to .gitignore if you don't want it tracked`));
2035
+ console.log(chalk11.dim(` hint: add "${filePath}" to .gitignore if you don't want it tracked`));
1832
2036
  } catch {
1833
2037
  }
1834
2038
  }
@@ -1836,23 +2040,23 @@ async function writeTarget(target, memories, opts) {
1836
2040
  const outPath = resolve(opts.output ?? target.defaultPath);
1837
2041
  const content = target.format(memories) + makeFooter();
1838
2042
  if (opts.dryRun) {
1839
- console.log(chalk10.dim(`\u2500\u2500 ${target.name} \u2192 ${outPath} \u2500\u2500`));
2043
+ console.log(chalk11.dim(`\u2500\u2500 ${target.name} \u2192 ${outPath} \u2500\u2500`));
1840
2044
  console.log(content);
1841
2045
  console.log();
1842
2046
  return;
1843
2047
  }
1844
- if (existsSync4(outPath)) {
2048
+ if (existsSync5(outPath)) {
1845
2049
  const ours = await hasOurMarker(outPath);
1846
2050
  if (!ours && !opts.force) {
1847
2051
  console.error(
1848
- chalk10.yellow("\u26A0") + ` ${outPath} exists and was not generated by memories.sh. Use ${chalk10.bold("--force")} to overwrite.`
2052
+ chalk11.yellow("\u26A0") + ` ${outPath} exists and was not generated by memories.sh. Use ${chalk11.bold("--force")} to overwrite.`
1849
2053
  );
1850
2054
  return;
1851
2055
  }
1852
2056
  }
1853
- await mkdir3(dirname(outPath), { recursive: true });
1854
- await writeFile4(outPath, content, "utf-8");
1855
- console.log(chalk10.green("\u2713") + ` Wrote ${target.name} \u2192 ${chalk10.dim(outPath)}`);
2057
+ await mkdir4(dirname(outPath), { recursive: true });
2058
+ await writeFile5(outPath, content, "utf-8");
2059
+ console.log(chalk11.green("\u2713") + ` Wrote ${target.name} \u2192 ${chalk11.dim(outPath)}`);
1856
2060
  await checkGitignore(opts.output ?? target.defaultPath);
1857
2061
  }
1858
2062
  async function fetchMemories(types) {
@@ -1868,23 +2072,23 @@ function parseTypes(raw) {
1868
2072
  const types = raw.split(",").map((s) => s.trim());
1869
2073
  for (const t of types) {
1870
2074
  if (!VALID_TYPES6.includes(t)) {
1871
- console.error(chalk10.red("\u2717") + ` Invalid type "${t}". Valid: ${VALID_TYPES6.join(", ")}`);
2075
+ console.error(chalk11.red("\u2717") + ` Invalid type "${t}". Valid: ${VALID_TYPES6.join(", ")}`);
1872
2076
  process.exit(1);
1873
2077
  }
1874
2078
  }
1875
2079
  return types;
1876
2080
  }
1877
2081
  function getDbPath2() {
1878
- const dataDir = process.env.MEMORIES_DATA_DIR ?? join4(homedir3(), ".config", "memories");
1879
- return join4(dataDir, "local.db");
2082
+ const dataDir = process.env.MEMORIES_DATA_DIR ?? join5(homedir4(), ".config", "memories");
2083
+ return join5(dataDir, "local.db");
1880
2084
  }
1881
2085
  async function runWatch(targets, memories, opts) {
1882
2086
  const dbPath = getDbPath2();
1883
- if (!existsSync4(dbPath)) {
1884
- console.error(chalk10.red("\u2717") + " Database not found. Run: memories init");
2087
+ if (!existsSync5(dbPath)) {
2088
+ console.error(chalk11.red("\u2717") + " Database not found. Run: memories init");
1885
2089
  process.exit(1);
1886
2090
  }
1887
- console.log(chalk10.dim(`Watching ${dbPath} for changes... (Ctrl+C to stop)
2091
+ console.log(chalk11.dim(`Watching ${dbPath} for changes... (Ctrl+C to stop)
1888
2092
  `));
1889
2093
  const mems = await memories();
1890
2094
  if (mems.length > 0) {
@@ -1904,7 +2108,7 @@ async function runWatch(targets, memories, opts) {
1904
2108
  }
1905
2109
  }
1906
2110
  } catch (err) {
1907
- console.error(chalk10.red("\u2717") + " Watch error:", err.message);
2111
+ console.error(chalk11.red("\u2717") + " Watch error:", err.message);
1908
2112
  }
1909
2113
  }, 500);
1910
2114
  });
@@ -1920,19 +2124,19 @@ var generateCommand = new Command13("generate").description("Generate IDE rule/i
1920
2124
  const selected = await checkbox({
1921
2125
  message: "Select targets to generate",
1922
2126
  choices: TARGETS.map((t) => ({
1923
- name: `${t.name} ${chalk10.dim(`\u2192 ${t.defaultPath}`)}`,
2127
+ name: `${t.name} ${chalk11.dim(`\u2192 ${t.defaultPath}`)}`,
1924
2128
  value: t.name,
1925
2129
  checked: true
1926
2130
  }))
1927
2131
  });
1928
2132
  if (selected.length === 0) {
1929
- console.log(chalk10.dim("No targets selected."));
2133
+ console.log(chalk11.dim("No targets selected."));
1930
2134
  return;
1931
2135
  }
1932
2136
  const types = parseTypes(opts.types);
1933
2137
  const memories = await fetchMemories(types);
1934
2138
  if (memories.length === 0) {
1935
- console.error(chalk10.dim('No memories found. Add some with: memories add --rule "Your rule"'));
2139
+ console.error(chalk11.dim('No memories found. Add some with: memories add --rule "Your rule"'));
1936
2140
  return;
1937
2141
  }
1938
2142
  const selectedSet = new Set(selected);
@@ -1942,9 +2146,9 @@ var generateCommand = new Command13("generate").description("Generate IDE rule/i
1942
2146
  if (opts.watch) {
1943
2147
  await runWatch(TARGETS, () => fetchMemories(types), opts);
1944
2148
  }
1945
- } catch (error) {
1946
- if (error.name === "ExitPromptError") return;
1947
- console.error(chalk10.red("\u2717") + " Failed to generate:", error instanceof Error ? error.message : "Unknown error");
2149
+ } catch (error2) {
2150
+ if (error2.name === "ExitPromptError") return;
2151
+ console.error(chalk11.red("\u2717") + " Failed to generate:", error2 instanceof Error ? error2.message : "Unknown error");
1948
2152
  process.exit(1);
1949
2153
  }
1950
2154
  });
@@ -1955,12 +2159,12 @@ for (const target of TARGETS) {
1955
2159
  const types = parseTypes(opts.types);
1956
2160
  const memories = await fetchMemories(types);
1957
2161
  if (memories.length === 0) {
1958
- console.error(chalk10.dim('No memories found. Add some with: memories add --rule "Your rule"'));
2162
+ console.error(chalk11.dim('No memories found. Add some with: memories add --rule "Your rule"'));
1959
2163
  return;
1960
2164
  }
1961
2165
  await writeTarget(target, memories, opts);
1962
- } catch (error) {
1963
- console.error(chalk10.red("\u2717") + ` Failed to generate ${target.name}:`, error instanceof Error ? error.message : "Unknown error");
2166
+ } catch (error2) {
2167
+ console.error(chalk11.red("\u2717") + ` Failed to generate ${target.name}:`, error2 instanceof Error ? error2.message : "Unknown error");
1964
2168
  process.exit(1);
1965
2169
  }
1966
2170
  })
@@ -1976,14 +2180,14 @@ generateCommand.addCommand(
1976
2180
  }
1977
2181
  const memories = await fetchMemories(types);
1978
2182
  if (memories.length === 0) {
1979
- console.error(chalk10.dim('No memories found. Add some with: memories add --rule "Your rule"'));
2183
+ console.error(chalk11.dim('No memories found. Add some with: memories add --rule "Your rule"'));
1980
2184
  return;
1981
2185
  }
1982
2186
  for (const target of TARGETS) {
1983
2187
  await writeTarget(target, memories, opts);
1984
2188
  }
1985
- } catch (error) {
1986
- console.error(chalk10.red("\u2717") + " Failed to generate:", error instanceof Error ? error.message : "Unknown error");
2189
+ } catch (error2) {
2190
+ console.error(chalk11.red("\u2717") + " Failed to generate:", error2 instanceof Error ? error2.message : "Unknown error");
1987
2191
  process.exit(1);
1988
2192
  }
1989
2193
  })
@@ -1991,11 +2195,11 @@ generateCommand.addCommand(
1991
2195
 
1992
2196
  // src/commands/edit.ts
1993
2197
  import { Command as Command14 } from "commander";
1994
- import chalk11 from "chalk";
2198
+ import chalk12 from "chalk";
1995
2199
  import { execFileSync as execFileSync2 } from "child_process";
1996
2200
  import { writeFileSync, readFileSync, unlinkSync as unlinkSync2 } from "fs";
1997
2201
  import { tmpdir } from "os";
1998
- import { join as join5 } from "path";
2202
+ import { join as join6 } from "path";
1999
2203
  import { nanoid as nanoid3 } from "nanoid";
2000
2204
  import { select } from "@inquirer/prompts";
2001
2205
  var VALID_TYPES7 = ["rule", "decision", "fact", "note"];
@@ -2007,13 +2211,13 @@ async function pickMemory() {
2007
2211
  const projectId = getProjectId() ?? void 0;
2008
2212
  const memories = await listMemories({ limit: 100, projectId });
2009
2213
  if (memories.length === 0) {
2010
- console.error(chalk11.dim("No memories found."));
2214
+ console.error(chalk12.dim("No memories found."));
2011
2215
  process.exit(0);
2012
2216
  }
2013
2217
  const id = await select({
2014
2218
  message: "Select a memory to edit",
2015
2219
  choices: memories.map((m) => ({
2016
- name: `${chalk11.dim(m.type.padEnd(9))} ${truncate2(m.content, 60)} ${chalk11.dim(m.id)}`,
2220
+ name: `${chalk12.dim(m.type.padEnd(9))} ${truncate2(m.content, 60)} ${chalk12.dim(m.id)}`,
2017
2221
  value: m.id
2018
2222
  }))
2019
2223
  });
@@ -2023,7 +2227,7 @@ var editCommand = new Command14("edit").description("Edit an existing memory").a
2023
2227
  try {
2024
2228
  if (!id) {
2025
2229
  if (!process.stdin.isTTY) {
2026
- console.error(chalk11.red("\u2717") + " Memory ID required in non-interactive mode");
2230
+ console.error(chalk12.red("\u2717") + " Memory ID required in non-interactive mode");
2027
2231
  process.exit(1);
2028
2232
  }
2029
2233
  id = await pickMemory();
@@ -2034,18 +2238,18 @@ var editCommand = new Command14("edit").description("Edit an existing memory").a
2034
2238
  args: [id]
2035
2239
  });
2036
2240
  if (result.rows.length === 0) {
2037
- console.error(chalk11.red("\u2717") + ` Memory ${chalk11.dim(id)} not found`);
2241
+ console.error(chalk12.red("\u2717") + ` Memory ${chalk12.dim(id)} not found`);
2038
2242
  process.exit(1);
2039
2243
  }
2040
2244
  const memory = result.rows[0];
2041
2245
  if (opts.type && !VALID_TYPES7.includes(opts.type)) {
2042
- console.error(chalk11.red("\u2717") + ` Invalid type "${opts.type}". Valid: ${VALID_TYPES7.join(", ")}`);
2246
+ console.error(chalk12.red("\u2717") + ` Invalid type "${opts.type}". Valid: ${VALID_TYPES7.join(", ")}`);
2043
2247
  process.exit(1);
2044
2248
  }
2045
2249
  let newContent = opts.content;
2046
2250
  if (newContent === void 0 && opts.tags === void 0 && opts.type === void 0) {
2047
2251
  const editor = process.env.EDITOR || process.env.VISUAL || "vi";
2048
- const tmpFile = join5(tmpdir(), `memories-edit-${nanoid3(6)}.md`);
2252
+ const tmpFile = join6(tmpdir(), `memories-edit-${nanoid3(6)}.md`);
2049
2253
  writeFileSync(tmpFile, memory.content, "utf-8");
2050
2254
  try {
2051
2255
  execFileSync2(editor, [tmpFile], { stdio: "inherit" });
@@ -2057,7 +2261,7 @@ var editCommand = new Command14("edit").description("Edit an existing memory").a
2057
2261
  }
2058
2262
  }
2059
2263
  if (newContent === memory.content) {
2060
- console.log(chalk11.dim("No changes made."));
2264
+ console.log(chalk12.dim("No changes made."));
2061
2265
  return;
2062
2266
  }
2063
2267
  }
@@ -2067,24 +2271,24 @@ var editCommand = new Command14("edit").description("Edit an existing memory").a
2067
2271
  if (opts.type !== void 0) updates.type = opts.type;
2068
2272
  const updated = await updateMemory(id, updates);
2069
2273
  if (!updated) {
2070
- console.error(chalk11.red("\u2717") + ` Failed to update memory ${chalk11.dim(id)}`);
2274
+ console.error(chalk12.red("\u2717") + ` Failed to update memory ${chalk12.dim(id)}`);
2071
2275
  process.exit(1);
2072
2276
  }
2073
2277
  const changes = [];
2074
2278
  if (updates.content !== void 0) changes.push("content");
2075
2279
  if (updates.tags !== void 0) changes.push("tags");
2076
2280
  if (updates.type !== void 0) changes.push(`type\u2192${updates.type}`);
2077
- console.log(chalk11.green("\u2713") + ` Updated ${chalk11.dim(id)} (${changes.join(", ")})`);
2078
- } catch (error) {
2079
- if (error.name === "ExitPromptError") return;
2080
- console.error(chalk11.red("\u2717") + " Failed to edit memory:", error instanceof Error ? error.message : "Unknown error");
2281
+ console.log(chalk12.green("\u2713") + ` Updated ${chalk12.dim(id)} (${changes.join(", ")})`);
2282
+ } catch (error2) {
2283
+ if (error2.name === "ExitPromptError") return;
2284
+ console.error(chalk12.red("\u2717") + " Failed to edit memory:", error2 instanceof Error ? error2.message : "Unknown error");
2081
2285
  process.exit(1);
2082
2286
  }
2083
2287
  });
2084
2288
 
2085
2289
  // src/commands/stats.ts
2086
2290
  import { Command as Command15 } from "commander";
2087
- import chalk12 from "chalk";
2291
+ import chalk13 from "chalk";
2088
2292
  var statsCommand = new Command15("stats").description("Show memory statistics").option("--json", "Output as JSON").action(async (opts) => {
2089
2293
  try {
2090
2294
  const db = await getDb();
@@ -2121,46 +2325,46 @@ var statsCommand = new Command15("stats").description("Show memory statistics").
2121
2325
  console.log(JSON.stringify(data, null, 2));
2122
2326
  return;
2123
2327
  }
2124
- console.log(chalk12.bold("Memory Statistics\n"));
2328
+ console.log(chalk13.bold("Memory Statistics\n"));
2125
2329
  if (projectId) {
2126
- console.log(` Project: ${chalk12.dim(projectId)}`);
2330
+ console.log(` Project: ${chalk13.dim(projectId)}`);
2127
2331
  }
2128
- console.log(` Total: ${chalk12.bold(String(total))} active, ${chalk12.dim(String(deleted))} deleted
2332
+ console.log(` Total: ${chalk13.bold(String(total))} active, ${chalk13.dim(String(deleted))} deleted
2129
2333
  `);
2130
2334
  if (rows.length === 0) {
2131
- console.log(chalk12.dim(' No memories yet. Add one with: memories add "Your memory"'));
2335
+ console.log(chalk13.dim(' No memories yet. Add one with: memories add "Your memory"'));
2132
2336
  return;
2133
2337
  }
2134
2338
  const typeWidths = { rule: 8, decision: 8, fact: 8, note: 8 };
2135
2339
  console.log(
2136
- ` ${chalk12.dim("Type".padEnd(12))}${chalk12.dim("Scope".padEnd(10))}${chalk12.dim("Count")}`
2340
+ ` ${chalk13.dim("Type".padEnd(12))}${chalk13.dim("Scope".padEnd(10))}${chalk13.dim("Count")}`
2137
2341
  );
2138
- console.log(chalk12.dim(" " + "\u2500".repeat(30)));
2342
+ console.log(chalk13.dim(" " + "\u2500".repeat(30)));
2139
2343
  for (const row of rows) {
2140
2344
  const type = row.type.padEnd(12);
2141
2345
  const scope = row.scope.padEnd(10);
2142
2346
  console.log(` ${type}${scope}${Number(row.count)}`);
2143
2347
  }
2144
- } catch (error) {
2145
- console.error(chalk12.red("\u2717") + " Failed to get stats:", error instanceof Error ? error.message : "Unknown error");
2348
+ } catch (error2) {
2349
+ console.error(chalk13.red("\u2717") + " Failed to get stats:", error2 instanceof Error ? error2.message : "Unknown error");
2146
2350
  process.exit(1);
2147
2351
  }
2148
2352
  });
2149
2353
 
2150
2354
  // src/commands/doctor.ts
2151
2355
  import { Command as Command16 } from "commander";
2152
- import chalk13 from "chalk";
2153
- import { existsSync as existsSync5 } from "fs";
2154
- import { join as join6 } from "path";
2356
+ import chalk14 from "chalk";
2357
+ import { existsSync as existsSync6 } from "fs";
2358
+ import { join as join7 } from "path";
2155
2359
  var doctorCommand = new Command16("doctor").description("Check memories health and diagnose issues").option("--fix", "Attempt to fix issues found").action(async (opts) => {
2156
2360
  try {
2157
- console.log(chalk13.bold("memories doctor\n"));
2361
+ console.log(chalk14.bold("memories doctor\n"));
2158
2362
  const checks = [
2159
2363
  {
2160
2364
  name: "Database file",
2161
2365
  run: async () => {
2162
- const dbPath = join6(getConfigDir(), "local.db");
2163
- if (existsSync5(dbPath)) {
2366
+ const dbPath = join7(getConfigDir(), "local.db");
2367
+ if (existsSync6(dbPath)) {
2164
2368
  return { ok: true, message: `Found at ${dbPath}` };
2165
2369
  }
2166
2370
  return { ok: false, message: `Not found at ${dbPath}. Run: memories init` };
@@ -2258,43 +2462,43 @@ var doctorCommand = new Command16("doctor").description("Check memories health a
2258
2462
  let hasIssues = false;
2259
2463
  for (const check of checks) {
2260
2464
  const { ok, message } = await check.run();
2261
- const icon = ok ? chalk13.green("\u2713") : chalk13.red("\u2717");
2262
- console.log(` ${icon} ${chalk13.bold(check.name)}: ${message}`);
2465
+ const icon = ok ? chalk14.green("\u2713") : chalk14.red("\u2717");
2466
+ console.log(` ${icon} ${chalk14.bold(check.name)}: ${message}`);
2263
2467
  if (!ok) hasIssues = true;
2264
2468
  }
2265
2469
  if (opts.fix) {
2266
- console.log(chalk13.bold("\nRunning fixes...\n"));
2470
+ console.log(chalk14.bold("\nRunning fixes...\n"));
2267
2471
  const db = await getDb();
2268
2472
  const purged = await db.execute(
2269
2473
  "DELETE FROM memories WHERE deleted_at IS NOT NULL"
2270
2474
  );
2271
- console.log(` ${chalk13.green("\u2713")} Purged ${purged.rowsAffected} soft-deleted records`);
2475
+ console.log(` ${chalk14.green("\u2713")} Purged ${purged.rowsAffected} soft-deleted records`);
2272
2476
  try {
2273
2477
  await db.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
2274
- console.log(` ${chalk13.green("\u2713")} Rebuilt FTS index`);
2478
+ console.log(` ${chalk14.green("\u2713")} Rebuilt FTS index`);
2275
2479
  } catch {
2276
- console.log(` ${chalk13.yellow("\u26A0")} Could not rebuild FTS index`);
2480
+ console.log(` ${chalk14.yellow("\u26A0")} Could not rebuild FTS index`);
2277
2481
  }
2278
2482
  }
2279
2483
  console.log();
2280
2484
  if (hasIssues) {
2281
- console.log(chalk13.yellow("Some issues detected.") + (opts.fix ? "" : " Run with --fix to attempt repairs."));
2485
+ console.log(chalk14.yellow("Some issues detected.") + (opts.fix ? "" : " Run with --fix to attempt repairs."));
2282
2486
  } else {
2283
- console.log(chalk13.green("All checks passed."));
2487
+ console.log(chalk14.green("All checks passed."));
2284
2488
  }
2285
- } catch (error) {
2286
- console.error(chalk13.red("\u2717") + " Doctor failed:", error instanceof Error ? error.message : "Unknown error");
2489
+ } catch (error2) {
2490
+ console.error(chalk14.red("\u2717") + " Doctor failed:", error2 instanceof Error ? error2.message : "Unknown error");
2287
2491
  process.exit(1);
2288
2492
  }
2289
2493
  });
2290
2494
 
2291
2495
  // src/commands/hook.ts
2292
2496
  import { Command as Command17 } from "commander";
2293
- import chalk14 from "chalk";
2294
- import { readFile as readFile5, writeFile as writeFile5, chmod } from "fs/promises";
2295
- import { existsSync as existsSync6, readFileSync as readFileSync2 } from "fs";
2497
+ import chalk15 from "chalk";
2498
+ import { readFile as readFile6, writeFile as writeFile6, chmod } from "fs/promises";
2499
+ import { existsSync as existsSync7, readFileSync as readFileSync2 } from "fs";
2296
2500
  import { execFileSync as execFileSync3 } from "child_process";
2297
- import { join as join7 } from "path";
2501
+ import { join as join8 } from "path";
2298
2502
  var HOOK_MARKER_START = "# >>> memories.sh hook >>>";
2299
2503
  var HOOK_MARKER_END = "# <<< memories.sh hook <<<";
2300
2504
  var HOOK_SNIPPET = `
@@ -2315,22 +2519,22 @@ function getGitDir() {
2315
2519
  function getHookLocation(hookName) {
2316
2520
  const gitDir = getGitDir();
2317
2521
  if (!gitDir) return null;
2318
- const huskyPath = join7(".husky", hookName);
2319
- if (existsSync6(".husky") && !existsSync6(join7(".husky", "_"))) {
2522
+ const huskyPath = join8(".husky", hookName);
2523
+ if (existsSync7(".husky") && !existsSync7(join8(".husky", "_"))) {
2320
2524
  return { path: huskyPath, type: "husky" };
2321
2525
  }
2322
- const huskyLegacyPath = join7(".husky", "_", hookName);
2323
- if (existsSync6(join7(".husky", "_"))) {
2526
+ const huskyLegacyPath = join8(".husky", "_", hookName);
2527
+ if (existsSync7(join8(".husky", "_"))) {
2324
2528
  return { path: huskyLegacyPath, type: "husky" };
2325
2529
  }
2326
- if (existsSync6(huskyPath)) {
2530
+ if (existsSync7(huskyPath)) {
2327
2531
  return { path: huskyPath, type: "husky" };
2328
2532
  }
2329
- return { path: join7(gitDir, "hooks", hookName), type: "git" };
2533
+ return { path: join8(gitDir, "hooks", hookName), type: "git" };
2330
2534
  }
2331
2535
  function detectLintStaged() {
2332
2536
  try {
2333
- if (!existsSync6("package.json")) return false;
2537
+ if (!existsSync7("package.json")) return false;
2334
2538
  const pkg = JSON.parse(readFileSync2("package.json", "utf-8"));
2335
2539
  return !!(pkg["lint-staged"] || pkg.devDependencies?.["lint-staged"] || pkg.dependencies?.["lint-staged"]);
2336
2540
  } catch {
@@ -2343,31 +2547,31 @@ hookCommand.addCommand(
2343
2547
  try {
2344
2548
  const location = getHookLocation(opts.hook);
2345
2549
  if (!location) {
2346
- console.error(chalk14.red("\u2717") + " Not in a git repository");
2550
+ console.error(chalk15.red("\u2717") + " Not in a git repository");
2347
2551
  process.exit(1);
2348
2552
  }
2349
2553
  const hookPath = location.path;
2350
- if (existsSync6(hookPath)) {
2351
- const content = await readFile5(hookPath, "utf-8");
2554
+ if (existsSync7(hookPath)) {
2555
+ const content = await readFile6(hookPath, "utf-8");
2352
2556
  if (content.includes(HOOK_MARKER_START)) {
2353
- console.log(chalk14.dim("Hook already installed. Use 'memories hook uninstall' first to reinstall."));
2557
+ console.log(chalk15.dim("Hook already installed. Use 'memories hook uninstall' first to reinstall."));
2354
2558
  return;
2355
2559
  }
2356
- await writeFile5(hookPath, content.trimEnd() + "\n" + HOOK_SNIPPET + "\n", "utf-8");
2560
+ await writeFile6(hookPath, content.trimEnd() + "\n" + HOOK_SNIPPET + "\n", "utf-8");
2357
2561
  } else {
2358
- await writeFile5(hookPath, "#!/bin/sh\n" + HOOK_SNIPPET + "\n", "utf-8");
2562
+ await writeFile6(hookPath, "#!/bin/sh\n" + HOOK_SNIPPET + "\n", "utf-8");
2359
2563
  }
2360
2564
  await chmod(hookPath, 493);
2361
2565
  const locationLabel = location.type === "husky" ? "Husky" : ".git/hooks";
2362
- console.log(chalk14.green("\u2713") + ` Installed memories hook in ${chalk14.dim(opts.hook)} (${locationLabel})`);
2363
- console.log(chalk14.dim(" Rule files will auto-generate on each commit."));
2566
+ console.log(chalk15.green("\u2713") + ` Installed memories hook in ${chalk15.dim(opts.hook)} (${locationLabel})`);
2567
+ console.log(chalk15.dim(" Rule files will auto-generate on each commit."));
2364
2568
  if (detectLintStaged()) {
2365
2569
  console.log(
2366
- chalk14.dim("\n lint-staged detected. You can also add to your lint-staged config:") + chalk14.dim('\n "*.md": "memories generate all --force"')
2570
+ chalk15.dim("\n lint-staged detected. You can also add to your lint-staged config:") + chalk15.dim('\n "*.md": "memories generate all --force"')
2367
2571
  );
2368
2572
  }
2369
- } catch (error) {
2370
- console.error(chalk14.red("\u2717") + " Failed to install hook:", error instanceof Error ? error.message : "Unknown error");
2573
+ } catch (error2) {
2574
+ console.error(chalk15.red("\u2717") + " Failed to install hook:", error2 instanceof Error ? error2.message : "Unknown error");
2371
2575
  process.exit(1);
2372
2576
  }
2373
2577
  })
@@ -2377,17 +2581,17 @@ hookCommand.addCommand(
2377
2581
  try {
2378
2582
  const location = getHookLocation(opts.hook);
2379
2583
  if (!location) {
2380
- console.error(chalk14.red("\u2717") + " Not in a git repository");
2584
+ console.error(chalk15.red("\u2717") + " Not in a git repository");
2381
2585
  process.exit(1);
2382
2586
  }
2383
2587
  const hookPath = location.path;
2384
- if (!existsSync6(hookPath)) {
2385
- console.log(chalk14.dim("No hook file found."));
2588
+ if (!existsSync7(hookPath)) {
2589
+ console.log(chalk15.dim("No hook file found."));
2386
2590
  return;
2387
2591
  }
2388
- const content = await readFile5(hookPath, "utf-8");
2592
+ const content = await readFile6(hookPath, "utf-8");
2389
2593
  if (!content.includes(HOOK_MARKER_START)) {
2390
- console.log(chalk14.dim("No memories hook found in " + opts.hook));
2594
+ console.log(chalk15.dim("No memories hook found in " + opts.hook));
2391
2595
  return;
2392
2596
  }
2393
2597
  const regex = new RegExp(
@@ -2395,15 +2599,15 @@ hookCommand.addCommand(
2395
2599
  );
2396
2600
  const cleaned = content.replace(regex, "\n");
2397
2601
  if (cleaned.trim() === "#!/bin/sh" || cleaned.trim() === "") {
2398
- const { unlink } = await import("fs/promises");
2399
- await unlink(hookPath);
2400
- console.log(chalk14.green("\u2713") + ` Removed ${chalk14.dim(opts.hook)} hook (was memories-only)`);
2602
+ const { unlink: unlink2 } = await import("fs/promises");
2603
+ await unlink2(hookPath);
2604
+ console.log(chalk15.green("\u2713") + ` Removed ${chalk15.dim(opts.hook)} hook (was memories-only)`);
2401
2605
  } else {
2402
- await writeFile5(hookPath, cleaned, "utf-8");
2403
- console.log(chalk14.green("\u2713") + ` Removed memories section from ${chalk14.dim(opts.hook)}`);
2606
+ await writeFile6(hookPath, cleaned, "utf-8");
2607
+ console.log(chalk15.green("\u2713") + ` Removed memories section from ${chalk15.dim(opts.hook)}`);
2404
2608
  }
2405
- } catch (error) {
2406
- console.error(chalk14.red("\u2717") + " Failed to uninstall hook:", error instanceof Error ? error.message : "Unknown error");
2609
+ } catch (error2) {
2610
+ console.error(chalk15.red("\u2717") + " Failed to uninstall hook:", error2 instanceof Error ? error2.message : "Unknown error");
2407
2611
  process.exit(1);
2408
2612
  }
2409
2613
  })
@@ -2413,21 +2617,21 @@ hookCommand.addCommand(
2413
2617
  try {
2414
2618
  const hookPath = getHookLocation(opts.hook)?.path;
2415
2619
  if (!hookPath) {
2416
- console.error(chalk14.red("\u2717") + " Not in a git repository");
2620
+ console.error(chalk15.red("\u2717") + " Not in a git repository");
2417
2621
  process.exit(1);
2418
2622
  }
2419
- if (!existsSync6(hookPath)) {
2420
- console.log(chalk14.dim("Not installed") + ` \u2014 no ${opts.hook} hook found`);
2623
+ if (!existsSync7(hookPath)) {
2624
+ console.log(chalk15.dim("Not installed") + ` \u2014 no ${opts.hook} hook found`);
2421
2625
  return;
2422
2626
  }
2423
- const content = await readFile5(hookPath, "utf-8");
2627
+ const content = await readFile6(hookPath, "utf-8");
2424
2628
  if (content.includes(HOOK_MARKER_START)) {
2425
- console.log(chalk14.green("\u2713") + ` Installed in ${chalk14.dim(hookPath)}`);
2629
+ console.log(chalk15.green("\u2713") + ` Installed in ${chalk15.dim(hookPath)}`);
2426
2630
  } else {
2427
- console.log(chalk14.dim("Not installed") + ` \u2014 ${opts.hook} exists but has no memories section`);
2631
+ console.log(chalk15.dim("Not installed") + ` \u2014 ${opts.hook} exists but has no memories section`);
2428
2632
  }
2429
- } catch (error) {
2430
- console.error(chalk14.red("\u2717") + " Failed to check hook:", error instanceof Error ? error.message : "Unknown error");
2633
+ } catch (error2) {
2634
+ console.error(chalk15.red("\u2717") + " Failed to check hook:", error2 instanceof Error ? error2.message : "Unknown error");
2431
2635
  process.exit(1);
2432
2636
  }
2433
2637
  })
@@ -2438,9 +2642,9 @@ function escapeRegex(str) {
2438
2642
 
2439
2643
  // src/commands/ingest.ts
2440
2644
  import { Command as Command18 } from "commander";
2441
- import chalk15 from "chalk";
2442
- import { readFile as readFile6 } from "fs/promises";
2443
- import { existsSync as existsSync7 } from "fs";
2645
+ import chalk16 from "chalk";
2646
+ import { readFile as readFile7 } from "fs/promises";
2647
+ import { existsSync as existsSync8 } from "fs";
2444
2648
  var SOURCES = [
2445
2649
  { name: "cursor", paths: [".cursor/rules/memories.mdc", ".cursorrules"], description: "Cursor rules" },
2446
2650
  { name: "claude", paths: ["CLAUDE.md"], description: "Claude Code instructions" },
@@ -2500,14 +2704,14 @@ function normalize(s) {
2500
2704
  var ingestCommand = new Command18("ingest").description("Import memories from existing IDE rule files").argument("[source]", "Source to import from (cursor, claude, agents, copilot, windsurf, cline, roo, gemini, or file path)").option("--type <type>", "Override type for all imported memories").option("--dry-run", "Preview without importing").option("--all", "Scan all known IDE rule file locations").option("--no-dedup", "Skip duplicate detection").action(async (source, opts) => {
2501
2705
  try {
2502
2706
  if (opts.type && !VALID_TYPES8.includes(opts.type)) {
2503
- console.error(chalk15.red("\u2717") + ` Invalid type "${opts.type}". Valid types: ${VALID_TYPES8.join(", ")}`);
2707
+ console.error(chalk16.red("\u2717") + ` Invalid type "${opts.type}". Valid types: ${VALID_TYPES8.join(", ")}`);
2504
2708
  process.exit(1);
2505
2709
  }
2506
2710
  const filesToProcess = [];
2507
2711
  if (opts.all) {
2508
2712
  for (const src of SOURCES) {
2509
2713
  for (const p of src.paths) {
2510
- if (existsSync7(p)) {
2714
+ if (existsSync8(p)) {
2511
2715
  filesToProcess.push({ name: src.name, path: p });
2512
2716
  }
2513
2717
  }
@@ -2516,27 +2720,27 @@ var ingestCommand = new Command18("ingest").description("Import memories from ex
2516
2720
  const known = SOURCES.find((s) => s.name === source);
2517
2721
  if (known) {
2518
2722
  for (const p of known.paths) {
2519
- if (existsSync7(p)) {
2723
+ if (existsSync8(p)) {
2520
2724
  filesToProcess.push({ name: known.name, path: p });
2521
2725
  break;
2522
2726
  }
2523
2727
  }
2524
2728
  if (filesToProcess.length === 0) {
2525
- console.error(chalk15.red("\u2717") + ` No ${known.description} file found at: ${known.paths.join(", ")}`);
2729
+ console.error(chalk16.red("\u2717") + ` No ${known.description} file found at: ${known.paths.join(", ")}`);
2526
2730
  process.exit(1);
2527
2731
  }
2528
- } else if (existsSync7(source)) {
2732
+ } else if (existsSync8(source)) {
2529
2733
  filesToProcess.push({ name: "file", path: source });
2530
2734
  } else {
2531
- console.error(chalk15.red("\u2717") + ` Unknown source "${source}". Valid: ${SOURCES.map((s) => s.name).join(", ")}, or a file path`);
2735
+ console.error(chalk16.red("\u2717") + ` Unknown source "${source}". Valid: ${SOURCES.map((s) => s.name).join(", ")}, or a file path`);
2532
2736
  process.exit(1);
2533
2737
  }
2534
2738
  } else {
2535
- console.error(chalk15.red("\u2717") + " Specify a source or use --all");
2739
+ console.error(chalk16.red("\u2717") + " Specify a source or use --all");
2536
2740
  process.exit(1);
2537
2741
  }
2538
2742
  if (filesToProcess.length === 0) {
2539
- console.log(chalk15.dim("No IDE rule files found."));
2743
+ console.log(chalk16.dim("No IDE rule files found."));
2540
2744
  return;
2541
2745
  }
2542
2746
  const existingSet = /* @__PURE__ */ new Set();
@@ -2550,29 +2754,29 @@ var ingestCommand = new Command18("ingest").description("Import memories from ex
2550
2754
  let totalImported = 0;
2551
2755
  let totalSkipped = 0;
2552
2756
  for (const file of filesToProcess) {
2553
- const content = await readFile6(file.path, "utf-8");
2757
+ const content = await readFile7(file.path, "utf-8");
2554
2758
  if (content.includes(MARKER2)) {
2555
- console.log(chalk15.dim(` Skipping ${file.path} (generated by memories.sh)`));
2759
+ console.log(chalk16.dim(` Skipping ${file.path} (generated by memories.sh)`));
2556
2760
  continue;
2557
2761
  }
2558
2762
  const memories = extractMemories(content);
2559
2763
  if (memories.length === 0) {
2560
- console.log(chalk15.dim(` No importable memories found in ${file.path}`));
2764
+ console.log(chalk16.dim(` No importable memories found in ${file.path}`));
2561
2765
  continue;
2562
2766
  }
2563
- console.log(chalk15.bold(`
2564
- ${file.name}`) + chalk15.dim(` (${file.path}) \u2014 ${memories.length} items`));
2767
+ console.log(chalk16.bold(`
2768
+ ${file.name}`) + chalk16.dim(` (${file.path}) \u2014 ${memories.length} items`));
2565
2769
  for (const mem of memories) {
2566
2770
  const type = opts.type ?? mem.type;
2567
2771
  if (opts.dedup !== false && existingSet.has(normalize(mem.content))) {
2568
2772
  if (opts.dryRun) {
2569
- console.log(` ${chalk15.dim("skip")} ${chalk15.dim(mem.content)}`);
2773
+ console.log(` ${chalk16.dim("skip")} ${chalk16.dim(mem.content)}`);
2570
2774
  }
2571
2775
  totalSkipped++;
2572
2776
  continue;
2573
2777
  }
2574
2778
  if (opts.dryRun) {
2575
- const typeColor = type === "rule" ? chalk15.blue : type === "decision" ? chalk15.yellow : type === "fact" ? chalk15.green : chalk15.dim;
2779
+ const typeColor = type === "rule" ? chalk16.blue : type === "decision" ? chalk16.yellow : type === "fact" ? chalk16.green : chalk16.dim;
2576
2780
  console.log(` ${typeColor(type.padEnd(9))} ${mem.content}`);
2577
2781
  } else {
2578
2782
  await addMemory(mem.content, { type });
@@ -2583,23 +2787,23 @@ var ingestCommand = new Command18("ingest").description("Import memories from ex
2583
2787
  }
2584
2788
  if (opts.dryRun) {
2585
2789
  const skipMsg = totalSkipped > 0 ? ` (${totalSkipped} duplicates skipped)` : "";
2586
- console.log(chalk15.dim(`
2790
+ console.log(chalk16.dim(`
2587
2791
  Dry run \u2014 no memories imported.${skipMsg} Remove --dry-run to import.`));
2588
2792
  } else {
2589
- const skipMsg = totalSkipped > 0 ? chalk15.dim(` (${totalSkipped} duplicates skipped)`) : "";
2590
- console.log(chalk15.green("\n\u2713") + ` Imported ${totalImported} memories` + skipMsg);
2793
+ const skipMsg = totalSkipped > 0 ? chalk16.dim(` (${totalSkipped} duplicates skipped)`) : "";
2794
+ console.log(chalk16.green("\n\u2713") + ` Imported ${totalImported} memories` + skipMsg);
2591
2795
  }
2592
- } catch (error) {
2593
- console.error(chalk15.red("\u2717") + " Failed to ingest:", error instanceof Error ? error.message : "Unknown error");
2796
+ } catch (error2) {
2797
+ console.error(chalk16.red("\u2717") + " Failed to ingest:", error2 instanceof Error ? error2.message : "Unknown error");
2594
2798
  process.exit(1);
2595
2799
  }
2596
2800
  });
2597
2801
 
2598
2802
  // src/commands/diff.ts
2599
2803
  import { Command as Command19 } from "commander";
2600
- import chalk16 from "chalk";
2601
- import { readFile as readFile7 } from "fs/promises";
2602
- import { existsSync as existsSync8 } from "fs";
2804
+ import chalk17 from "chalk";
2805
+ import { readFile as readFile8 } from "fs/promises";
2806
+ import { existsSync as existsSync9 } from "fs";
2603
2807
  import { resolve as resolve2 } from "path";
2604
2808
  var MARKER3 = "Generated by memories.sh";
2605
2809
  var VALID_TYPES9 = ["rule", "decision", "fact", "note"];
@@ -2632,7 +2836,7 @@ function parseTypes2(raw) {
2632
2836
  const types = raw.split(",").map((s) => s.trim());
2633
2837
  for (const t of types) {
2634
2838
  if (!VALID_TYPES9.includes(t)) {
2635
- console.error(chalk16.red("\u2717") + ` Invalid type "${t}". Valid: ${VALID_TYPES9.join(", ")}`);
2839
+ console.error(chalk17.red("\u2717") + ` Invalid type "${t}". Valid: ${VALID_TYPES9.join(", ")}`);
2636
2840
  process.exit(1);
2637
2841
  }
2638
2842
  }
@@ -2644,7 +2848,7 @@ async function fetchMemories2(types) {
2644
2848
  }
2645
2849
  async function diffTarget(target, currentMemories, outputPath) {
2646
2850
  const filePath = resolve2(outputPath ?? target.defaultPath);
2647
- if (!existsSync8(filePath)) {
2851
+ if (!existsSync9(filePath)) {
2648
2852
  return {
2649
2853
  added: currentMemories.map((m) => m.content),
2650
2854
  removed: [],
@@ -2655,7 +2859,7 @@ async function diffTarget(target, currentMemories, outputPath) {
2655
2859
  generatedAt: null
2656
2860
  };
2657
2861
  }
2658
- const content = await readFile7(filePath, "utf-8");
2862
+ const content = await readFile8(filePath, "utf-8");
2659
2863
  const isOurs = content.includes(MARKER3);
2660
2864
  const generatedAt = extractTimestamp(content);
2661
2865
  const fileMemories = extractFileMemories(content);
@@ -2671,7 +2875,7 @@ var diffCommand = new Command19("diff").description("Show what changed since las
2671
2875
  const memories = await fetchMemories2(types);
2672
2876
  const targetsToCheck = target && target !== "all" ? TARGETS2.filter((t) => t.name === target) : TARGETS2;
2673
2877
  if (target && target !== "all" && targetsToCheck.length === 0) {
2674
- console.error(chalk16.red("\u2717") + ` Unknown target "${target}". Valid: ${TARGETS2.map((t) => t.name).join(", ")}`);
2878
+ console.error(chalk17.red("\u2717") + ` Unknown target "${target}". Valid: ${TARGETS2.map((t) => t.name).join(", ")}`);
2675
2879
  process.exit(1);
2676
2880
  }
2677
2881
  let anyStale = false;
@@ -2680,54 +2884,54 @@ var diffCommand = new Command19("diff").description("Show what changed since las
2680
2884
  if (!result.exists && !target) continue;
2681
2885
  const hasChanges = result.added.length > 0 || result.removed.length > 0;
2682
2886
  if (!result.exists) {
2683
- console.log(chalk16.bold(`
2684
- ${t.name}`) + chalk16.dim(` \u2192 ${result.filePath}`));
2685
- console.log(chalk16.yellow(" Not generated yet.") + chalk16.dim(` Run: memories generate ${t.name}`));
2887
+ console.log(chalk17.bold(`
2888
+ ${t.name}`) + chalk17.dim(` \u2192 ${result.filePath}`));
2889
+ console.log(chalk17.yellow(" Not generated yet.") + chalk17.dim(` Run: memories generate ${t.name}`));
2686
2890
  anyStale = true;
2687
2891
  continue;
2688
2892
  }
2689
2893
  if (!result.isOurs) {
2690
- console.log(chalk16.bold(`
2691
- ${t.name}`) + chalk16.dim(` \u2192 ${result.filePath}`));
2692
- console.log(chalk16.dim(" Not managed by memories.sh (no marker found)"));
2894
+ console.log(chalk17.bold(`
2895
+ ${t.name}`) + chalk17.dim(` \u2192 ${result.filePath}`));
2896
+ console.log(chalk17.dim(" Not managed by memories.sh (no marker found)"));
2693
2897
  continue;
2694
2898
  }
2695
2899
  if (!hasChanges) {
2696
2900
  if (target) {
2697
- console.log(chalk16.bold(`
2698
- ${t.name}`) + chalk16.dim(` \u2192 ${result.filePath}`));
2699
- const since = result.generatedAt ? chalk16.dim(` (generated ${formatRelative(result.generatedAt)})`) : "";
2700
- console.log(chalk16.green(" Up to date.") + since);
2901
+ console.log(chalk17.bold(`
2902
+ ${t.name}`) + chalk17.dim(` \u2192 ${result.filePath}`));
2903
+ const since = result.generatedAt ? chalk17.dim(` (generated ${formatRelative(result.generatedAt)})`) : "";
2904
+ console.log(chalk17.green(" Up to date.") + since);
2701
2905
  }
2702
2906
  continue;
2703
2907
  }
2704
2908
  anyStale = true;
2705
- console.log(chalk16.bold(`
2706
- ${t.name}`) + chalk16.dim(` \u2192 ${result.filePath}`));
2909
+ console.log(chalk17.bold(`
2910
+ ${t.name}`) + chalk17.dim(` \u2192 ${result.filePath}`));
2707
2911
  if (result.generatedAt) {
2708
- console.log(chalk16.dim(` Generated ${formatRelative(result.generatedAt)}`));
2912
+ console.log(chalk17.dim(` Generated ${formatRelative(result.generatedAt)}`));
2709
2913
  }
2710
2914
  for (const a of result.added) {
2711
- console.log(chalk16.green(` + ${a}`));
2915
+ console.log(chalk17.green(` + ${a}`));
2712
2916
  }
2713
2917
  for (const r of result.removed) {
2714
- console.log(chalk16.red(` - ${r}`));
2918
+ console.log(chalk17.red(` - ${r}`));
2715
2919
  }
2716
2920
  if (result.unchanged > 0) {
2717
- console.log(chalk16.dim(` ${result.unchanged} unchanged`));
2921
+ console.log(chalk17.dim(` ${result.unchanged} unchanged`));
2718
2922
  }
2719
2923
  }
2720
2924
  if (!anyStale) {
2721
2925
  if (target) {
2722
2926
  } else {
2723
- console.log(chalk16.green("\n All generated files are up to date."));
2927
+ console.log(chalk17.green("\n All generated files are up to date."));
2724
2928
  }
2725
2929
  } else {
2726
- console.log(chalk16.dim(`
2727
- Run ${chalk16.bold("memories generate")} to update stale files.`));
2930
+ console.log(chalk17.dim(`
2931
+ Run ${chalk17.bold("memories generate")} to update stale files.`));
2728
2932
  }
2729
- } catch (error) {
2730
- console.error(chalk16.red("\u2717") + " Diff failed:", error instanceof Error ? error.message : "Unknown error");
2933
+ } catch (error2) {
2934
+ console.error(chalk17.red("\u2717") + " Diff failed:", error2 instanceof Error ? error2.message : "Unknown error");
2731
2935
  process.exit(1);
2732
2936
  }
2733
2937
  });
@@ -2748,7 +2952,7 @@ function formatRelative(isoDate) {
2748
2952
 
2749
2953
  // src/commands/tag.ts
2750
2954
  import { Command as Command20 } from "commander";
2751
- import chalk17 from "chalk";
2955
+ import chalk18 from "chalk";
2752
2956
  var VALID_TYPES10 = ["rule", "decision", "fact", "note"];
2753
2957
  function buildWhere(filters) {
2754
2958
  const conditions = ["deleted_at IS NULL"];
@@ -2800,12 +3004,12 @@ tagCommand.addCommand(
2800
3004
  updated++;
2801
3005
  }
2802
3006
  if (opts.dryRun) {
2803
- console.log(chalk17.dim(`Dry run \u2014 would tag ${updated} memories with "${tag}" (${skipped} already tagged)`));
3007
+ console.log(chalk18.dim(`Dry run \u2014 would tag ${updated} memories with "${tag}" (${skipped} already tagged)`));
2804
3008
  } else {
2805
- console.log(chalk17.green("\u2713") + ` Tagged ${updated} memories with "${tag}"` + (skipped > 0 ? chalk17.dim(` (${skipped} already tagged)`) : ""));
3009
+ console.log(chalk18.green("\u2713") + ` Tagged ${updated} memories with "${tag}"` + (skipped > 0 ? chalk18.dim(` (${skipped} already tagged)`) : ""));
2806
3010
  }
2807
- } catch (error) {
2808
- console.error(chalk17.red("\u2717") + ` Failed: ${error instanceof Error ? error.message : "Unknown error"}`);
3011
+ } catch (error2) {
3012
+ console.error(chalk18.red("\u2717") + ` Failed: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
2809
3013
  process.exit(1);
2810
3014
  }
2811
3015
  })
@@ -2834,12 +3038,12 @@ tagCommand.addCommand(
2834
3038
  updated++;
2835
3039
  }
2836
3040
  if (opts.dryRun) {
2837
- console.log(chalk17.dim(`Dry run \u2014 would remove "${tag}" from ${updated} memories`));
3041
+ console.log(chalk18.dim(`Dry run \u2014 would remove "${tag}" from ${updated} memories`));
2838
3042
  } else {
2839
- console.log(chalk17.green("\u2713") + ` Removed "${tag}" from ${updated} memories`);
3043
+ console.log(chalk18.green("\u2713") + ` Removed "${tag}" from ${updated} memories`);
2840
3044
  }
2841
- } catch (error) {
2842
- console.error(chalk17.red("\u2717") + ` Failed: ${error instanceof Error ? error.message : "Unknown error"}`);
3045
+ } catch (error2) {
3046
+ console.error(chalk18.red("\u2717") + ` Failed: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
2843
3047
  process.exit(1);
2844
3048
  }
2845
3049
  })
@@ -2860,22 +3064,110 @@ tagCommand.addCommand(
2860
3064
  }
2861
3065
  }
2862
3066
  if (counts.size === 0) {
2863
- console.log(chalk17.dim("No tags found."));
3067
+ console.log(chalk18.dim("No tags found."));
2864
3068
  return;
2865
3069
  }
2866
3070
  const sorted = [...counts.entries()].sort((a, b) => b[1] - a[1]);
2867
3071
  for (const [tag, count] of sorted) {
2868
- console.log(` ${chalk17.bold(tag)} ${chalk17.dim(`(${count})`)}`);
3072
+ console.log(` ${chalk18.bold(tag)} ${chalk18.dim(`(${count})`)}`);
2869
3073
  }
2870
- } catch (error) {
2871
- console.error(chalk17.red("\u2717") + ` Failed: ${error instanceof Error ? error.message : "Unknown error"}`);
3074
+ } catch (error2) {
3075
+ console.error(chalk18.red("\u2717") + ` Failed: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
2872
3076
  process.exit(1);
2873
3077
  }
2874
3078
  })
2875
3079
  );
2876
3080
 
3081
+ // src/commands/login.ts
3082
+ import { Command as Command21 } from "commander";
3083
+ import chalk19 from "chalk";
3084
+ import ora2 from "ora";
3085
+ import { randomBytes } from "crypto";
3086
+ import { execFile } from "child_process";
3087
+ var DEFAULT_API_URL = "https://memories.sh";
3088
+ function openBrowser(url) {
3089
+ const platform = process.platform;
3090
+ const cmd = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
3091
+ execFile(cmd, [url], () => {
3092
+ });
3093
+ }
3094
+ var loginCommand = new Command21("login").description("Log in to memories.sh to enable cloud sync").option("--api-url <url>", "API base URL", DEFAULT_API_URL).action(async (opts) => {
3095
+ banner();
3096
+ const existing = await readAuth();
3097
+ if (existing) {
3098
+ warn(`Already logged in as ${chalk19.bold(existing.email)}`);
3099
+ dim(`Run ${chalk19.cyan("memories logout")} to sign out first.`);
3100
+ return;
3101
+ }
3102
+ box(
3103
+ chalk19.bold("Pro features include:\n\n") + chalk19.dim("\u2192 ") + "Cloud sync & backup\n" + chalk19.dim("\u2192 ") + "Cross-device access\n" + chalk19.dim("\u2192 ") + "Web dashboard\n" + chalk19.dim("\u2192 ") + "Priority support",
3104
+ "Upgrade to Pro"
3105
+ );
3106
+ const code = randomBytes(16).toString("hex");
3107
+ const authUrl = `${opts.apiUrl}/app/auth/cli?code=${code}`;
3108
+ console.log(chalk19.bold("Open this URL in your browser:\n"));
3109
+ console.log(` ${chalk19.cyan(authUrl)}
3110
+ `);
3111
+ try {
3112
+ openBrowser(authUrl);
3113
+ dim("Browser opened automatically");
3114
+ } catch {
3115
+ }
3116
+ const spinner = ora2({
3117
+ text: "Waiting for authorization...",
3118
+ color: "magenta"
3119
+ }).start();
3120
+ const maxAttempts = 60;
3121
+ for (let i = 0; i < maxAttempts; i++) {
3122
+ await new Promise((r) => setTimeout(r, 5e3));
3123
+ spinner.text = `Waiting for authorization... (${Math.floor((maxAttempts - i) * 5 / 60)}m remaining)`;
3124
+ try {
3125
+ const res = await fetch(`${opts.apiUrl}/api/auth/cli`, {
3126
+ method: "POST",
3127
+ headers: { "Content-Type": "application/json" },
3128
+ body: JSON.stringify({ action: "poll", code })
3129
+ });
3130
+ if (res.ok) {
3131
+ const data = await res.json();
3132
+ await saveAuth({
3133
+ token: data.token,
3134
+ email: data.email,
3135
+ apiUrl: opts.apiUrl
3136
+ });
3137
+ spinner.stop();
3138
+ console.log("");
3139
+ success(`Logged in as ${chalk19.bold(data.email)}`);
3140
+ dim("Your cloud database has been provisioned automatically.");
3141
+ nextSteps([
3142
+ `${chalk19.cyan("memories sync")} ${chalk19.dim("to sync your memories")}`,
3143
+ `${chalk19.cyan("memories.sh/app")} ${chalk19.dim("to view your dashboard")}`
3144
+ ]);
3145
+ return;
3146
+ }
3147
+ if (res.status !== 202) {
3148
+ const text = await res.text();
3149
+ spinner.stop();
3150
+ error(`Authorization failed: ${text}`);
3151
+ return;
3152
+ }
3153
+ } catch {
3154
+ }
3155
+ }
3156
+ spinner.stop();
3157
+ error("Authorization timed out. Please try again.");
3158
+ });
3159
+ var logoutCommand = new Command21("logout").description("Log out of memories.sh").action(async () => {
3160
+ const existing = await readAuth();
3161
+ if (!existing) {
3162
+ info("Not logged in.");
3163
+ return;
3164
+ }
3165
+ await clearAuth();
3166
+ success("Logged out successfully.");
3167
+ });
3168
+
2877
3169
  // src/index.ts
2878
- var program = new Command21().name("memories").description("A local-first memory layer for AI agents").version("0.1.0");
3170
+ var program = new Command22().name("memories").description("A local-first memory layer for AI agents").version("0.2.1");
2879
3171
  program.addCommand(initCommand);
2880
3172
  program.addCommand(addCommand);
2881
3173
  program.addCommand(recallCommand);
@@ -2896,4 +3188,6 @@ program.addCommand(hookCommand);
2896
3188
  program.addCommand(ingestCommand);
2897
3189
  program.addCommand(diffCommand);
2898
3190
  program.addCommand(tagCommand);
3191
+ program.addCommand(loginCommand);
3192
+ program.addCommand(logoutCommand);
2899
3193
  program.parse();