opencode-swarm-plugin 0.46.0 → 0.47.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 (3) hide show
  1. package/bin/swarm.ts +346 -108
  2. package/dist/bin/swarm.js +1439 -590
  3. package/package.json +1 -1
package/bin/swarm.ts CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env bun
2
2
  /**
3
3
  * OpenCode Swarm Plugin CLI
4
4
  *
@@ -51,7 +51,7 @@ import {
51
51
  createDurableStreamAdapter,
52
52
  createDurableStreamServer,
53
53
  } from "swarm-mail";
54
- import { execSync } from "child_process";
54
+ import { execSync, spawn } from "child_process";
55
55
  import { tmpdir } from "os";
56
56
 
57
57
  // Query & observability tools
@@ -464,6 +464,15 @@ interface CheckResult {
464
464
  // ============================================================================
465
465
 
466
466
  const DEPENDENCIES: Dependency[] = [
467
+ {
468
+ name: "Bun",
469
+ command: "bun",
470
+ checkArgs: ["--version"],
471
+ required: true,
472
+ install: "curl -fsSL https://bun.sh/install | bash",
473
+ installType: "manual",
474
+ description: "JavaScript runtime (required for CLI)",
475
+ },
467
476
  {
468
477
  name: "OpenCode",
469
478
  command: "opencode",
@@ -512,34 +521,53 @@ async function checkCommand(
512
521
  cmd: string,
513
522
  args: string[],
514
523
  ): Promise<{ available: boolean; version?: string }> {
515
- try {
516
- const proc = Bun.spawn([cmd, ...args], {
517
- stdout: "pipe",
518
- stderr: "pipe",
519
- });
520
- const exitCode = await proc.exited;
521
- if (exitCode === 0) {
522
- const output = await new Response(proc.stdout).text();
523
- const versionMatch = output.match(/v?(\d+\.\d+\.\d+)/);
524
- return { available: true, version: versionMatch?.[1] };
524
+ return new Promise((resolve) => {
525
+ try {
526
+ const proc = spawn(cmd, args, {
527
+ stdio: ["ignore", "pipe", "pipe"],
528
+ });
529
+
530
+ let stdout = "";
531
+ proc.stdout?.on("data", (data) => {
532
+ stdout += data.toString();
533
+ });
534
+
535
+ proc.on("error", () => {
536
+ resolve({ available: false });
537
+ });
538
+
539
+ proc.on("close", (exitCode) => {
540
+ if (exitCode === 0) {
541
+ const versionMatch = stdout.match(/v?(\d+\.\d+\.\d+)/);
542
+ resolve({ available: true, version: versionMatch?.[1] });
543
+ } else {
544
+ resolve({ available: false });
545
+ }
546
+ });
547
+ } catch {
548
+ resolve({ available: false });
525
549
  }
526
- return { available: false };
527
- } catch {
528
- return { available: false };
529
- }
550
+ });
530
551
  }
531
552
 
532
553
  async function runInstall(command: string): Promise<boolean> {
533
- try {
534
- const proc = Bun.spawn(["bash", "-c", command], {
535
- stdout: "inherit",
536
- stderr: "inherit",
537
- });
538
- const exitCode = await proc.exited;
539
- return exitCode === 0;
540
- } catch {
541
- return false;
542
- }
554
+ return new Promise((resolve) => {
555
+ try {
556
+ const proc = spawn("bash", ["-c", command], {
557
+ stdio: "inherit",
558
+ });
559
+
560
+ proc.on("error", () => {
561
+ resolve(false);
562
+ });
563
+
564
+ proc.on("close", (exitCode) => {
565
+ resolve(exitCode === 0);
566
+ });
567
+ } catch {
568
+ resolve(false);
569
+ }
570
+ });
543
571
  }
544
572
 
545
573
  async function checkAllDependencies(): Promise<CheckResult[]> {
@@ -707,68 +735,173 @@ function buildAgentsSkillsSection(
707
735
  ].join(newline);
708
736
  }
709
737
 
710
- function buildAgentsCassSection(newline: string): string {
738
+ /**
739
+ * Build the unified Hivemind section (ADR-011).
740
+ * Replaces separate CASS and Semantic Memory sections.
741
+ */
742
+ function buildAgentsHivemindSection(newline: string): string {
711
743
  return [
712
- "## CASS - Cross-Agent Session Search",
744
+ "## Hivemind - Unified Memory System",
713
745
  "",
714
- "Search across ALL your AI coding agent histories before solving problems from scratch.",
746
+ "The hive remembers everything. Learnings, sessions, patterns—all searchable.",
747
+ "",
748
+ "**Unified storage:** Manual learnings and AI agent session histories stored in the same database, searchable together. Powered by libSQL vectors + Ollama embeddings.",
749
+ "",
750
+ "**Indexed agents:** Claude Code, Codex, Cursor, Gemini, Aider, ChatGPT, Cline, OpenCode, Amp, Pi-Agent",
715
751
  "",
716
752
  "### When to Use",
717
753
  "",
718
- '- **BEFORE implementing anything**: check if any agent solved it before',
719
- '- **Debugging**: "what did I try last time this error happened?"',
720
- '- **Learning patterns**: "how did Cursor handle this API?"',
754
+ "- **BEFORE implementing** - check if you or any agent solved it before",
755
+ "- **After solving hard problems** - store learnings for future sessions",
756
+ "- **Debugging** - search past sessions for similar errors",
757
+ "- **Architecture decisions** - record reasoning, alternatives, tradeoffs",
758
+ "- **Project-specific patterns** - capture domain rules and gotchas",
759
+ "",
760
+ "### Tools",
761
+ "",
762
+ "| Tool | Purpose |",
763
+ "|------|---------|",
764
+ "| `hivemind_store` | Store a memory (learnings, decisions, patterns) |",
765
+ "| `hivemind_find` | Search all memories (learnings + sessions, semantic + FTS fallback) |",
766
+ "| `hivemind_get` | Get specific memory by ID |",
767
+ "| `hivemind_remove` | Delete outdated/incorrect memory |",
768
+ "| `hivemind_validate` | Confirm memory still accurate (resets 90-day decay timer) |",
769
+ "| `hivemind_stats` | Memory statistics and health check |",
770
+ "| `hivemind_index` | Index AI session directories |",
771
+ "| `hivemind_sync` | Sync to .hive/memories.jsonl (git-backed, team-shared) |",
721
772
  "",
722
773
  "### Usage",
723
774
  "",
775
+ "**Store a learning** (include WHY, not just WHAT):",
776
+ "",
777
+ "```typescript",
778
+ "hivemind_store({",
779
+ ' information: "OAuth refresh tokens need 5min buffer before expiry to avoid race conditions. Without buffer, token refresh can fail mid-request if expiry happens between check and use.",',
780
+ ' tags: "auth,oauth,tokens,race-conditions"',
781
+ "})",
782
+ "```",
783
+ "",
784
+ "**Search all memories** (learnings + sessions):",
785
+ "",
786
+ "```typescript",
787
+ "// Search everything",
788
+ 'hivemind_find({ query: "token refresh", limit: 5 })',
789
+ "",
790
+ "// Search only learnings (manual entries)",
791
+ 'hivemind_find({ query: "authentication", collection: "default" })',
792
+ "",
793
+ "// Search only Claude sessions",
794
+ 'hivemind_find({ query: "Next.js caching", collection: "claude" })',
795
+ "",
796
+ "// Search only Cursor sessions",
797
+ 'hivemind_find({ query: "API design", collection: "cursor" })',
798
+ "```",
799
+ "",
800
+ "**Get specific memory**:",
801
+ "",
802
+ "```typescript",
803
+ 'hivemind_get({ id: "mem_xyz123" })',
804
+ "```",
805
+ "",
806
+ "**Delete outdated memory**:",
807
+ "",
808
+ "```typescript",
809
+ 'hivemind_remove({ id: "mem_old456" })',
810
+ "```",
811
+ "",
812
+ "**Validate memory is still accurate** (resets decay):",
813
+ "",
814
+ "```typescript",
815
+ "// Confirmed this memory is still relevant",
816
+ 'hivemind_validate({ id: "mem_xyz123" })',
817
+ "```",
818
+ "",
819
+ "**Index new sessions**:",
820
+ "",
821
+ "```typescript",
822
+ "// Automatically indexes ~/.config/opencode/sessions, ~/.cursor-tutor, etc.",
823
+ "hivemind_index()",
824
+ "```",
825
+ "",
826
+ "**Sync to git**:",
827
+ "",
828
+ "```typescript",
829
+ "// Writes learnings to .hive/memories.jsonl for git sync",
830
+ "hivemind_sync()",
831
+ "```",
832
+ "",
833
+ "**Check stats**:",
834
+ "",
835
+ "```typescript",
836
+ "hivemind_stats()",
837
+ "```",
838
+ "",
839
+ "### Usage Pattern",
840
+ "",
724
841
  "```bash",
725
- "# Search all agents",
726
- 'cass_search(query="authentication token refresh", limit=5)',
842
+ "# 1. Before starting work - query for relevant learnings",
843
+ 'hivemind_find({ query: "<task keywords>", limit: 5 })',
727
844
  "",
728
- "# Filter by agent/time",
729
- 'cass_search(query="useEffect cleanup", agent="claude", days=7)',
845
+ "# 2. Do the work...",
730
846
  "",
731
- "# View specific result",
732
- 'cass_view(path="/path/from/search", line=42)',
847
+ "# 3. After solving hard problem - store learning",
848
+ "hivemind_store({",
849
+ ' information: "<what you learned, WHY it matters>",',
850
+ ' tags: "<relevant,tags>"',
851
+ "})",
733
852
  "",
734
- "# Expand context around match",
735
- 'cass_expand(path="/path", line=42, context=10)',
853
+ "# 4. Validate memories when you confirm they're still accurate",
854
+ 'hivemind_validate({ id: "<memory-id>" })',
736
855
  "```",
737
856
  "",
738
- "**Pro tip:** Query CASS at the START of complex tasks. Past solutions save time.",
739
- ].join(newline);
740
- }
741
-
742
- function buildAgentsSemanticMemorySection(newline: string): string {
743
- return [
744
- "## Semantic Memory - Persistent Learning",
857
+ "### Integration with Workflow",
745
858
  "",
746
- "Store and retrieve learnings across sessions. Memories persist and are searchable.",
859
+ "**At task start** (query BEFORE implementing):",
747
860
  "",
748
- "### When to Use",
861
+ "```bash",
862
+ "# Check if you or any agent solved similar problems",
863
+ 'hivemind_find({ query: "OAuth token refresh buffer", limit: 5 })',
864
+ "```",
749
865
  "",
750
- "- After solving a tricky problem - store the solution",
751
- "- After making architectural decisions - store the reasoning",
752
- "- Before starting work - search for relevant past learnings",
753
- "- When you discover project-specific patterns",
866
+ "**During debugging** (search past sessions):",
754
867
  "",
755
- "### Usage",
868
+ "```bash",
869
+ "# Find similar errors from past sessions",
870
+ 'hivemind_find({ query: "cannot read property of undefined", collection: "claude" })',
871
+ "```",
872
+ "",
873
+ "**After solving problems** (store learnings):",
756
874
  "",
757
875
  "```bash",
758
- "# Store a learning",
759
- 'semantic-memory_store(information="OAuth refresh tokens need 5min buffer before expiry", metadata="auth, tokens")',
876
+ '# Store root cause + solution, not just "fixed it"',
877
+ "hivemind_store({",
878
+ ' information: "Next.js searchParams causes dynamic rendering. Workaround: destructure in parent, pass as props to cached child.",',
879
+ ' tags: "nextjs,cache-components,dynamic-rendering,searchparams"',
880
+ "})",
881
+ "```",
760
882
  "",
761
- "# Search for relevant memories",
762
- 'semantic-memory_find(query="token refresh", limit=5)',
883
+ "**Learning from other agents**:",
763
884
  "",
764
- "# Validate a memory is still accurate (resets decay timer)",
765
- 'semantic-memory_validate(id="mem_123")',
885
+ "```bash",
886
+ "# See how Cursor handled similar feature",
887
+ 'hivemind_find({ query: "implement authentication", collection: "cursor" })',
766
888
  "```",
767
889
  "",
768
- "**Pro tip:** Store the WHY, not just the WHAT. Future you needs context.",
890
+ "**Pro tip:** Query Hivemind at the START of complex tasks. Past solutions (yours or other agents') save time and prevent reinventing wheels.",
769
891
  ].join(newline);
770
892
  }
771
893
 
894
+ // Legacy functions kept for backwards compatibility during migration
895
+ function buildAgentsCassSection(newline: string): string {
896
+ // Redirect to Hivemind section
897
+ return buildAgentsHivemindSection(newline);
898
+ }
899
+
900
+ function buildAgentsSemanticMemorySection(newline: string): string {
901
+ // Redirect to Hivemind section
902
+ return buildAgentsHivemindSection(newline);
903
+ }
904
+
772
905
  function buildAgentsSwarmCoordinatorSection(newline: string): string {
773
906
  return [
774
907
  "## Swarm Coordinator Checklist (MANDATORY)",
@@ -935,6 +1068,53 @@ function updateAgentsMdContent({
935
1068
  changes.push("Updated bundled skills list");
936
1069
  }
937
1070
 
1071
+ // ADR-011: Migrate old tool names to hivemind
1072
+ const hasOldCassTools = /cass_search\(|cass_view\(|cass_expand\(/i.test(updated);
1073
+ const hasOldSemanticTools = /semantic-memory_store\(|semantic-memory_find\(/i.test(updated);
1074
+ const hasHivemindTools = /hivemind_store\(|hivemind_find\(/i.test(updated);
1075
+
1076
+ // If has old tools but not new hivemind tools, we need to update
1077
+ if ((hasOldCassTools || hasOldSemanticTools) && !hasHivemindTools) {
1078
+ // Replace old tool references with hivemind equivalents
1079
+ const beforeMigration = updated;
1080
+
1081
+ // Tool name replacements
1082
+ updated = updated.replace(/semantic-memory_store\(/g, "hivemind_store(");
1083
+ updated = updated.replace(/semantic-memory_find\(/g, "hivemind_find(");
1084
+ updated = updated.replace(/semantic-memory_get\(/g, "hivemind_get(");
1085
+ updated = updated.replace(/semantic-memory_remove\(/g, "hivemind_remove(");
1086
+ updated = updated.replace(/semantic-memory_validate\(/g, "hivemind_validate(");
1087
+ updated = updated.replace(/semantic-memory_list\(/g, "hivemind_find(");
1088
+ updated = updated.replace(/semantic-memory_stats\(/g, "hivemind_stats(");
1089
+ updated = updated.replace(/cass_search\(/g, "hivemind_find(");
1090
+ updated = updated.replace(/cass_view\(/g, "hivemind_get(");
1091
+ updated = updated.replace(/cass_expand\(/g, "hivemind_get(");
1092
+ updated = updated.replace(/cass_health\(/g, "hivemind_stats(");
1093
+ updated = updated.replace(/cass_index\(/g, "hivemind_index(");
1094
+ updated = updated.replace(/cass_stats\(/g, "hivemind_stats(");
1095
+
1096
+ // Table references (without parentheses)
1097
+ updated = updated.replace(/\| `semantic-memory_store` \|/g, "| `hivemind_store` |");
1098
+ updated = updated.replace(/\| `semantic-memory_find` \|/g, "| `hivemind_find` |");
1099
+ updated = updated.replace(/\| `semantic-memory_get` \|/g, "| `hivemind_get` |");
1100
+ updated = updated.replace(/\| `semantic-memory_remove` \|/g, "| `hivemind_remove` |");
1101
+ updated = updated.replace(/\| `semantic-memory_validate` \|/g, "| `hivemind_validate` |");
1102
+ updated = updated.replace(/\| `semantic-memory_list` \|/g, "| `hivemind_find` |");
1103
+ updated = updated.replace(/\| `semantic-memory_stats` \|/g, "| `hivemind_stats` |");
1104
+ updated = updated.replace(/\| `semantic-memory_migrate` \|/g, "| `hivemind_stats` |");
1105
+ updated = updated.replace(/\| `semantic-memory_check` \|/g, "| `hivemind_stats` |");
1106
+ updated = updated.replace(/\| `cass_search` \|/g, "| `hivemind_find` |");
1107
+ updated = updated.replace(/\| `cass_view` \|/g, "| `hivemind_get` |");
1108
+ updated = updated.replace(/\| `cass_expand` \|/g, "| `hivemind_get` |");
1109
+ updated = updated.replace(/\| `cass_health` \|/g, "| `hivemind_stats` |");
1110
+ updated = updated.replace(/\| `cass_index` \|/g, "| `hivemind_index` |");
1111
+ updated = updated.replace(/\| `cass_stats` \|/g, "| `hivemind_stats` |");
1112
+
1113
+ if (updated !== beforeMigration) {
1114
+ changes.push("Migrated cass_*/semantic-memory_* to hivemind_* (ADR-011)");
1115
+ }
1116
+ }
1117
+
938
1118
  // Update tool preferences block if present
939
1119
  const toolPrefsResult = updateAgentsToolPreferencesBlock(updated, newline);
940
1120
  if (toolPrefsResult.changed) {
@@ -942,14 +1122,11 @@ function updateAgentsMdContent({
942
1122
  changes.push("Updated tool_preferences tool list");
943
1123
  }
944
1124
 
945
- // Add missing sections (append at end)
1125
+ // Check for sections - now unified under Hivemind
946
1126
  const hasSkillsSection =
947
1127
  /^#{1,6}\s+Skills\b/im.test(updated) || /skills_list\(\)/.test(updated);
948
- const hasCassSection =
949
- /^#{1,6}\s+.*CASS\b/im.test(updated) || /cass_search\(/.test(updated);
950
- const hasSemanticMemorySection =
951
- /^#{1,6}\s+Semantic Memory\b/im.test(updated) ||
952
- /semantic-memory_store\(/.test(updated);
1128
+ const hasHivemindSection =
1129
+ /^#{1,6}\s+Hivemind\b/im.test(updated) || /hivemind_store\(/.test(updated);
953
1130
  const hasSwarmCoordinatorSection =
954
1131
  /^#{1,6}\s+Swarm Coordinator\b/im.test(updated) ||
955
1132
  /swarm_review\(/.test(updated) ||
@@ -962,13 +1139,9 @@ function updateAgentsMdContent({
962
1139
  );
963
1140
  changes.push("Added Skills section");
964
1141
  }
965
- if (!hasCassSection) {
966
- sectionsToAppend.push(buildAgentsCassSection(newline));
967
- changes.push("Added CASS section");
968
- }
969
- if (!hasSemanticMemorySection) {
970
- sectionsToAppend.push(buildAgentsSemanticMemorySection(newline));
971
- changes.push("Added Semantic Memory section");
1142
+ if (!hasHivemindSection) {
1143
+ sectionsToAppend.push(buildAgentsHivemindSection(newline));
1144
+ changes.push("Added Hivemind section (unified memory)");
972
1145
  }
973
1146
  if (!hasSwarmCoordinatorSection) {
974
1147
  sectionsToAppend.push(buildAgentsSwarmCoordinatorSection(newline));
@@ -1434,15 +1607,33 @@ function getFixCommand(dep: Dependency): string | null {
1434
1607
  }
1435
1608
  }
1436
1609
 
1437
- async function doctor() {
1610
+ async function doctor(debug = false) {
1438
1611
  p.intro("swarm doctor v" + VERSION);
1439
1612
 
1613
+ if (debug) {
1614
+ p.log.step("Debug info:");
1615
+ p.log.message(dim(` Runtime: ${typeof Bun !== 'undefined' ? 'Bun' : 'Node.js'}`));
1616
+ p.log.message(dim(` Node version: ${process.version}`));
1617
+ p.log.message(dim(` Platform: ${process.platform}`));
1618
+ p.log.message(dim(` Arch: ${process.arch}`));
1619
+ p.log.message(dim(` CWD: ${process.cwd()}`));
1620
+ p.log.message(dim(` PATH entries: ${(process.env.PATH || '').split(':').length}`));
1621
+ }
1622
+
1440
1623
  const s = p.spinner();
1441
1624
  s.start("Checking dependencies...");
1442
1625
 
1443
1626
  const results = await checkAllDependencies();
1444
1627
 
1445
1628
  s.stop("Dependencies checked");
1629
+
1630
+ if (debug) {
1631
+ p.log.step("Dependency check details:");
1632
+ for (const { dep, available, version } of results) {
1633
+ const status = available ? green("✓") : red("✗");
1634
+ p.log.message(dim(` ${status} ${dep.command} ${dep.checkArgs.join(" ")} → ${available ? `v${version || "unknown"}` : "not found"}`));
1635
+ }
1636
+ }
1446
1637
 
1447
1638
  const required = results.filter((r) => r.dep.required);
1448
1639
  const optional = results.filter((r) => !r.dep.required);
@@ -1571,6 +1762,23 @@ async function setup(forceReinstall = false, nonInteractive = false) {
1571
1762
 
1572
1763
  p.intro("opencode-swarm-plugin v" + VERSION);
1573
1764
 
1765
+ // CRITICAL: Check for Bun first - the CLI requires Bun runtime
1766
+ const bunCheck = await checkCommand("bun", ["--version"]);
1767
+ if (!bunCheck.available) {
1768
+ p.log.error("Bun is required but not installed!");
1769
+ console.log();
1770
+ console.log(dim(" The swarm CLI requires Bun runtime for Bun-specific APIs."));
1771
+ console.log();
1772
+ console.log(" Install Bun:");
1773
+ console.log(cyan(" curl -fsSL https://bun.sh/install | bash"));
1774
+ console.log();
1775
+ console.log(dim(" Or via Homebrew:"));
1776
+ console.log(cyan(" brew install oven-sh/bun/bun"));
1777
+ console.log();
1778
+ process.exit(1);
1779
+ }
1780
+ p.log.success(`Bun v${bunCheck.version} detected`);
1781
+
1574
1782
  // Migrate legacy database if present (do this first, before config check)
1575
1783
  const cwd = process.cwd();
1576
1784
  const tempDirName = getLibSQLProjectTempDirName(cwd);
@@ -3257,7 +3465,7 @@ async function listTools() {
3257
3465
  // Agents Command - Update AGENTS.md with skill awareness
3258
3466
  // ============================================================================
3259
3467
 
3260
- async function agents() {
3468
+ async function agents(nonInteractive = false) {
3261
3469
  const home = process.env.HOME || process.env.USERPROFILE || "~";
3262
3470
  const agentsPath = join(home, ".config", "opencode", "AGENTS.md");
3263
3471
 
@@ -3273,44 +3481,70 @@ async function agents() {
3273
3481
  return;
3274
3482
  }
3275
3483
 
3276
- const confirm = await p.confirm({
3277
- message: "Update AGENTS.md with skill awareness?",
3278
- initialValue: true,
3279
- });
3484
+ if (!nonInteractive) {
3485
+ const result = await p.confirm({
3486
+ message: "Update AGENTS.md with Hivemind unification?",
3487
+ initialValue: true,
3488
+ });
3280
3489
 
3281
- if (p.isCancel(confirm) || !confirm) {
3282
- p.outro("Aborted");
3283
- return;
3490
+ if (p.isCancel(result) || !result) {
3491
+ p.outro("Aborted");
3492
+ return;
3493
+ }
3284
3494
  }
3285
3495
 
3286
3496
  const s = p.spinner();
3287
- s.start("Updating AGENTS.md with skill awareness...");
3497
+ s.start("Updating AGENTS.md via LLM...");
3288
3498
 
3289
- const bundledSkillsPath = join(__dirname, "..", "global-skills");
3290
- const bundledSkills = listDirectoryNames(bundledSkillsPath);
3499
+ const prompt = `You are updating ~/.config/opencode/AGENTS.md to unify memory tools under Hivemind (ADR-011).
3500
+
3501
+ TASK: Update the AGENTS.md file to:
3502
+
3503
+ 1. **Rename tool references** throughout the file:
3504
+ - \`cass_search\` → \`hivemind_find\`
3505
+ - \`cass_view\` → \`hivemind_get\`
3506
+ - \`cass_expand\` → \`hivemind_get\`
3507
+ - \`cass_health\` → \`hivemind_stats\`
3508
+ - \`cass_index\` → \`hivemind_index\`
3509
+ - \`cass_stats\` → \`hivemind_stats\`
3510
+ - \`semantic-memory_store\` → \`hivemind_store\`
3511
+ - \`semantic-memory_find\` → \`hivemind_find\`
3512
+ - \`semantic-memory_get\` → \`hivemind_get\`
3513
+ - \`semantic-memory_remove\` → \`hivemind_remove\`
3514
+ - \`semantic-memory_validate\` → \`hivemind_validate\`
3515
+ - \`semantic-memory_list\` → \`hivemind_find\`
3516
+ - \`semantic-memory_stats\` → \`hivemind_stats\`
3517
+
3518
+ 2. **Consolidate sections**: If there are separate "CASS" and "Semantic Memory" sections, merge them into a single "Hivemind - Unified Memory System" section that covers:
3519
+ - Unified storage (learnings + sessions in same DB)
3520
+ - All hivemind_* tools with descriptions
3521
+ - Usage examples showing both storing learnings and searching sessions
3522
+ - The 90-day decay and validation workflow
3523
+
3524
+ 3. **Update any prose** that mentions "CASS" or "semantic memory" separately to use "Hivemind" terminology.
3525
+
3526
+ 4. **Keep existing structure** - don't reorganize unrelated sections.
3527
+
3528
+ Read the file, make the updates, and save it. Create a backup first.`;
3291
3529
 
3292
3530
  try {
3293
- const bundledSkillsCsv =
3294
- bundledSkills.length > 0
3295
- ? bundledSkills.join(", ")
3296
- : "cli-builder, learning-systems, skill-creator, swarm-coordination, system-design, testing-patterns";
3297
-
3298
- const result = updateAgentsMdFile({ agentsPath, bundledSkillsCsv });
3299
-
3300
- if (result.changed) {
3301
- s.stop("AGENTS.md updated with skill awareness");
3302
- p.log.success("Skills section added to " + agentsPath);
3303
- p.log.message(
3304
- dim("Skills available: skills_list, skills_use, skills_read"),
3305
- );
3306
- if (result.backupPath) {
3307
- p.log.message(dim("Backup: " + result.backupPath));
3308
- }
3531
+ const proc = Bun.spawn(["opencode", "run", prompt], {
3532
+ stdio: ["inherit", "pipe", "pipe"],
3533
+ cwd: home,
3534
+ });
3535
+
3536
+ const exitCode = await proc.exited;
3537
+
3538
+ if (exitCode === 0) {
3539
+ s.stop("AGENTS.md updated via LLM");
3540
+ p.log.success("Hivemind unification complete");
3309
3541
  } else {
3310
- s.stop("AGENTS.md already up to date");
3542
+ const stderr = await new Response(proc.stderr).text();
3543
+ s.stop("LLM update failed");
3544
+ p.log.error(stderr || `Exit code: ${exitCode}`);
3311
3545
  }
3312
3546
  } catch (error) {
3313
- s.stop("Failed to update AGENTS.md");
3547
+ s.stop("Failed to run opencode");
3314
3548
  p.log.error(String(error));
3315
3549
  }
3316
3550
 
@@ -5282,9 +5516,11 @@ switch (command) {
5282
5516
  await setup(reinstallFlag || yesFlag, yesFlag);
5283
5517
  break;
5284
5518
  }
5285
- case "doctor":
5286
- await doctor();
5519
+ case "doctor": {
5520
+ const debugFlag = process.argv.includes("--debug") || process.argv.includes("-d");
5521
+ await doctor(debugFlag);
5287
5522
  break;
5523
+ }
5288
5524
  case "init":
5289
5525
  await init();
5290
5526
  break;
@@ -5313,9 +5549,11 @@ switch (command) {
5313
5549
  }
5314
5550
  break;
5315
5551
  }
5316
- case "agents":
5317
- await agents();
5552
+ case "agents": {
5553
+ const agentsNonInteractive = process.argv.includes("--yes") || process.argv.includes("-y");
5554
+ await agents(agentsNonInteractive);
5318
5555
  break;
5556
+ }
5319
5557
  case "migrate":
5320
5558
  await migrate();
5321
5559
  break;