codeam-cli 2.74.6 → 2.74.7

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,12 @@ 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.74.6] — 2026-09-05
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Expo preview reads the tunnel URL a non-TTY Expo actually emits (exp.direct) (#713)
12
+
7
13
  ## [2.74.5] — 2026-09-04
8
14
 
9
15
  ### Chore
package/dist/index.js CHANGED
@@ -8136,7 +8136,7 @@ function readAnonId() {
8136
8136
  }
8137
8137
  function superProperties() {
8138
8138
  return {
8139
- cliVersion: true ? "2.74.6" : "0.0.0-dev",
8139
+ cliVersion: true ? "2.74.7" : "0.0.0-dev",
8140
8140
  nodeVersion: process.version,
8141
8141
  platform: process.platform,
8142
8142
  arch: process.arch,
@@ -8378,7 +8378,7 @@ var http = __toESM(require("http"));
8378
8378
  // package.json
8379
8379
  var package_default = {
8380
8380
  name: "codeam-cli",
8381
- version: "2.74.6",
8381
+ version: "2.74.7",
8382
8382
  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.",
8383
8383
  type: "commonjs",
8384
8384
  main: "dist/index.js",
@@ -9971,7 +9971,7 @@ var CommandRelayService = class _CommandRelayService {
9971
9971
  // fresh + clear the "CLI update available" banner after a self-update
9972
9972
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
9973
9973
  // pair/reconnect). Older backends ignore the extra field.
9974
- ..."2.74.6" ? { ideVersion: "2.74.6" } : {}
9974
+ ..."2.74.7" ? { ideVersion: "2.74.7" } : {}
9975
9975
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
9976
9976
  }
9977
9977
  /**
@@ -18410,14 +18410,14 @@ function defaultSdkDir() {
18410
18410
  return resolveSdkDirViaRequire();
18411
18411
  }
18412
18412
  function resolveClaudeNativeBinary(deps = {}) {
18413
- const existsSync30 = deps.existsSync ?? import_fs.default.existsSync;
18413
+ const existsSync29 = deps.existsSync ?? import_fs.default.existsSync;
18414
18414
  const platformKey = deps.platformKey ?? currentPlatformKey();
18415
18415
  const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
18416
18416
  if (!sdkDir) return null;
18417
18417
  const scopeDir = import_path4.default.dirname(sdkDir);
18418
18418
  const binName = platformKey.startsWith("win32-") ? "claude.exe" : "claude";
18419
18419
  const candidate = import_path4.default.join(scopeDir, `claude-agent-sdk-${platformKey}`, binName);
18420
- return existsSync30(candidate) ? candidate : null;
18420
+ return existsSync29(candidate) ? candidate : null;
18421
18421
  }
18422
18422
  var realSleep = (ms) => new Promise((resolve11) => setTimeout(resolve11, ms));
18423
18423
  async function waitForClaudeNativeBinary(opts = {}) {
@@ -18499,18 +18499,18 @@ function augmentUserLocalBinPaths(deps = {}) {
18499
18499
  env.PATH = [...additions, ...parts].join(p2.delimiter);
18500
18500
  }
18501
18501
  function resolveCursorAgentBinary(deps = {}) {
18502
- const existsSync30 = deps.existsSync ?? import_fs.default.existsSync;
18502
+ const existsSync29 = deps.existsSync ?? import_fs.default.existsSync;
18503
18503
  const platform3 = deps.platform ?? process.platform;
18504
18504
  const env = deps.env ?? process.env;
18505
18505
  if (platform3 === "win32") {
18506
18506
  const localAppData = env.LOCALAPPDATA;
18507
18507
  if (!localAppData) return null;
18508
18508
  const exe = import_path4.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
18509
- return existsSync30(exe) ? exe : null;
18509
+ return existsSync29(exe) ? exe : null;
18510
18510
  }
18511
18511
  const home = deps.homedir ?? import_os4.default.homedir();
18512
18512
  const unix = import_path4.default.posix.join(home, ".local", "bin", "cursor-agent");
18513
- return existsSync30(unix) ? unix : null;
18513
+ return existsSync29(unix) ? unix : null;
18514
18514
  }
18515
18515
  async function waitForCursorAgent(opts = {}) {
18516
18516
  const timeoutMs = opts.timeoutMs ?? 18e4;
@@ -22272,7 +22272,7 @@ async function autoUpgradeBeforeCriticalCommand() {
22272
22272
  if (process.env.NODE_ENV === "test") return;
22273
22273
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
22274
22274
  if (process.env.CI) return;
22275
- const current2 = true ? "2.74.6" : null;
22275
+ const current2 = true ? "2.74.7" : null;
22276
22276
  if (!current2) return;
22277
22277
  const cache = readCache();
22278
22278
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -22289,7 +22289,7 @@ function checkForUpdates() {
22289
22289
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
22290
22290
  if (process.env.CI) return;
22291
22291
  if (!process.stdout.isTTY) return;
22292
- const current2 = true ? "2.74.6" : null;
22292
+ const current2 = true ? "2.74.7" : null;
22293
22293
  if (!current2) return;
22294
22294
  const cache = readCache();
22295
22295
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -22312,7 +22312,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
22312
22312
  var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
22313
22313
  var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
22314
22314
  function currentCliVersion() {
22315
- return true ? "2.74.6" : null;
22315
+ return true ? "2.74.7" : null;
22316
22316
  }
22317
22317
  async function installedVersion(deps) {
22318
22318
  const ls = await deps.run(
@@ -23738,11 +23738,16 @@ var HostAgentSupervisor = class {
23738
23738
  };
23739
23739
  proc.stdout?.on("data", appendTail);
23740
23740
  proc.stderr?.on("data", appendTail);
23741
- proc.once("exit", (code) => {
23741
+ proc.once("exit", (code, signal) => {
23742
23742
  if (this.children.get(deployId)?.proc === proc) this.children.delete(deployId);
23743
23743
  if (typeof code === "number" && code !== 0) {
23744
23744
  this.onResumeChildExit(session, code, tail.trim().slice(-300));
23745
+ return;
23745
23746
  }
23747
+ log.warn(
23748
+ "host-agent",
23749
+ `resumed session ${session.id.slice(0, 8)} exited ${signal ?? code ?? 0} without taking over \u2014 tail: ${tail.trim().slice(-300) || "(no output)"}`
23750
+ );
23746
23751
  });
23747
23752
  log.info(
23748
23753
  "host-agent",
@@ -30153,6 +30158,52 @@ async function claim(token, pluginId, pluginSecretHash) {
30153
30158
  function pairAutoLockPath() {
30154
30159
  return path72.join(os55.homedir(), ".codeam", "pair-auto.lock");
30155
30160
  }
30161
+ var procRoot = "/proc";
30162
+ function readProcFile(rel) {
30163
+ try {
30164
+ return fs66.readFileSync(path72.join(procRoot, rel), "utf8");
30165
+ } catch {
30166
+ return void 0;
30167
+ }
30168
+ }
30169
+ function procStartTicks(pid) {
30170
+ const stat3 = readProcFile(`${pid}/stat`);
30171
+ if (!stat3) return void 0;
30172
+ const afterComm = stat3.slice(stat3.lastIndexOf(")") + 2).trim().split(/\s+/);
30173
+ return afterComm[19];
30174
+ }
30175
+ function procTgid(pid) {
30176
+ const m = readProcFile(`${pid}/status`)?.match(/^Tgid:\s+(\d+)/m);
30177
+ return m ? Number(m[1]) : void 0;
30178
+ }
30179
+ function currentBootId() {
30180
+ return readProcFile("sys/kernel/random/boot_id")?.trim() || void 0;
30181
+ }
30182
+ function readLockRecord(lockPath) {
30183
+ let raw;
30184
+ try {
30185
+ raw = fs66.readFileSync(lockPath, "utf8");
30186
+ } catch {
30187
+ return void 0;
30188
+ }
30189
+ const [first = "", second = ""] = raw.split("\n");
30190
+ const pid = Number(first.trim());
30191
+ if (!Number.isInteger(pid) || pid <= 0) return void 0;
30192
+ const rec = { pid };
30193
+ const start2 = /(?:^|\s)start=(\S+)/.exec(second)?.[1];
30194
+ const boot = /(?:^|\s)boot=(\S+)/.exec(second)?.[1];
30195
+ if (start2) rec.start = start2;
30196
+ if (boot) rec.boot = boot;
30197
+ return rec;
30198
+ }
30199
+ function ownLockBody() {
30200
+ const start2 = procStartTicks(process.pid);
30201
+ const boot = currentBootId();
30202
+ const tags = [start2 ? `start=${start2}` : "", boot ? `boot=${boot}` : ""].filter(Boolean);
30203
+ return tags.length ? `${process.pid}
30204
+ ${tags.join(" ")}
30205
+ ` : String(process.pid);
30206
+ }
30156
30207
  function isLivePairAuto(pid) {
30157
30208
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
30158
30209
  try {
@@ -30160,15 +30211,30 @@ function isLivePairAuto(pid) {
30160
30211
  } catch (e) {
30161
30212
  if (e.code !== "EPERM") return false;
30162
30213
  }
30214
+ const cmdline = readProcFile(`${pid}/cmdline`);
30215
+ if (cmdline === void 0) return true;
30216
+ const tgid = procTgid(pid);
30217
+ if (tgid !== void 0 && tgid !== pid) return false;
30218
+ return cmdline.includes("codeam");
30219
+ }
30220
+ function isLiveLockHolder(rec) {
30221
+ if (!rec || rec.pid === process.pid) return false;
30222
+ if (rec.boot) {
30223
+ const boot = currentBootId();
30224
+ if (boot && boot !== rec.boot) return false;
30225
+ }
30226
+ if (rec.start) {
30227
+ const start2 = procStartTicks(rec.pid);
30228
+ if (start2 !== void 0 && start2 !== rec.start) return false;
30229
+ }
30230
+ return isLivePairAuto(rec.pid);
30231
+ }
30232
+ function releaseOwnLock(lockPath) {
30163
30233
  try {
30164
- return fs66.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
30234
+ if (readLockRecord(lockPath)?.pid === process.pid) fs66.unlinkSync(lockPath);
30165
30235
  } catch {
30166
- return true;
30167
30236
  }
30168
30237
  }
30169
- function isLiveCodeam(pid) {
30170
- return isLivePairAuto(pid);
30171
- }
30172
30238
  function daemonLockPath(sessionId) {
30173
30239
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
30174
30240
  return path72.join(os55.homedir(), ".codeam", `daemon-${safe}.lock`);
@@ -30178,21 +30244,13 @@ function acquireDaemonLock(sessionId) {
30178
30244
  try {
30179
30245
  fs66.mkdirSync(path72.dirname(lockPath), { recursive: true });
30180
30246
  try {
30181
- fs66.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
30247
+ fs66.writeFileSync(lockPath, ownLockBody(), { flag: "wx" });
30182
30248
  } catch (e) {
30183
30249
  if (e.code !== "EEXIST") throw e;
30184
- const holder = Number(fs66.readFileSync(lockPath, "utf8").trim());
30185
- if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
30186
- fs66.writeFileSync(lockPath, String(process.pid));
30250
+ if (isLiveLockHolder(readLockRecord(lockPath))) return false;
30251
+ fs66.writeFileSync(lockPath, ownLockBody());
30187
30252
  }
30188
- const release3 = () => {
30189
- try {
30190
- if (fs66.existsSync(lockPath) && Number(fs66.readFileSync(lockPath, "utf8").trim()) === process.pid) {
30191
- fs66.unlinkSync(lockPath);
30192
- }
30193
- } catch {
30194
- }
30195
- };
30253
+ const release3 = () => releaseOwnLock(lockPath);
30196
30254
  process.once("exit", release3);
30197
30255
  process.once("SIGTERM", () => {
30198
30256
  release3();
@@ -30212,21 +30270,13 @@ function acquireSingletonLock() {
30212
30270
  try {
30213
30271
  fs66.mkdirSync(path72.dirname(lockPath), { recursive: true });
30214
30272
  try {
30215
- fs66.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
30273
+ fs66.writeFileSync(lockPath, ownLockBody(), { flag: "wx" });
30216
30274
  } catch (e) {
30217
30275
  if (e.code !== "EEXIST") throw e;
30218
- const holder = Number(fs66.readFileSync(lockPath, "utf8").trim());
30219
- if (isLivePairAuto(holder)) return false;
30220
- fs66.writeFileSync(lockPath, String(process.pid));
30276
+ if (isLiveLockHolder(readLockRecord(lockPath))) return false;
30277
+ fs66.writeFileSync(lockPath, ownLockBody());
30221
30278
  }
30222
- process.once("exit", () => {
30223
- try {
30224
- if (fs66.existsSync(lockPath) && Number(fs66.readFileSync(lockPath, "utf8").trim()) === process.pid) {
30225
- fs66.unlinkSync(lockPath);
30226
- }
30227
- } catch {
30228
- }
30229
- });
30279
+ process.once("exit", () => releaseOwnLock(lockPath));
30230
30280
  return true;
30231
30281
  } catch {
30232
30282
  return true;
@@ -47540,7 +47590,7 @@ function checkChokidar() {
47540
47590
  }
47541
47591
  async function doctor(args2 = []) {
47542
47592
  const json = args2.includes("--json");
47543
- const cliVersion = true ? "2.74.6" : "0.0.0-dev";
47593
+ const cliVersion = true ? "2.74.7" : "0.0.0-dev";
47544
47594
  const apiBase2 = resolveApiBaseUrl();
47545
47595
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
47546
47596
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -48064,7 +48114,7 @@ async function mcpWarm(argv = [], opts = {}) {
48064
48114
  // src/commands/version.ts
48065
48115
  var import_picocolors15 = __toESM(require("picocolors"));
48066
48116
  function version2() {
48067
- const v = true ? "2.74.6" : "unknown";
48117
+ const v = true ? "2.74.7" : "unknown";
48068
48118
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
48069
48119
  }
48070
48120
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.74.6",
3
+ "version": "2.74.7",
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",