create-egregore 0.18.5 → 0.18.6

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.5.19
2
+ // egregore-launcher-version: 0.5.20
3
3
  //
4
4
  // egregore — launch and browse Egregore instances from your terminal.
5
5
  // Installed by create-egregore. Reads ~/.egregore/instances.json.
@@ -30,7 +30,7 @@ const https = require("node:https");
30
30
  const { spawnSync, spawn } = require("node:child_process");
31
31
  const readline = require("node:readline");
32
32
 
33
- const VERSION = "0.5.19";
33
+ const VERSION = "0.5.20";
34
34
  const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
35
35
  const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
36
36
  const PUBLIC_NPX_PACKAGE = "create-egregore";
@@ -200,6 +200,28 @@ function die(msg) {
200
200
  process.exit(1);
201
201
  }
202
202
 
203
+ // process.cwd() throws (EPERM/ENOENT, "uv_cwd") when the shell's working
204
+ // directory was moved, deleted, or recreated out from under it. Fall back to
205
+ // home so spawned children never inherit a dead cwd.
206
+ function safeCwd() {
207
+ try {
208
+ return process.cwd();
209
+ } catch {
210
+ return os.homedir();
211
+ }
212
+ }
213
+
214
+ // Turn a raw startup error into actionable guidance when it's a stale-cwd one.
215
+ function friendlyError(err) {
216
+ const msg = (err && (err.message || String(err))) || "unknown error";
217
+ if (/uv_cwd|getcwd/i.test(msg)) {
218
+ return "your terminal's working directory is stale or inaccessible.\n" +
219
+ " It was likely moved, deleted, or recreated out from under the shell.\n" +
220
+ " Open a new terminal (or run: cd ~), then run: egregore";
221
+ }
222
+ return msg;
223
+ }
224
+
203
225
  function readRegistry() {
204
226
  if (!fs.existsSync(REGISTRY)) return [];
205
227
  try {
@@ -274,7 +296,7 @@ function pathContains(parent, child) {
274
296
  return rel === "" || (!!rel && !rel.startsWith("..") && !path.isAbsolute(rel));
275
297
  }
276
298
 
277
- function initialCursorForCwd(registry, cwd = process.cwd()) {
299
+ function initialCursorForCwd(registry, cwd = safeCwd()) {
278
300
  let best = -1;
279
301
  let bestLen = -1;
280
302
  for (let i = 0; i < registry.length; i++) {
@@ -624,6 +646,18 @@ function runtimeLaunchArgs(runtime, egregoreDir) {
624
646
  async function launch(inst, runtimeOverride) {
625
647
  if (!inst) die("no instance to launch");
626
648
  if (!fs.existsSync(inst.path)) die(`instance path does not exist: ${inst.path}`);
649
+ // existsSync can pass while the path is still untraversable (a parent lost
650
+ // execute permission, or the dir was recreated under the shell). realpathSync
651
+ // walks the full path and surfaces that before we spawn the harness into a
652
+ // dead directory and produce a cryptic getcwd/EPERM cascade.
653
+ try {
654
+ fs.realpathSync(inst.path);
655
+ fs.accessSync(inst.path, fs.constants.X_OK);
656
+ } catch {
657
+ die(`instance directory isn't accessible: ${inst.path}\n` +
658
+ " Your terminal's working directory may be stale (the folder was moved or recreated).\n" +
659
+ " Open a new terminal (or run: cd ~), then run: egregore");
660
+ }
627
661
  const runtime = await chooseRuntimeForLaunch(inst, runtimeOverride);
628
662
  if (!runtime) return;
629
663
  const binary = runtimeBinary(runtime);
@@ -661,7 +695,7 @@ function setupNewEgregore(runtimeOverride) {
661
695
  if (runtimeOverride) args.push("--runtime", runtimeOverride);
662
696
  const child = spawn("npx", args, {
663
697
  stdio: "inherit",
664
- cwd: process.cwd(),
698
+ cwd: safeCwd(),
665
699
  env: { ...process.env },
666
700
  });
667
701
  child.on("exit", (code, signal) => {
@@ -1964,6 +1998,15 @@ async function numberedPicker(registry, runtimeOverride) {
1964
1998
  // ── main ────────────────────────────────────────────────────────────
1965
1999
 
1966
2000
  function main() {
2001
+ // Self-heal a stale/inaccessible working directory before anything spawns —
2002
+ // otherwise every child (harness, npx) inherits the dead cwd and fails with
2003
+ // getcwd/EPERM. Home is always a safe place to stand.
2004
+ try {
2005
+ process.cwd();
2006
+ } catch {
2007
+ try { process.chdir(os.homedir()); } catch { /* nothing more we can do */ }
2008
+ }
2009
+
1967
2010
  const parsed = parseRuntimeFlags(process.argv.slice(2));
1968
2011
  const args = parsed.args;
1969
2012
  const runtimeOverride = parsed.runtimeOverride;
@@ -2022,8 +2065,8 @@ function main() {
2022
2065
  try {
2023
2066
  const r = main();
2024
2067
  if (r && typeof r.then === "function") {
2025
- r.catch((err) => die(err.message || String(err)));
2068
+ r.catch((err) => die(friendlyError(err)));
2026
2069
  }
2027
2070
  } catch (err) {
2028
- die(err.message || String(err));
2071
+ die(friendlyError(err));
2029
2072
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-egregore",
3
- "version": "0.18.5",
3
+ "version": "0.18.6",
4
4
  "description": "Set up Egregore for your team in one command — installs the egregore launcher and your choice of Claude Code or Codex.",
5
5
  "license": "MIT",
6
6
  "bin": {