@just-every/code 0.2.43 → 0.2.45

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 (2) hide show
  1. package/package.json +6 -6
  2. package/postinstall.js +173 -90
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@just-every/code",
3
- "version": "0.2.43",
3
+ "version": "0.2.45",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Lightweight coding agent that runs in your terminal - fork of OpenAI Codex",
6
6
  "bin": {
@@ -35,10 +35,10 @@
35
35
  "prettier": "^3.3.3"
36
36
  },
37
37
  "optionalDependencies": {
38
- "@just-every/code-darwin-arm64": "0.2.43",
39
- "@just-every/code-darwin-x64": "0.2.43",
40
- "@just-every/code-linux-x64-musl": "0.2.43",
41
- "@just-every/code-linux-arm64-musl": "0.2.43",
42
- "@just-every/code-win32-x64": "0.2.43"
38
+ "@just-every/code-darwin-arm64": "0.2.45",
39
+ "@just-every/code-darwin-x64": "0.2.45",
40
+ "@just-every/code-linux-x64-musl": "0.2.45",
41
+ "@just-every/code-linux-arm64-musl": "0.2.45",
42
+ "@just-every/code-win32-x64": "0.2.45"
43
43
  }
44
44
  }
package/postinstall.js CHANGED
@@ -30,6 +30,30 @@ function getTargetTriple() {
30
30
  return `${rustArch}-${rustPlatform}`;
31
31
  }
32
32
 
33
+ // Resolve a persistent user cache directory for binaries so that repeated
34
+ // npx installs can reuse a previously downloaded artifact and skip work.
35
+ function getCacheDir(version) {
36
+ const plt = platform();
37
+ const home = process.env.HOME || process.env.USERPROFILE || '';
38
+ let base = '';
39
+ if (plt === 'win32') {
40
+ base = process.env.LOCALAPPDATA || join(home, 'AppData', 'Local');
41
+ } else if (plt === 'darwin') {
42
+ base = join(home, 'Library', 'Caches');
43
+ } else {
44
+ base = process.env.XDG_CACHE_HOME || join(home, '.cache');
45
+ }
46
+ const dir = join(base, 'just-every', 'code', version);
47
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
48
+ return dir;
49
+ }
50
+
51
+ function getCachedBinaryPath(version, targetTriple, isWindows) {
52
+ const ext = isWindows ? '.exe' : '';
53
+ const cacheDir = getCacheDir(version);
54
+ return join(cacheDir, `code-${targetTriple}${ext}`);
55
+ }
56
+
33
57
  async function downloadBinary(url, dest, maxRedirects = 5, maxRetries = 3) {
34
58
  const sleep = (ms) => new Promise(r => setTimeout(r, ms));
35
59
 
@@ -151,27 +175,33 @@ function validateDownloadedBinary(p) {
151
175
 
152
176
  async function main() {
153
177
  // Detect potential PATH conflict with an existing `code` command (e.g., VS Code)
154
- try {
155
- const whichCmd = process.platform === 'win32' ? 'where code' : 'command -v code || which code || true';
156
- const resolved = execSync(whichCmd, { stdio: ['ignore', 'pipe', 'ignore'], shell: process.platform !== 'win32' }).toString().split(/\r?\n/).filter(Boolean)[0];
157
- if (resolved) {
158
- let contents = '';
159
- try {
160
- contents = readFileSync(resolved, 'utf8');
161
- } catch {
162
- contents = '';
163
- }
164
- const looksLikeOurs = contents.includes('@just-every/code') || contents.includes('bin/coder.js');
165
- if (!looksLikeOurs) {
166
- console.warn('[notice] Found an existing `code` on PATH at:');
167
- console.warn(` ${resolved}`);
168
- console.warn('[notice] We will still install our CLI, also available as `coder`.');
169
- console.warn(' If `code` runs another tool, prefer using: coder');
170
- console.warn(' Or run our CLI explicitly via: npx -y @just-every/code');
178
+ // Only relevant for global installs; skip for npx/local installs to keep postinstall fast.
179
+ const ua = process.env.npm_config_user_agent || '';
180
+ const isNpx = ua.includes('npx');
181
+ const isGlobal = process.env.npm_config_global === 'true';
182
+ if (isGlobal && !isNpx) {
183
+ try {
184
+ const whichCmd = process.platform === 'win32' ? 'where code' : 'command -v code || which code || true';
185
+ const resolved = execSync(whichCmd, { stdio: ['ignore', 'pipe', 'ignore'], shell: process.platform !== 'win32' }).toString().split(/\r?\n/).filter(Boolean)[0];
186
+ if (resolved) {
187
+ let contents = '';
188
+ try {
189
+ contents = readFileSync(resolved, 'utf8');
190
+ } catch {
191
+ contents = '';
192
+ }
193
+ const looksLikeOurs = contents.includes('@just-every/code') || contents.includes('bin/coder.js');
194
+ if (!looksLikeOurs) {
195
+ console.warn('[notice] Found an existing `code` on PATH at:');
196
+ console.warn(` ${resolved}`);
197
+ console.warn('[notice] We will still install our CLI, also available as `coder`.');
198
+ console.warn(' If `code` runs another tool, prefer using: coder');
199
+ console.warn(' Or run our CLI explicitly via: npx -y @just-every/code');
200
+ }
171
201
  }
202
+ } catch {
203
+ // Ignore detection failures; proceed with install.
172
204
  }
173
- } catch {
174
- // Ignore detection failures; proceed with install.
175
205
  }
176
206
 
177
207
  const targetTriple = getTargetTriple();
@@ -195,6 +225,7 @@ async function main() {
195
225
  for (const binary of binaries) {
196
226
  const binaryName = `${binary}-${targetTriple}${binaryExt}`;
197
227
  const localPath = join(binDir, binaryName);
228
+ const cachePath = getCachedBinaryPath(version, targetTriple, isWindows);
198
229
 
199
230
  // Skip if already exists and has correct permissions
200
231
  if (existsSync(localPath)) {
@@ -211,6 +242,21 @@ async function main() {
211
242
  }
212
243
  continue;
213
244
  }
245
+
246
+ // Fast path: if a valid cached binary exists for this version+triple, reuse it.
247
+ try {
248
+ if (existsSync(cachePath)) {
249
+ const valid = validateDownloadedBinary(cachePath);
250
+ if (valid.ok) {
251
+ copyFileSync(cachePath, localPath);
252
+ if (!isWindows) chmodSync(localPath, 0o755);
253
+ console.log(`✓ Installed ${binaryName} from user cache`);
254
+ continue; // next binary
255
+ }
256
+ }
257
+ } catch {
258
+ // Ignore cache errors and fall through to normal paths
259
+ }
214
260
 
215
261
  // First try platform package via npm optionalDependencies (fast path on npm CDN).
216
262
  const require = createRequire(import.meta.url);
@@ -245,6 +291,12 @@ async function main() {
245
291
  copyFileSync(src, localPath);
246
292
  if (!isWindows) chmodSync(localPath, 0o755);
247
293
  console.log(`✓ Installed ${binaryName} from ${platformPkg.name}`);
294
+ // Populate cache for future npx runs
295
+ try {
296
+ if (!existsSync(cachePath)) {
297
+ copyFileSync(localPath, cachePath);
298
+ }
299
+ } catch {}
248
300
  continue; // next binary
249
301
  } catch (e) {
250
302
  console.warn(`⚠ Failed platform package install (${e.message}), falling back to GitHub download`);
@@ -317,6 +369,10 @@ async function main() {
317
369
  }
318
370
 
319
371
  console.log(`✓ Installed ${binaryName}`);
372
+ // Save into persistent cache for future fast installs
373
+ try {
374
+ copyFileSync(localPath, cachePath);
375
+ } catch {}
320
376
  } catch (error) {
321
377
  console.error(`✗ Failed to install ${binaryName}: ${error.message}`);
322
378
  console.error(` Downloaded from: ${downloadUrl}`);
@@ -353,26 +409,23 @@ async function main() {
353
409
  }
354
410
 
355
411
  // With bin name = 'code', handle collisions (e.g., VS Code) and add legacy wrappers
356
- try {
412
+ // Only do this for global installs; skip under npx/local to avoid extra work and collisions.
413
+ if (isGlobal && !isNpx) try {
357
414
  const isTTY = process.stdout && process.stdout.isTTY;
358
415
  const isWindows = platform() === 'win32';
416
+ const ua = process.env.npm_config_user_agent || '';
417
+ const isBun = ua.includes('bun') || !!process.env.BUN_INSTALL;
359
418
 
360
- let globalBin = '';
361
- try {
362
- globalBin = execSync('npm bin -g', { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
363
- } catch {}
364
-
365
- const ourShim = join(globalBin || '', isWindows ? 'code.cmd' : 'code');
419
+ const installedCmds = new Set(['coder']); // global install always exposes coder via package manager
420
+ const skippedCmds = [];
366
421
 
367
- // Resolve all 'code' candidates on PATH (so we detect collisions even if
368
- // our npm global bin currently appears first).
422
+ // Helper to resolve all 'code' on PATH
369
423
  const resolveAllOnPath = () => {
370
424
  try {
371
425
  if (isWindows) {
372
426
  const out = execSync('where code', { stdio: ['ignore', 'pipe', 'ignore'] }).toString();
373
427
  return out.split(/\r?\n/).map(s => s.trim()).filter(Boolean);
374
428
  }
375
- // Prefer 'which -a' if available; fall back to 'command -v'
376
429
  let out = '';
377
430
  try {
378
431
  out = execSync('bash -lc "which -a code 2>/dev/null"', { stdio: ['ignore', 'pipe', 'ignore'] }).toString();
@@ -387,81 +440,111 @@ async function main() {
387
440
  }
388
441
  };
389
442
 
390
- const candidates = resolveAllOnPath();
391
- const others = candidates.filter(p => p && ourShim && p !== ourShim);
392
- const collision = others.length > 0;
393
-
394
- const ensureWrapper = (name, args) => {
395
- if (!globalBin) return;
443
+ if (isBun) {
444
+ // Bun creates shims for every bin; if another 'code' exists elsewhere on PATH, remove Bun's shim
445
+ let bunBin = '';
396
446
  try {
397
- const wrapperPath = join(globalBin, isWindows ? `${name}.cmd` : name);
398
- if (isWindows) {
399
- const content = `@echo off\r\n"%~dp0${collision ? 'coder' : 'code'}" ${args} %*\r\n`;
400
- writeFileSync(wrapperPath, content);
401
- } else {
402
- const content = `#!/bin/sh\nexec "$(dirname \"$0\")/${collision ? 'coder' : 'code'}" ${args} "$@"\n`;
403
- writeFileSync(wrapperPath, content);
404
- chmodSync(wrapperPath, 0o755);
447
+ const home = process.env.HOME || process.env.USERPROFILE || '';
448
+ const bunBase = process.env.BUN_INSTALL || join(home, '.bun');
449
+ bunBin = join(bunBase, 'bin');
450
+ } catch {}
451
+
452
+ const bunShim = join(bunBin || '', isWindows ? 'code.cmd' : 'code');
453
+ const candidates = resolveAllOnPath();
454
+ const other = candidates.find(p => p && (!bunBin || !p.startsWith(bunBin)));
455
+ if (other && existsSync(bunShim)) {
456
+ try {
457
+ unlinkSync(bunShim);
458
+ console.log(`✓ Skipped global 'code' shim under Bun (existing: ${other})`);
459
+ skippedCmds.push({ name: 'code', reason: `existing: ${other}` });
460
+ } catch (e) {
461
+ console.log(`⚠ Could not remove Bun shim '${bunShim}': ${e.message}`);
405
462
  }
406
- console.log(`✓ Created wrapper '${name}' -> ${collision ? 'coder' : 'code'} ${args}`);
407
- } catch (e) {
408
- console.log(`⚠ Failed to create '${name}' wrapper: ${e.message}`);
463
+ } else if (existsSync(bunShim)) {
464
+ installedCmds.add('code');
409
465
  }
410
- };
411
466
 
412
- // Always create legacy wrappers so existing scripts keep working
413
- ensureWrapper('code-tui', '');
414
- ensureWrapper('code-exec', 'exec');
467
+ // Print summary for Bun
468
+ const list = Array.from(installedCmds).sort().join(', ');
469
+ console.log(`Commands installed (bun): ${list}`);
470
+ if (skippedCmds.length) {
471
+ for (const s of skippedCmds) console.log(`Commands skipped: ${s.name} (${s.reason})`);
472
+ console.log('→ Use `coder` to run this tool.');
473
+ }
474
+ // Final friendly usage hint
475
+ if (installedCmds.has('code')) {
476
+ console.log("Use 'code' to launch Code.");
477
+ } else {
478
+ console.log("Use 'coder' to launch Code.");
479
+ }
480
+ } else {
481
+ // npm/pnpm/yarn path
482
+ let globalBin = '';
483
+ try {
484
+ globalBin = execSync('npm bin -g', { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
485
+ } catch {}
415
486
 
416
- if (collision) {
417
- console.log('⚠ Detected existing `code` on PATH:');
418
- for (const p of others) console.log(` - ${p}`);
419
- if (globalBin) {
420
- // Remove our global `code` shim to avoid shadowing editors like VS Code
487
+ const ourShim = join(globalBin || '', isWindows ? 'code.cmd' : 'code');
488
+ const candidates = resolveAllOnPath();
489
+ const others = candidates.filter(p => p && ourShim && p !== ourShim);
490
+ const collision = others.length > 0;
491
+
492
+ const ensureWrapper = (name, args) => {
493
+ if (!globalBin) return;
421
494
  try {
422
- if (existsSync(ourShim)) {
423
- unlinkSync(ourShim);
424
- console.log(`✓ Skipped global 'code' shim (removed ${ourShim})`);
495
+ const wrapperPath = join(globalBin, isWindows ? `${name}.cmd` : name);
496
+ if (isWindows) {
497
+ const content = `@echo off\r\n"%~dp0${collision ? 'coder' : 'code'}" ${args} %*\r\n`;
498
+ writeFileSync(wrapperPath, content);
499
+ } else {
500
+ const content = `#!/bin/sh\nexec "$(dirname \"$0\")/${collision ? 'coder' : 'code'}" ${args} "$@"\n`;
501
+ writeFileSync(wrapperPath, content);
502
+ chmodSync(wrapperPath, 0o755);
425
503
  }
504
+ console.log(`✓ Created wrapper '${name}' -> ${collision ? 'coder' : 'code'} ${args}`);
505
+ installedCmds.add(name);
426
506
  } catch (e) {
427
- console.log(`⚠ Could not remove npm shim '${ourShim}': ${e.message}`);
507
+ console.log(`⚠ Failed to create '${name}' wrapper: ${e.message}`);
428
508
  }
509
+ };
429
510
 
430
- // Offer to create a 'vscode' alias that points to the existing system VS Code
431
- const primaryOther = others[0];
432
- if (isTTY && primaryOther) {
433
- const prompt = (msg) => {
434
- process.stdout.write(msg);
435
- try {
436
- const buf = Buffer.alloc(1024);
437
- const bytes = readSync(0, buf, 0, 1024, null);
438
- const ans = buf.slice(0, bytes).toString('utf8').trim().toLowerCase();
439
- return ans;
440
- } catch { return 'n'; }
441
- };
442
- const ans = prompt('Create a `vscode` alias for your existing editor? [y/N] ');
443
- if (ans === 'y' || ans === 'yes') {
444
- try {
445
- const vscodeShim = join(globalBin, isWindows ? 'vscode.cmd' : 'vscode');
446
- if (isWindows) {
447
- const content = `@echo off\r\n"${primaryOther}" %*\r\n`;
448
- writeFileSync(vscodeShim, content);
449
- } else {
450
- const content = `#!/bin/sh\nexec "${primaryOther}" "$@"\n`;
451
- writeFileSync(vscodeShim, content);
452
- chmodSync(vscodeShim, 0o755);
453
- }
454
- console.log('✓ Created `vscode` alias for your editor');
455
- } catch (e) {
456
- console.log(`⚠ Failed to create 'vscode' alias: ${e.message}`);
511
+ // Always create legacy wrappers so existing scripts keep working
512
+ ensureWrapper('code-tui', '');
513
+ ensureWrapper('code-exec', 'exec');
514
+
515
+ if (collision) {
516
+ console.log('⚠ Detected existing `code` on PATH:');
517
+ for (const p of others) console.log(` - ${p}`);
518
+ if (globalBin) {
519
+ try {
520
+ if (existsSync(ourShim)) {
521
+ unlinkSync(ourShim);
522
+ console.log(`✓ Skipped global 'code' shim (removed ${ourShim})`);
523
+ skippedCmds.push({ name: 'code', reason: `existing: ${others[0]}` });
457
524
  }
458
- } else {
459
- console.log('Skipping creation of `vscode` alias.');
525
+ } catch (e) {
526
+ console.log(`⚠ Could not remove npm shim '${ourShim}': ${e.message}`);
460
527
  }
528
+ console.log('→ Use `coder` to run this tool.');
529
+ } else {
530
+ console.log('Note: could not determine npm global bin; skipping alias creation.');
461
531
  }
462
- console.log('→ Use `coder` to run this tool, and `vscode` (if created) for your editor.');
463
532
  } else {
464
- console.log('Note: could not determine npm global bin; skipping alias creation.');
533
+ // No collision; npm created a 'code' shim for us.
534
+ if (globalBin && existsSync(ourShim)) installedCmds.add('code');
535
+ }
536
+
537
+ // Print summary for npm/pnpm/yarn
538
+ const list = Array.from(installedCmds).sort().join(', ');
539
+ console.log(`Commands installed: ${list}`);
540
+ if (skippedCmds.length) {
541
+ for (const s of skippedCmds) console.log(`Commands skipped: ${s.name} (${s.reason})`);
542
+ }
543
+ // Final friendly usage hint
544
+ if (installedCmds.has('code')) {
545
+ console.log("Use 'code' to launch Code.");
546
+ } else {
547
+ console.log("Use 'coder' to launch Code.");
465
548
  }
466
549
  }
467
550
  } catch {