@memories.sh/cli 0.1.0 → 0.2.0

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