codeam-cli 2.76.32 → 2.76.34

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 (3) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/index.js +201 -45
  3. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -4,6 +4,32 @@ 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.76.33] — 2026-10-14
8
+
9
+ ### Added
10
+
11
+ - **box:** Bake PHP CLI + Composer into the Box image
12
+ - **cli:** Composer pre-flight + PHP guidance for in-app Preview
13
+
14
+ ## [2.76.32] — 2026-10-14
15
+
16
+ ### Fixed
17
+
18
+ - **cli:** Don't resume a session that was deleted from the app while the host slept (codeagent-xwoy)
19
+
20
+ ## [2.76.31] — 2026-10-14
21
+
22
+ ### Fixed
23
+
24
+ - **cli:** Cap the chat-pipe text frame and never loop on a 413
25
+ - **cli:** Make a python static-site preview ready instead of timing out
26
+ - **cli:** Let codex one-shots run outside a git repo
27
+ - **cli:** A failed agent preview hands the agent the dev server's output
28
+
29
+ ### Tests
30
+
31
+ - **cli:** Skip the POSIX-only preview subdir spawn test on Windows
32
+
7
33
  ## [2.76.30] — 2026-10-14
8
34
 
9
35
  ### CI
package/dist/index.js CHANGED
@@ -3428,14 +3428,23 @@ Rules:
3428
3428
  otherwise "python3".
3429
3429
  - Prefer binding to 0.0.0.0 \u2014 most frameworks default to localhost which the tunnel cannot reach.
3430
3430
  - For Expo: framework="Expo", command="npx", args=["expo","start","--tunnel"], port=8081, notes="Scan QR with Expo Go".
3431
+ - For PHP (composer.json / index.php): use PHP's built-in server bound to 0.0.0.0 with the
3432
+ web root as docroot \u2014 command="php", args=["-S","0.0.0.0:8080","-t","public"] (Yii3,
3433
+ Symfony, Slim, Mezzio; use the real docroot, e.g. "web" for Yii2, "." for plain PHP),
3434
+ port=8080, ready_pattern="Development Server". Laravel: command="php",
3435
+ args=["artisan","serve","--host=0.0.0.0","--port=8000"], port=8000,
3436
+ ready_pattern="Server running". Do NOT use "composer serve", "symfony serve" or a
3437
+ "./yii serve" wrapper \u2014 call php directly.
3431
3438
  - If no dev server applies (CLI library, lambda, batch script): {"framework":"unsupported","notes":"<reason>"}.
3432
3439
 
3433
3440
  CRITICAL \u2014 setup_commands:
3434
3441
  - DO NOT include an install command (npm install, pnpm install, yarn install,
3435
- yarn, bun install) in setup_commands. A lockfile-aware pre-flight installer
3436
- runs BEFORE setup_commands and picks the correct package manager from the
3437
- lockfile present (pnpm-lock.yaml -> pnpm, yarn.lock -> yarn, bun.lockb -> bun,
3438
- else npm). Emitting an install here either duplicates that work or, worse,
3442
+ yarn, bun install, composer install) in setup_commands. Pre-flight installers
3443
+ run BEFORE setup_commands: composer install whenever composer.json exists and
3444
+ vendor/ is missing, and a lockfile-aware Node installer that picks the
3445
+ correct package manager from the lockfile present (pnpm-lock.yaml -> pnpm,
3446
+ yarn.lock -> yarn, bun.lockb -> bun, else npm). Emitting an install here
3447
+ either duplicates that work or, worse,
3439
3448
  uses the WRONG package manager on top of node_modules just populated by the
3440
3449
  pre-flight, which crashes (e.g. npm errors with "Cannot read properties of
3441
3450
  null (reading 'matches')" when run over pnpm's .pnpm/ layout).
@@ -10627,7 +10636,7 @@ function readAnonId() {
10627
10636
  }
10628
10637
  function superProperties() {
10629
10638
  return {
10630
- cliVersion: true ? "2.76.32" : "0.0.0-dev",
10639
+ cliVersion: true ? "2.76.34" : "0.0.0-dev",
10631
10640
  nodeVersion: process.version,
10632
10641
  platform: process.platform,
10633
10642
  arch: process.arch,
@@ -10876,7 +10885,7 @@ var http = __toESM(require("http"));
10876
10885
  // package.json
10877
10886
  var package_default = {
10878
10887
  name: "codeam-cli",
10879
- version: "2.76.32",
10888
+ version: "2.76.34",
10880
10889
  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.",
10881
10890
  type: "commonjs",
10882
10891
  main: "dist/index.js",
@@ -10964,7 +10973,7 @@ var package_default = {
10964
10973
  zod: "^4.3.6"
10965
10974
  },
10966
10975
  optionalDependencies: {
10967
- "@beads/bd": "1.0.5"
10976
+ "@beads/bd": "1.3.1"
10968
10977
  },
10969
10978
  devDependencies: {
10970
10979
  "@codeam/shared": "*",
@@ -12252,7 +12261,7 @@ var CommandRelayService = class _CommandRelayService {
12252
12261
  // fresh + clear the "CLI update available" banner after a self-update
12253
12262
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
12254
12263
  // pair/reconnect). Older backends ignore the extra field.
12255
- ..."2.76.32" ? { ideVersion: "2.76.32" } : {}
12264
+ ..."2.76.34" ? { ideVersion: "2.76.34" } : {}
12256
12265
  };
12257
12266
  try {
12258
12267
  const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body, this.pollSecretHeader());
@@ -24657,6 +24666,24 @@ function isJsInstallCommand(cmd, args2) {
24657
24666
  const verb = args2[0];
24658
24667
  return verb === "install" || verb === "i" || verb === "ci";
24659
24668
  }
24669
+ function detectMissingPhpDeps(cwd) {
24670
+ if (!import_fs5.default.existsSync(import_path8.default.join(cwd, "composer.json"))) return null;
24671
+ if (import_fs5.default.existsSync(import_path8.default.join(cwd, "vendor"))) return null;
24672
+ return {
24673
+ cmd: "composer",
24674
+ args: [
24675
+ "install",
24676
+ "--no-interaction",
24677
+ "--no-progress",
24678
+ "--prefer-dist",
24679
+ "--ignore-platform-req=ext-*"
24680
+ ]
24681
+ };
24682
+ }
24683
+ function isComposerInstallCommand(cmd, args2) {
24684
+ if (cmd !== "composer") return false;
24685
+ return args2[0] === "install" || args2[0] === "i";
24686
+ }
24660
24687
 
24661
24688
  // src/services/preview/script-candidates.ts
24662
24689
  var fs47 = __toESM(require("fs"));
@@ -27119,6 +27146,29 @@ function announceReady(ctx, dev, tun) {
27119
27146
  port: detection.port
27120
27147
  });
27121
27148
  }
27149
+ async function runPreflightInstall(ctx, install, why) {
27150
+ const { detection, cwd, emit: emit2, emitProgress } = ctx;
27151
+ const label = `${install.cmd} ${install.args.join(" ")}`;
27152
+ emitProgress("SETUP_RUN", `${label} (pre-flight \u2014 ${why})`);
27153
+ const result = await runSetupCommand(install.cmd, install.args, cwd, detection.env, {
27154
+ timeoutMs: INSTALL_TIMEOUT_MS2
27155
+ });
27156
+ if (result.status === "timeout") {
27157
+ emit2(USER_EVENTS.PREVIEW_ERROR, {
27158
+ stage: "ready_timeout",
27159
+ message: `Dependency install (${label}) didn't finish within ${Math.round(INSTALL_TIMEOUT_MS2 / 1e3)}s and was stopped. Run it manually in this project, then try the preview again.`
27160
+ });
27161
+ return false;
27162
+ }
27163
+ if (result.status === "failed") {
27164
+ emit2(USER_EVENTS.PREVIEW_ERROR, {
27165
+ stage: "spawn",
27166
+ message: `Dependency install failed (${label}, exit ${result.code}). Run it manually in this project and try again.`
27167
+ });
27168
+ return false;
27169
+ }
27170
+ return true;
27171
+ }
27122
27172
  async function provisionDeps(ctx) {
27123
27173
  const { detection, cwd, emit: emit2, emitProgress } = ctx;
27124
27174
  if (ctx.projectEnvAuth?.pluginAuthToken) {
@@ -27155,32 +27205,21 @@ async function provisionDeps(ctx) {
27155
27205
  return false;
27156
27206
  }
27157
27207
  }
27158
- emitProgress(
27159
- "SETUP_RUN",
27160
- `${missingDeps.cmd} ${missingDeps.args.join(" ")} (pre-flight \u2014 node_modules missing)`
27161
- );
27162
- const result = await runSetupCommand(
27163
- missingDeps.cmd,
27164
- missingDeps.args,
27165
- cwd,
27166
- detection.env,
27167
- { timeoutMs: INSTALL_TIMEOUT_MS2 }
27168
- );
27169
- if (result.status === "timeout") {
27170
- emit2(USER_EVENTS.PREVIEW_ERROR, {
27171
- stage: "ready_timeout",
27172
- message: `Dependency install (${missingDeps.cmd} ${missingDeps.args.join(" ")}) didn't finish within ${Math.round(INSTALL_TIMEOUT_MS2 / 1e3)}s and was stopped. Run it manually in this project, then try the preview again.`
27173
- });
27174
- return false;
27175
- }
27176
- if (result.status === "failed") {
27208
+ if (!await runPreflightInstall(ctx, missingDeps, "node_modules missing")) return false;
27209
+ preflightRan = true;
27210
+ }
27211
+ const missingPhpDeps = detectMissingPhpDeps(cwd);
27212
+ let composerPreflightRan = false;
27213
+ if (missingPhpDeps) {
27214
+ if (!await (0, import_which3.default)("composer", { nothrow: true })) {
27177
27215
  emit2(USER_EVENTS.PREVIEW_ERROR, {
27178
27216
  stage: "spawn",
27179
- message: `Dependency install failed (${missingDeps.cmd} ${missingDeps.args.join(" ")}, exit ${result.code}). Run it manually in this project and try again.`
27217
+ message: "This is a PHP project (composer.json) but Composer isn't installed in this environment, so its dependencies (vendor/) can't be installed. Install PHP and Composer, then try the preview again."
27180
27218
  });
27181
27219
  return false;
27182
27220
  }
27183
- preflightRan = true;
27221
+ if (!await runPreflightInstall(ctx, missingPhpDeps, "vendor/ missing")) return false;
27222
+ composerPreflightRan = true;
27184
27223
  }
27185
27224
  const normalizedSetup = (detection.setup_commands ?? []).map((entry) => {
27186
27225
  if (typeof entry === "string") {
@@ -27193,10 +27232,12 @@ async function provisionDeps(ctx) {
27193
27232
  args: Array.isArray(o.args) ? o.args.filter((a) => typeof a === "string") : []
27194
27233
  };
27195
27234
  }).filter((s) => s.cmd.length > 0);
27196
- const agentSetupCommands = preflightRan ? normalizedSetup.filter((s) => !isJsInstallCommand(s.cmd, s.args)) : normalizedSetup;
27235
+ const agentSetupCommands = normalizedSetup.filter(
27236
+ (s) => !(preflightRan && isJsInstallCommand(s.cmd, s.args)) && !(composerPreflightRan && isComposerInstallCommand(s.cmd, s.args))
27237
+ );
27197
27238
  for (const setup of agentSetupCommands) {
27198
27239
  emitProgress("SETUP_RUN", `${setup.cmd} ${setup.args.join(" ")}`);
27199
- const timeoutMs = isJsInstallCommand(setup.cmd, setup.args) ? INSTALL_TIMEOUT_MS2 : SETUP_TIMEOUT_MS;
27240
+ const timeoutMs = isJsInstallCommand(setup.cmd, setup.args) || isComposerInstallCommand(setup.cmd, setup.args) ? INSTALL_TIMEOUT_MS2 : SETUP_TIMEOUT_MS;
27200
27241
  const result = await runSetupCommand(setup.cmd, setup.args, cwd, detection.env, {
27201
27242
  timeoutMs
27202
27243
  });
@@ -27468,6 +27509,43 @@ var import_child_process21 = require("child_process");
27468
27509
  var fs59 = __toESM(require("fs"));
27469
27510
  var os40 = __toESM(require("os"));
27470
27511
  var path67 = __toESM(require("path"));
27512
+
27513
+ // src/beads/schema-migrate.ts
27514
+ var SCHEMA_SKEW_RE = /Error 1146|table not found|refusing to auto-apply \d+ pending schema migration/i;
27515
+ function isSchemaSkew(text) {
27516
+ return SCHEMA_SKEW_RE.test(text);
27517
+ }
27518
+ var APPLIED_RE = /applying (\d+) pending schema migration/i;
27519
+ var REMOTE_GATE_RE = /remote-backed database/i;
27520
+ async function migrateSchema(bd) {
27521
+ let forced = false;
27522
+ let res = await bd.run(["migrate", "schema"]);
27523
+ if (res.code !== 0 && REMOTE_GATE_RE.test(res.stderr + res.stdout)) {
27524
+ log.info("beads", "schema migrate refused for a remote-backed DB \u2014 migrating with --force");
27525
+ forced = true;
27526
+ res = await bd.run(["migrate", "schema", "--force"]);
27527
+ }
27528
+ const text = `${res.stderr}
27529
+ ${res.stdout}`;
27530
+ if (res.code !== 0) {
27531
+ const detail = (res.stderr || res.stdout).trim().slice(0, 200);
27532
+ log.warn("beads", `bd migrate schema failed (code=${res.code}): ${detail}`);
27533
+ return { status: "failed", detail };
27534
+ }
27535
+ const applied = APPLIED_RE.exec(text);
27536
+ if (applied) {
27537
+ const count = Number(applied[1]);
27538
+ log.info(
27539
+ "beads",
27540
+ `bd migrate schema applied ${count} migration(s)${forced ? " (--force)" : ""}`
27541
+ );
27542
+ return { status: "applied", count, forced };
27543
+ }
27544
+ log.trace("beads", "bd migrate schema: already current");
27545
+ return { status: "current" };
27546
+ }
27547
+
27548
+ // src/beads/bd-adapter.ts
27471
27549
  var BD_PACKAGE = "@beads/bd";
27472
27550
  function resolveBundledBdBinary() {
27473
27551
  return _resolveSeam.resolveBundled();
@@ -27545,6 +27623,8 @@ var BdAdapter = class {
27545
27623
  }
27546
27624
  opts;
27547
27625
  resolved;
27626
+ /** Set when a bd call failed on schema skew; read + cleared by `takeSchemaSkew`. */
27627
+ schemaSkewSeen = false;
27548
27628
  /**
27549
27629
  * Resolve the bd binary lazily, caching the result. Order:
27550
27630
  * bundled @beads/bd → PATH. Returns null when neither is available — the
@@ -27600,8 +27680,20 @@ var BdAdapter = class {
27600
27680
  await _adapterSeam.sleep(750 * attempt);
27601
27681
  res = await _spawnSeam.run(binary, args2, { cwd, env });
27602
27682
  }
27683
+ if (res.code !== 0 && isSchemaSkew(res.stderr + res.stdout)) this.schemaSkewSeen = true;
27603
27684
  return res;
27604
27685
  }
27686
+ /**
27687
+ * Whether a bd call since the last check failed because the project DB is
27688
+ * behind this bd's schema (see `schema-migrate.ts`). `listIssues` /
27689
+ * `statusSummary` swallow failures into []/null, so this is how the watcher
27690
+ * learns the cause. Clears the flag.
27691
+ */
27692
+ takeSchemaSkew() {
27693
+ const seen2 = this.schemaSkewSeen;
27694
+ this.schemaSkewSeen = false;
27695
+ return seen2;
27696
+ }
27605
27697
  /**
27606
27698
  * `bd ready --json` → typed issue array. `bd list --json` shares the shape,
27607
27699
  * so `listIssues` reuses the same parser. Bad JSON / non-zero exit → [].
@@ -28167,7 +28259,8 @@ async function provisionBeads(opts = {}) {
28167
28259
  prefix: null,
28168
28260
  initialized: false,
28169
28261
  exportEnabled: false,
28170
- agentsWired: []
28262
+ agentsWired: [],
28263
+ schemaMigrate: null
28171
28264
  };
28172
28265
  if (!bd.isAvailable()) {
28173
28266
  log.info("beads", "bd binary missing \u2014 running OS installer fallback");
@@ -28249,6 +28342,7 @@ async function provisionBeads(opts = {}) {
28249
28342
  log.warn("beads", "shared dolt sql-server not up \u2014 beads disabled this run");
28250
28343
  return result;
28251
28344
  }
28345
+ result.schemaMigrate = await migrateSchemaSafely(bd);
28252
28346
  try {
28253
28347
  if (!await projectDbReachable(bd)) {
28254
28348
  log.info(
@@ -28264,6 +28358,8 @@ async function provisionBeads(opts = {}) {
28264
28358
  "beads",
28265
28359
  `bd bootstrap failed (code=${boot.code}): ${boot.stderr.slice(0, 200)} \u2014 prefix DB may be absent`
28266
28360
  );
28361
+ } else {
28362
+ result.schemaMigrate = await migrateSchemaSafely(bd);
28267
28363
  }
28268
28364
  }
28269
28365
  if (!await projectDbReachable(bd)) {
@@ -28315,10 +28411,25 @@ async function provisionBeads(opts = {}) {
28315
28411
  result.agentsWired = await setupAgents(bd, opts.agents ?? []);
28316
28412
  log.info(
28317
28413
  "beads",
28318
- `provision done dolt=${result.doltAvailable} server=${result.serverUp} prefix=${result.prefix} initialized=${result.initialized} export=${result.exportEnabled} agentsWired=[${result.agentsWired.join(",")}]`
28414
+ `provision done dolt=${result.doltAvailable} server=${result.serverUp} prefix=${result.prefix} initialized=${result.initialized} schema=${describeSchemaMigrate(result.schemaMigrate)} export=${result.exportEnabled} agentsWired=[${result.agentsWired.join(",")}]`
28319
28415
  );
28320
28416
  return result;
28321
28417
  }
28418
+ async function migrateSchemaSafely(bd) {
28419
+ try {
28420
+ return await migrateSchema(bd);
28421
+ } catch (err) {
28422
+ log.warn("beads", "bd migrate schema threw (non-fatal)", err);
28423
+ return { status: "failed", detail: err.message };
28424
+ }
28425
+ }
28426
+ function describeSchemaMigrate(outcome) {
28427
+ if (!outcome) return "skipped";
28428
+ if (outcome.status === "applied") {
28429
+ return `applied:${outcome.count}${outcome.forced ? ":forced" : ""}`;
28430
+ }
28431
+ return outcome.status;
28432
+ }
28322
28433
  async function projectDbReachable(bd) {
28323
28434
  const ping = await bd.run(["ping"]);
28324
28435
  return ping.code === 0;
@@ -28414,6 +28525,8 @@ var BeadsWatcher = class {
28414
28525
  debounceTimer = null;
28415
28526
  stopped = false;
28416
28527
  lastPushedHash = null;
28528
+ /** One schema-heal attempt per watcher — a failing migrate must not loop. */
28529
+ schemaHealTried = false;
28417
28530
  bd;
28418
28531
  feedPath;
28419
28532
  apiBase;
@@ -28482,10 +28595,15 @@ var BeadsWatcher = class {
28482
28595
  async syncNow() {
28483
28596
  if (this.stopped) return;
28484
28597
  const { projectKey, projectLabel } = deriveProjectIdentity(this.opts.cwd);
28485
- const [issues, summary] = await Promise.all([
28486
- this.bd.listIssues(projectKey),
28487
- this.bd.statusSummary()
28488
- ]);
28598
+ let [issues, summary] = await this.readSnapshot(projectKey);
28599
+ if (!this.schemaHealTried && this.bd.takeSchemaSkew()) {
28600
+ this.schemaHealTried = true;
28601
+ log.info("beads", "snapshot hit schema skew \u2014 running bd migrate schema once");
28602
+ const outcome = await migrateSchema(this.bd);
28603
+ if (outcome.status !== "failed") {
28604
+ [issues, summary] = await this.readSnapshot(projectKey);
28605
+ }
28606
+ }
28489
28607
  const payload = {
28490
28608
  sessionId: this.opts.sessionId,
28491
28609
  pluginId: this.opts.pluginId,
@@ -28524,6 +28642,9 @@ var BeadsWatcher = class {
28524
28642
  log.warn("beads", "ingest POST error", err);
28525
28643
  }
28526
28644
  }
28645
+ readSnapshot(projectKey) {
28646
+ return Promise.all([this.bd.listIssues(projectKey), this.bd.statusSummary()]);
28647
+ }
28527
28648
  headers() {
28528
28649
  return {
28529
28650
  "Content-Type": "application/json",
@@ -51501,7 +51622,7 @@ async function autoUpgradeBeforeCriticalCommand() {
51501
51622
  if (process.env.NODE_ENV === "test") return;
51502
51623
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
51503
51624
  if (process.env.CI) return;
51504
- const current2 = true ? "2.76.32" : null;
51625
+ const current2 = true ? "2.76.34" : null;
51505
51626
  if (!current2) return;
51506
51627
  const cache = readCache();
51507
51628
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -51518,7 +51639,7 @@ function checkForUpdates() {
51518
51639
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
51519
51640
  if (process.env.CI) return;
51520
51641
  if (!process.stdout.isTTY) return;
51521
- const current2 = true ? "2.76.32" : null;
51642
+ const current2 = true ? "2.76.34" : null;
51522
51643
  if (!current2) return;
51523
51644
  const cache = readCache();
51524
51645
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -51694,14 +51815,37 @@ function pidAlive3(pid) {
51694
51815
  return err.code === "EPERM";
51695
51816
  }
51696
51817
  }
51818
+ var CLK_TCK = 100;
51819
+ function processStartMs(pid) {
51820
+ try {
51821
+ const stat3 = fs96.readFileSync(`/proc/${pid}/stat`, "utf8");
51822
+ const ticks = Number(stat3.slice(stat3.lastIndexOf(")") + 2).split(" ")[19]);
51823
+ const btime = /^btime (\d+)$/m.exec(fs96.readFileSync("/proc/stat", "utf8"))?.[1];
51824
+ if (!Number.isFinite(ticks) || !btime) return null;
51825
+ return Number(btime) * 1e3 + ticks * 1e3 / CLK_TCK;
51826
+ } catch {
51827
+ return null;
51828
+ }
51829
+ }
51830
+ var PID_REUSE_SLACK_MS = 2e3;
51697
51831
  function livePids(versionDir) {
51832
+ const dir = path109.join(versionDir, ".pids");
51698
51833
  let names;
51699
51834
  try {
51700
- names = fs96.readdirSync(path109.join(versionDir, ".pids"));
51835
+ names = fs96.readdirSync(dir);
51701
51836
  } catch {
51702
51837
  return [];
51703
51838
  }
51704
- return names.map(Number).filter((pid) => Number.isInteger(pid) && pid > 0 && pidAlive3(pid));
51839
+ return names.map(Number).filter((pid) => {
51840
+ if (!Number.isInteger(pid) || pid <= 0 || !pidAlive3(pid)) return false;
51841
+ const started = processStartMs(pid);
51842
+ if (started === null) return true;
51843
+ try {
51844
+ return started <= fs96.statSync(path109.join(dir, String(pid))).mtimeMs + PID_REUSE_SLACK_MS;
51845
+ } catch {
51846
+ return true;
51847
+ }
51848
+ });
51705
51849
  }
51706
51850
  function registerRunningVersion(root = cliVersionsRoot(), entry = process.argv[1]) {
51707
51851
  const dir = versionDirContaining(root, entry);
@@ -51801,7 +51945,7 @@ var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
51801
51945
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
51802
51946
  var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
51803
51947
  function currentCliVersion() {
51804
- return true ? "2.76.32" : null;
51948
+ return true ? "2.76.34" : null;
51805
51949
  }
51806
51950
  async function installedVersion(deps) {
51807
51951
  const ls = await deps.run(
@@ -51886,6 +52030,7 @@ async function runSelfUpdateWith(deps) {
51886
52030
  }
51887
52031
  if (compareSemver(latest, current2) <= 0) {
51888
52032
  log.info("host-agent", `self-update: running ${current2}, npm latest ${latest} \u2014 up to date`);
52033
+ if (versionedModeSupported(deps.platform)) collectOldVersions(root);
51889
52034
  return { status: "current" };
51890
52035
  }
51891
52036
  if (!versionedModeSupported(deps.platform)) {
@@ -51902,6 +52047,17 @@ async function runSelfUpdateWith(deps) {
51902
52047
  return { status: "skipped" };
51903
52048
  }
51904
52049
  }
52050
+ function collectOldVersions(root) {
52051
+ const release3 = acquireInstallLock(root);
52052
+ if (!release3) return [];
52053
+ try {
52054
+ const removed = gcVersions(root);
52055
+ if (removed.length) log.info("host-agent", `self-update: gc removed ${removed.join(", ")}`);
52056
+ return removed;
52057
+ } finally {
52058
+ release3();
52059
+ }
52060
+ }
51905
52061
  var VERIFY_TIMEOUT_MS = 3e4;
51906
52062
  async function installVersioned(deps, root, latest, running2) {
51907
52063
  const node = deps.nodePath ?? process.execPath;
@@ -52012,7 +52168,7 @@ function signalHostReady(send = process.send?.bind(process)) {
52012
52168
  }
52013
52169
  function defaultDeps() {
52014
52170
  return {
52015
- ownVersion: true ? "2.76.32" : null,
52171
+ ownVersion: true ? "2.76.34" : null,
52016
52172
  root: cliVersionsRoot(),
52017
52173
  args: process.argv.slice(3),
52018
52174
  execPath: process.execPath,
@@ -54550,7 +54706,7 @@ function checkChokidar() {
54550
54706
  }
54551
54707
  async function doctor(args2 = []) {
54552
54708
  const json = args2.includes("--json");
54553
- const cliVersion = true ? "2.76.32" : "0.0.0-dev";
54709
+ const cliVersion = true ? "2.76.34" : "0.0.0-dev";
54554
54710
  const apiBase2 = resolveApiBaseUrl();
54555
54711
  const diagnosticId = (0, import_node_crypto17.randomUUID)();
54556
54712
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -55086,7 +55242,7 @@ async function mcpWarm(argv = [], opts = {}) {
55086
55242
  // src/commands/version.ts
55087
55243
  var import_picocolors15 = __toESM(require("picocolors"));
55088
55244
  function version2() {
55089
- const v = true ? "2.76.32" : "unknown";
55245
+ const v = true ? "2.76.34" : "unknown";
55090
55246
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
55091
55247
  }
55092
55248
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.76.32",
3
+ "version": "2.76.34",
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",
@@ -88,7 +88,7 @@
88
88
  "zod": "^4.3.6"
89
89
  },
90
90
  "optionalDependencies": {
91
- "@beads/bd": "1.0.5"
91
+ "@beads/bd": "1.3.1"
92
92
  },
93
93
  "devDependencies": {
94
94
  "@codeam/shared": "*",