create-egregore 0.19.33 → 0.20.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 (171) hide show
  1. package/assets/egregore-launcher.js +118 -13
  2. package/bin/cli.js +19 -3
  3. package/lib/connect-runtime.js +4 -2
  4. package/lib/local.js +15 -1
  5. package/lib/prime-runtime.js +208 -0
  6. package/lib/setup.js +45 -3
  7. package/package.json +4 -3
  8. package/runtime/codex/.codex/skills/ingest-notion/SKILL.md +29 -0
  9. package/runtime/codex/.codex/skills/notion-connect/SKILL.md +29 -0
  10. package/runtime/codex/.codex/skills/teams-connect/SKILL.md +29 -0
  11. package/runtime/codex/.codex/spec-manifest.json +3 -3
  12. package/runtime/codex/AGENTS.md +11 -4
  13. package/runtime/codex/bin/activity-data.sh +4 -8
  14. package/runtime/codex/bin/attendant.sh +13 -0
  15. package/runtime/codex/bin/autosave.sh +27 -1
  16. package/runtime/codex/bin/codex-render-spec.mjs +6 -0
  17. package/runtime/codex/bin/codex-session-start.sh +3 -1
  18. package/runtime/codex/bin/graph-batch.sh +25 -6
  19. package/runtime/codex/bin/graph-op.sh +5 -4
  20. package/runtime/codex/bin/graph.sh +31 -5
  21. package/runtime/codex/bin/ingest.py +81 -5
  22. package/runtime/codex/bin/lib/context.sh +26 -1
  23. package/runtime/codex/bin/lib/greeting.sh +4 -1
  24. package/runtime/codex/bin/lib/worktree-links.sh +25 -0
  25. package/runtime/codex/manifest.json +7 -1
  26. package/runtime/pi/.codex/skills/ingest-notion/SKILL.md +29 -0
  27. package/runtime/pi/.codex/skills/notion-connect/SKILL.md +29 -0
  28. package/runtime/pi/.codex/skills/teams-connect/SKILL.md +29 -0
  29. package/runtime/pi/.codex/spec-manifest.json +3 -3
  30. package/runtime/pi/.pi/APPEND_SYSTEM.md +3 -2
  31. package/runtime/pi/.pi/extensions/egregore.ts +17 -6
  32. package/runtime/pi/.pi/spec-manifest.json +2 -2
  33. package/runtime/pi/AGENTS.md +11 -4
  34. package/runtime/pi/bin/activity-data.sh +4 -8
  35. package/runtime/pi/bin/attendant.sh +13 -0
  36. package/runtime/pi/bin/autosave.sh +27 -1
  37. package/runtime/pi/bin/codex-render-spec.mjs +6 -0
  38. package/runtime/pi/bin/codex-session-start.sh +3 -1
  39. package/runtime/pi/bin/graph-batch.sh +25 -6
  40. package/runtime/pi/bin/graph-op.sh +5 -4
  41. package/runtime/pi/bin/graph.sh +31 -5
  42. package/runtime/pi/bin/ingest.py +81 -5
  43. package/runtime/pi/bin/lib/context.sh +26 -1
  44. package/runtime/pi/bin/lib/greeting.sh +4 -1
  45. package/runtime/pi/bin/lib/worktree-links.sh +25 -0
  46. package/runtime/pi/bin/pi-branch-policy.mjs +138 -1
  47. package/runtime/pi/bin/pi-product-workflows.mjs +35 -7
  48. package/runtime/pi/manifest.json +7 -1
  49. package/runtime/prime/.claude/context/notification-consent.md +66 -0
  50. package/runtime/prime/.codex/config.toml +17 -0
  51. package/runtime/prime/.codex/hooks/branch-guard.js +461 -0
  52. package/runtime/prime/.codex/hooks/search-hint.js +67 -0
  53. package/runtime/prime/.codex/hooks.json +30 -0
  54. package/runtime/prime/.codex/skills/activity/SKILL.md +82 -0
  55. package/runtime/prime/.codex/skills/announce/SKILL.md +67 -0
  56. package/runtime/prime/.codex/skills/archive/SKILL.md +45 -0
  57. package/runtime/prime/.codex/skills/branch/SKILL.md +29 -0
  58. package/runtime/prime/.codex/skills/checkup/SKILL.md +45 -0
  59. package/runtime/prime/.codex/skills/commit/SKILL.md +29 -0
  60. package/runtime/prime/.codex/skills/contribute/SKILL.md +29 -0
  61. package/runtime/prime/.codex/skills/create-skill/SKILL.md +29 -0
  62. package/runtime/prime/.codex/skills/dark-mode/SKILL.md +29 -0
  63. package/runtime/prime/.codex/skills/dashboard/SKILL.md +59 -0
  64. package/runtime/prime/.codex/skills/deep-reflect/SKILL.md +109 -0
  65. package/runtime/prime/.codex/skills/delete-user/SKILL.md +29 -0
  66. package/runtime/prime/.codex/skills/emissary/SKILL.md +45 -0
  67. package/runtime/prime/.codex/skills/handoff/SKILL.md +166 -0
  68. package/runtime/prime/.codex/skills/harvest/QUESTION_PALETTE.md +76 -0
  69. package/runtime/prime/.codex/skills/harvest/SKILL.md +131 -0
  70. package/runtime/prime/.codex/skills/ingest/SKILL.md +29 -0
  71. package/runtime/prime/.codex/skills/ingest-notion/SKILL.md +29 -0
  72. package/runtime/prime/.codex/skills/ingest-user-interview/SKILL.md +45 -0
  73. package/runtime/prime/.codex/skills/invite/SKILL.md +44 -0
  74. package/runtime/prime/.codex/skills/issue/SKILL.md +45 -0
  75. package/runtime/prime/.codex/skills/me/SKILL.md +29 -0
  76. package/runtime/prime/.codex/skills/meeting/SKILL.md +45 -0
  77. package/runtime/prime/.codex/skills/note/SKILL.md +29 -0
  78. package/runtime/prime/.codex/skills/notion-connect/SKILL.md +29 -0
  79. package/runtime/prime/.codex/skills/onboarding/SKILL.md +45 -0
  80. package/runtime/prime/.codex/skills/pr/SKILL.md +29 -0
  81. package/runtime/prime/.codex/skills/pull/SKILL.md +29 -0
  82. package/runtime/prime/.codex/skills/push/SKILL.md +29 -0
  83. package/runtime/prime/.codex/skills/quest/SKILL.md +80 -0
  84. package/runtime/prime/.codex/skills/reflect/SKILL.md +45 -0
  85. package/runtime/prime/.codex/skills/review-pr/SKILL.md +45 -0
  86. package/runtime/prime/.codex/skills/save/SKILL.md +125 -0
  87. package/runtime/prime/.codex/skills/slack-connect/SKILL.md +29 -0
  88. package/runtime/prime/.codex/skills/summon/SKILL.md +45 -0
  89. package/runtime/prime/.codex/skills/sync-repos/SKILL.md +29 -0
  90. package/runtime/prime/.codex/skills/teams-connect/SKILL.md +29 -0
  91. package/runtime/prime/.codex/skills/telegram-connect/SKILL.md +29 -0
  92. package/runtime/prime/.codex/skills/telemetry/SKILL.md +29 -0
  93. package/runtime/prime/.codex/skills/test/SKILL.md +45 -0
  94. package/runtime/prime/.codex/skills/the-spiral/SKILL.md +84 -0
  95. package/runtime/prime/.codex/skills/tui-design/SKILL.md +45 -0
  96. package/runtime/prime/.codex/skills/tutorial/SKILL.md +45 -0
  97. package/runtime/prime/.codex/skills/update/SKILL.md +29 -0
  98. package/runtime/prime/.codex/skills/view/SKILL.md +156 -0
  99. package/runtime/prime/.codex/skills/view/agents/openai.yaml +4 -0
  100. package/runtime/prime/.codex/skills/view/assets/compose-scaffold.html +221 -0
  101. package/runtime/prime/.codex/skills/visual-explain/SKILL.md +45 -0
  102. package/runtime/prime/.codex/skills/wrap/SKILL.md +58 -0
  103. package/runtime/prime/.codex/spec-manifest.json +132 -0
  104. package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +393 -0
  105. package/runtime/prime/.prime/agent/extensions/egregore.ts +460 -0
  106. package/runtime/prime/.prime/agent/settings.json +4 -0
  107. package/runtime/prime/.prime/agent/skills/egregore/SKILL.md +34 -0
  108. package/runtime/prime/.prime/agent/skills/egregore/pyproject.toml +13 -0
  109. package/runtime/prime/.prime/agent/skills/egregore/src/egregore/__init__.py +156 -0
  110. package/runtime/prime/.prime/agent/spec-manifest.json +12 -0
  111. package/runtime/prime/AGENTS.md +489 -0
  112. package/runtime/prime/bin/activity-data.sh +238 -0
  113. package/runtime/prime/bin/agent.sh +775 -0
  114. package/runtime/prime/bin/attendant.sh +707 -0
  115. package/runtime/prime/bin/autosave.sh +112 -0
  116. package/runtime/prime/bin/capture-reconcile.sh +69 -0
  117. package/runtime/prime/bin/capture-run.sh +341 -0
  118. package/runtime/prime/bin/codex-install-skills.sh +78 -0
  119. package/runtime/prime/bin/codex-render-spec.mjs +440 -0
  120. package/runtime/prime/bin/codex-session-start.sh +265 -0
  121. package/runtime/prime/bin/codex-skill-render.mjs +347 -0
  122. package/runtime/prime/bin/codex-sync-skills.sh +232 -0
  123. package/runtime/prime/bin/connect-refresh.sh +33 -0
  124. package/runtime/prime/bin/dashboard-data.sh +178 -0
  125. package/runtime/prime/bin/graph-batch.sh +79 -0
  126. package/runtime/prime/bin/graph-op.sh +1102 -0
  127. package/runtime/prime/bin/graph-wal.sh +229 -0
  128. package/runtime/prime/bin/graph.sh +223 -0
  129. package/runtime/prime/bin/handoff-pr-backfill.sh +86 -0
  130. package/runtime/prime/bin/handoff-run.sh +671 -0
  131. package/runtime/prime/bin/handoff-save-egregore.sh +212 -0
  132. package/runtime/prime/bin/index-handoff.sh +322 -0
  133. package/runtime/prime/bin/ingest-graph.sh +80 -0
  134. package/runtime/prime/bin/ingest-surface.html +495 -0
  135. package/runtime/prime/bin/ingest.py +756 -0
  136. package/runtime/prime/bin/ingest.sh +279 -0
  137. package/runtime/prime/bin/ingest_graph.py +856 -0
  138. package/runtime/prime/bin/ingest_surface.py +544 -0
  139. package/runtime/prime/bin/lib/artifact-id.sh +46 -0
  140. package/runtime/prime/bin/lib/config.sh +116 -0
  141. package/runtime/prime/bin/lib/context.sh +621 -0
  142. package/runtime/prime/bin/lib/dashboard-artifact.sh +242 -0
  143. package/runtime/prime/bin/lib/ensure-develop.sh +183 -0
  144. package/runtime/prime/bin/lib/git-sync.sh +406 -0
  145. package/runtime/prime/bin/lib/greeting.sh +519 -0
  146. package/runtime/prime/bin/lib/hash.sh +13 -0
  147. package/runtime/prime/bin/lib/identity.sh +213 -0
  148. package/runtime/prime/bin/lib/metrics.sh +374 -0
  149. package/runtime/prime/bin/lib/noncode.sh +31 -0
  150. package/runtime/prime/bin/lib/permissions.sh +106 -0
  151. package/runtime/prime/bin/lib/time.sh +56 -0
  152. package/runtime/prime/bin/lib/worktree-links.sh +79 -0
  153. package/runtime/prime/bin/notify.sh +636 -0
  154. package/runtime/prime/bin/person.py +630 -0
  155. package/runtime/prime/bin/person.sh +448 -0
  156. package/runtime/prime/bin/pi-branch-policy.mjs +312 -0
  157. package/runtime/prime/bin/pi-product-workflows.mjs +394 -0
  158. package/runtime/prime/bin/prime-render-spec.mjs +123 -0
  159. package/runtime/prime/bin/prime-session-start.sh +24 -0
  160. package/runtime/prime/bin/publish-artifact.sh +271 -0
  161. package/runtime/prime/bin/publish-references.sh +144 -0
  162. package/runtime/prime/bin/repo-state.sh +96 -0
  163. package/runtime/prime/bin/search.sh +240 -0
  164. package/runtime/prime/bin/session-autosave.sh +209 -0
  165. package/runtime/prime/bin/session-log.sh +199 -0
  166. package/runtime/prime/bin/settings.sh +304 -0
  167. package/runtime/prime/bin/telemetry.sh +391 -0
  168. package/runtime/prime/bin/worktree-create.sh +128 -0
  169. package/runtime/prime/bin/worktree-remove.sh +50 -0
  170. package/runtime/prime/bin/worktree.sh +198 -0
  171. package/runtime/prime/manifest.json +178 -0
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // egregore-launcher-version: 0.19.33
2
+ // egregore-launcher-version: 0.20.0
3
3
  //
4
4
  // egregore — launch and browse Egregore instances from your terminal.
5
5
  // Installed by create-egregore. Reads ~/.egregore/instances.json.
@@ -33,7 +33,7 @@ const crypto = require("node:crypto");
33
33
  const { spawnSync, spawn } = require("node:child_process");
34
34
  const readline = require("node:readline");
35
35
 
36
- const VERSION = "0.19.33";
36
+ const VERSION = "0.20.0";
37
37
  const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
38
38
  const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
39
39
  const UPDATE_CACHE_FILE = path.join(os.homedir(), ".egregore", "update-check.json");
@@ -368,6 +368,7 @@ function normalizeRuntime(raw) {
368
368
  if (value === "claude" || value === "claude-code" || value === "claude_code") return "claude-code";
369
369
  if (value === "codex" || value === "openai-codex" || value === "openai_codex") return "codex";
370
370
  if (value === "pi" || value === "pi-coding-agent" || value === "pi_coding_agent") return "pi";
371
+ if (value === "prime" || value === "prime-agent" || value === "prime_agent") return "prime";
371
372
  return null;
372
373
  }
373
374
 
@@ -380,6 +381,8 @@ function parseRuntimeFlags(argv) {
380
381
  runtimeOverride = "codex";
381
382
  } else if (arg === "--pi") {
382
383
  runtimeOverride = "pi";
384
+ } else if (arg === "--prime") {
385
+ runtimeOverride = "prime";
383
386
  } else if (arg === "--claude" || arg === "--claude-code") {
384
387
  runtimeOverride = "claude-code";
385
388
  } else if (arg === "--runtime") {
@@ -393,7 +396,7 @@ function parseRuntimeFlags(argv) {
393
396
  }
394
397
  }
395
398
  const normalized = runtimeOverride ? normalizeRuntime(runtimeOverride) : null;
396
- if (runtimeOverride && !normalized) die(`unknown runtime: ${runtimeOverride}\n expected claude-code, codex, or pi`);
399
+ if (runtimeOverride && !normalized) die(`unknown runtime: ${runtimeOverride}\n expected claude-code, codex, pi, or prime`);
397
400
  return { args: rest, runtimeOverride: normalized };
398
401
  }
399
402
 
@@ -412,20 +415,23 @@ function runtimeFor(inst, runtimeOverride) {
412
415
  function runtimeLabel(runtime) {
413
416
  if (runtime === "codex") return "Codex";
414
417
  if (runtime === "pi") return "Pi";
418
+ if (runtime === "prime") return "Prime Agent";
415
419
  return "Claude Code";
416
420
  }
417
421
 
418
422
  function runtimeShort(runtime) {
419
- return runtime === "codex" ? "codex" : runtime === "pi" ? "pi" : "claude-code";
423
+ return runtime === "codex" ? "codex" : runtime === "pi" ? "pi" : runtime === "prime" ? "prime" : "claude-code";
420
424
  }
421
425
 
422
426
  function runtimeBinary(runtime) {
423
- return runtime === "codex" ? "codex" : runtime === "pi" ? "pi" : "claude";
427
+ return runtime === "codex" ? "codex" : runtime === "pi" ? "pi" : runtime === "prime" ? "prime-agent" : "claude";
424
428
  }
425
429
 
426
430
  function assistantInstallCommand(runtime) {
427
431
  if (runtime === "codex") return "npm install -g @openai/codex";
428
432
  if (runtime === "pi") return "npm install -g --ignore-scripts @earendil-works/pi-coding-agent";
433
+ // Prime Agent is not on the public npm registry — install via its own script.
434
+ if (runtime === "prime") return "curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh";
429
435
  return "npm install -g @anthropic-ai/claude-code";
430
436
  }
431
437
 
@@ -438,6 +444,15 @@ function piTrustArgs() {
438
444
  }
439
445
  }
440
446
 
447
+ function primeTrustArgs() {
448
+ try {
449
+ const help = spawnSync("prime-agent", ["--help"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
450
+ return `${help.stdout || ""}\n${help.stderr || ""}`.includes("--approve") ? ["--approve"] : [];
451
+ } catch {
452
+ return [];
453
+ }
454
+ }
455
+
441
456
  function commandExists(bin) {
442
457
  if (typeof bin !== "string" || bin.length === 0) return false;
443
458
  const pathValue = process.env.PATH || process.env.Path || process.env.path || "";
@@ -477,7 +492,7 @@ function runtimeChoiceDescription(runtime, inst, stored) {
477
492
  bits.push("installed");
478
493
  if (runtime === stored) bits.push("saved default");
479
494
  if (runtime === "codex") bits.push("portable agent protocol");
480
- else if (runtime === "pi") bits.push("project-local meta-harness");
495
+ else if (runtime === "pi" || runtime === "prime") bits.push("project-local meta-harness");
481
496
  else bits.push("Claude Code integration");
482
497
  return bits.join(" · ");
483
498
  }
@@ -590,7 +605,7 @@ function runtimeChoicesFor(inst, runtimeOverride) {
590
605
  const override = normalizeRuntime(runtimeOverride);
591
606
  if (override) return [override];
592
607
  const stored = storedRuntimeFor(inst);
593
- const choices = [stored, ...["claude-code", "codex", "pi"].filter((runtime) => runtime !== stored)];
608
+ const choices = [stored, ...["claude-code", "codex", "pi", "prime"].filter((runtime) => runtime !== stored)];
594
609
  return choices.sort((a, b) => Number(commandExists(runtimeBinary(b))) - Number(commandExists(runtimeBinary(a))));
595
610
  }
596
611
 
@@ -722,6 +737,75 @@ function piSupportMessage(egregoreDir) {
722
737
  ].join("\n");
723
738
  }
724
739
 
740
+ function hasPrimeCoreSupport(egregoreDir) {
741
+ return (
742
+ fs.existsSync(path.join(egregoreDir, "bin", "prime-session-start.sh")) &&
743
+ fs.existsSync(path.join(egregoreDir, ".prime", "agent", "APPEND_SYSTEM.md")) &&
744
+ fs.existsSync(path.join(egregoreDir, ".prime", "agent", "settings.json")) &&
745
+ fs.existsSync(path.join(egregoreDir, ".prime", "agent", "extensions", "egregore.ts")) &&
746
+ fs.existsSync(path.join(egregoreDir, ".codex", "skills"))
747
+ );
748
+ }
749
+
750
+ function primeSupportMessage(egregoreDir) {
751
+ return [
752
+ "Prime Agent runtime support is missing from this Egregore checkout.",
753
+ ` path: ${egregoreDir}`,
754
+ "",
755
+ "Run npx -y create-egregore@latest to install the packaged Prime Agent runtime, then rerun egregore.",
756
+ ].join("\n");
757
+ }
758
+
759
+ // Minimal y/N line prompt for pre-launch decisions (the TUI select machinery
760
+ // is torn down by the time launch() runs).
761
+ function confirmLine(question) {
762
+ return new Promise((resolve) => {
763
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
764
+ rl.question(` ${question} [Y/n] `, (answer) => {
765
+ rl.close();
766
+ resolve(!/^n/i.test(String(answer).trim()));
767
+ });
768
+ });
769
+ }
770
+
771
+ // Guided install: never leave the user alone with a curl one-liner. Runs the
772
+ // official installer with full output visible, then re-checks the binary.
773
+ async function offerPrimeInstall() {
774
+ const command = assistantInstallCommand("prime");
775
+ process.stdout.write([
776
+ "",
777
+ ` ${BOLD}Prime Agent isn't installed.${RESET}`,
778
+ ` ${DIM}Egregore can run the official installer now:${RESET}`,
779
+ ` ${command}`,
780
+ "",
781
+ ].join("\n"));
782
+ const yes = await confirmLine("Install Prime Agent now?");
783
+ if (!yes) return false;
784
+ const result = spawnSync("sh", ["-c", command], { stdio: "inherit" });
785
+ if (result.status !== 0 || !commandExists(runtimeBinary("prime"))) {
786
+ process.stdout.write(`\n ${DIM}Installer did not complete — run it manually, then: egregore${RESET}\n`);
787
+ return false;
788
+ }
789
+ process.stdout.write(`\n ${CYAN}✓${RESET} Prime Agent installed\n`);
790
+ return true;
791
+ }
792
+
793
+ // Auth stays harness-owned; the launcher only removes the dead end of a first
794
+ // session with no model account connected.
795
+ function primeAuthHint() {
796
+ const agentDir = process.env.PRIME_AGENT_CODING_AGENT_DIR ||
797
+ path.join(os.homedir(), ".prime", "agent");
798
+ try {
799
+ const auth = JSON.parse(fs.readFileSync(path.join(agentDir, "auth.json"), "utf-8"));
800
+ if (auth && Object.keys(auth).length > 0) return;
801
+ } catch {}
802
+ process.stdout.write(
803
+ `\n ${DIM}First run: connect a model account inside Prime Agent — type ${RESET}/login${DIM}` +
804
+ ` (Claude Pro/Max subscription or an API key). Heads-up: subscription usage in` +
805
+ ` third-party harnesses bills per token as extra usage.${RESET}\n\n`,
806
+ );
807
+ }
808
+
725
809
  function installCodexSkills(egregoreDir) {
726
810
  const script = path.join(egregoreDir, "bin", "codex-install-skills.sh");
727
811
  if (!fs.existsSync(script)) return false;
@@ -766,6 +850,7 @@ function runtimeLaunchArgs(runtime, egregoreDir) {
766
850
  ];
767
851
  }
768
852
  if (runtime === "pi") return piTrustArgs();
853
+ if (runtime === "prime") return primeTrustArgs();
769
854
  return claudeLaunchArgs(egregoreDir);
770
855
  }
771
856
 
@@ -792,7 +877,12 @@ async function launch(inst, runtimeOverride) {
792
877
  }
793
878
  const binary = runtimeBinary(runtime);
794
879
  if (!commandExists(binary)) {
795
- die(`${runtimeLabel(runtime)} is not installed.\n Install it with:\n ${assistantInstallCommand(runtime)}\n Then run: egregore`);
880
+ // Never run a curl|sh installer off non-interactive stdin: piped or
881
+ // closed input must fall through to the printed install command.
882
+ const installed = runtime === "prime" && canPrompt() && await offerPrimeInstall();
883
+ if (!installed) {
884
+ die(`${runtimeLabel(runtime)} is not installed.\n Install it with:\n ${assistantInstallCommand(runtime)}\n Then run: egregore`);
885
+ }
796
886
  }
797
887
  if (runtime === "codex") {
798
888
  if (!hasCodexCoreSupport(inst.path)) {
@@ -806,6 +896,20 @@ async function launch(inst, runtimeOverride) {
806
896
  } else if (runtime === "pi") {
807
897
  if (!hasPiCoreSupport(inst.path)) die(piSupportMessage(inst.path));
808
898
  }
899
+ let launchArgs = null;
900
+ if (runtime === "prime") {
901
+ // Cover the gap between choosing the harness and Prime's first paint:
902
+ // the loader runs through the launcher-side pre-flight (core-support
903
+ // check + the trust-flag probe, which shells out to the binary), then a
904
+ // single handoff line explains the remaining in-harness startup.
905
+ const stopLoader = startSpinner("Starting Prime Agent");
906
+ const coreOk = hasPrimeCoreSupport(inst.path);
907
+ launchArgs = coreOk ? runtimeLaunchArgs(runtime, inst.path) : null;
908
+ stopLoader();
909
+ if (!coreOk) die(primeSupportMessage(inst.path));
910
+ primeAuthHint();
911
+ process.stdout.write(` ${CYAN}◆${RESET} ${BOLD}Prime Agent starting${RESET}${DIM} — the Egregore greeting loads inside in a few seconds${RESET}\n`);
912
+ }
809
913
  // Claude Code renders the greeting in-chat — no pre-launch card. Claude Code
810
914
  // ≥2.1.89 boots into the alternate screen buffer, which hides anything
811
915
  // printed here; the launcher-card fast path is parked in PR #1493.
@@ -816,7 +920,7 @@ async function launch(inst, runtimeOverride) {
816
920
  EGREGORE_RUNTIME: runtime,
817
921
  EGREGORE_CODEX_TRUSTED: runtime === "codex" ? "1" : process.env.EGREGORE_CODEX_TRUSTED,
818
922
  };
819
- const child = spawn(binary, runtimeLaunchArgs(runtime, inst.path), {
923
+ const child = spawn(binary, launchArgs || runtimeLaunchArgs(runtime, inst.path), {
820
924
  cwd: inst.path,
821
925
  stdio: "inherit",
822
926
  env: launchEnv,
@@ -940,7 +1044,7 @@ function cmdHelp() {
940
1044
  ` ${CYAN}egregore${RESET} pick an instance, then pick a harness`,
941
1045
  ` ${CYAN}egregore${RESET} ${DIM}<slug|name>${RESET} pick a harness for the matching instance`,
942
1046
  ` ${CYAN}egregore --runtime${RESET} ${DIM}<name> <slug>${RESET} advanced harness override`,
943
- ` ${DIM}names: claude-code · codex · pi${RESET}`,
1047
+ ` ${DIM}names: claude-code · codex · pi · prime${RESET}`,
944
1048
  ` ${CYAN}egregore browse${RESET} force the full-screen browser`,
945
1049
  ` ${CYAN}egregore ls${RESET} ${DIM}| list${RESET} list installed instances`,
946
1050
  ` ${CYAN}egregore use${RESET} ${DIM}<slug>${RESET} set the default for bare ${BOLD}egregore${RESET}`,
@@ -2176,6 +2280,7 @@ function renderHeroPanel({ selected, pv, width, height, countSuffix, filter, fil
2176
2280
  `${DIM}claude-code${RESET}: ${commandExists("claude") ? "installed" : "not installed"}`,
2177
2281
  `${DIM}codex${RESET}: ${commandExists("codex") ? "installed" : "not installed"}`,
2178
2282
  `${DIM}pi${RESET}: ${commandExists("pi") ? "installed" : "not installed"}`,
2283
+ `${DIM}prime${RESET}: ${commandExists("prime-agent") ? "installed" : "not installed"}`,
2179
2284
  `${DIM}Hermes — Coming Soon${RESET}`,
2180
2285
  ];
2181
2286
  const rows = Math.max(EGREGORE_SIGIL.length + 2, right.length);
@@ -2188,11 +2293,11 @@ function renderHeroPanel({ selected, pv, width, height, countSuffix, filter, fil
2188
2293
  lines.push(boxLine(`${BOLD}Available Skills${RESET}`, innerWidth, margin));
2189
2294
  for (const group of skillGroups) lines.push(boxLine(group, innerWidth, margin));
2190
2295
  lines.push(emptyBoxLine(innerWidth, margin));
2191
- lines.push(boxLine(`${BOLD}Harnesses${RESET} ${DIM}claude-code${RESET} ${commandExists("claude") ? "installed" : "missing"} · ${DIM}codex${RESET} ${commandExists("codex") ? "installed" : "missing"} · ${DIM}pi${RESET} ${commandExists("pi") ? "installed" : "missing"} · ${DIM}Hermes — Coming Soon${RESET}`, innerWidth, margin));
2296
+ lines.push(boxLine(`${BOLD}Harnesses${RESET} ${DIM}claude-code${RESET} ${commandExists("claude") ? "installed" : "missing"} · ${DIM}codex${RESET} ${commandExists("codex") ? "installed" : "missing"} · ${DIM}pi${RESET} ${commandExists("pi") ? "installed" : "missing"} · ${DIM}prime${RESET} ${commandExists("prime-agent") ? "installed" : "missing"} · ${DIM}Hermes — Coming Soon${RESET}`, innerWidth, margin));
2192
2297
  }
2193
2298
 
2194
2299
  lines.push(emptyBoxLine(innerWidth, margin));
2195
- lines.push(boxLine(`${DIM}enter selects an instance, then choose Claude Code, Codex, or Pi without leaving this screen${RESET}`, innerWidth, margin));
2300
+ lines.push(boxLine(`${DIM}enter selects an instance, then choose Claude Code, Codex, Pi, or Prime Agent without leaving this screen${RESET}`, innerWidth, margin));
2196
2301
  lines.push(bottom);
2197
2302
  return lines;
2198
2303
  }
@@ -2555,7 +2660,7 @@ async function browser(args = {}) {
2555
2660
  const label = (k) => `${DIM}${pad(k, 10)}${RESET}`;
2556
2661
  previewLines.push(` ${label("action")} ${BOLD}Set up a new Egregore${RESET}`);
2557
2662
  previewLines.push(` ${label("flow")} guided install, Telegram, invite, ready/start`);
2558
- previewLines.push(` ${label("harness")} choose Claude Code, Codex, or Pi during setup`);
2663
+ previewLines.push(` ${label("harness")} choose Claude Code, Codex, Pi, or Prime Agent during setup`);
2559
2664
  previewLines.push(` ${label("start")} press enter to begin`);
2560
2665
  } else if (!selected) {
2561
2666
  previewLines.push(`${DIM} (no selection)${RESET}`);
package/bin/cli.js CHANGED
@@ -35,6 +35,11 @@ const {
35
35
  installPiRuntime,
36
36
  reportPiRuntimeSummary,
37
37
  } = require("../lib/pi-runtime");
38
+ const {
39
+ hasPrimeRuntimeSupport,
40
+ installPrimeRuntime,
41
+ reportPrimeRuntimeSummary,
42
+ } = require("../lib/prime-runtime");
38
43
  const {
39
44
  connectEligibility,
40
45
  fetchConnectRuntimePack,
@@ -111,6 +116,7 @@ function assistantLabel(runtime) {
111
116
  const normalized = normalizeRuntime(runtime);
112
117
  if (normalized === "codex") return "Codex";
113
118
  if (normalized === "pi") return "Pi";
119
+ if (normalized === "prime") return "Prime Agent";
114
120
  return "Claude Code";
115
121
  }
116
122
 
@@ -137,6 +143,12 @@ async function upgradePortableRuntimesForExisting(instances) {
137
143
  label: `Pi meta-harness for ${inst.slug || inst.name || path.basename(inst.path)}`,
138
144
  includeConflicts: !piReady,
139
145
  });
146
+ const primeSummary = installPrimeRuntime(inst.path);
147
+ const primeReady = hasPrimeRuntimeSupport(inst.path);
148
+ reportPrimeRuntimeSummary(primeSummary, ui, {
149
+ label: `Prime Agent runtime for ${inst.slug || inst.name || path.basename(inst.path)}`,
150
+ includeConflicts: !primeReady,
151
+ });
140
152
  const connectSummary = await installConnectRuntime(inst.path, { validatedPack: connectPack });
141
153
  reportConnectRuntimeSummary(connectSummary, ui, {
142
154
  label: `Connect features for ${inst.slug || inst.name || path.basename(inst.path)}`,
@@ -163,9 +175,10 @@ async function chooseRuntime(args) {
163
175
  "claude-code": binaryOnPath("claude"),
164
176
  codex: binaryOnPath("codex"),
165
177
  pi: binaryOnPath("pi"),
178
+ prime: binaryOnPath("prime-agent"),
166
179
  };
167
180
  const recommended = Object.keys(installedByRuntime).find((runtime) => installedByRuntime[runtime]) || "claude-code";
168
- const choices = ["claude-code", "codex", "pi"]
181
+ const choices = ["claude-code", "codex", "pi", "prime"]
169
182
  .map((runtime) => {
170
183
  const installed = installedByRuntime[runtime];
171
184
  const label = assistantLabel(runtime);
@@ -173,7 +186,7 @@ async function chooseRuntime(args) {
173
186
  return {
174
187
  label: `${label}${installed ? "" : " (not installed)"}${recommended === runtime ? " (recommended)" : ""}`,
175
188
  description: installed
176
- ? (runtime === "claude-code" ? "Installed · Claude Code integration" : runtime === "pi" ? "Installed · project-local meta-harness" : "Installed · portable agent protocol")
189
+ ? (runtime === "claude-code" ? "Installed · Claude Code integration" : runtime === "pi" || runtime === "prime" ? "Installed · project-local meta-harness" : "Installed · portable agent protocol")
177
190
  : missingCopy,
178
191
  runtime,
179
192
  installed,
@@ -249,6 +262,8 @@ function parseArgs(argv) {
249
262
  args.runtime = "codex";
250
263
  } else if (argv[i] === "--pi") {
251
264
  args.runtime = "pi";
265
+ } else if (argv[i] === "--prime") {
266
+ args.runtime = "prime";
252
267
  } else if (argv[i] === "--claude" || argv[i] === "--claude-code") {
253
268
  args.runtime = "claude-code";
254
269
  } else if (argv[i] === "--runtime" && argv[i + 1]) {
@@ -412,8 +427,9 @@ function showHelp() {
412
427
  ui.info(" --api <url> Use connected API setup with this URL");
413
428
  ui.info(" --codex Prefer Codex for this local install");
414
429
  ui.info(" --pi Prefer Pi for this local install");
430
+ ui.info(" --prime Prefer Prime Agent for this local install");
415
431
  ui.info(" --claude Prefer Claude Code for this local install");
416
- ui.info(" --runtime <name> Harness override: claude-code, codex, or pi");
432
+ ui.info(" --runtime <name> Harness override: claude-code, codex, pi, or prime");
417
433
  ui.info(" --force Skip the in-repo detection check");
418
434
  ui.info(" --no-autolaunch Don't launch the harness at the end (for CI)");
419
435
  ui.info(" --no-screens Skip the full-screen welcome/ready bookends");
@@ -83,14 +83,16 @@ function validateConnectPack(pack) {
83
83
  if (pack.schemaVersion !== 1 || pack.availability !== "connect") {
84
84
  throw new Error(`Unsupported Connect runtime pack schema: ${pack.schemaVersion}`);
85
85
  }
86
- if (!Array.isArray(pack.skills) || pack.skills.length === 0) {
86
+ if (!Array.isArray(pack.skills)) {
87
87
  throw new Error("Connect runtime pack has no skill inventory");
88
88
  }
89
+ // An empty inventory is valid: every gated connector skill can ship in the
90
+ // OSS base, leaving the overlay with nothing to add for now.
89
91
  const skills = [...new Set(pack.skills)];
90
92
  if (skills.length !== pack.skills.length || skills.some((name) => !/^[a-z0-9-]+$/.test(name))) {
91
93
  throw new Error("Connect runtime pack has an invalid skill inventory");
92
94
  }
93
- if (!Array.isArray(pack.files) || pack.files.length === 0 || pack.files.length > MAX_FILES) {
95
+ if (!Array.isArray(pack.files) || pack.files.length > MAX_FILES) {
94
96
  throw new Error("Connect runtime pack has an invalid file inventory");
95
97
  }
96
98
  if (!/^[a-f0-9]{64}$/.test(pack.packVersion || "")) {
package/lib/local.js CHANGED
@@ -17,6 +17,7 @@ const {
17
17
  } = require("./auth");
18
18
  const { installCodexRuntime, reportCodexRuntimeSummary } = require("./codex-runtime");
19
19
  const { installPiRuntime, reportPiRuntimeSummary } = require("./pi-runtime");
20
+ const { installPrimeRuntime, reportPrimeRuntimeSummary } = require("./prime-runtime");
20
21
  const {
21
22
  install,
22
23
  ghApi,
@@ -1398,6 +1399,17 @@ async function localFounderFlow(ui, ctx = {}) {
1398
1399
  run("git push", { cwd: egregoreDir });
1399
1400
  }
1400
1401
  } catch {}
1402
+ } else if (preferredRuntime === "prime") {
1403
+ const primeRuntime = installPrimeRuntime(egregoreDir);
1404
+ reportPrimeRuntimeSummary(primeRuntime, ui);
1405
+ try {
1406
+ const toCommit = Array.isArray(primeRuntime.files) ? [...primeRuntime.files] : [];
1407
+ if (toCommit.length) {
1408
+ execFileSync("git", ["add", "--", ...toCommit], { cwd: egregoreDir, stdio: "pipe" });
1409
+ run('git commit -m "Add Prime Agent meta-harness runtime"', { cwd: egregoreDir });
1410
+ run("git push", { cwd: egregoreDir });
1411
+ }
1412
+ } catch {}
1401
1413
  } else {
1402
1414
  stripCodexRuntimeForClaude(egregoreDir, ui);
1403
1415
  }
@@ -1570,7 +1582,9 @@ async function localFounderFlow(ui, ctx = {}) {
1570
1582
  ? "Codex"
1571
1583
  : preferredRuntime === "pi"
1572
1584
  ? "Pi"
1573
- : "Claude Code";
1585
+ : preferredRuntime === "prime"
1586
+ ? "Prime Agent"
1587
+ : "Claude Code";
1574
1588
  const setupSummary = {
1575
1589
  workspace: "created",
1576
1590
  invite: invitedUsers.length
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+
3
+ const crypto = require("node:crypto");
4
+ const fs = require("node:fs");
5
+ const path = require("node:path");
6
+
7
+ const PACKAGE = require("../package.json");
8
+
9
+ const BUNDLE_DIR = path.join(__dirname, "..", "runtime", "prime");
10
+ const BUNDLE_MANIFEST = path.join(BUNDLE_DIR, "manifest.json");
11
+ const LOCAL_MANIFEST = path.join(".egregore", "prime-runtime-manifest.json");
12
+
13
+ const REQUIRED_RUNTIME_PATHS = [
14
+ "AGENTS.md",
15
+ ".prime/agent/APPEND_SYSTEM.md",
16
+ ".prime/agent/settings.json",
17
+ ".prime/agent/extensions/egregore.ts",
18
+ ".prime/agent/skills/egregore/SKILL.md",
19
+ ".codex/skills",
20
+ "bin/agent.sh",
21
+ "bin/pi-branch-policy.mjs",
22
+ "bin/pi-product-workflows.mjs",
23
+ "bin/prime-session-start.sh",
24
+ "bin/codex-session-start.sh",
25
+ "bin/codex-skill-render.mjs",
26
+ ];
27
+
28
+ function hashBuffer(buffer) {
29
+ return crypto.createHash("sha256").update(buffer).digest("hex");
30
+ }
31
+
32
+ function readJson(file, fallback) {
33
+ try {
34
+ return JSON.parse(fs.readFileSync(file, "utf8"));
35
+ } catch {
36
+ return fallback;
37
+ }
38
+ }
39
+
40
+ function listFiles(dir, prefix = "") {
41
+ if (!fs.existsSync(dir)) return [];
42
+ const result = [];
43
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
44
+ const rel = prefix ? path.join(prefix, entry.name) : entry.name;
45
+ const full = path.join(dir, entry.name);
46
+ if (entry.isDirectory()) result.push(...listFiles(full, rel));
47
+ else if (entry.isFile()) result.push(rel);
48
+ }
49
+ return result.sort();
50
+ }
51
+
52
+ function bundleManifest() {
53
+ return readJson(BUNDLE_MANIFEST, { files: [], skills: [], skillCount: 0 });
54
+ }
55
+
56
+ function bundleFiles() {
57
+ return listFiles(BUNDLE_DIR).filter((rel) => rel !== "manifest.json");
58
+ }
59
+
60
+ function installManifestPath(egregoreDir) {
61
+ const gitPath = path.join(egregoreDir, ".git");
62
+ try {
63
+ const stat = fs.lstatSync(gitPath);
64
+ if (stat.isDirectory()) return path.join(gitPath, "info", "egregore-prime-runtime.json");
65
+ if (stat.isFile()) {
66
+ const match = fs.readFileSync(gitPath, "utf8").trim().match(/^gitdir:\s*(.+)$/);
67
+ if (match) {
68
+ const gitDir = path.isAbsolute(match[1]) ? match[1] : path.resolve(egregoreDir, match[1]);
69
+ return path.join(gitDir, "info", "egregore-prime-runtime.json");
70
+ }
71
+ }
72
+ } catch {}
73
+ return path.join(egregoreDir, LOCAL_MANIFEST);
74
+ }
75
+
76
+ function pathExists(file) {
77
+ try {
78
+ fs.lstatSync(file);
79
+ return true;
80
+ } catch {
81
+ return false;
82
+ }
83
+ }
84
+
85
+ function copyFile(src, dest) {
86
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
87
+ fs.copyFileSync(src, dest);
88
+ try { fs.chmodSync(dest, fs.statSync(src).mode & 0o777); } catch {}
89
+ }
90
+
91
+ function installPrimeRuntime(egregoreDir) {
92
+ if (!fs.existsSync(BUNDLE_DIR)) throw new Error(`Prime runtime bundle missing: ${BUNDLE_DIR}`);
93
+
94
+ const previousPath = installManifestPath(egregoreDir);
95
+ const previous = readJson(previousPath, { files: {} });
96
+ const previousFiles = previous.files || {};
97
+ const next = {
98
+ package: PACKAGE.name,
99
+ version: PACKAGE.version,
100
+ installedAt: new Date().toISOString(),
101
+ files: {},
102
+ };
103
+ const summary = {
104
+ installed: 0,
105
+ updated: 0,
106
+ removed: 0,
107
+ skipped: 0,
108
+ conflicted: 0,
109
+ conflicts: [],
110
+ files: [],
111
+ bundleSkills: bundleManifest().skills || [],
112
+ bundleSkillCount: bundleManifest().skillCount || 0,
113
+ };
114
+ const currentBundleFiles = bundleFiles();
115
+ const currentBundleSet = new Set(currentBundleFiles);
116
+
117
+ for (const [rel, record] of Object.entries(previousFiles)) {
118
+ if (currentBundleSet.has(rel)) continue;
119
+ const dest = path.join(egregoreDir, rel);
120
+ if (!pathExists(dest)) continue;
121
+ let stat;
122
+ try { stat = fs.lstatSync(dest); } catch { continue; }
123
+ if (stat.isFile() && hashBuffer(fs.readFileSync(dest)) === record.hash) {
124
+ fs.unlinkSync(dest);
125
+ try { fs.rmdirSync(path.dirname(dest)); } catch {}
126
+ summary.removed += 1;
127
+ } else {
128
+ summary.conflicted += 1;
129
+ summary.conflicts.push(rel);
130
+ next.files[rel] = { hash: record.hash };
131
+ }
132
+ }
133
+
134
+ for (const rel of currentBundleFiles) {
135
+ const src = path.join(BUNDLE_DIR, rel);
136
+ const dest = path.join(egregoreDir, rel);
137
+ const sourceHash = hashBuffer(fs.readFileSync(src));
138
+ const previousHash = previousFiles[rel]?.hash;
139
+ const record = () => {
140
+ next.files[rel] = { hash: sourceHash };
141
+ summary.files.push(rel);
142
+ };
143
+
144
+ if (!pathExists(dest)) {
145
+ copyFile(src, dest);
146
+ summary.installed += 1;
147
+ record();
148
+ continue;
149
+ }
150
+
151
+ let stat;
152
+ try { stat = fs.lstatSync(dest); } catch {}
153
+ if (!stat?.isFile()) {
154
+ summary.conflicted += 1;
155
+ summary.conflicts.push(rel);
156
+ if (previousHash) next.files[rel] = { hash: previousHash };
157
+ continue;
158
+ }
159
+
160
+ const currentHash = hashBuffer(fs.readFileSync(dest));
161
+ if (currentHash === sourceHash) {
162
+ try { fs.chmodSync(dest, fs.statSync(src).mode & 0o777); } catch {}
163
+ summary.skipped += 1;
164
+ record();
165
+ } else if (previousHash && currentHash === previousHash) {
166
+ copyFile(src, dest);
167
+ summary.updated += 1;
168
+ record();
169
+ } else {
170
+ summary.conflicted += 1;
171
+ summary.conflicts.push(rel);
172
+ if (previousHash) next.files[rel] = { hash: previousHash };
173
+ }
174
+ }
175
+
176
+ fs.mkdirSync(path.dirname(previousPath), { recursive: true });
177
+ fs.writeFileSync(previousPath, JSON.stringify(next, null, 2) + "\n");
178
+ return summary;
179
+ }
180
+
181
+ function hasPrimeRuntimeSupport(egregoreDir) {
182
+ return REQUIRED_RUNTIME_PATHS.every((rel) => fs.existsSync(path.join(egregoreDir, rel)));
183
+ }
184
+
185
+ function reportPrimeRuntimeSummary(summary, ui, opts = {}) {
186
+ if (!summary || !ui) return;
187
+ const label = opts.label || "Prime Agent runtime";
188
+ const changed = summary.installed + summary.updated + (summary.removed || 0);
189
+ if (changed > 0) {
190
+ ui.success(`${label} ready (${summary.installed} installed, ${summary.updated} updated, ${summary.removed || 0} removed, ${summary.skipped} unchanged)`);
191
+ }
192
+ if (opts.includeConflicts !== false && summary.conflicted > 0) {
193
+ const count = summary.conflicted;
194
+ ui.info(ui.dim
195
+ ? ui.dim(`${label}: kept ${count} framework file${count === 1 ? "" : "s"} this Egregore already manages.`)
196
+ : `${label}: kept ${count} framework file${count === 1 ? "" : "s"} this Egregore already manages.`);
197
+ }
198
+ }
199
+
200
+ module.exports = {
201
+ BUNDLE_DIR,
202
+ bundleFiles,
203
+ bundleManifest,
204
+ hasPrimeRuntimeSupport,
205
+ installManifestPath,
206
+ installPrimeRuntime,
207
+ reportPrimeRuntimeSummary,
208
+ };