codeam-cli 2.35.0 → 2.35.2

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 +16 -0
  2. package/dist/index.js +239 -96
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@ 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.35.1] — 2026-06-10
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Sync package-lock with @beads/bd@1.0.5 (npm ci was failing on main CI)
12
+ - **cli:** Symlink bd into a dir that is actually on PATH
13
+
14
+ ## [2.35.0] — 2026-06-10
15
+
16
+ ### Fixed
17
+
18
+ - **shared:** Rename BeadsIngestPayload.deps to required dependencies
19
+ - **cli:** Symlink bd onto PATH + set git beads.role during provisioning
20
+ - **cli:** Set BEADS_DIR pre-spawn so the agent inherits the home brain
21
+ - **cli:** Always send dependencies + summary in beads ingest payload
22
+
7
23
  ## [2.34.0] — 2026-06-10
8
24
 
9
25
  ### 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.35.0",
501
+ version: "2.35.2",
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",
@@ -5898,7 +5898,7 @@ function readAnonId() {
5898
5898
  }
5899
5899
  function superProperties() {
5900
5900
  return {
5901
- cliVersion: true ? "2.35.0" : "0.0.0-dev",
5901
+ cliVersion: true ? "2.35.2" : "0.0.0-dev",
5902
5902
  nodeVersion: process.version,
5903
5903
  platform: process.platform,
5904
5904
  arch: process.arch,
@@ -6630,11 +6630,17 @@ var AgentService = class _AgentService {
6630
6630
  restart(sessionId, auto = false) {
6631
6631
  if (!this.strategy || !this.initialLaunch) return;
6632
6632
  const resumeArgs = this.runtime.resumeLaunchArgs(sessionId, { auto });
6633
+ const launch = this.runtime.prepareResumeLaunch?.(sessionId, { auto }) ?? {
6634
+ cmd: this.initialLaunch.cmd,
6635
+ args: [...this.initialLaunch.args, ...resumeArgs]
6636
+ };
6637
+ this.agentBusy = false;
6638
+ if (this.quietTimer) {
6639
+ clearTimeout(this.quietTimer);
6640
+ this.quietTimer = null;
6641
+ }
6633
6642
  this.strategy.kill();
6634
- this.strategy.spawn(this.initialLaunch.cmd, this.opts.cwd, [
6635
- ...this.initialLaunch.args,
6636
- ...resumeArgs
6637
- ]);
6643
+ this.strategy.spawn(launch.cmd, this.opts.cwd, launch.args);
6638
6644
  if (resumeArgs.length === 0 && this.runtime.postSpawnInstruction) {
6639
6645
  const { ptyInput } = this.runtime.postSpawnInstruction(sessionId);
6640
6646
  setTimeout(() => {
@@ -10037,6 +10043,28 @@ var ClaudeRuntimeStrategy = class {
10037
10043
  if (opts?.auto) args2.push("--dangerously-skip-permissions");
10038
10044
  return args2;
10039
10045
  }
10046
+ /**
10047
+ * Resume relaunch as a COMPLETE command. We deliberately rebuild the
10048
+ * launch from scratch with `--resume <id>` rather than appending it
10049
+ * onto the spawn-time args, because those carried `--session-id
10050
+ * <uuid>` (the conversation binding from the initial spawn). Claude
10051
+ * Code rejects `--session-id` together with `--resume` and exits
10052
+ * immediately — that was the "resume → agent fully dead, even new
10053
+ * prompts get no response" bug. Building a fresh launch drops the
10054
+ * conflicting flag by construction.
10055
+ *
10056
+ * Synchronous on purpose: by the time a resume happens the binary
10057
+ * was already resolved (the initial spawn succeeded), so
10058
+ * `buildClaudeLaunch` re-probes PATH without needing the async
10059
+ * installer fallback.
10060
+ */
10061
+ prepareResumeLaunch(sessionId, opts) {
10062
+ const launch = buildClaudeLaunch(this.resumeLaunchArgs(sessionId, opts), this.os);
10063
+ if (!launch) {
10064
+ return { cmd: this.meta.binaryName, args: this.resumeLaunchArgs(sessionId, opts) };
10065
+ }
10066
+ return launch;
10067
+ }
10040
10068
  resolveHistoryDir(cwd) {
10041
10069
  return resolveHistoryDir(cwd);
10042
10070
  }
@@ -15714,7 +15742,7 @@ var fs32 = __toESM(require("fs"));
15714
15742
  var os25 = __toESM(require("os"));
15715
15743
  var path39 = __toESM(require("path"));
15716
15744
  var import_crypto3 = require("crypto");
15717
- var import_child_process16 = require("child_process");
15745
+ var import_child_process17 = require("child_process");
15718
15746
 
15719
15747
  // src/lib/payload.ts
15720
15748
  var import_zod = require("zod");
@@ -17136,6 +17164,77 @@ function parseExpoUrl(stdout) {
17136
17164
  return match ? match[0] : null;
17137
17165
  }
17138
17166
 
17167
+ // src/services/preview/port-ready.ts
17168
+ var net = __toESM(require("net"));
17169
+ function isPortListening(port, host = "127.0.0.1") {
17170
+ return new Promise((resolve7) => {
17171
+ const socket = new net.Socket();
17172
+ const done = (result) => {
17173
+ socket.removeAllListeners();
17174
+ socket.destroy();
17175
+ resolve7(result);
17176
+ };
17177
+ socket.setTimeout(1e3);
17178
+ socket.once("connect", () => done(true));
17179
+ socket.once("timeout", () => done(false));
17180
+ socket.once("error", () => done(false));
17181
+ socket.connect(port, host);
17182
+ });
17183
+ }
17184
+ async function waitForPortListening(port, opts) {
17185
+ const interval = opts.intervalMs ?? 500;
17186
+ const deadline = Date.now() + opts.timeoutMs;
17187
+ for (; ; ) {
17188
+ if (await isPortListening(port)) return true;
17189
+ if (Date.now() >= deadline) return false;
17190
+ await new Promise((r) => setTimeout(r, interval));
17191
+ }
17192
+ }
17193
+
17194
+ // src/services/preview/run-setup.ts
17195
+ var import_child_process12 = require("child_process");
17196
+ function runSetupCommand(cmd, args2, cwd, env, opts) {
17197
+ return new Promise((resolve7) => {
17198
+ const child = (0, import_child_process12.spawn)(cmd, args2, {
17199
+ cwd,
17200
+ env: { ...process.env, ...env ?? {} },
17201
+ stdio: ["ignore", "pipe", "pipe"]
17202
+ });
17203
+ let settled = false;
17204
+ const tag = `setup:${cmd}`;
17205
+ const onChunk = (chunk) => {
17206
+ const text = chunk.toString().replace(/\n+$/g, "");
17207
+ if (text.length === 0) return;
17208
+ log.info("preview", `${tag}: ${text}`);
17209
+ };
17210
+ child.stdout?.on("data", onChunk);
17211
+ child.stderr?.on("data", onChunk);
17212
+ const timer = setTimeout(() => {
17213
+ if (settled) return;
17214
+ settled = true;
17215
+ log.info("preview", `${tag}: timed out after ${opts.timeoutMs}ms \u2014 killing`);
17216
+ try {
17217
+ child.kill("SIGTERM");
17218
+ } catch {
17219
+ }
17220
+ resolve7({ status: "timeout", code: null });
17221
+ }, opts.timeoutMs);
17222
+ child.once("exit", (code) => {
17223
+ if (settled) return;
17224
+ settled = true;
17225
+ clearTimeout(timer);
17226
+ if (code === 0) resolve7({ status: "ok", code: 0 });
17227
+ else resolve7({ status: "failed", code });
17228
+ });
17229
+ child.once("error", () => {
17230
+ if (settled) return;
17231
+ settled = true;
17232
+ clearTimeout(timer);
17233
+ resolve7({ status: "failed", code: null });
17234
+ });
17235
+ });
17236
+ }
17237
+
17139
17238
  // src/services/preview/setup-deps.ts
17140
17239
  var import_fs2 = __toESM(require("fs"));
17141
17240
  var import_path6 = __toESM(require("path"));
@@ -17202,7 +17301,7 @@ function activePreviewSessionIds() {
17202
17301
  }
17203
17302
 
17204
17303
  // src/beads/bd-adapter.ts
17205
- var import_child_process12 = require("child_process");
17304
+ var import_child_process13 = require("child_process");
17206
17305
  var fs29 = __toESM(require("fs"));
17207
17306
  var os24 = __toESM(require("os"));
17208
17307
  var path35 = __toESM(require("path"));
@@ -17256,7 +17355,7 @@ function _defaultSpawn(binaryPath, args2, opts) {
17256
17355
  return new Promise((resolve7) => {
17257
17356
  let proc;
17258
17357
  try {
17259
- proc = (0, import_child_process12.spawn)(binaryPath, args2, { cwd: opts.cwd, env: opts.env });
17358
+ proc = (0, import_child_process13.spawn)(binaryPath, args2, { cwd: opts.cwd, env: opts.env });
17260
17359
  } catch (err) {
17261
17360
  resolve7({ code: -1, stdout: "", stderr: err.message });
17262
17361
  return;
@@ -17392,12 +17491,12 @@ function defaultBeadsHomeDir() {
17392
17491
  }
17393
17492
 
17394
17493
  // src/beads/provisioner.ts
17395
- var import_child_process14 = require("child_process");
17494
+ var import_child_process15 = require("child_process");
17396
17495
  var fs30 = __toESM(require("fs"));
17397
17496
  var path36 = __toESM(require("path"));
17398
17497
 
17399
17498
  // src/beads/install-bd.ts
17400
- var import_child_process13 = require("child_process");
17499
+ var import_child_process14 = require("child_process");
17401
17500
  var INSTALL_SH_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh";
17402
17501
  var INSTALL_PS1_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/install.ps1";
17403
17502
  function resolveInstallStrategy(platform2) {
@@ -17428,7 +17527,7 @@ function _defaultInstallSpawn(strategy) {
17428
17527
  return new Promise((resolve7) => {
17429
17528
  let proc;
17430
17529
  try {
17431
- proc = (0, import_child_process13.spawn)(strategy.command, strategy.args, { env: process.env });
17530
+ proc = (0, import_child_process14.spawn)(strategy.command, strategy.args, { env: process.env });
17432
17531
  } catch (err) {
17433
17532
  resolve7({ ok: false, code: -1, stderr: err.message });
17434
17533
  return;
@@ -17478,20 +17577,35 @@ var _provisionSeam = {
17478
17577
  var _linkSeam = {
17479
17578
  platform: () => process.platform,
17480
17579
  /**
17481
- * The directory the `codeam` executable lives in guaranteed on PATH (npm
17482
- * puts global bins there, and that's how the user launched us). We symlink
17483
- * `bd` alongside it so the AGENT's shell resolves `bd` natively. Derived from
17484
- * `process.argv[1]` (the CLI entry script). Returns null when it can't be
17485
- * determined.
17580
+ * A directory ON PATH to symlink `bd` into, so the AGENT's shell + the
17581
+ * SessionStart `bd prime` hook resolve `bd` by name.
17582
+ *
17583
+ * Earlier this used `dirname(realpath(process.argv[1]))` but for a GLOBAL
17584
+ * npm install that resolves to the package's own `dist/` dir (e.g.
17585
+ * `…/node_modules/codeam-cli/dist`), which is NOT on PATH. The symlink landed
17586
+ * somewhere nothing sees, so `which bd` and the hook still failed (observed
17587
+ * live in a codespace). `dirname(process.execPath)` is the dir the `node`
17588
+ * binary lives in — for a global install that's the npm prefix `bin/` where
17589
+ * the `codeam` launcher also lives, and IS on PATH. We prefer the first
17590
+ * candidate that actually appears in `$PATH`, falling back to node's bin dir.
17486
17591
  */
17487
17592
  cliBinDir: () => {
17488
- const entry = process.argv[1];
17489
- if (!entry) return null;
17593
+ const pathDirs = (process.env.PATH ?? "").split(path36.delimiter).filter(Boolean);
17594
+ const candidates = [];
17490
17595
  try {
17491
- return path36.dirname(fs30.realpathSync(entry));
17596
+ candidates.push(path36.dirname(process.execPath));
17492
17597
  } catch {
17493
- return path36.dirname(entry);
17494
17598
  }
17599
+ const entry = process.argv[1];
17600
+ if (entry) {
17601
+ try {
17602
+ candidates.push(path36.dirname(fs30.realpathSync(entry)));
17603
+ } catch {
17604
+ candidates.push(path36.dirname(entry));
17605
+ }
17606
+ }
17607
+ if (candidates.length === 0) return null;
17608
+ return candidates.find((d3) => pathDirs.includes(d3)) ?? candidates[0];
17495
17609
  },
17496
17610
  /** Current symlink target at `linkPath`, or null when absent / not a link. */
17497
17611
  readlink: (linkPath) => {
@@ -17517,7 +17631,7 @@ function linkBdOntoPath(binaryPath) {
17517
17631
  log.info("beads", `linked bd onto PATH: ${linkPath} -> ${binaryPath}`);
17518
17632
  }
17519
17633
  function setGitBeadsRole() {
17520
- (0, import_child_process14.execFileSync)("git", ["config", "--global", "beads.role", "contributor"], {
17634
+ (0, import_child_process15.execFileSync)("git", ["config", "--global", "beads.role", "contributor"], {
17521
17635
  stdio: "ignore"
17522
17636
  });
17523
17637
  }
@@ -17624,7 +17738,7 @@ var crypto3 = __toESM(require("crypto"));
17624
17738
  var path38 = __toESM(require("path"));
17625
17739
 
17626
17740
  // src/beads/project-key.ts
17627
- var import_child_process15 = require("child_process");
17741
+ var import_child_process16 = require("child_process");
17628
17742
  var crypto2 = __toESM(require("crypto"));
17629
17743
  var fs31 = __toESM(require("fs"));
17630
17744
  var path37 = __toESM(require("path"));
@@ -17671,7 +17785,7 @@ function findRepoRoot(cwd) {
17671
17785
  }
17672
17786
  var _execSeam2 = {
17673
17787
  exec: (file, args2, opts) => {
17674
- const out2 = (0, import_child_process15.execFileSync)(file, args2, opts);
17788
+ const out2 = (0, import_child_process16.execFileSync)(file, args2, opts);
17675
17789
  return typeof out2 === "string" ? out2 : out2.toString("utf8");
17676
17790
  },
17677
17791
  realpath: (p2) => fs31.realpathSync(p2)
@@ -18211,7 +18325,7 @@ var sessionTerminated = async (ctx, cmd) => {
18211
18325
  } catch {
18212
18326
  }
18213
18327
  try {
18214
- const proc = (0, import_child_process16.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18328
+ const proc = (0, import_child_process17.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18215
18329
  detached: true,
18216
18330
  stdio: "ignore"
18217
18331
  });
@@ -18233,7 +18347,7 @@ var shutdownSession = async (ctx, cmd) => {
18233
18347
  }
18234
18348
  if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
18235
18349
  try {
18236
- const stopProc = (0, import_child_process16.spawn)(
18350
+ const stopProc = (0, import_child_process17.spawn)(
18237
18351
  "bash",
18238
18352
  ["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
18239
18353
  { detached: true, stdio: "ignore" }
@@ -18243,7 +18357,7 @@ var shutdownSession = async (ctx, cmd) => {
18243
18357
  }
18244
18358
  }
18245
18359
  try {
18246
- const proc = (0, import_child_process16.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18360
+ const proc = (0, import_child_process17.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18247
18361
  detached: true,
18248
18362
  stdio: "ignore"
18249
18363
  });
@@ -18643,11 +18757,21 @@ async function waitForDevServerReady(devServer, readyRe, opts = {
18643
18757
  };
18644
18758
  devServer.stdout?.on("data", consume);
18645
18759
  devServer.stderr?.on("data", consume);
18760
+ let probeInFlight = false;
18646
18761
  const deadline = Date.now() + opts.timeoutMs;
18647
18762
  while (!readyMatched && Date.now() < deadline) {
18648
18763
  if (devServer.exitCode !== null) {
18649
18764
  return { kind: "exited", code: devServer.exitCode };
18650
18765
  }
18766
+ if (opts.portProbe && !probeInFlight) {
18767
+ probeInFlight = true;
18768
+ void opts.portProbe().then((up) => {
18769
+ if (up) readyMatched = true;
18770
+ }).catch(() => {
18771
+ }).finally(() => {
18772
+ probeInFlight = false;
18773
+ });
18774
+ }
18651
18775
  await new Promise((r) => setTimeout(r, 250));
18652
18776
  }
18653
18777
  if (readyMatched) return { kind: "ready" };
@@ -18667,6 +18791,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
18667
18791
  args: args2.slice(1)
18668
18792
  };
18669
18793
  }
18794
+ var INSTALL_TIMEOUT_MS = 5 * 6e4;
18795
+ var SETUP_TIMEOUT_MS = 2 * 6e4;
18670
18796
  var previewStartH = (ctx, _cmd, parsed) => {
18671
18797
  if (!ctx.pluginAuthToken) {
18672
18798
  log.info("preview", "no pluginAuthToken \u2014 skipping start");
@@ -18704,13 +18830,27 @@ var previewStartH = (ctx, _cmd, parsed) => {
18704
18830
  "SETUP_RUN",
18705
18831
  `${missingDeps.cmd} ${missingDeps.args.join(" ")} (pre-flight \u2014 node_modules missing)`
18706
18832
  );
18707
- const exitCode = await runOnce(
18833
+ const result = await runSetupCommand(
18708
18834
  missingDeps.cmd,
18709
18835
  missingDeps.args,
18710
18836
  process.cwd(),
18711
- detection.env
18837
+ detection.env,
18838
+ { timeoutMs: INSTALL_TIMEOUT_MS }
18712
18839
  );
18713
- if (exitCode !== 0) {
18840
+ if (result.status === "timeout") {
18841
+ void postPreviewEvent({
18842
+ sessionId: ctx.sessionId,
18843
+ pluginId: ctx.pluginId,
18844
+ pluginAuthToken,
18845
+ type: "preview_error",
18846
+ payload: {
18847
+ stage: "ready_timeout",
18848
+ message: `Dependency install (${missingDeps.cmd} ${missingDeps.args.join(" ")}) didn't finish within ${Math.round(INSTALL_TIMEOUT_MS / 1e3)}s and was stopped. Run it manually in this project, then try the preview again.`
18849
+ }
18850
+ });
18851
+ return;
18852
+ }
18853
+ if (result.status === "failed") {
18714
18854
  void postPreviewEvent({
18715
18855
  sessionId: ctx.sessionId,
18716
18856
  pluginId: ctx.pluginId,
@@ -18718,7 +18858,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
18718
18858
  type: "preview_error",
18719
18859
  payload: {
18720
18860
  stage: "spawn",
18721
- message: `Dependency install failed (${missingDeps.cmd} ${missingDeps.args.join(" ")}, exit ${exitCode}). Run it manually in this project and try again.`
18861
+ message: `Dependency install failed (${missingDeps.cmd} ${missingDeps.args.join(" ")}, exit ${result.code}). Run it manually in this project and try again.`
18722
18862
  }
18723
18863
  });
18724
18864
  return;
@@ -18730,8 +18870,28 @@ var previewStartH = (ctx, _cmd, parsed) => {
18730
18870
  ) : detection.setup_commands ?? [];
18731
18871
  for (const setup of agentSetupCommands) {
18732
18872
  emitProgress("SETUP_RUN", `${setup.cmd} ${setup.args.join(" ")}`);
18733
- const exitCode = await runOnce(setup.cmd, setup.args, process.cwd(), detection.env);
18734
- if (exitCode !== 0) {
18873
+ const timeoutMs = isJsInstallCommand(setup.cmd, setup.args) ? INSTALL_TIMEOUT_MS : SETUP_TIMEOUT_MS;
18874
+ const result = await runSetupCommand(
18875
+ setup.cmd,
18876
+ setup.args,
18877
+ process.cwd(),
18878
+ detection.env,
18879
+ { timeoutMs }
18880
+ );
18881
+ if (result.status === "timeout") {
18882
+ void postPreviewEvent({
18883
+ sessionId: ctx.sessionId,
18884
+ pluginId: ctx.pluginId,
18885
+ pluginAuthToken,
18886
+ type: "preview_error",
18887
+ payload: {
18888
+ stage: "ready_timeout",
18889
+ message: `Setup step (${setup.cmd} ${setup.args.join(" ")}) didn't finish within ${Math.round(timeoutMs / 1e3)}s and was stopped.`
18890
+ }
18891
+ });
18892
+ return;
18893
+ }
18894
+ if (result.status === "failed") {
18735
18895
  void postPreviewEvent({
18736
18896
  sessionId: ctx.sessionId,
18737
18897
  pluginId: ctx.pluginId,
@@ -18739,7 +18899,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
18739
18899
  type: "preview_error",
18740
18900
  payload: {
18741
18901
  stage: "spawn",
18742
- message: `Setup failed (${setup.cmd} ${setup.args.join(" ")}, exit ${exitCode}).`
18902
+ message: `Setup failed (${setup.cmd} ${setup.args.join(" ")}, exit ${result.code}).`
18743
18903
  }
18744
18904
  });
18745
18905
  return;
@@ -18750,7 +18910,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
18750
18910
  "BOOT_SEQUENCE",
18751
18911
  `${spawnable.command} ${spawnable.args.join(" ")}`
18752
18912
  );
18753
- const devServer = (0, import_child_process16.spawn)(spawnable.command, spawnable.args, {
18913
+ const devServer = (0, import_child_process17.spawn)(spawnable.command, spawnable.args, {
18754
18914
  cwd: process.cwd(),
18755
18915
  env: { ...process.env, ...spawnable.env ?? {} },
18756
18916
  stdio: ["ignore", "pipe", "pipe"]
@@ -18759,13 +18919,15 @@ var previewStartH = (ctx, _cmd, parsed) => {
18759
18919
  emitProgress("WAITING_FOR_READY", detection.ready_pattern);
18760
18920
  let expoUrl = null;
18761
18921
  const readyRe = compileReadyPattern(detection.ready_pattern);
18922
+ const isNextJs = /next/i.test(detection.framework);
18762
18923
  const outcome = await waitForDevServerReady(devServer, readyRe, {
18763
18924
  timeoutMs: 12e4,
18764
18925
  onChunk: (s) => {
18765
18926
  if (!expoUrl && detection.framework === "Expo") {
18766
18927
  expoUrl = parseExpoUrl(s);
18767
18928
  }
18768
- }
18929
+ },
18930
+ portProbe: isNextJs ? () => waitForPortListening(detection.port, { timeoutMs: 1e3, intervalMs: 250 }) : void 0
18769
18931
  });
18770
18932
  if (outcome.kind === "exited") {
18771
18933
  void postPreviewEvent({
@@ -18876,7 +19038,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
18876
19038
  });
18877
19039
  return;
18878
19040
  }
18879
- tunnel = (0, import_child_process16.spawn)(bin, ["tunnel", "--url", `http://localhost:${detection.port}`], {
19041
+ tunnel = (0, import_child_process17.spawn)(bin, ["tunnel", "--url", `http://localhost:${detection.port}`], {
18880
19042
  stdio: ["ignore", "pipe", "pipe"]
18881
19043
  });
18882
19044
  let parsedUrl = null;
@@ -18972,25 +19134,6 @@ var previewStopH = (ctx) => {
18972
19134
  });
18973
19135
  })();
18974
19136
  };
18975
- function runOnce(cmd, args2, cwd, env) {
18976
- return new Promise((resolve7) => {
18977
- const child = (0, import_child_process16.spawn)(cmd, args2, {
18978
- cwd,
18979
- env: { ...process.env, ...env ?? {} },
18980
- stdio: ["ignore", "pipe", "pipe"]
18981
- });
18982
- const tag = `setup:${cmd}`;
18983
- const onChunk = (chunk) => {
18984
- const text = chunk.toString().replace(/\n+$/g, "");
18985
- if (text.length === 0) return;
18986
- log.info("preview", `${tag}: ${text}`);
18987
- };
18988
- child.stdout?.on("data", onChunk);
18989
- child.stderr?.on("data", onChunk);
18990
- child.once("exit", (code) => resolve7(code));
18991
- child.once("error", () => resolve7(-1));
18992
- });
18993
- }
18994
19137
  var savePreviewConfigH = (_ctx, _cmd, parsed) => {
18995
19138
  const detection = parsed.detection;
18996
19139
  if (!detection) {
@@ -19070,7 +19213,7 @@ async function dispatchCommand(ctx, cmd) {
19070
19213
  }
19071
19214
 
19072
19215
  // src/services/file-watcher.service.ts
19073
- var import_child_process17 = require("child_process");
19216
+ var import_child_process18 = require("child_process");
19074
19217
  var fs33 = __toESM(require("fs"));
19075
19218
  var os26 = __toESM(require("os"));
19076
19219
  var path40 = __toESM(require("path"));
@@ -19836,7 +19979,7 @@ async function _runGitImpl(cwd, args2, opts = {}) {
19836
19979
  return new Promise((resolve7) => {
19837
19980
  let proc;
19838
19981
  try {
19839
- proc = (0, import_child_process17.spawn)("git", args2, { cwd, env: process.env });
19982
+ proc = (0, import_child_process18.spawn)("git", args2, { cwd, env: process.env });
19840
19983
  } catch {
19841
19984
  resolve7(null);
19842
19985
  return;
@@ -19868,7 +20011,7 @@ function _runGit(cwd, args2, opts = {}) {
19868
20011
  var import_crypto4 = require("crypto");
19869
20012
 
19870
20013
  // src/services/turn-files/git-changeset.ts
19871
- var import_child_process18 = require("child_process");
20014
+ var import_child_process19 = require("child_process");
19872
20015
  var path41 = __toESM(require("path"));
19873
20016
  async function collectRepoChangeset(opts) {
19874
20017
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
@@ -19952,7 +20095,7 @@ function defaultRunGit(cwd, args2) {
19952
20095
  return new Promise((resolve7) => {
19953
20096
  let proc;
19954
20097
  try {
19955
- proc = (0, import_child_process18.spawn)("git", args2, { cwd, env: process.env });
20098
+ proc = (0, import_child_process19.spawn)("git", args2, { cwd, env: process.env });
19956
20099
  } catch {
19957
20100
  resolve7(null);
19958
20101
  return;
@@ -22807,13 +22950,13 @@ function fetchQuotaUsage(runtime, historySvc) {
22807
22950
  }
22808
22951
 
22809
22952
  // src/commands/start/keep-alive.ts
22810
- var import_child_process19 = require("child_process");
22953
+ var import_child_process20 = require("child_process");
22811
22954
  function buildKeepAlive(ctx) {
22812
22955
  let timer = null;
22813
22956
  async function setIdleTimeout(minutes) {
22814
22957
  if (!ctx.inCodespace || !ctx.codespaceName) return;
22815
22958
  await new Promise((resolve7) => {
22816
- const proc = (0, import_child_process19.spawn)(
22959
+ const proc = (0, import_child_process20.spawn)(
22817
22960
  "gh",
22818
22961
  [
22819
22962
  "api",
@@ -23762,11 +23905,11 @@ async function logout() {
23762
23905
  var import_picocolors10 = __toESM(require("picocolors"));
23763
23906
 
23764
23907
  // src/services/providers/github-codespaces.ts
23765
- var import_child_process20 = require("child_process");
23908
+ var import_child_process21 = require("child_process");
23766
23909
  var import_util4 = require("util");
23767
23910
  var import_picocolors8 = __toESM(require("picocolors"));
23768
23911
  var path44 = __toESM(require("path"));
23769
- var execFileP5 = (0, import_util4.promisify)(import_child_process20.execFile);
23912
+ var execFileP5 = (0, import_util4.promisify)(import_child_process21.execFile);
23770
23913
  var MAX_BUFFER = 8 * 1024 * 1024;
23771
23914
  function resetStdinForChild() {
23772
23915
  if (process.stdin.isTTY) {
@@ -23810,7 +23953,7 @@ var GitHubCodespacesProvider = class {
23810
23953
  if (!isAuthed) {
23811
23954
  resetStdinForChild();
23812
23955
  await new Promise((resolve7, reject) => {
23813
- const proc = (0, import_child_process20.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
23956
+ const proc = (0, import_child_process21.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
23814
23957
  stdio: "inherit"
23815
23958
  });
23816
23959
  proc.on("exit", (code) => {
@@ -23844,7 +23987,7 @@ var GitHubCodespacesProvider = class {
23844
23987
  wt(noteLines.join("\n"), "One more permission needed");
23845
23988
  resetStdinForChild();
23846
23989
  const refreshCode = await new Promise((resolve7, reject) => {
23847
- const proc = (0, import_child_process20.spawn)(
23990
+ const proc = (0, import_child_process21.spawn)(
23848
23991
  "gh",
23849
23992
  ["auth", "refresh", "-h", "github.com", "-s", "codespace"],
23850
23993
  { stdio: "inherit" }
@@ -23994,7 +24137,7 @@ var GitHubCodespacesProvider = class {
23994
24137
  O2.step(`Installing gh via ${installCmd.describe}\u2026`);
23995
24138
  resetStdinForChild();
23996
24139
  const ok = await new Promise((resolve7) => {
23997
- const proc = (0, import_child_process20.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
24140
+ const proc = (0, import_child_process21.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
23998
24141
  proc.on("exit", (code) => resolve7(code === 0));
23999
24142
  proc.on("error", () => resolve7(false));
24000
24143
  });
@@ -24021,7 +24164,7 @@ var GitHubCodespacesProvider = class {
24021
24164
  );
24022
24165
  resetStdinForChild();
24023
24166
  await new Promise((resolve7, reject) => {
24024
- const proc = (0, import_child_process20.spawn)(
24167
+ const proc = (0, import_child_process21.spawn)(
24025
24168
  "gh",
24026
24169
  ["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
24027
24170
  { stdio: "inherit" }
@@ -24199,7 +24342,7 @@ var GitHubCodespacesProvider = class {
24199
24342
  async streamCommand(workspaceId, command2) {
24200
24343
  resetStdinForChild();
24201
24344
  return new Promise((resolve7, reject) => {
24202
- const proc = (0, import_child_process20.spawn)(
24345
+ const proc = (0, import_child_process21.spawn)(
24203
24346
  "gh",
24204
24347
  ["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
24205
24348
  { stdio: "inherit" }
@@ -24226,11 +24369,11 @@ var GitHubCodespacesProvider = class {
24226
24369
  `mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
24227
24370
  ];
24228
24371
  await new Promise((resolve7, reject) => {
24229
- const tar = (0, import_child_process20.spawn)("tar", tarArgs, {
24372
+ const tar = (0, import_child_process21.spawn)("tar", tarArgs, {
24230
24373
  stdio: ["ignore", "pipe", "pipe"],
24231
24374
  env: tarEnv
24232
24375
  });
24233
- const ssh = (0, import_child_process20.spawn)("gh", sshArgs, {
24376
+ const ssh = (0, import_child_process21.spawn)("gh", sshArgs, {
24234
24377
  stdio: [tar.stdout, "pipe", "pipe"]
24235
24378
  });
24236
24379
  let tarErr = "";
@@ -24264,7 +24407,7 @@ var GitHubCodespacesProvider = class {
24264
24407
  }
24265
24408
  const cmd = parts.join(" && ");
24266
24409
  await new Promise((resolve7, reject) => {
24267
- const proc = (0, import_child_process20.spawn)(
24410
+ const proc = (0, import_child_process21.spawn)(
24268
24411
  "gh",
24269
24412
  ["codespace", "ssh", "-c", workspaceId, "--", cmd],
24270
24413
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -24322,11 +24465,11 @@ function shellQuote(s) {
24322
24465
  }
24323
24466
 
24324
24467
  // src/services/providers/gitpod.ts
24325
- var import_child_process21 = require("child_process");
24468
+ var import_child_process22 = require("child_process");
24326
24469
  var import_util5 = require("util");
24327
24470
  var path45 = __toESM(require("path"));
24328
24471
  var import_picocolors9 = __toESM(require("picocolors"));
24329
- var execFileP6 = (0, import_util5.promisify)(import_child_process21.execFile);
24472
+ var execFileP6 = (0, import_util5.promisify)(import_child_process22.execFile);
24330
24473
  var MAX_BUFFER2 = 8 * 1024 * 1024;
24331
24474
  function resetStdinForChild2() {
24332
24475
  if (process.stdin.isTTY) {
@@ -24366,7 +24509,7 @@ var GitpodProvider = class {
24366
24509
  );
24367
24510
  resetStdinForChild2();
24368
24511
  await new Promise((resolve7, reject) => {
24369
- const proc = (0, import_child_process21.spawn)("gitpod", ["login"], { stdio: "inherit" });
24512
+ const proc = (0, import_child_process22.spawn)("gitpod", ["login"], { stdio: "inherit" });
24370
24513
  proc.on("exit", (code) => {
24371
24514
  if (code === 0) resolve7();
24372
24515
  else reject(new Error("gitpod login failed."));
@@ -24518,7 +24661,7 @@ var GitpodProvider = class {
24518
24661
  async streamCommand(workspaceId, command2) {
24519
24662
  resetStdinForChild2();
24520
24663
  return new Promise((resolve7, reject) => {
24521
- const proc = (0, import_child_process21.spawn)(
24664
+ const proc = (0, import_child_process22.spawn)(
24522
24665
  "gitpod",
24523
24666
  ["workspace", "ssh", workspaceId, "--", "-tt", command2],
24524
24667
  { stdio: "inherit" }
@@ -24538,11 +24681,11 @@ var GitpodProvider = class {
24538
24681
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
24539
24682
  const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
24540
24683
  await new Promise((resolve7, reject) => {
24541
- const tar = (0, import_child_process21.spawn)("tar", tarArgs, {
24684
+ const tar = (0, import_child_process22.spawn)("tar", tarArgs, {
24542
24685
  stdio: ["ignore", "pipe", "pipe"],
24543
24686
  env: tarEnv
24544
24687
  });
24545
- const ssh = (0, import_child_process21.spawn)(
24688
+ const ssh = (0, import_child_process22.spawn)(
24546
24689
  "gitpod",
24547
24690
  ["workspace", "ssh", workspaceId, "--", remoteCmd],
24548
24691
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -24574,7 +24717,7 @@ var GitpodProvider = class {
24574
24717
  }
24575
24718
  const cmd = parts.join(" && ");
24576
24719
  await new Promise((resolve7, reject) => {
24577
- const proc = (0, import_child_process21.spawn)(
24720
+ const proc = (0, import_child_process22.spawn)(
24578
24721
  "gitpod",
24579
24722
  ["workspace", "ssh", workspaceId, "--", cmd],
24580
24723
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -24598,10 +24741,10 @@ function shellQuote2(s) {
24598
24741
  }
24599
24742
 
24600
24743
  // src/services/providers/gitlab-workspaces.ts
24601
- var import_child_process22 = require("child_process");
24744
+ var import_child_process23 = require("child_process");
24602
24745
  var import_util6 = require("util");
24603
24746
  var path46 = __toESM(require("path"));
24604
- var execFileP7 = (0, import_util6.promisify)(import_child_process22.execFile);
24747
+ var execFileP7 = (0, import_util6.promisify)(import_child_process23.execFile);
24605
24748
  var MAX_BUFFER3 = 8 * 1024 * 1024;
24606
24749
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
24607
24750
  function resetStdinForChild3() {
@@ -24643,7 +24786,7 @@ var GitLabWorkspacesProvider = class {
24643
24786
  );
24644
24787
  resetStdinForChild3();
24645
24788
  await new Promise((resolve7, reject) => {
24646
- const proc = (0, import_child_process22.spawn)(
24789
+ const proc = (0, import_child_process23.spawn)(
24647
24790
  "glab",
24648
24791
  ["auth", "login", "--scopes", "api,read_user,read_repository"],
24649
24792
  { stdio: "inherit" }
@@ -24815,7 +24958,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
24815
24958
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
24816
24959
  resetStdinForChild3();
24817
24960
  return new Promise((resolve7, reject) => {
24818
- const proc = (0, import_child_process22.spawn)(
24961
+ const proc = (0, import_child_process23.spawn)(
24819
24962
  "ssh",
24820
24963
  ["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
24821
24964
  { stdio: "inherit" }
@@ -24836,8 +24979,8 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
24836
24979
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
24837
24980
  const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
24838
24981
  await new Promise((resolve7, reject) => {
24839
- const tar = (0, import_child_process22.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
24840
- const ssh = (0, import_child_process22.spawn)(
24982
+ const tar = (0, import_child_process23.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
24983
+ const ssh = (0, import_child_process23.spawn)(
24841
24984
  "ssh",
24842
24985
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
24843
24986
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -24867,7 +25010,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
24867
25010
  }
24868
25011
  const cmd = parts.join(" && ");
24869
25012
  await new Promise((resolve7, reject) => {
24870
- const proc = (0, import_child_process22.spawn)(
25013
+ const proc = (0, import_child_process23.spawn)(
24871
25014
  "ssh",
24872
25015
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
24873
25016
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -24926,10 +25069,10 @@ function shellQuote3(s) {
24926
25069
  }
24927
25070
 
24928
25071
  // src/services/providers/railway.ts
24929
- var import_child_process23 = require("child_process");
25072
+ var import_child_process24 = require("child_process");
24930
25073
  var import_util7 = require("util");
24931
25074
  var path47 = __toESM(require("path"));
24932
- var execFileP8 = (0, import_util7.promisify)(import_child_process23.execFile);
25075
+ var execFileP8 = (0, import_util7.promisify)(import_child_process24.execFile);
24933
25076
  var MAX_BUFFER4 = 8 * 1024 * 1024;
24934
25077
  function resetStdinForChild4() {
24935
25078
  if (process.stdin.isTTY) {
@@ -24970,7 +25113,7 @@ var RailwayProvider = class {
24970
25113
  );
24971
25114
  resetStdinForChild4();
24972
25115
  await new Promise((resolve7, reject) => {
24973
- const proc = (0, import_child_process23.spawn)("railway", ["login"], { stdio: "inherit" });
25116
+ const proc = (0, import_child_process24.spawn)("railway", ["login"], { stdio: "inherit" });
24974
25117
  proc.on("exit", (code) => {
24975
25118
  if (code === 0) resolve7();
24976
25119
  else reject(new Error("railway login failed."));
@@ -25113,7 +25256,7 @@ var RailwayProvider = class {
25113
25256
  }
25114
25257
  resetStdinForChild4();
25115
25258
  return new Promise((resolve7, reject) => {
25116
- const proc = (0, import_child_process23.spawn)(
25259
+ const proc = (0, import_child_process24.spawn)(
25117
25260
  "railway",
25118
25261
  ["shell", "--project", projectId, "--service", serviceId, "--command", command2],
25119
25262
  { stdio: "inherit" }
@@ -25137,8 +25280,8 @@ var RailwayProvider = class {
25137
25280
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
25138
25281
  const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
25139
25282
  await new Promise((resolve7, reject) => {
25140
- const tar = (0, import_child_process23.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
25141
- const sh = (0, import_child_process23.spawn)(
25283
+ const tar = (0, import_child_process24.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
25284
+ const sh = (0, import_child_process24.spawn)(
25142
25285
  "railway",
25143
25286
  ["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
25144
25287
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -25171,7 +25314,7 @@ var RailwayProvider = class {
25171
25314
  }
25172
25315
  const cmd = parts.join(" && ");
25173
25316
  await new Promise((resolve7, reject) => {
25174
- const proc = (0, import_child_process23.spawn)(
25317
+ const proc = (0, import_child_process24.spawn)(
25175
25318
  "railway",
25176
25319
  ["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
25177
25320
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -25876,7 +26019,7 @@ function checkChokidar() {
25876
26019
  }
25877
26020
  async function doctor(args2 = []) {
25878
26021
  const json = args2.includes("--json");
25879
- const cliVersion = true ? "2.35.0" : "0.0.0-dev";
26022
+ const cliVersion = true ? "2.35.2" : "0.0.0-dev";
25880
26023
  const apiBase = resolveApiBaseUrl();
25881
26024
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
25882
26025
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -26075,7 +26218,7 @@ async function completion(args2) {
26075
26218
  // src/commands/version.ts
26076
26219
  var import_picocolors13 = __toESM(require("picocolors"));
26077
26220
  function version2() {
26078
- const v = true ? "2.35.0" : "unknown";
26221
+ const v = true ? "2.35.2" : "unknown";
26079
26222
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
26080
26223
  }
26081
26224
 
@@ -26361,7 +26504,7 @@ function checkForUpdates() {
26361
26504
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
26362
26505
  if (process.env.CI) return;
26363
26506
  if (!process.stdout.isTTY) return;
26364
- const current = true ? "2.35.0" : null;
26507
+ const current = true ? "2.35.2" : null;
26365
26508
  if (!current) return;
26366
26509
  const cache = readCache();
26367
26510
  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.35.0",
3
+ "version": "2.35.2",
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",