codeam-cli 2.26.11 → 2.26.13

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 +12 -0
  2. package/dist/index.js +141 -70
  3. package/package.json +1 -1
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.26.12] — 2026-06-04
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Gate preview_ready on DNS resolution via c-ares + 1.1.1.1 (#249)
12
+
13
+ ## [2.26.11] — 2026-06-03
14
+
15
+ ### Added
16
+
17
+ - **cli:** Emit preview_progress SSE events at each bring-up milestone (#244)
18
+
7
19
  ## [2.26.10] — 2026-06-03
8
20
 
9
21
  ### Fixed
package/dist/index.js CHANGED
@@ -472,7 +472,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
472
472
  // package.json
473
473
  var package_default = {
474
474
  name: "codeam-cli",
475
- version: "2.26.11",
475
+ version: "2.26.13",
476
476
  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.",
477
477
  type: "commonjs",
478
478
  main: "dist/index.js",
@@ -1115,8 +1115,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
1115
1115
  return decodedFile;
1116
1116
  };
1117
1117
  }
1118
- function normalizeWindowsPath(path42) {
1119
- return path42.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1118
+ function normalizeWindowsPath(path43) {
1119
+ return path43.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1120
1120
  }
1121
1121
 
1122
1122
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -3596,9 +3596,9 @@ async function addSourceContext(frames) {
3596
3596
  LRU_FILE_CONTENTS_CACHE.reduce();
3597
3597
  return frames;
3598
3598
  }
3599
- function getContextLinesFromFile(path42, ranges, output) {
3599
+ function getContextLinesFromFile(path43, ranges, output) {
3600
3600
  return new Promise((resolve5) => {
3601
- const stream = (0, import_node_fs.createReadStream)(path42);
3601
+ const stream = (0, import_node_fs.createReadStream)(path43);
3602
3602
  const lineReaded = (0, import_node_readline.createInterface)({
3603
3603
  input: stream
3604
3604
  });
@@ -3613,7 +3613,7 @@ function getContextLinesFromFile(path42, ranges, output) {
3613
3613
  let rangeStart = range[0];
3614
3614
  let rangeEnd = range[1];
3615
3615
  function onStreamError() {
3616
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path42, 1);
3616
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path43, 1);
3617
3617
  lineReaded.close();
3618
3618
  lineReaded.removeAllListeners();
3619
3619
  destroyStreamAndResolve();
@@ -3674,8 +3674,8 @@ function clearLineContext(frame) {
3674
3674
  delete frame.context_line;
3675
3675
  delete frame.post_context;
3676
3676
  }
3677
- function shouldSkipContextLinesForFile(path42) {
3678
- return path42.startsWith("node:") || path42.endsWith(".min.js") || path42.endsWith(".min.cjs") || path42.endsWith(".min.mjs") || path42.startsWith("data:");
3677
+ function shouldSkipContextLinesForFile(path43) {
3678
+ return path43.startsWith("node:") || path43.endsWith(".min.js") || path43.endsWith(".min.cjs") || path43.endsWith(".min.mjs") || path43.startsWith("data:");
3679
3679
  }
3680
3680
  function shouldSkipContextLinesForFrame(frame) {
3681
3681
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -5829,7 +5829,7 @@ function readAnonId() {
5829
5829
  }
5830
5830
  function superProperties() {
5831
5831
  return {
5832
- cliVersion: true ? "2.26.11" : "0.0.0-dev",
5832
+ cliVersion: true ? "2.26.13" : "0.0.0-dev",
5833
5833
  nodeVersion: process.version,
5834
5834
  platform: process.platform,
5835
5835
  arch: process.arch,
@@ -9901,13 +9901,13 @@ function detectStartupBanner(lines) {
9901
9901
  while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
9902
9902
  if (metaIdx - artStart < 2) return null;
9903
9903
  const pathLine = (lines[metaIdx + 1] ?? "").trim();
9904
- const path42 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9904
+ const path43 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9905
9905
  return {
9906
9906
  title: "",
9907
9907
  subtitle: lines[metaIdx].trim(),
9908
- path: path42,
9908
+ path: path43,
9909
9909
  startIdx: artStart,
9910
- endIdx: metaIdx + (path42 ? 1 : 0)
9910
+ endIdx: metaIdx + (path43 ? 1 : 0)
9911
9911
  };
9912
9912
  }
9913
9913
 
@@ -11205,11 +11205,11 @@ function parseReview(stdout) {
11205
11205
  for (const line of lines) {
11206
11206
  const m = line.match(HUNK_LINE_RE);
11207
11207
  if (!m) continue;
11208
- const [, path42, lineNo, sevToken, message] = m;
11209
- if (!path42 || !lineNo || !message) continue;
11208
+ const [, path43, lineNo, sevToken, message] = m;
11209
+ if (!path43 || !lineNo || !message) continue;
11210
11210
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
11211
11211
  hunks.push({
11212
- path: path42.trim(),
11212
+ path: path43.trim(),
11213
11213
  line: Number(lineNo),
11214
11214
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
11215
11215
  message: cleanedMessage
@@ -13845,7 +13845,7 @@ function defaultRunGit(cwd, args2) {
13845
13845
  });
13846
13846
  }
13847
13847
  async function discoverRepos(workingDir, maxDepth = 4) {
13848
- const fs33 = await import("fs/promises");
13848
+ const fs34 = await import("fs/promises");
13849
13849
  const out2 = [];
13850
13850
  await walk(workingDir, 0);
13851
13851
  return out2;
@@ -13853,7 +13853,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
13853
13853
  if (depth > maxDepth) return;
13854
13854
  let entries = [];
13855
13855
  try {
13856
- const dirents = await fs33.readdir(dir, { withFileTypes: true });
13856
+ const dirents = await fs34.readdir(dir, { withFileTypes: true });
13857
13857
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
13858
13858
  } catch {
13859
13859
  return;
@@ -14755,9 +14755,9 @@ function buildKeepAlive(ctx) {
14755
14755
  }
14756
14756
 
14757
14757
  // src/commands/start/handlers.ts
14758
- var fs29 = __toESM(require("fs"));
14758
+ var fs30 = __toESM(require("fs"));
14759
14759
  var os24 = __toESM(require("os"));
14760
- var path35 = __toESM(require("path"));
14760
+ var path36 = __toESM(require("path"));
14761
14761
  var import_crypto5 = require("crypto");
14762
14762
  var import_child_process15 = require("child_process");
14763
14763
 
@@ -16057,25 +16057,29 @@ async function linkDryRunPreflight(ctx) {
16057
16057
  }
16058
16058
 
16059
16059
  // src/services/preview/cloudflared.ts
16060
+ var import_promises = require("dns/promises");
16060
16061
  var import_fs = require("fs");
16061
- var import_promises = __toESM(require("fs/promises"));
16062
+ var import_promises2 = __toESM(require("fs/promises"));
16062
16063
  var import_os7 = __toESM(require("os"));
16063
16064
  var import_path4 = __toESM(require("path"));
16064
- var import_promises2 = require("stream/promises");
16065
+ var import_promises3 = require("stream/promises");
16065
16066
  var import_which = __toESM(require("which"));
16066
16067
  var CACHED_BINARY = import_path4.default.join(import_os7.default.homedir(), ".codeam", "bin", "cloudflared");
16067
- async function waitForCloudflaredReady(url, timeoutMs = 3e4) {
16068
+ async function waitForCloudflaredReady(url, timeoutMs = 6e4) {
16069
+ const hostname3 = new URL(url).hostname;
16070
+ const resolver = new import_promises.Resolver();
16071
+ resolver.setServers(["1.1.1.1", "1.0.0.1"]);
16068
16072
  const start2 = Date.now();
16069
16073
  while (Date.now() - start2 < timeoutMs) {
16070
16074
  try {
16071
- const res = await fetch(url, { method: "HEAD" });
16072
- if (res.status < 500) return;
16075
+ const addrs = await resolver.resolve4(hostname3);
16076
+ if (addrs.length > 0) return;
16073
16077
  } catch {
16074
16078
  }
16075
16079
  await new Promise((r) => setTimeout(r, 500));
16076
16080
  }
16077
16081
  throw new Error(
16078
- `Tunnel URL ${url} not reachable after ${timeoutMs}ms (DNS may still be propagating).`
16082
+ `DNS for ${hostname3} did not resolve within ${timeoutMs}ms (Cloudflare Quick Tunnel registration may have failed).`
16079
16083
  );
16080
16084
  }
16081
16085
  async function resolveCloudflared(opts = {}) {
@@ -16084,7 +16088,7 @@ async function resolveCloudflared(opts = {}) {
16084
16088
  } catch {
16085
16089
  }
16086
16090
  try {
16087
- await import_promises.default.access(CACHED_BINARY);
16091
+ await import_promises2.default.access(CACHED_BINARY);
16088
16092
  return CACHED_BINARY;
16089
16093
  } catch {
16090
16094
  }
@@ -16098,14 +16102,14 @@ async function resolveCloudflared(opts = {}) {
16098
16102
  }
16099
16103
  async function downloadCloudflared(target) {
16100
16104
  const url = downloadUrlForPlatform();
16101
- await import_promises.default.mkdir(import_path4.default.dirname(target), { recursive: true });
16105
+ await import_promises2.default.mkdir(import_path4.default.dirname(target), { recursive: true });
16102
16106
  const response = await fetch(url);
16103
16107
  if (!response.ok || !response.body) {
16104
16108
  throw new Error(
16105
16109
  `Failed to download cloudflared from ${url}: HTTP ${response.status}. Install manually from https://github.com/cloudflare/cloudflared/releases.`
16106
16110
  );
16107
16111
  }
16108
- await (0, import_promises2.pipeline)(
16112
+ await (0, import_promises3.pipeline)(
16109
16113
  response.body,
16110
16114
  (0, import_fs.createWriteStream)(target, { mode: 493 })
16111
16115
  );
@@ -16158,7 +16162,7 @@ async function waitForCodespacePortReady(url, timeoutMs = 15e3) {
16158
16162
  }
16159
16163
 
16160
16164
  // src/services/preview/config-file.ts
16161
- var import_promises3 = __toESM(require("fs/promises"));
16165
+ var import_promises4 = __toESM(require("fs/promises"));
16162
16166
  var import_path5 = __toESM(require("path"));
16163
16167
  var CONFIG_DIR = ".codeam";
16164
16168
  var CONFIG_FILE = "preview.json";
@@ -16175,7 +16179,7 @@ var REQUIRED_FIELDS = [
16175
16179
  async function readPreviewConfig(cwd) {
16176
16180
  let raw;
16177
16181
  try {
16178
- raw = await import_promises3.default.readFile(configPath(cwd), "utf-8");
16182
+ raw = await import_promises4.default.readFile(configPath(cwd), "utf-8");
16179
16183
  } catch {
16180
16184
  return null;
16181
16185
  }
@@ -16194,8 +16198,8 @@ async function readPreviewConfig(cwd) {
16194
16198
  }
16195
16199
  async function writePreviewConfig(cwd, detection) {
16196
16200
  const filePath = configPath(cwd);
16197
- await import_promises3.default.mkdir(import_path5.default.dirname(filePath), { recursive: true });
16198
- await import_promises3.default.writeFile(filePath, JSON.stringify(detection, null, 2) + "\n", "utf-8");
16201
+ await import_promises4.default.mkdir(import_path5.default.dirname(filePath), { recursive: true });
16202
+ await import_promises4.default.writeFile(filePath, JSON.stringify(detection, null, 2) + "\n", "utf-8");
16199
16203
  }
16200
16204
 
16201
16205
  // src/services/preview/parser.ts
@@ -16277,6 +16281,24 @@ function parseExpoUrl(stdout) {
16277
16281
  return match ? match[0] : null;
16278
16282
  }
16279
16283
 
16284
+ // src/services/preview/setup-deps.ts
16285
+ var import_fs2 = __toESM(require("fs"));
16286
+ var import_path6 = __toESM(require("path"));
16287
+ function detectMissingNodeDeps(cwd) {
16288
+ if (!import_fs2.default.existsSync(import_path6.default.join(cwd, "package.json"))) return null;
16289
+ if (import_fs2.default.existsSync(import_path6.default.join(cwd, "node_modules"))) return null;
16290
+ if (import_fs2.default.existsSync(import_path6.default.join(cwd, "pnpm-lock.yaml"))) {
16291
+ return { cmd: "pnpm", args: ["install"] };
16292
+ }
16293
+ if (import_fs2.default.existsSync(import_path6.default.join(cwd, "yarn.lock"))) {
16294
+ return { cmd: "yarn", args: ["install"] };
16295
+ }
16296
+ if (import_fs2.default.existsSync(import_path6.default.join(cwd, "bun.lockb")) || import_fs2.default.existsSync(import_path6.default.join(cwd, "bun.lock"))) {
16297
+ return { cmd: "bun", args: ["install"] };
16298
+ }
16299
+ return { cmd: "npm", args: ["install"] };
16300
+ }
16301
+
16280
16302
  // src/services/preview/index.ts
16281
16303
  var activePreviews = /* @__PURE__ */ new Map();
16282
16304
  function registerPreview(sessionId, preview) {
@@ -16322,7 +16344,7 @@ var pendingAttachmentFiles = /* @__PURE__ */ new Set();
16322
16344
  function cleanupAttachmentTempFiles() {
16323
16345
  for (const p2 of pendingAttachmentFiles) {
16324
16346
  try {
16325
- fs29.unlinkSync(p2);
16347
+ fs30.unlinkSync(p2);
16326
16348
  } catch {
16327
16349
  }
16328
16350
  }
@@ -16331,8 +16353,8 @@ function cleanupAttachmentTempFiles() {
16331
16353
  function saveFilesTemp(files) {
16332
16354
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
16333
16355
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
16334
- const tmpPath = path35.join(os24.tmpdir(), `codeam-${(0, import_crypto5.randomUUID)()}-${safeName}`);
16335
- fs29.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
16356
+ const tmpPath = path36.join(os24.tmpdir(), `codeam-${(0, import_crypto5.randomUUID)()}-${safeName}`);
16357
+ fs30.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
16336
16358
  pendingAttachmentFiles.add(tmpPath);
16337
16359
  return tmpPath;
16338
16360
  });
@@ -16352,7 +16374,7 @@ var startTask = (ctx, _cmd, parsed) => {
16352
16374
  setTimeout(() => {
16353
16375
  for (const p2 of paths) {
16354
16376
  try {
16355
- fs29.unlinkSync(p2);
16377
+ fs30.unlinkSync(p2);
16356
16378
  } catch {
16357
16379
  }
16358
16380
  pendingAttachmentFiles.delete(p2);
@@ -16917,6 +16939,32 @@ var previewStartH = (ctx, _cmd, parsed) => {
16917
16939
  payload: { framework: detection.framework, port: detection.port }
16918
16940
  });
16919
16941
  emitProgress("ENV_DETECTED", `${detection.framework}`);
16942
+ const missingDeps = detectMissingNodeDeps(process.cwd());
16943
+ if (missingDeps) {
16944
+ emitProgress(
16945
+ "SETUP_RUN",
16946
+ `${missingDeps.cmd} ${missingDeps.args.join(" ")} (pre-flight \u2014 node_modules missing)`
16947
+ );
16948
+ const exitCode = await runOnce(
16949
+ missingDeps.cmd,
16950
+ missingDeps.args,
16951
+ process.cwd(),
16952
+ detection.env
16953
+ );
16954
+ if (exitCode !== 0) {
16955
+ void postPreviewEvent({
16956
+ sessionId: ctx.sessionId,
16957
+ pluginId: ctx.pluginId,
16958
+ pluginAuthToken,
16959
+ type: "preview_error",
16960
+ payload: {
16961
+ stage: "spawn",
16962
+ message: `Dependency install failed (${missingDeps.cmd} ${missingDeps.args.join(" ")}, exit ${exitCode}). Run it manually in this project and try again.`
16963
+ }
16964
+ });
16965
+ return;
16966
+ }
16967
+ }
16920
16968
  for (const setup of detection.setup_commands ?? []) {
16921
16969
  emitProgress("SETUP_RUN", `${setup.cmd} ${setup.args.join(" ")}`);
16922
16970
  const exitCode = await runOnce(setup.cmd, setup.args, process.cwd(), detection.env);
@@ -17102,7 +17150,30 @@ var previewStartH = (ctx, _cmd, parsed) => {
17102
17150
  });
17103
17151
  return;
17104
17152
  }
17105
- void waitForCloudflaredReady(parsedUrl, 3e4).then(() => log.info("preview", `cloudflared probe: ${parsedUrl} reachable from CLI host`)).catch((e) => log.info("preview", `cloudflared probe: ${String(e.message)} (non-fatal)`));
17153
+ try {
17154
+ await waitForCloudflaredReady(parsedUrl, 6e4);
17155
+ log.info("preview", `cloudflared probe: ${parsedUrl} reachable from CLI host`);
17156
+ } catch (e) {
17157
+ try {
17158
+ tunnel.kill("SIGTERM");
17159
+ } catch {
17160
+ }
17161
+ try {
17162
+ devServer.kill("SIGTERM");
17163
+ } catch {
17164
+ }
17165
+ void postPreviewEvent({
17166
+ sessionId: ctx.sessionId,
17167
+ pluginId: ctx.pluginId,
17168
+ pluginAuthToken,
17169
+ type: "preview_error",
17170
+ payload: {
17171
+ stage: "tunnel",
17172
+ message: `Tunnel ${parsedUrl} did not become reachable within 60s (${e.message}). Cloudflare Quick Tunnels occasionally fail to register \u2014 retry usually succeeds.`
17173
+ }
17174
+ });
17175
+ return;
17176
+ }
17106
17177
  url = parsedUrl;
17107
17178
  }
17108
17179
  emitProgress("TUNNEL_READY", url);
@@ -17609,7 +17680,7 @@ async function autoLinkAfterPair(opts) {
17609
17680
  }
17610
17681
 
17611
17682
  // src/commands/pair-auto.ts
17612
- var fs30 = __toESM(require("fs"));
17683
+ var fs31 = __toESM(require("fs"));
17613
17684
  var os25 = __toESM(require("os"));
17614
17685
  var import_crypto7 = require("crypto");
17615
17686
 
@@ -17778,12 +17849,12 @@ function readTokenFromArgs(args2) {
17778
17849
  }
17779
17850
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
17780
17851
  if (fileFlag) {
17781
- const path42 = fileFlag.slice("--token-file=".length);
17852
+ const path43 = fileFlag.slice("--token-file=".length);
17782
17853
  try {
17783
- const content = fs30.readFileSync(path42, "utf8").trim();
17784
- if (content.length === 0) fail(`--token-file ${path42} is empty`);
17854
+ const content = fs31.readFileSync(path43, "utf8").trim();
17855
+ if (content.length === 0) fail(`--token-file ${path43} is empty`);
17785
17856
  try {
17786
- fs30.unlinkSync(path42);
17857
+ fs31.unlinkSync(path43);
17787
17858
  } catch {
17788
17859
  }
17789
17860
  return content;
@@ -18049,7 +18120,7 @@ var import_picocolors10 = __toESM(require("picocolors"));
18049
18120
  var import_child_process16 = require("child_process");
18050
18121
  var import_util4 = require("util");
18051
18122
  var import_picocolors8 = __toESM(require("picocolors"));
18052
- var path36 = __toESM(require("path"));
18123
+ var path37 = __toESM(require("path"));
18053
18124
  var execFileP5 = (0, import_util4.promisify)(import_child_process16.execFile);
18054
18125
  var MAX_BUFFER = 8 * 1024 * 1024;
18055
18126
  function resetStdinForChild() {
@@ -18538,7 +18609,7 @@ var GitHubCodespacesProvider = class {
18538
18609
  });
18539
18610
  }
18540
18611
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
18541
- const remoteDir = path36.posix.dirname(remotePath);
18612
+ const remoteDir = path37.posix.dirname(remotePath);
18542
18613
  const parts = [
18543
18614
  `mkdir -p ${shellQuote(remoteDir)}`,
18544
18615
  `cat > ${shellQuote(remotePath)}`
@@ -18608,7 +18679,7 @@ function shellQuote(s) {
18608
18679
  // src/services/providers/gitpod.ts
18609
18680
  var import_child_process17 = require("child_process");
18610
18681
  var import_util5 = require("util");
18611
- var path37 = __toESM(require("path"));
18682
+ var path38 = __toESM(require("path"));
18612
18683
  var import_picocolors9 = __toESM(require("picocolors"));
18613
18684
  var execFileP6 = (0, import_util5.promisify)(import_child_process17.execFile);
18614
18685
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -18848,7 +18919,7 @@ var GitpodProvider = class {
18848
18919
  });
18849
18920
  }
18850
18921
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
18851
- const remoteDir = path37.posix.dirname(remotePath);
18922
+ const remoteDir = path38.posix.dirname(remotePath);
18852
18923
  const parts = [
18853
18924
  `mkdir -p ${shellQuote2(remoteDir)}`,
18854
18925
  `cat > ${shellQuote2(remotePath)}`
@@ -18884,7 +18955,7 @@ function shellQuote2(s) {
18884
18955
  // src/services/providers/gitlab-workspaces.ts
18885
18956
  var import_child_process18 = require("child_process");
18886
18957
  var import_util6 = require("util");
18887
- var path38 = __toESM(require("path"));
18958
+ var path39 = __toESM(require("path"));
18888
18959
  var execFileP7 = (0, import_util6.promisify)(import_child_process18.execFile);
18889
18960
  var MAX_BUFFER3 = 8 * 1024 * 1024;
18890
18961
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -19144,7 +19215,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
19144
19215
  }
19145
19216
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
19146
19217
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
19147
- const remoteDir = path38.posix.dirname(remotePath);
19218
+ const remoteDir = path39.posix.dirname(remotePath);
19148
19219
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
19149
19220
  if (options.mode != null) {
19150
19221
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -19212,7 +19283,7 @@ function shellQuote3(s) {
19212
19283
  // src/services/providers/railway.ts
19213
19284
  var import_child_process19 = require("child_process");
19214
19285
  var import_util7 = require("util");
19215
- var path39 = __toESM(require("path"));
19286
+ var path40 = __toESM(require("path"));
19216
19287
  var execFileP8 = (0, import_util7.promisify)(import_child_process19.execFile);
19217
19288
  var MAX_BUFFER4 = 8 * 1024 * 1024;
19218
19289
  function resetStdinForChild4() {
@@ -19448,7 +19519,7 @@ var RailwayProvider = class {
19448
19519
  if (!projectId || !serviceId) {
19449
19520
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
19450
19521
  }
19451
- const remoteDir = path39.posix.dirname(remotePath);
19522
+ const remoteDir = path40.posix.dirname(remotePath);
19452
19523
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
19453
19524
  if (options.mode != null) {
19454
19525
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -19991,8 +20062,8 @@ async function stopWorkspaceFromLocal(target) {
19991
20062
  var import_node_dns = require("dns");
19992
20063
  var import_node_util4 = require("util");
19993
20064
  var import_node_crypto6 = require("crypto");
19994
- var fs31 = __toESM(require("fs"));
19995
- var path40 = __toESM(require("path"));
20065
+ var fs32 = __toESM(require("fs"));
20066
+ var path41 = __toESM(require("path"));
19996
20067
  var import_picocolors12 = __toESM(require("picocolors"));
19997
20068
  var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
19998
20069
  async function checkDns(apiBase) {
@@ -20048,13 +20119,13 @@ async function checkHealth(apiBase) {
20048
20119
  }
20049
20120
  }
20050
20121
  function checkConfigDir() {
20051
- const dir = path40.join(require("os").homedir(), ".codeam");
20122
+ const dir = path41.join(require("os").homedir(), ".codeam");
20052
20123
  try {
20053
- fs31.mkdirSync(dir, { recursive: true, mode: 448 });
20054
- const probe = path40.join(dir, ".doctor-probe");
20055
- fs31.writeFileSync(probe, "ok", { mode: 384 });
20056
- const read = fs31.readFileSync(probe, "utf8");
20057
- fs31.unlinkSync(probe);
20124
+ fs32.mkdirSync(dir, { recursive: true, mode: 448 });
20125
+ const probe = path41.join(dir, ".doctor-probe");
20126
+ fs32.writeFileSync(probe, "ok", { mode: 384 });
20127
+ const read = fs32.readFileSync(probe, "utf8");
20128
+ fs32.unlinkSync(probe);
20058
20129
  if (read !== "ok") throw new Error("write/read round-trip mismatch");
20059
20130
  return {
20060
20131
  id: "config-dir",
@@ -20118,7 +20189,7 @@ function checkNodePty() {
20118
20189
  detail: "not required on this platform"
20119
20190
  };
20120
20191
  }
20121
- const vendoredPath = path40.join(__dirname, "vendor", "node-pty");
20192
+ const vendoredPath = path41.join(__dirname, "vendor", "node-pty");
20122
20193
  for (const target of [vendoredPath, "node-pty"]) {
20123
20194
  try {
20124
20195
  require(target);
@@ -20160,7 +20231,7 @@ function checkChokidar() {
20160
20231
  }
20161
20232
  async function doctor(args2 = []) {
20162
20233
  const json = args2.includes("--json");
20163
- const cliVersion = true ? "2.26.11" : "0.0.0-dev";
20234
+ const cliVersion = true ? "2.26.13" : "0.0.0-dev";
20164
20235
  const apiBase = resolveApiBaseUrl();
20165
20236
  const diagnosticId = (0, import_node_crypto6.randomUUID)();
20166
20237
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -20359,7 +20430,7 @@ async function completion(args2) {
20359
20430
  // src/commands/version.ts
20360
20431
  var import_picocolors13 = __toESM(require("picocolors"));
20361
20432
  function version2() {
20362
- const v = true ? "2.26.11" : "unknown";
20433
+ const v = true ? "2.26.13" : "unknown";
20363
20434
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
20364
20435
  }
20365
20436
 
@@ -20487,9 +20558,9 @@ function tryShowSubcommandHelp(cmd, args2) {
20487
20558
  var _subcommandHelpKeys = Object.keys(HELPS);
20488
20559
 
20489
20560
  // src/lib/updateNotifier.ts
20490
- var fs32 = __toESM(require("fs"));
20561
+ var fs33 = __toESM(require("fs"));
20491
20562
  var os26 = __toESM(require("os"));
20492
- var path41 = __toESM(require("path"));
20563
+ var path42 = __toESM(require("path"));
20493
20564
  var https7 = __toESM(require("https"));
20494
20565
  var import_picocolors16 = __toESM(require("picocolors"));
20495
20566
  var PKG_NAME = "codeam-cli";
@@ -20497,12 +20568,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
20497
20568
  var TTL_MS = 24 * 60 * 60 * 1e3;
20498
20569
  var REQUEST_TIMEOUT_MS = 1500;
20499
20570
  function cachePath() {
20500
- const dir = path41.join(os26.homedir(), ".codeam");
20501
- return path41.join(dir, "update-check.json");
20571
+ const dir = path42.join(os26.homedir(), ".codeam");
20572
+ return path42.join(dir, "update-check.json");
20502
20573
  }
20503
20574
  function readCache() {
20504
20575
  try {
20505
- const raw = fs32.readFileSync(cachePath(), "utf8");
20576
+ const raw = fs33.readFileSync(cachePath(), "utf8");
20506
20577
  const parsed = JSON.parse(raw);
20507
20578
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
20508
20579
  return parsed;
@@ -20513,10 +20584,10 @@ function readCache() {
20513
20584
  function writeCache(cache) {
20514
20585
  try {
20515
20586
  const file = cachePath();
20516
- fs32.mkdirSync(path41.dirname(file), { recursive: true });
20587
+ fs33.mkdirSync(path42.dirname(file), { recursive: true });
20517
20588
  const tmp = `${file}.${process.pid}.tmp`;
20518
- fs32.writeFileSync(tmp, JSON.stringify(cache));
20519
- fs32.renameSync(tmp, file);
20589
+ fs33.writeFileSync(tmp, JSON.stringify(cache));
20590
+ fs33.renameSync(tmp, file);
20520
20591
  } catch {
20521
20592
  }
20522
20593
  }
@@ -20587,7 +20658,7 @@ function checkForUpdates() {
20587
20658
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20588
20659
  if (process.env.CI) return;
20589
20660
  if (!process.stdout.isTTY) return;
20590
- const current = true ? "2.26.11" : null;
20661
+ const current = true ? "2.26.13" : null;
20591
20662
  if (!current) return;
20592
20663
  const cache = readCache();
20593
20664
  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.26.11",
3
+ "version": "2.26.13",
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",