@hanzo/dev 0.6.73 → 0.6.75

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
- // Unified entry point for the Code CLI (fork of OpenAI Codex).
2
+ // Unified entry point for the Hanzo Dev CLI.
3
3
 
4
4
  import path from "path";
5
5
  import { fileURLToPath } from "url";
@@ -14,10 +14,6 @@ const __dirname = path.dirname(__filename);
14
14
 
15
15
  const { platform, arch } = process;
16
16
 
17
- // Important: Never delegate to another system's `code` binary (e.g., VS Code).
18
- // When users run via `npx @just-every/code`, we must always execute our
19
- // packaged native binary by absolute path to avoid PATH collisions.
20
-
21
17
  function isWSL() {
22
18
  if (platform !== "linux") return false;
23
19
  try {
@@ -74,11 +70,10 @@ if (!targetTriple) {
74
70
  throw new Error(`Unsupported platform: ${platform} (${arch})`);
75
71
  }
76
72
 
77
- // Prefer new 'code-*' binary names; fall back to legacy 'coder-*' if missing.
78
- let binaryPath = path.join(__dirname, "..", "bin", `code-${targetTriple}`);
79
- let legacyBinaryPath = path.join(__dirname, "..", "bin", `coder-${targetTriple}`);
73
+ // Binary names for Hanzo dev
74
+ let binaryPath = path.join(__dirname, "..", "bin", `dev-${targetTriple}`);
75
+ let legacyBinaryPath = path.join(__dirname, "..", "bin", `code-${targetTriple}`);
80
76
 
81
- // --- Bootstrap helper (runs if the binary is missing, e.g. Bun blocked postinstall) ---
82
77
  import { existsSync, chmodSync, statSync, openSync, readSync, closeSync, mkdirSync, copyFileSync, readFileSync, unlinkSync, createWriteStream } from "fs";
83
78
 
84
79
  const validateBinary = (p) => {
@@ -121,16 +116,14 @@ const getCacheDir = (version) => {
121
116
  } else {
122
117
  base = process.env.XDG_CACHE_HOME || path.join(home, ".cache");
123
118
  }
124
- const dir = path.join(base, "just-every", "code", version);
119
+ const dir = path.join(base, "hanzo", "dev", version);
125
120
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
126
121
  return dir;
127
122
  };
128
123
 
129
124
  const getCachedBinaryPath = (version) => {
130
- // targetTriple already includes the proper extension on Windows ("...msvc.exe").
131
- // Do not append another suffix; just use the exact targetTriple-derived name.
132
125
  const cacheDir = getCacheDir(version);
133
- return path.join(cacheDir, `code-${targetTriple}`);
126
+ return path.join(cacheDir, `dev-${targetTriple}`);
134
127
  };
135
128
 
136
129
  let lastBootstrapError = null;
@@ -139,7 +132,6 @@ const httpsDownload = (url, dest) => new Promise((resolve, reject) => {
139
132
  const req = httpsGet(url, (res) => {
140
133
  const status = res.statusCode || 0;
141
134
  if (status >= 300 && status < 400 && res.headers.location) {
142
- // follow one redirect recursively
143
135
  return resolve(httpsDownload(res.headers.location, dest));
144
136
  }
145
137
  if (status !== 200) {
@@ -164,19 +156,17 @@ const httpsDownload = (url, dest) => new Promise((resolve, reject) => {
164
156
 
165
157
  const tryBootstrapBinary = async () => {
166
158
  try {
167
- // 1) Read our published version
168
159
  const pkg = JSON.parse(readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
169
160
  const version = pkg.version;
170
161
 
171
162
  const binDir = path.join(__dirname, "..", "bin");
172
163
  if (!existsSync(binDir)) mkdirSync(binDir, { recursive: true });
173
164
 
174
- // 2) Fast path: user cache
165
+ // Fast path: user cache
175
166
  const cachePath = getCachedBinaryPath(version);
176
167
  if (existsSync(cachePath)) {
177
168
  const v = validateBinary(cachePath);
178
169
  if (v.ok) {
179
- // Prefer running directly from cache; mirror into node_modules on Unix
180
170
  if (platform !== "win32") {
181
171
  copyFileSync(cachePath, binaryPath);
182
172
  try { chmodSync(binaryPath, 0o755); } catch {}
@@ -185,26 +175,25 @@ const tryBootstrapBinary = async () => {
185
175
  }
186
176
  }
187
177
 
188
- // 3) Try platform package (if present)
178
+ // Try platform package (if present)
189
179
  try {
190
180
  const req = (await import("module")).createRequire(import.meta.url);
191
181
  const name = (() => {
192
- if (platform === "win32") return "@just-every/code-win32-x64"; // may be unpublished; falls through
182
+ if (platform === "win32") return "@hanzo/dev-win32-x64";
193
183
  const plt = nodePlatform();
194
184
  const cpu = nodeArch();
195
- if (plt === "darwin" && cpu === "arm64") return "@just-every/code-darwin-arm64";
196
- if (plt === "darwin" && cpu === "x64") return "@just-every/code-darwin-x64";
197
- if (plt === "linux" && cpu === "x64") return "@just-every/code-linux-x64-musl";
198
- if (plt === "linux" && cpu === "arm64") return "@just-every/code-linux-arm64-musl";
185
+ if (plt === "darwin" && cpu === "arm64") return "@hanzo/dev-darwin-arm64";
186
+ if (plt === "darwin" && cpu === "x64") return "@hanzo/dev-darwin-x64";
187
+ if (plt === "linux" && cpu === "x64") return "@hanzo/dev-linux-x64-musl";
188
+ if (plt === "linux" && cpu === "arm64") return "@hanzo/dev-linux-arm64-musl";
199
189
  return null;
200
190
  })();
201
191
  if (name) {
202
192
  try {
203
193
  const pkgJson = req.resolve(`${name}/package.json`);
204
194
  const pkgDir = path.dirname(pkgJson);
205
- const src = path.join(pkgDir, "bin", `code-${targetTriple}`);
195
+ const src = path.join(pkgDir, "bin", `dev-${targetTriple}`);
206
196
  if (existsSync(src)) {
207
- // Always ensure cache has the binary; on Unix mirror into node_modules
208
197
  copyFileSync(src, cachePath);
209
198
  if (platform !== "win32") {
210
199
  copyFileSync(cachePath, binaryPath);
@@ -216,21 +205,22 @@ const tryBootstrapBinary = async () => {
216
205
  }
217
206
  } catch { /* ignore */ }
218
207
 
219
- // 4) Download from GitHub release
208
+ // Download from GitHub release
220
209
  const isWin = platform === "win32";
210
+ // Use 'code-*' binary names since that's what the release produces
211
+ const binaryName = `code-${targetTriple}`;
221
212
  const archiveName = isWin
222
- ? `code-${targetTriple}.zip`
223
- : (() => { try { execSync("zstd --version", { stdio: "ignore", shell: true }); return `code-${targetTriple}.zst`; } catch { return `code-${targetTriple}.tar.gz`; } })();
224
- const url = `https://github.com/just-every/code/releases/download/v${version}/${archiveName}`;
213
+ ? `${binaryName}.zip`
214
+ : (() => { try { execSync("zstd --version", { stdio: "ignore", shell: true }); return `${binaryName}.zst`; } catch { return `${binaryName}.tar.gz`; } })();
215
+ const url = `https://github.com/hanzoai/dev/releases/download/v${version}/${archiveName}`;
225
216
  const tmp = path.join(binDir, `.${archiveName}.part`);
226
217
  return httpsDownload(url, tmp)
227
218
  .then(() => {
228
219
  if (isWin) {
229
- // Extract zip with robust fallbacks and use a safe temp dir, then move to cache
230
220
  try {
231
- const sysRoot = process.env.SystemRoot || process.env.windir || 'C:\\\Windows';
221
+ const sysRoot = process.env.SystemRoot || process.env.windir || 'C:\\Windows';
232
222
  const psFull = path.join(sysRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
233
- const unzipDest = getCacheDir(version); // extract directly to cache location
223
+ const unzipDest = getCacheDir(version);
234
224
  const psCmd = `Expand-Archive -Path '${tmp}' -DestinationPath '${unzipDest}' -Force`;
235
225
  let ok = false;
236
226
  try { execSync(`"${psFull}" -NoProfile -NonInteractive -Command "${psCmd}"`, { stdio: 'ignore' }); ok = true; } catch {}
@@ -251,11 +241,7 @@ const tryBootstrapBinary = async () => {
251
241
  try { unlinkSync(tmp); } catch {}
252
242
  }
253
243
  }
254
- // On Windows, the file was extracted directly into the cache dir
255
- if (platform === "win32") {
256
- // Ensure the expected filename exists in cache; Expand-Archive extracts exact name
257
- // No action required here; validation occurs below against cachePath
258
- } else {
244
+ if (platform !== "win32") {
259
245
  try { copyFileSync(binaryPath, cachePath); } catch {}
260
246
  }
261
247
 
@@ -270,7 +256,7 @@ const tryBootstrapBinary = async () => {
270
256
  }
271
257
  };
272
258
 
273
- // If missing, attempt to bootstrap into place (helps when Bun blocks postinstall)
259
+ // If missing, attempt to bootstrap into place
274
260
  let binaryReady = existsSync(binaryPath) || existsSync(legacyBinaryPath);
275
261
  if (!binaryReady) {
276
262
  let runtimePostinstallError = null;
@@ -287,7 +273,6 @@ if (!binaryReady) {
287
273
  if (runtimePostinstallError && !lastBootstrapError) {
288
274
  lastBootstrapError = runtimePostinstallError;
289
275
  }
290
- // retry legacy name in case archive provided coder-*
291
276
  if (existsSync(legacyBinaryPath) && !existsSync(binaryPath)) {
292
277
  binaryPath = legacyBinaryPath;
293
278
  }
@@ -310,17 +295,14 @@ try {
310
295
  // ignore
311
296
  }
312
297
 
313
- // Check if binary exists and try to fix permissions if needed
314
- // fs imports are above; keep for readability if tree-shaken by bundlers
315
298
  import { spawnSync } from "child_process";
316
299
  if (existsSync(binaryPath)) {
317
300
  try {
318
- // Ensure binary is executable on Unix-like systems
319
301
  if (platform !== "win32") {
320
302
  chmodSync(binaryPath, 0o755);
321
303
  }
322
304
  } catch (e) {
323
- // Ignore permission errors, will be caught below if it's a real problem
305
+ // Ignore permission errors
324
306
  }
325
307
  } else {
326
308
  console.error(`Binary not found: ${binaryPath}`);
@@ -329,97 +311,69 @@ if (existsSync(binaryPath)) {
329
311
  console.error(`Bootstrap error: ${msg}`);
330
312
  }
331
313
  console.error(`Please try reinstalling the package:`);
332
- console.error(` npm uninstall -g @just-every/code`);
333
- console.error(` npm install -g @just-every/code`);
314
+ console.error(` npm uninstall -g @hanzo/dev`);
315
+ console.error(` npm install -g @hanzo/dev`);
334
316
  if (isWSL()) {
335
317
  console.error("Detected WSL. Install inside WSL (Ubuntu) separately:");
336
- console.error(" npx -y @just-every/code@latest (run inside WSL)");
318
+ console.error(" npx -y @hanzo/dev@latest (run inside WSL)");
337
319
  console.error("If installed globally on Windows, those binaries are not usable from WSL.");
338
320
  }
339
321
  process.exit(1);
340
322
  }
341
323
 
342
- // Lightweight header validation to provide clearer errors before spawn
343
- // Reuse the validateBinary helper defined above in the bootstrap section.
344
-
345
324
  const validation = validateBinary(binaryPath);
346
325
  if (!validation.ok) {
347
326
  console.error(`The native binary at ${binaryPath} appears invalid: ${validation.reason}`);
348
327
  console.error("This can happen if the download failed or was modified by antivirus/proxy.");
349
328
  console.error("Please try reinstalling:");
350
- console.error(" npm uninstall -g @just-every/code");
351
- console.error(" npm install -g @just-every/code");
329
+ console.error(" npm uninstall -g @hanzo/dev");
330
+ console.error(" npm install -g @hanzo/dev");
352
331
  if (platform === "win32") {
353
332
  console.error("If the issue persists, clear npm cache and disable antivirus temporarily:");
354
333
  console.error(" npm cache clean --force");
355
334
  }
356
335
  if (isWSL()) {
357
336
  console.error("Detected WSL. Ensure you install/run inside WSL, not Windows:");
358
- console.error(" npx -y @just-every/code@latest (inside WSL)");
337
+ console.error(" npx -y @hanzo/dev@latest (inside WSL)");
359
338
  }
360
339
  process.exit(1);
361
340
  }
362
341
 
363
- // If running under npx/npm, emit a concise notice about which binary path is used
342
+ // If running under npx/npm, emit a concise notice
364
343
  try {
365
344
  const ua = process.env.npm_config_user_agent || "";
366
345
  const isNpx = ua.includes("npx");
367
346
  if (isNpx && process.stderr && process.stderr.isTTY) {
368
- // Best-effort discovery of another 'code' on PATH for user clarity
369
- let otherCode = "";
370
- try {
371
- const cmd = process.platform === "win32" ? "where code" : "command -v code || which code || true";
372
- const out = spawnSync(process.platform === "win32" ? "cmd" : "bash", [
373
- process.platform === "win32" ? "/c" : "-lc",
374
- cmd,
375
- ], { encoding: "utf8" });
376
- const line = (out.stdout || "").split(/\r?\n/).map((s) => s.trim()).filter(Boolean)[0];
377
- if (line && !line.includes("@just-every/code")) {
378
- otherCode = line;
379
- }
380
- } catch {}
381
- if (otherCode) {
382
- console.error(`@just-every/code: running bundled binary -> ${binaryPath}`);
383
- console.error(`Note: a different 'code' exists at ${otherCode}; not delegating.`);
384
- } else {
385
- console.error(`@just-every/code: running bundled binary -> ${binaryPath}`);
386
- }
347
+ console.error(`@hanzo/dev: running bundled binary -> ${binaryPath}`);
387
348
  }
388
349
  } catch {}
389
350
 
390
- // Use an asynchronous spawn instead of spawnSync so that Node is able to
391
- // respond to signals (e.g. Ctrl-C / SIGINT) while the native binary is
392
- // executing. This allows us to forward those signals to the child process
393
- // and guarantees that when either the child terminates or the parent
394
- // receives a fatal signal, both processes exit in a predictable manner.
395
351
  const { spawn } = await import("child_process");
396
352
 
397
- // Make the resolved native binary path visible to spawned agents/subprocesses.
398
- process.env.CODE_BINARY_PATH = binaryPath;
353
+ process.env.DEV_BINARY_PATH = binaryPath;
399
354
 
400
355
  const child = spawn(binaryPath, process.argv.slice(2), {
401
356
  stdio: "inherit",
402
- env: { ...process.env, CODER_MANAGED_BY_NPM: "1", CODEX_MANAGED_BY_NPM: "1", CODE_BINARY_PATH: binaryPath },
357
+ env: { ...process.env, DEV_MANAGED_BY_NPM: "1", DEV_BINARY_PATH: binaryPath },
403
358
  });
404
359
 
405
360
  child.on("error", (err) => {
406
- // Typically triggered when the binary is missing or not executable.
407
361
  const code = err && err.code;
408
362
  if (code === 'EACCES') {
409
363
  console.error(`Permission denied: ${binaryPath}`);
410
364
  console.error(`Try running: chmod +x "${binaryPath}"`);
411
- console.error(`Or reinstall the package with: npm install -g @just-every/code`);
365
+ console.error(`Or reinstall the package with: npm install -g @hanzo/dev`);
412
366
  } else if (code === 'EFTYPE' || code === 'ENOEXEC') {
413
367
  console.error(`Failed to execute native binary: ${binaryPath}`);
414
368
  console.error("The file may be corrupt or of the wrong type. Reinstall usually fixes this:");
415
- console.error(" npm uninstall -g @just-every/code && npm install -g @just-every/code");
369
+ console.error(" npm uninstall -g @hanzo/dev && npm install -g @hanzo/dev");
416
370
  if (platform === 'win32') {
417
371
  console.error("On Windows, ensure the .exe downloaded correctly (proxy/AV can interfere).");
418
372
  console.error("Try clearing cache: npm cache clean --force");
419
373
  }
420
374
  if (isWSL()) {
421
375
  console.error("Detected WSL. Windows binaries cannot be executed from WSL.");
422
- console.error("Install inside WSL and run there: npx -y @just-every/code@latest");
376
+ console.error("Install inside WSL and run there: npx -y @hanzo/dev@latest");
423
377
  }
424
378
  } else {
425
379
  console.error(err);
@@ -427,10 +381,6 @@ child.on("error", (err) => {
427
381
  process.exit(1);
428
382
  });
429
383
 
430
- // Forward common termination signals to the child so that it shuts down
431
- // gracefully. In the handler we temporarily disable the default behavior of
432
- // exiting immediately; once the child has been signaled we simply wait for
433
- // its exit event which will in turn terminate the parent (see below).
434
384
  const forwardSignal = (signal) => {
435
385
  if (child.killed) {
436
386
  return;
@@ -446,11 +396,6 @@ const forwardSignal = (signal) => {
446
396
  process.on(sig, () => forwardSignal(sig));
447
397
  });
448
398
 
449
- // When the child exits, mirror its termination reason in the parent so that
450
- // shell scripts and other tooling observe the correct exit status.
451
- // Wrap the lifetime of the child process in a Promise so that we can await
452
- // its termination in a structured way. The Promise resolves with an object
453
- // describing how the child exited: either via exit code or due to a signal.
454
399
  const childResult = await new Promise((resolve) => {
455
400
  child.on("exit", (code, signal) => {
456
401
  if (signal) {
@@ -462,8 +407,6 @@ const childResult = await new Promise((resolve) => {
462
407
  });
463
408
 
464
409
  if (childResult.type === "signal") {
465
- // Re-emit the same signal so that the parent terminates with the expected
466
- // semantics (this also sets the correct exit code of 128 + n).
467
410
  process.kill(process.pid, childResult.signal);
468
411
  } else {
469
412
  process.exit(childResult.exitCode);
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@hanzo/dev",
3
- "version": "0.6.73",
3
+ "version": "0.6.75",
4
4
  "license": "Apache-2.0",
5
- "description": "Lightweight coding agent that runs in your terminal - fork of OpenAI Codex",
5
+ "description": "Hanzo AI coding assistant - intelligent CLI for developers",
6
6
  "bin": {
7
- "coder": "bin/coder.js"
7
+ "dev": "bin/dev.js",
8
+ "hanzo": "bin/dev.js"
8
9
  },
9
10
  "type": "module",
10
11
  "engines": {
11
12
  "node": ">=16"
12
13
  },
13
14
  "files": [
14
- "bin/coder.js",
15
- "bin/codex.js",
15
+ "bin/dev.js",
16
16
  "postinstall.js",
17
17
  "scripts/preinstall.js",
18
18
  "scripts/windows-cleanup.ps1",
@@ -21,7 +21,7 @@
21
21
  "scripts": {
22
22
  "preinstall": "node scripts/preinstall.js",
23
23
  "postinstall": "node postinstall.js",
24
- "prepublishOnly": "node -e \"const fs=require('fs'),path=require('path'); const repoGit=path.join(__dirname,'..','.git'); const inCi=process.env.GITHUB_ACTIONS==='true'||process.env.CI==='true'; if(fs.existsSync(repoGit) && !inCi){ console.error('Refusing to publish from codex-cli. Publishing happens via release.yml.'); process.exit(1);} else { console.log(inCi ? 'CI publish detected.' : 'Publishing staged package...'); }\""
24
+ "prepublishOnly": "node -e \"const fs=require('fs'),path=require('path'); const repoGit=path.join(__dirname,'..','.git'); const inCi=process.env.GITHUB_ACTIONS==='true'||process.env.CI==='true'; if(fs.existsSync(repoGit) && !inCi){ console.error('Refusing to publish from dev-cli. Publishing happens via release.yml.'); process.exit(1);} else { console.log(inCi ? 'CI publish detected.' : 'Publishing staged package...'); }\""
25
25
  },
26
26
  "repository": {
27
27
  "type": "git",
@@ -35,10 +35,10 @@
35
35
  "prettier": "^3.3.3"
36
36
  },
37
37
  "optionalDependencies": {
38
- "@hanzo/dev-darwin-arm64": "0.6.73",
39
- "@hanzo/dev-darwin-x64": "0.6.73",
40
- "@hanzo/dev-linux-x64-musl": "0.6.73",
41
- "@hanzo/dev-linux-arm64-musl": "0.6.73",
42
- "@hanzo/dev-win32-x64": "0.6.73"
38
+ "@hanzo/dev-darwin-arm64": "0.6.75",
39
+ "@hanzo/dev-darwin-x64": "0.6.75",
40
+ "@hanzo/dev-linux-x64-musl": "0.6.75",
41
+ "@hanzo/dev-linux-arm64-musl": "0.6.75",
42
+ "@hanzo/dev-win32-x64": "0.6.75"
43
43
  }
44
44
  }