create-egregore 0.18.4 → 0.18.5

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.18
2
+ // egregore-launcher-version: 0.5.19
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.18";
33
+ const VERSION = "0.5.19";
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";
@@ -99,9 +99,57 @@ const ANSI = {
99
99
  clear: "\x1b[2J",
100
100
  home: "\x1b[H",
101
101
  clearLine: "\x1b[K",
102
+ // Disable every terminal mouse-reporting mode. Some terminals (tmux,
103
+ // iTerm2) or a TUI run earlier in the session leave mouse reporting ON,
104
+ // which turns the scroll wheel into escape sequences that corrupt our
105
+ // pickers. Emitting this on picker entry makes the wheel do native
106
+ // scrollback instead. Modes: 1000 (click), 1002 (drag), 1003 (any-motion),
107
+ // 1006 (SGR encoding), 1015 (urxvt encoding).
108
+ mouseOff: "\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1006l\x1b[?1015l",
102
109
  moveTo: (row, col) => `\x1b[${row};${col}H`,
103
110
  };
104
111
 
112
+ // Scroll-wheel / mouse-event filter (defense-in-depth for ANSI.mouseOff).
113
+ // With mouse reporting on, the scroll wheel and shift+arrow arrive as escape
114
+ // sequences. Node's readline decomposes them into stray keypresses:
115
+ // • SGR mouse "\x1b[<b;x;yM" → an event with key.code "[<", then each
116
+ // coordinate DIGIT as its own keypress (a "1"/"2" hits the picker's
117
+ // number quick-select and LAUNCHES a runtime), then a final "M".
118
+ // • X11 mouse "\x1b[M" + 3 raw bytes → key.code "[M" then 3 stray chars.
119
+ // • shift+arrow "\x1b[1;2A" / "\x1b[1;2B" → key.name "up"/"down" with
120
+ // key.shift set, which would advance the selection.
121
+ // This factory returns a stateful predicate: pass it every (chunk, key) at the
122
+ // top of a keypress handler and early-return when it reports true, so no
123
+ // mouse-derived byte is ever treated as navigation.
124
+ function makeMouseFilter() {
125
+ let sgr = false; // inside an SGR mouse report (ESC [ < ... M|m)
126
+ let x11 = 0; // raw bytes left to swallow after ESC [ M
127
+ return function isMouseEvent(chunk, key) {
128
+ const seq = (key && key.sequence) || (typeof chunk === "string" ? chunk : "") || "";
129
+ if (sgr) {
130
+ if (/[Mm]/.test(seq)) sgr = false; // SGR terminates on M (press) / m (release)
131
+ return true;
132
+ }
133
+ if (x11 > 0) {
134
+ x11 -= seq.length || 1;
135
+ return true;
136
+ }
137
+ if ((key && key.code === "[<") || seq.startsWith("\x1b[<")) {
138
+ sgr = !/[Mm]$/.test(seq); // single-chunk variant already includes terminator
139
+ return true;
140
+ }
141
+ if ((key && key.code === "[M") || seq.startsWith("\x1b[M")) {
142
+ const extra = Math.max(0, seq.length - 3); // bytes past "ESC [ M" in this chunk
143
+ x11 = Math.max(0, 3 - extra);
144
+ return true;
145
+ }
146
+ if (key && key.shift && (key.name === "up" || key.name === "down")) {
147
+ return true; // shift+arrow scroll fallback
148
+ }
149
+ return false;
150
+ };
151
+ }
152
+
105
153
  const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, "");
106
154
  const visLen = (s) => stripAnsi(s).length;
107
155
  const pad = (s, n) => s + " ".repeat(Math.max(0, n - visLen(s)));
@@ -363,6 +411,7 @@ function pickRuntimeInteractive(inst, runtimes, stored) {
363
411
  let done = false;
364
412
  const title = inst.slug || inst.name || path.basename(inst.path);
365
413
  const previousRaw = !!process.stdin.isRaw;
414
+ const isMouseEvent = makeMouseFilter();
366
415
 
367
416
  const erase = () => {
368
417
  if (!rendered) return;
@@ -378,6 +427,7 @@ function pickRuntimeInteractive(inst, runtimes, stored) {
378
427
  if (done) return;
379
428
  done = true;
380
429
  process.stdin.removeListener("keypress", onKey);
430
+ process.stdout.write(ANSI.mouseOff);
381
431
  if (process.stdin.setRawMode) process.stdin.setRawMode(previousRaw);
382
432
  if (!previousRaw) process.stdin.pause();
383
433
  erase();
@@ -399,6 +449,7 @@ function pickRuntimeInteractive(inst, runtimes, stored) {
399
449
  };
400
450
 
401
451
  function onKey(chunk, key = {}) {
452
+ if (isMouseEvent(chunk, key)) return; // drop scroll-wheel / mouse escape sequences
402
453
  if (key.ctrl && key.name === "c") {
403
454
  cleanup();
404
455
  process.exit(130);
@@ -424,6 +475,7 @@ function pickRuntimeInteractive(inst, runtimes, stored) {
424
475
  readline.emitKeypressEvents(process.stdin);
425
476
  if (process.stdin.setRawMode) process.stdin.setRawMode(true);
426
477
  process.stdin.resume();
478
+ process.stdout.write(ANSI.mouseOff);
427
479
  process.stdin.on("keypress", onKey);
428
480
  render();
429
481
  });
@@ -1586,7 +1638,8 @@ async function browser(args = {}) {
1586
1638
  };
1587
1639
 
1588
1640
  // ── setup / teardown ───────────────────
1589
- process.stdout.write(ANSI.altScreenEnter + ANSI.cursorHide + ANSI.clear + ANSI.home);
1641
+ process.stdout.write(ANSI.altScreenEnter + ANSI.mouseOff + ANSI.cursorHide + ANSI.clear + ANSI.home);
1642
+ const isMouseEvent = makeMouseFilter();
1590
1643
  let done = false;
1591
1644
  const cleanup = () => {
1592
1645
  if (done) return;
@@ -1594,7 +1647,7 @@ async function browser(args = {}) {
1594
1647
  process.stdin.setRawMode(false);
1595
1648
  process.stdin.pause();
1596
1649
  process.stdin.removeAllListeners("keypress");
1597
- process.stdout.write(ANSI.cursorShow + ANSI.altScreenLeave);
1650
+ process.stdout.write(ANSI.mouseOff + ANSI.cursorShow + ANSI.altScreenLeave);
1598
1651
  };
1599
1652
  process.on("exit", cleanup);
1600
1653
  process.on("SIGINT", () => { cleanup(); process.exit(130); });
@@ -1618,6 +1671,7 @@ async function browser(args = {}) {
1618
1671
  return new Promise((resolve) => {
1619
1672
  process.stdin.on("keypress", (chunk, key) => {
1620
1673
  if (!key) return;
1674
+ if (isMouseEvent(chunk, key)) return; // drop scroll-wheel / mouse escape sequences
1621
1675
 
1622
1676
  if (state.runtimeInst) {
1623
1677
  const runtimes = runtimeChoicesFor(state.runtimeInst, args.runtimeOverride);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-egregore",
3
- "version": "0.18.4",
3
+ "version": "0.18.5",
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": {
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "scripts": {
13
13
  "build:runtime": "node scripts/build-runtime-bundle.mjs",
14
- "test": "node scripts/build-runtime-bundle.mjs --check && node --test test/context.test.js test/parse-join-target.test.js test/skip-repos.test.js test/onboarding-shortcircuit.test.js test/welcome-screen.test.js test/runtime-selection.test.js test/command-generation.test.js test/auth-gh.test.js test/gauntlet-fixes.test.js test/codex-runtime.test.js test/installer-runtime-source.test.js",
14
+ "test": "node scripts/build-runtime-bundle.mjs --check && node --test test/context.test.js test/parse-join-target.test.js test/skip-repos.test.js test/onboarding-shortcircuit.test.js test/welcome-screen.test.js test/runtime-selection.test.js test/command-generation.test.js test/auth-gh.test.js test/gauntlet-fixes.test.js test/codex-runtime.test.js test/installer-runtime-source.test.js test/scroll-repro.test.js",
15
15
  "test:e2e": "node --test test/e2e-local.test.js",
16
16
  "test:all": "node scripts/build-runtime-bundle.mjs --check && node --test test/"
17
17
  },
@@ -134,7 +134,7 @@ DASHBOARD_URL=$(echo "$_DB_PUBLISH_OUT" | grep -o 'https://[^ ]*' | tail -1)
134
134
  if [ -z "$DASHBOARD_URL" ]; then
135
135
  _DB_HTML="/tmp/egregore-artifacts/dashboard-${EGREGORE_SESSION_ID}.html"
136
136
  mkdir -p /tmp/egregore-artifacts
137
- if npx egregore-artifacts document "$_DB_MD" --output "$_DB_HTML" --no-open >/dev/null 2>&1 && [ -f "$_DB_HTML" ]; then
137
+ if npx egregore-artifacts@latest document "$_DB_MD" --output "$_DB_HTML" --no-open >/dev/null 2>&1 && [ -f "$_DB_HTML" ]; then
138
138
  DASHBOARD_URL="file://${_DB_HTML}"
139
139
  fi
140
140
  fi
@@ -109,7 +109,7 @@ else
109
109
  exit 0
110
110
  fi
111
111
  else
112
- if ! npx egregore-artifacts "${RENDER_ARGS[@]}" >/dev/null 2>&1; then
112
+ if ! npx egregore-artifacts@latest "${RENDER_ARGS[@]}" >/dev/null 2>&1; then
113
113
  exit 0
114
114
  fi
115
115
  fi