codeam-cli 2.39.41 → 2.39.43

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to `codeam-cli` are documented here.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.39.42] — 2026-06-19
8
+
9
+ ### Added
10
+
11
+ - **cli:** Refuse preview + notify app when the detected port is in use
12
+
13
+ ## [2.39.41] — 2026-06-19
14
+
15
+ ### Fixed
16
+
17
+ - **cli:** Install yarn on demand when a yarn project lacks it
18
+
7
19
  ## [2.39.40] — 2026-06-19
8
20
 
9
21
  ### Added
package/dist/index.js CHANGED
@@ -498,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
498
498
  // package.json
499
499
  var package_default = {
500
500
  name: "codeam-cli",
501
- version: "2.39.41",
501
+ version: "2.39.43",
502
502
  description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
503
503
  type: "commonjs",
504
504
  main: "dist/index.js",
@@ -5908,7 +5908,7 @@ function readAnonId() {
5908
5908
  }
5909
5909
  function superProperties() {
5910
5910
  return {
5911
- cliVersion: true ? "2.39.41" : "0.0.0-dev",
5911
+ cliVersion: true ? "2.39.43" : "0.0.0-dev",
5912
5912
  nodeVersion: process.version,
5913
5913
  platform: process.platform,
5914
5914
  arch: process.arch,
@@ -16480,7 +16480,10 @@ async function resolveCloudflared(opts = {}) {
16480
16480
  }
16481
16481
  try {
16482
16482
  await import_promises.default.access(CACHED_BINARY);
16483
- return CACHED_BINARY;
16483
+ if (await isExecutableBinary(CACHED_BINARY)) {
16484
+ return CACHED_BINARY;
16485
+ }
16486
+ await import_promises.default.rm(CACHED_BINARY, { force: true });
16484
16487
  } catch {
16485
16488
  }
16486
16489
  if (opts.skipDownload) {
@@ -16500,11 +16503,53 @@ async function downloadCloudflared(target) {
16500
16503
  `Failed to download cloudflared from ${url}: HTTP ${response.status}. Install manually from https://github.com/cloudflare/cloudflared/releases.`
16501
16504
  );
16502
16505
  }
16506
+ if (url.endsWith(".tgz")) {
16507
+ const tmp = `${target}.download.tgz`;
16508
+ await (0, import_promises2.pipeline)(
16509
+ response.body,
16510
+ (0, import_fs.createWriteStream)(tmp)
16511
+ );
16512
+ try {
16513
+ await extractTgz(tmp, import_path4.default.dirname(target));
16514
+ await import_promises.default.access(target);
16515
+ await import_promises.default.chmod(target, 493);
16516
+ } catch (err) {
16517
+ throw new Error(
16518
+ `Downloaded the cloudflared archive but could not extract the binary: ${err.message}. Install manually via \`brew install cloudflared\`.`
16519
+ );
16520
+ } finally {
16521
+ await import_promises.default.rm(tmp, { force: true });
16522
+ }
16523
+ return;
16524
+ }
16503
16525
  await (0, import_promises2.pipeline)(
16504
16526
  response.body,
16505
16527
  (0, import_fs.createWriteStream)(target, { mode: 493 })
16506
16528
  );
16507
16529
  }
16530
+ async function isExecutableBinary(p2) {
16531
+ let handle;
16532
+ try {
16533
+ handle = await import_promises.default.open(p2, "r");
16534
+ const buf = Buffer.alloc(2);
16535
+ await handle.read(buf, 0, 2, 0);
16536
+ return !(buf[0] === 31 && buf[1] === 139);
16537
+ } catch {
16538
+ return false;
16539
+ } finally {
16540
+ await handle?.close();
16541
+ }
16542
+ }
16543
+ function extractTgz(tgzPath, destDir) {
16544
+ return new Promise((resolve7, reject) => {
16545
+ const child = (0, import_child_process11.spawn)("tar", ["-xzf", tgzPath, "-C", destDir], { stdio: "ignore" });
16546
+ child.on("error", (err) => reject(err));
16547
+ child.on(
16548
+ "exit",
16549
+ (code) => code === 0 ? resolve7() : reject(new Error(`tar exited with code ${code} while extracting cloudflared`))
16550
+ );
16551
+ });
16552
+ }
16508
16553
  function downloadUrlForPlatform() {
16509
16554
  const platform3 = process.platform;
16510
16555
  const arch2 = process.arch;
@@ -19073,6 +19118,19 @@ var previewStartH = (ctx, _cmd, parsed) => {
19073
19118
  return;
19074
19119
  }
19075
19120
  }
19121
+ if (await isPortListening(detection.port)) {
19122
+ void postPreviewEvent({
19123
+ sessionId: ctx.sessionId,
19124
+ pluginId: ctx.pluginId,
19125
+ pluginAuthToken,
19126
+ type: "preview_error",
19127
+ payload: {
19128
+ stage: "spawn",
19129
+ message: `Port ${detection.port} is already in use by another process, so the dev server can't start there. Stop whatever is listening on port ${detection.port} and try the preview again.`
19130
+ }
19131
+ });
19132
+ return;
19133
+ }
19076
19134
  const spawnable = normalizeDetectionForSpawn(detection, process.cwd());
19077
19135
  emitProgress(
19078
19136
  "BOOT_SEQUENCE",
@@ -27276,7 +27334,7 @@ function checkChokidar() {
27276
27334
  }
27277
27335
  async function doctor(args2 = []) {
27278
27336
  const json = args2.includes("--json");
27279
- const cliVersion = true ? "2.39.41" : "0.0.0-dev";
27337
+ const cliVersion = true ? "2.39.43" : "0.0.0-dev";
27280
27338
  const apiBase2 = resolveApiBaseUrl();
27281
27339
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
27282
27340
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -27475,7 +27533,7 @@ async function completion(args2) {
27475
27533
  // src/commands/version.ts
27476
27534
  var import_picocolors13 = __toESM(require("picocolors"));
27477
27535
  function version2() {
27478
- const v = true ? "2.39.41" : "unknown";
27536
+ const v = true ? "2.39.43" : "unknown";
27479
27537
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
27480
27538
  }
27481
27539
 
@@ -27761,7 +27819,7 @@ function checkForUpdates() {
27761
27819
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
27762
27820
  if (process.env.CI) return;
27763
27821
  if (!process.stdout.isTTY) return;
27764
- const current = true ? "2.39.41" : null;
27822
+ const current = true ? "2.39.43" : null;
27765
27823
  if (!current) return;
27766
27824
  const cache = readCache();
27767
27825
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.39.41",
3
+ "version": "2.39.43",
4
4
  "description": "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device — async. The terminal companion for CodeAgent Mobile.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",