create-egregore 0.20.2 → 0.20.3

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // egregore-launcher-version: 0.20.2
2
+ // egregore-launcher-version: 0.20.3
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.20.2";
36
+ const VERSION = "0.20.3";
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");
@@ -702,9 +702,8 @@ function codexSupportMessage(egregoreDir) {
702
702
  " .codex/hooks.json",
703
703
  " .codex/hooks/",
704
704
  "",
705
- "Automatic repair did not complete. Retry with:",
706
- " npx -y create-egregore@latest --refresh-launcher",
707
- "Then rerun egregore.",
705
+ "Restore this instance using its installed runtime version, then rerun egregore.",
706
+ "A global CLI refresh does not repair instance files.",
708
707
  "Egregore workflows appear as slash commands. In Codex, invoke them with the matching $skill token or ask in natural language.",
709
708
  ].join("\n");
710
709
  }
@@ -735,7 +734,7 @@ function piSupportMessage(egregoreDir) {
735
734
  "Pi meta-harness support is missing from this Egregore checkout.",
736
735
  ` path: ${egregoreDir}`,
737
736
  "",
738
- "Run npx -y create-egregore@latest to install the packaged Pi runtime, then rerun egregore.",
737
+ "Restore this instance using its installed runtime version, then rerun egregore.",
739
738
  ].join("\n");
740
739
  }
741
740
 
@@ -754,31 +753,10 @@ function primeSupportMessage(egregoreDir) {
754
753
  "Prime Agent runtime support is missing from this Egregore checkout.",
755
754
  ` path: ${egregoreDir}`,
756
755
  "",
757
- "Run npx -y create-egregore@latest to install the packaged Prime Agent runtime, then rerun egregore.",
756
+ "Restore this instance using its installed runtime version, then rerun egregore.",
758
757
  ].join("\n");
759
758
  }
760
759
 
761
- function repairPortableRuntime(egregoreDir, runtime) {
762
- const label = runtimeLabel(runtime);
763
- process.stdout.write(`\n ${CYAN}↻${RESET} ${BOLD}Repairing ${label} support${RESET}${DIM} — updating this checkout${RESET}\n`);
764
- const result = spawnSync(
765
- "npx",
766
- ["-y", `${PUBLIC_NPX_PACKAGE}@latest`, "--refresh-launcher"],
767
- {
768
- cwd: egregoreDir,
769
- stdio: "inherit",
770
- env: { ...process.env, EGREGORE_RUNTIME_REPAIR: runtime },
771
- timeout: 3 * 60 * 1000,
772
- },
773
- );
774
- if (result.error || result.status !== 0) {
775
- process.stderr.write(` ${YELLOW}!${RESET} Automatic ${label} repair failed; the checkout was left in place.\n`);
776
- return false;
777
- }
778
- process.stdout.write(` ${GREEN}✓${RESET} ${label} support repaired\n\n`);
779
- return true;
780
- }
781
-
782
760
  // Minimal y/N line prompt for pre-launch decisions (the TUI select machinery
783
761
  // is torn down by the time launch() runs).
784
762
  function confirmLine(question) {
@@ -908,19 +886,15 @@ async function launch(inst, runtimeOverride) {
908
886
  }
909
887
  }
910
888
  if (runtime === "codex") {
911
- if (!hasCodexCoreSupport(inst.path)) {
912
- if (!repairPortableRuntime(inst.path, runtime) || !hasCodexCoreSupport(inst.path)) {
913
- die(codexSupportMessage(inst.path));
914
- }
915
- }
889
+ // Launching never changes an instance's runtime or release channel.
890
+ if (!hasCodexCoreSupport(inst.path)) die(codexSupportMessage(inst.path));
916
891
  const skillsInstalled = installCodexSkills(inst.path);
917
892
  const cardRendered = await renderCodexStartupCard(inst.path);
918
893
  if (!skillsInstalled || !cardRendered) {
919
894
  die(codexSupportMessage(inst.path));
920
895
  }
921
896
  } else if (runtime === "pi") {
922
- if (!hasPiCoreSupport(inst.path) &&
923
- (!repairPortableRuntime(inst.path, runtime) || !hasPiCoreSupport(inst.path))) {
897
+ if (!hasPiCoreSupport(inst.path)) {
924
898
  die(piSupportMessage(inst.path));
925
899
  }
926
900
  }
@@ -931,10 +905,7 @@ async function launch(inst, runtimeOverride) {
931
905
  // check + the trust-flag probe, which shells out to the binary), then a
932
906
  // single handoff line explains the remaining in-harness startup.
933
907
  const stopLoader = startSpinner("Starting Prime Agent");
934
- let coreOk = hasPrimeCoreSupport(inst.path);
935
- if (!coreOk && repairPortableRuntime(inst.path, runtime)) {
936
- coreOk = hasPrimeCoreSupport(inst.path);
937
- }
908
+ const coreOk = hasPrimeCoreSupport(inst.path);
938
909
  launchArgs = coreOk ? runtimeLaunchArgs(runtime, inst.path) : null;
939
910
  stopLoader();
940
911
  if (!coreOk) die(primeSupportMessage(inst.path));
@@ -1797,9 +1768,10 @@ async function cmdConnect(args) {
1797
1768
  console.log(` ${DIM}${line}${RESET}`);
1798
1769
  }
1799
1770
  }
1771
+ // Connect is an instance-scoped overlay; never refresh other runtimes here.
1800
1772
  const runtimeRefresh = spawnSync(
1801
1773
  "npx",
1802
- ["-y", `${PUBLIC_NPX_PACKAGE}@latest`, "--refresh-launcher"],
1774
+ ["-y", `${PUBLIC_NPX_PACKAGE}@${VERSION}`, "--refresh-connect"],
1803
1775
  {
1804
1776
  cwd: inst.path,
1805
1777
  encoding: "utf-8",
@@ -1811,7 +1783,7 @@ async function cmdConnect(args) {
1811
1783
  console.log(` ${GREEN}✓${RESET} Connect features installed`);
1812
1784
  } else {
1813
1785
  console.log(` ${YELLOW}!${RESET} Connect features will retry on the next update`);
1814
- console.log(` ${DIM}npx -y ${PUBLIC_NPX_PACKAGE}@latest --refresh-launcher${RESET}`);
1786
+ console.log(` ${DIM}npx -y ${PUBLIC_NPX_PACKAGE}@${VERSION} --refresh-connect${RESET}`);
1815
1787
  }
1816
1788
  console.log("");
1817
1789
  console.log(` ${GREEN}✓${RESET} ${BOLD}${inst.slug}${RESET} is connected. Local files remain the source of truth.`);
package/bin/cli.js CHANGED
@@ -25,27 +25,8 @@ const {
25
25
  ghCliExists,
26
26
  tryGhAuthOrLogin,
27
27
  } = require("../lib/auth");
28
- const {
29
- hasCodexRuntimeSupport,
30
- installCodexRuntime,
31
- reportCodexRuntimeSummary,
32
- } = require("../lib/codex-runtime");
33
- const {
34
- hasPiRuntimeSupport,
35
- installPiRuntime,
36
- reportPiRuntimeSummary,
37
- } = require("../lib/pi-runtime");
38
- const {
39
- hasPrimeRuntimeSupport,
40
- installPrimeRuntime,
41
- reportPrimeRuntimeSummary,
42
- } = require("../lib/prime-runtime");
43
- const {
44
- connectEligibility,
45
- fetchConnectRuntimePack,
46
- installConnectRuntime,
47
- reportConnectRuntimeSummary,
48
- } = require("../lib/connect-runtime");
28
+ // Global CLI maintenance never installs or reconciles instance runtimes.
29
+ // Fresh installation and explicit instance updates own those writes.
49
30
  const {
50
31
  install,
51
32
  ghApi,
@@ -120,45 +101,6 @@ function assistantLabel(runtime) {
120
101
  return "Claude Code";
121
102
  }
122
103
 
123
- async function upgradePortableRuntimesForExisting(instances) {
124
- for (const inst of instances) {
125
- if (!inst || !inst.path || !fs.existsSync(inst.path)) continue;
126
- try {
127
- // Fetch and validate the private overlay before pruning the old public
128
- // bundle. During the one-time ownership migration, an API outage must
129
- // leave an existing Connect installation untouched.
130
- const eligibility = connectEligibility(inst.path);
131
- const connectPack = eligibility.eligible
132
- ? await fetchConnectRuntimePack(inst.path)
133
- : null;
134
- const summary = installCodexRuntime(inst.path);
135
- const ready = hasCodexRuntimeSupport(inst.path);
136
- reportCodexRuntimeSummary(summary, ui, {
137
- label: `Codex runtime for ${inst.slug || inst.name || path.basename(inst.path)}`,
138
- includeConflicts: !ready,
139
- });
140
- const piSummary = installPiRuntime(inst.path);
141
- const piReady = hasPiRuntimeSupport(inst.path);
142
- reportPiRuntimeSummary(piSummary, ui, {
143
- label: `Pi meta-harness for ${inst.slug || inst.name || path.basename(inst.path)}`,
144
- includeConflicts: !piReady,
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
- });
152
- const connectSummary = await installConnectRuntime(inst.path, { validatedPack: connectPack });
153
- reportConnectRuntimeSummary(connectSummary, ui, {
154
- label: `Connect features for ${inst.slug || inst.name || path.basename(inst.path)}`,
155
- });
156
- } catch (err) {
157
- ui.warn(`Could not refresh shell-runtime support for ${inst.path}: ${err.message}`);
158
- }
159
- }
160
- }
161
-
162
104
  async function chooseRuntime(args) {
163
105
  if (args.runtime) {
164
106
  try {
@@ -199,7 +141,6 @@ async function chooseRuntime(args) {
199
141
  }
200
142
 
201
143
  async function upgradeLauncherFromExisting(instances) {
202
- await upgradePortableRuntimesForExisting(instances);
203
144
  const inst = instances.find((entry) => entry && entry.path && fs.existsSync(entry.path));
204
145
  if (!inst) return null;
205
146
  try {
@@ -433,7 +374,7 @@ function showHelp() {
433
374
  ui.info(" --force Skip the in-repo detection check");
434
375
  ui.info(" --no-autolaunch Don't launch the harness at the end (for CI)");
435
376
  ui.info(" --no-screens Skip the full-screen welcome/ready bookends");
436
- ui.info(" --refresh-launcher Refresh the Egregore CLI and runtime packs, then exit");
377
+ ui.info(" --refresh-launcher Refresh only the global Egregore CLI, then exit");
437
378
  ui.info(" -h, --help Show this help");
438
379
  ui.info("");
439
380
  }
@@ -513,7 +454,6 @@ async function main() {
513
454
  ui.error("No installed Egregore instance was found. Run create-egregore without --refresh-launcher.");
514
455
  process.exit(1);
515
456
  }
516
- await upgradePortableRuntimesForExisting(instances);
517
457
  const alias = await installLauncherBinary(instances[0].path, ui);
518
458
  if (!alias || !alias.binaryPath) {
519
459
  ui.error("Could not refresh the Egregore CLI.");
package/lib/setup.js CHANGED
@@ -1021,7 +1021,7 @@ function codexSupportMessage(egregoreDir) {
1021
1021
  " .codex/hooks.json",
1022
1022
  " .codex/hooks/",
1023
1023
  "",
1024
- "Run npx -y create-egregore@latest to install the packaged Codex runtime, then rerun egregore.",
1024
+ "Restore this instance using its installed runtime version, then rerun egregore.",
1025
1025
  "Egregore workflows appear as slash commands. In Codex, invoke them with the matching $skill token or ask in natural language.",
1026
1026
  ].join("\n");
1027
1027
  }
@@ -1035,7 +1035,7 @@ function piSupportMessage(egregoreDir) {
1035
1035
  "Pi meta-harness support is missing from this Egregore checkout.",
1036
1036
  ` path: ${egregoreDir}`,
1037
1037
  "",
1038
- "Run npx -y create-egregore@latest to install the packaged Pi runtime, then rerun egregore.",
1038
+ "Restore this instance using its installed runtime version, then rerun egregore.",
1039
1039
  "Pi loads Egregore through project-local .pi resources and the shared portable skill corpus.",
1040
1040
  ].join("\n");
1041
1041
  }
@@ -1045,7 +1045,7 @@ function primeSupportMessage(egregoreDir) {
1045
1045
  "Prime Agent runtime support is missing from this Egregore checkout.",
1046
1046
  ` path: ${egregoreDir}`,
1047
1047
  "",
1048
- "Run npx -y create-egregore@latest to install the packaged Prime Agent runtime, then rerun egregore.",
1048
+ "Restore this instance using its installed runtime version, then rerun egregore.",
1049
1049
  "Prime Agent loads Egregore through project-local .prime/agent resources and the shared portable skill corpus.",
1050
1050
  ].join("\n");
1051
1051
  }
@@ -1171,8 +1171,6 @@ async function launchOrInstruct(egregoreDir, alias, ui, ctx = {}) {
1171
1171
  console.log("");
1172
1172
 
1173
1173
  if (runtime === "codex") {
1174
- const codexRuntime = installCodexRuntime(egregoreDir);
1175
- reportCodexRuntimeSummary(codexRuntime, ui);
1176
1174
  if (!hasCodexCoreSupport(egregoreDir)) {
1177
1175
  ui.warn(codexSupportMessage(egregoreDir));
1178
1176
  ui.info(`Run ${ui.bold(aliasName)} after updating the checkout.`);
@@ -1188,8 +1186,6 @@ async function launchOrInstruct(egregoreDir, alias, ui, ctx = {}) {
1188
1186
  return;
1189
1187
  }
1190
1188
  } else if (runtime === "pi") {
1191
- const piRuntime = installPiRuntime(egregoreDir);
1192
- reportPiRuntimeSummary(piRuntime, ui);
1193
1189
  if (!hasPiRuntimeSupport(egregoreDir)) {
1194
1190
  ui.warn(piSupportMessage(egregoreDir));
1195
1191
  ui.info(`Run ${ui.bold(aliasName)} after updating the checkout.`);
@@ -1197,8 +1193,6 @@ async function launchOrInstruct(egregoreDir, alias, ui, ctx = {}) {
1197
1193
  return;
1198
1194
  }
1199
1195
  } else if (runtime === "prime") {
1200
- const primeRuntime = installPrimeRuntime(egregoreDir);
1201
- reportPrimeRuntimeSummary(primeRuntime, ui);
1202
1196
  if (!hasPrimeRuntimeSupport(egregoreDir)) {
1203
1197
  ui.warn(primeSupportMessage(egregoreDir));
1204
1198
  ui.info(`Run ${ui.bold(aliasName)} after updating the checkout.`);
@@ -1309,11 +1303,15 @@ function appendLocalBinToRc(ui) {
1309
1303
  */
1310
1304
  async function installLauncherBinary(egregoreDir, ui) {
1311
1305
  const template = readLauncherTemplate();
1312
- const candidates = [
1313
- { dir: "/usr/local/bin", location: "system" },
1314
- { dir: "/opt/homebrew/bin", location: "system" },
1315
- { dir: path.join(os.homedir(), ".local", "bin"), location: "user" },
1316
- ];
1306
+ // An explicit destination must never fall through to machine-wide paths.
1307
+ const configuredBinDir = process.env.EGREGORE_LAUNCHER_BIN_DIR;
1308
+ const candidates = configuredBinDir
1309
+ ? [{ dir: path.resolve(configuredBinDir), location: "user" }]
1310
+ : [
1311
+ { dir: "/usr/local/bin", location: "system" },
1312
+ { dir: "/opt/homebrew/bin", location: "system" },
1313
+ { dir: path.join(os.homedir(), ".local", "bin"), location: "user" },
1314
+ ];
1317
1315
 
1318
1316
  let chosen = null;
1319
1317
  for (const c of candidates) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-egregore",
3
- "version": "0.20.2",
3
+ "version": "0.20.3",
4
4
  "description": "Set up Egregore for your team in one command \u2014 installs the egregore launcher and your choice of Claude Code, Codex, or Pi.",
5
5
  "license": "MIT",
6
6
  "bin": {