codeam-cli 2.39.9 → 2.39.10

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 +6 -0
  2. package/dist/index.js +153 -121
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to `codeam-cli` are documented here.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.39.9] — 2026-06-13
8
+
9
+ ### Added
10
+
11
+ - **cli:** Auto-provision project deps (docker compose) gated before the agent
12
+
7
13
  ## [2.39.8] — 2026-06-13
8
14
 
9
15
  ### Fixed
package/dist/index.js CHANGED
@@ -498,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
498
498
  // package.json
499
499
  var package_default = {
500
500
  name: "codeam-cli",
501
- version: "2.39.9",
501
+ version: "2.39.10",
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",
@@ -1186,8 +1186,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
1186
1186
  return decodedFile;
1187
1187
  };
1188
1188
  }
1189
- function normalizeWindowsPath(path54) {
1190
- return path54.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1189
+ function normalizeWindowsPath(path55) {
1190
+ return path55.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1191
1191
  }
1192
1192
 
1193
1193
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -3667,9 +3667,9 @@ async function addSourceContext(frames) {
3667
3667
  LRU_FILE_CONTENTS_CACHE.reduce();
3668
3668
  return frames;
3669
3669
  }
3670
- function getContextLinesFromFile(path54, ranges, output) {
3670
+ function getContextLinesFromFile(path55, ranges, output) {
3671
3671
  return new Promise((resolve7) => {
3672
- const stream = (0, import_node_fs.createReadStream)(path54);
3672
+ const stream = (0, import_node_fs.createReadStream)(path55);
3673
3673
  const lineReaded = (0, import_node_readline.createInterface)({
3674
3674
  input: stream
3675
3675
  });
@@ -3684,7 +3684,7 @@ function getContextLinesFromFile(path54, ranges, output) {
3684
3684
  let rangeStart = range[0];
3685
3685
  let rangeEnd = range[1];
3686
3686
  function onStreamError() {
3687
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path54, 1);
3687
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path55, 1);
3688
3688
  lineReaded.close();
3689
3689
  lineReaded.removeAllListeners();
3690
3690
  destroyStreamAndResolve();
@@ -3745,8 +3745,8 @@ function clearLineContext(frame) {
3745
3745
  delete frame.context_line;
3746
3746
  delete frame.post_context;
3747
3747
  }
3748
- function shouldSkipContextLinesForFile(path54) {
3749
- return path54.startsWith("node:") || path54.endsWith(".min.js") || path54.endsWith(".min.cjs") || path54.endsWith(".min.mjs") || path54.startsWith("data:");
3748
+ function shouldSkipContextLinesForFile(path55) {
3749
+ return path55.startsWith("node:") || path55.endsWith(".min.js") || path55.endsWith(".min.cjs") || path55.endsWith(".min.mjs") || path55.startsWith("data:");
3750
3750
  }
3751
3751
  function shouldSkipContextLinesForFrame(frame) {
3752
3752
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -5900,7 +5900,7 @@ function readAnonId() {
5900
5900
  }
5901
5901
  function superProperties() {
5902
5902
  return {
5903
- cliVersion: true ? "2.39.9" : "0.0.0-dev",
5903
+ cliVersion: true ? "2.39.10" : "0.0.0-dev",
5904
5904
  nodeVersion: process.version,
5905
5905
  platform: process.platform,
5906
5906
  arch: process.arch,
@@ -7248,10 +7248,10 @@ function buildForPlatform(platform2) {
7248
7248
  var import_node_crypto4 = require("crypto");
7249
7249
 
7250
7250
  // src/agents/claude/resolver.ts
7251
- function buildClaudeLaunch(extraArgs = [], os32 = createOsStrategy()) {
7252
- const found = os32.findInPath("claude") ?? os32.findInPath("claude-code");
7251
+ function buildClaudeLaunch(extraArgs = [], os33 = createOsStrategy()) {
7252
+ const found = os33.findInPath("claude") ?? os33.findInPath("claude-code");
7253
7253
  if (!found) return null;
7254
- return os32.buildLaunch(found, extraArgs);
7254
+ return os33.buildLaunch(found, extraArgs);
7255
7255
  }
7256
7256
 
7257
7257
  // src/agents/claude/installer.ts
@@ -9978,13 +9978,13 @@ function detectStartupBanner(lines) {
9978
9978
  while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
9979
9979
  if (metaIdx - artStart < 2) return null;
9980
9980
  const pathLine = (lines[metaIdx + 1] ?? "").trim();
9981
- const path54 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9981
+ const path55 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9982
9982
  return {
9983
9983
  title: "",
9984
9984
  subtitle: lines[metaIdx].trim(),
9985
- path: path54,
9985
+ path: path55,
9986
9986
  startIdx: artStart,
9987
- endIdx: metaIdx + (path54 ? 1 : 0)
9987
+ endIdx: metaIdx + (path55 ? 1 : 0)
9988
9988
  };
9989
9989
  }
9990
9990
 
@@ -9994,8 +9994,8 @@ var ClaudeRuntimeStrategy = class {
9994
9994
  meta = getAgent("claude");
9995
9995
  mode = "interactive";
9996
9996
  os;
9997
- constructor(os32) {
9998
- this.os = os32;
9997
+ constructor(os33) {
9998
+ this.os = os33;
9999
9999
  }
10000
10000
  /**
10001
10001
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -11025,8 +11025,8 @@ function codexCredentialLocator() {
11025
11025
  function codexLoginLauncher() {
11026
11026
  return {
11027
11027
  async ensureInstalled() {
11028
- const os32 = createOsStrategy();
11029
- return os32.findInPath("codex") !== null;
11028
+ const os33 = createOsStrategy();
11029
+ return os33.findInPath("codex") !== null;
11030
11030
  },
11031
11031
  launch() {
11032
11032
  return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -11049,8 +11049,8 @@ var CodexRuntimeStrategy = class {
11049
11049
  meta = getAgent("codex");
11050
11050
  mode = "interactive";
11051
11051
  os;
11052
- constructor(os32) {
11053
- this.os = os32;
11052
+ constructor(os33) {
11053
+ this.os = os33;
11054
11054
  }
11055
11055
  async prepareLaunch() {
11056
11056
  let binary = this.os.findInPath("codex");
@@ -11156,12 +11156,12 @@ var CodexRuntimeStrategy = class {
11156
11156
  });
11157
11157
  }
11158
11158
  };
11159
- function resolveNpm(os32) {
11160
- return os32.id === "win32" ? "npm.cmd" : "npm";
11159
+ function resolveNpm(os33) {
11160
+ return os33.id === "win32" ? "npm.cmd" : "npm";
11161
11161
  }
11162
- async function installCodexViaNpm(os32) {
11162
+ async function installCodexViaNpm(os33) {
11163
11163
  return new Promise((resolve7, reject) => {
11164
- const proc = (0, import_node_child_process4.spawn)(resolveNpm(os32), ["install", "-g", "@openai/codex"], {
11164
+ const proc = (0, import_node_child_process4.spawn)(resolveNpm(os33), ["install", "-g", "@openai/codex"], {
11165
11165
  stdio: "inherit"
11166
11166
  });
11167
11167
  proc.on("close", (code) => {
@@ -11178,16 +11178,16 @@ async function installCodexViaNpm(os32) {
11178
11178
  });
11179
11179
  });
11180
11180
  }
11181
- function augmentNpmGlobalBin(os32) {
11181
+ function augmentNpmGlobalBin(os33) {
11182
11182
  try {
11183
- const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os32), ["prefix", "-g"], {
11183
+ const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os33), ["prefix", "-g"], {
11184
11184
  stdio: ["ignore", "pipe", "ignore"]
11185
11185
  });
11186
11186
  if (result.status !== 0) return;
11187
11187
  const prefix = result.stdout.toString().trim();
11188
11188
  if (!prefix) return;
11189
- const binDir = os32.id === "win32" ? prefix : path17.join(prefix, "bin");
11190
- os32.augmentPath([binDir]);
11189
+ const binDir = os33.id === "win32" ? prefix : path17.join(prefix, "bin");
11190
+ os33.augmentPath([binDir]);
11191
11191
  } catch {
11192
11192
  }
11193
11193
  }
@@ -11271,9 +11271,9 @@ var import_node_child_process7 = require("child_process");
11271
11271
  // src/agents/coderabbit/installer.ts
11272
11272
  var import_node_child_process5 = require("child_process");
11273
11273
  var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
11274
- async function ensureCoderabbitInstalled(os32) {
11275
- if (os32.findInPath("coderabbit")) return true;
11276
- if (os32.id === "win32") {
11274
+ async function ensureCoderabbitInstalled(os33) {
11275
+ if (os33.findInPath("coderabbit")) return true;
11276
+ if (os33.id === "win32") {
11277
11277
  console.error(
11278
11278
  "\n \u2717 CodeRabbit on Windows requires WSL.\n Install the CLI inside your WSL distribution\n (curl -fsSL https://cli.coderabbit.ai/install.sh | sh)\n then re-run `codeam link coderabbit` from WSL.\n"
11279
11279
  );
@@ -11288,8 +11288,8 @@ async function ensureCoderabbitInstalled(os32) {
11288
11288
  proc.on("error", () => resolve7(false));
11289
11289
  });
11290
11290
  if (!ok) return false;
11291
- os32.augmentPath([`${os32.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
11292
- return os32.findInPath("coderabbit") !== null;
11291
+ os33.augmentPath([`${os33.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
11292
+ return os33.findInPath("coderabbit") !== null;
11293
11293
  }
11294
11294
 
11295
11295
  // src/agents/coderabbit/link.ts
@@ -11316,10 +11316,10 @@ function coderabbitCredentialLocator() {
11316
11316
  extract: extractLocalCoderabbitToken
11317
11317
  };
11318
11318
  }
11319
- function coderabbitLoginLauncher(os32) {
11319
+ function coderabbitLoginLauncher(os33) {
11320
11320
  return {
11321
11321
  async ensureInstalled() {
11322
- return ensureCoderabbitInstalled(os32);
11322
+ return ensureCoderabbitInstalled(os33);
11323
11323
  },
11324
11324
  launch() {
11325
11325
  return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
@@ -11342,11 +11342,11 @@ function parseReview(stdout) {
11342
11342
  for (const line of lines) {
11343
11343
  const m = line.match(HUNK_LINE_RE);
11344
11344
  if (!m) continue;
11345
- const [, path54, lineNo, sevToken, message] = m;
11346
- if (!path54 || !lineNo || !message) continue;
11345
+ const [, path55, lineNo, sevToken, message] = m;
11346
+ if (!path55 || !lineNo || !message) continue;
11347
11347
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
11348
11348
  hunks.push({
11349
- path: path54.trim(),
11349
+ path: path55.trim(),
11350
11350
  line: Number(lineNo),
11351
11351
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
11352
11352
  message: cleanedMessage
@@ -11365,8 +11365,8 @@ var CoderabbitRuntimeStrategy = class {
11365
11365
  meta = getAgent("coderabbit");
11366
11366
  mode = "batch";
11367
11367
  os;
11368
- constructor(os32) {
11369
- this.os = os32;
11368
+ constructor(os33) {
11369
+ this.os = os33;
11370
11370
  }
11371
11371
  getDefaultArgs() {
11372
11372
  return ["review"];
@@ -11481,10 +11481,10 @@ function cursorCredentialLocator() {
11481
11481
  extract: extractLocalCursorToken
11482
11482
  };
11483
11483
  }
11484
- function cursorLoginLauncher(os32) {
11484
+ function cursorLoginLauncher(os33) {
11485
11485
  return {
11486
11486
  async ensureInstalled() {
11487
- if (os32.findInPath("cursor-agent")) return true;
11487
+ if (os33.findInPath("cursor-agent")) return true;
11488
11488
  console.error(
11489
11489
  "\n \u2717 cursor-agent binary not on PATH.\n Install Cursor (https://cursor.com/) and ensure the CLI\n plugin is enabled, then re-run `codeam link cursor`.\n"
11490
11490
  );
@@ -11546,8 +11546,8 @@ var CursorRuntimeStrategy = class {
11546
11546
  meta = getAgent("cursor");
11547
11547
  mode = "interactive";
11548
11548
  os;
11549
- constructor(os32) {
11550
- this.os = os32;
11549
+ constructor(os33) {
11550
+ this.os = os33;
11551
11551
  }
11552
11552
  async prepareLaunch() {
11553
11553
  const binary = this.os.findInPath("cursor-agent");
@@ -11667,10 +11667,10 @@ function aiderCredentialLocator() {
11667
11667
  extract: extractLocalAiderToken
11668
11668
  };
11669
11669
  }
11670
- function aiderLoginLauncher(os32) {
11670
+ function aiderLoginLauncher(os33) {
11671
11671
  return {
11672
11672
  async ensureInstalled() {
11673
- if (os32.findInPath("aider")) return true;
11673
+ if (os33.findInPath("aider")) return true;
11674
11674
  console.error(
11675
11675
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
11676
11676
  );
@@ -11680,7 +11680,7 @@ function aiderLoginLauncher(os32) {
11680
11680
  console.error(
11681
11681
  "\n Aider has no interactive login flow.\n Set ANTHROPIC_API_KEY or OPENAI_API_KEY in your shell,\n or re-run `codeam link aider --api-key=<your-key>`.\n"
11682
11682
  );
11683
- return (0, import_node_child_process9.spawn)(os32.id === "win32" ? "cmd.exe" : "sh", os32.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
11683
+ return (0, import_node_child_process9.spawn)(os33.id === "win32" ? "cmd.exe" : "sh", os33.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
11684
11684
  stdio: "ignore"
11685
11685
  });
11686
11686
  }
@@ -11752,8 +11752,8 @@ var AiderRuntimeStrategy = class {
11752
11752
  meta = getAgent("aider");
11753
11753
  mode = "interactive";
11754
11754
  os;
11755
- constructor(os32) {
11756
- this.os = os32;
11755
+ constructor(os33) {
11756
+ this.os = os33;
11757
11757
  }
11758
11758
  async prepareLaunch() {
11759
11759
  const binary = this.os.findInPath("aider");
@@ -11882,8 +11882,8 @@ function geminiCredentialLocator() {
11882
11882
  function geminiLoginLauncher() {
11883
11883
  return {
11884
11884
  async ensureInstalled() {
11885
- const os32 = createOsStrategy();
11886
- return os32.findInPath("gemini") !== null;
11885
+ const os33 = createOsStrategy();
11886
+ return os33.findInPath("gemini") !== null;
11887
11887
  },
11888
11888
  launch() {
11889
11889
  return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -11916,8 +11916,8 @@ var GeminiRuntimeStrategy = class {
11916
11916
  meta = getAgent("gemini");
11917
11917
  mode = "interactive";
11918
11918
  os;
11919
- constructor(os32) {
11920
- this.os = os32;
11919
+ constructor(os33) {
11920
+ this.os = os33;
11921
11921
  }
11922
11922
  async prepareLaunch() {
11923
11923
  const binary = this.os.findInPath("gemini");
@@ -12017,18 +12017,18 @@ var GeminiRuntimeStrategy = class {
12017
12017
 
12018
12018
  // src/agents/registry.ts
12019
12019
  var runtimeBuilders = {
12020
- claude: (os32) => new ClaudeRuntimeStrategy(os32),
12021
- codex: (os32) => new CodexRuntimeStrategy(os32),
12022
- coderabbit: (os32) => new CoderabbitRuntimeStrategy(os32),
12023
- cursor: (os32) => new CursorRuntimeStrategy(os32),
12024
- aider: (os32) => new AiderRuntimeStrategy(os32),
12025
- gemini: (os32) => new GeminiRuntimeStrategy(os32)
12020
+ claude: (os33) => new ClaudeRuntimeStrategy(os33),
12021
+ codex: (os33) => new CodexRuntimeStrategy(os33),
12022
+ coderabbit: (os33) => new CoderabbitRuntimeStrategy(os33),
12023
+ cursor: (os33) => new CursorRuntimeStrategy(os33),
12024
+ aider: (os33) => new AiderRuntimeStrategy(os33),
12025
+ gemini: (os33) => new GeminiRuntimeStrategy(os33)
12026
12026
  };
12027
12027
  var deployBuilders = {
12028
12028
  claude: () => new ClaudeDeployStrategy(),
12029
12029
  codex: () => new CodexDeployStrategy()
12030
12030
  };
12031
- function createAgentStrategy(agent, os32 = createOsStrategy()) {
12031
+ function createAgentStrategy(agent, os33 = createOsStrategy()) {
12032
12032
  if (!AGENT_REGISTRY[agent]?.enabled) {
12033
12033
  throw new Error(
12034
12034
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -12038,10 +12038,10 @@ function createAgentStrategy(agent, os32 = createOsStrategy()) {
12038
12038
  if (!build) {
12039
12039
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
12040
12040
  }
12041
- return build(os32);
12041
+ return build(os33);
12042
12042
  }
12043
- function createInteractiveAgentStrategy(agent, os32 = createOsStrategy()) {
12044
- const s = createAgentStrategy(agent, os32);
12043
+ function createInteractiveAgentStrategy(agent, os33 = createOsStrategy()) {
12044
+ const s = createAgentStrategy(agent, os33);
12045
12045
  if (s.mode !== "interactive") {
12046
12046
  throw new Error(
12047
12047
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -17970,11 +17970,11 @@ function resolveDoltInstallStrategy(platform2) {
17970
17970
  }
17971
17971
  var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
17972
17972
  function doltPlatformTuple(platform2, arch) {
17973
- const os32 = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "darwin" : "linux";
17973
+ const os33 = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "darwin" : "linux";
17974
17974
  const a = arch === "x64" ? "amd64" : arch === "arm64" ? "arm64" : null;
17975
17975
  if (!a) return null;
17976
- if (os32 === "windows" && a !== "amd64") return null;
17977
- return `${os32}-${a}`;
17976
+ if (os33 === "windows" && a !== "amd64") return null;
17977
+ return `${os33}-${a}`;
17978
17978
  }
17979
17979
  function resolveDoltTarballStrategy(targetDir, platform2, arch) {
17980
17980
  const tuple = doltPlatformTuple(platform2, arch);
@@ -19457,6 +19457,9 @@ var requestPreviewDetectH = (ctx) => {
19457
19457
  return;
19458
19458
  }
19459
19459
  log.info("preview", `detect: ${detection.framework} on :${detection.port} (took ${tookMs}ms)`);
19460
+ void writePreviewConfig(process.cwd(), detection).catch((err) => {
19461
+ log.info("preview", `detect: writePreviewConfig failed (non-fatal): ${String(err)}`);
19462
+ });
19460
19463
  void postPreviewEvent({
19461
19464
  sessionId: ctx.sessionId,
19462
19465
  pluginId: ctx.pluginId,
@@ -20085,10 +20088,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
20085
20088
  /[\\/]Start Menu([\\/]|$)/i,
20086
20089
  /[\\/]Templates([\\/]|$)/i
20087
20090
  ];
20088
- function isUnsafeWindowsWatchRoot(dir, homedir25) {
20091
+ function isUnsafeWindowsWatchRoot(dir, homedir26) {
20089
20092
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
20090
20093
  const cwd = norm(dir);
20091
- const home = norm(homedir25);
20094
+ const home = norm(homedir26);
20092
20095
  if (cwd === home) return true;
20093
20096
  if (/^[a-z]:$/.test(cwd)) return true;
20094
20097
  const sysRoots = [
@@ -20882,7 +20885,7 @@ function defaultRunGit(cwd, args2) {
20882
20885
  });
20883
20886
  }
20884
20887
  async function discoverRepos(workingDir, maxDepth = 4) {
20885
- const fs42 = await import("fs/promises");
20888
+ const fs43 = await import("fs/promises");
20886
20889
  const out2 = [];
20887
20890
  await walk(workingDir, 0);
20888
20891
  return out2;
@@ -20890,7 +20893,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20890
20893
  if (depth > maxDepth) return;
20891
20894
  let entries = [];
20892
20895
  try {
20893
- const dirents = await fs42.readdir(dir, { withFileTypes: true });
20896
+ const dirents = await fs43.readdir(dir, { withFileTypes: true });
20894
20897
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
20895
20898
  } catch {
20896
20899
  return;
@@ -23843,6 +23846,34 @@ function buildKeepAlive(ctx) {
23843
23846
  };
23844
23847
  }
23845
23848
 
23849
+ // src/agents/claude/onboarding.ts
23850
+ var fs39 = __toESM(require("fs"));
23851
+ var os30 = __toESM(require("os"));
23852
+ var path47 = __toESM(require("path"));
23853
+ function ensureClaudeOnboarded() {
23854
+ try {
23855
+ const file = path47.join(os30.homedir(), ".claude.json");
23856
+ let config = {};
23857
+ try {
23858
+ config = JSON.parse(fs39.readFileSync(file, "utf8"));
23859
+ } catch {
23860
+ }
23861
+ if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
23862
+ return;
23863
+ }
23864
+ config.hasCompletedOnboarding = true;
23865
+ config.theme = typeof config.theme === "string" ? config.theme : "dark";
23866
+ if (typeof config.lastOnboardingVersion !== "string") {
23867
+ config.lastOnboardingVersion = "2.1.177";
23868
+ }
23869
+ fs39.mkdirSync(path47.dirname(file), { recursive: true });
23870
+ fs39.writeFileSync(file, JSON.stringify(config, null, 2));
23871
+ log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
23872
+ } catch (err) {
23873
+ log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
23874
+ }
23875
+ }
23876
+
23846
23877
  // src/commands/start.ts
23847
23878
  async function start(requestedAgent) {
23848
23879
  showIntro();
@@ -23897,6 +23928,7 @@ async function start(requestedAgent) {
23897
23928
  "pluginAuth",
23898
23929
  `boot triple sessionId=${session.id} pluginId=${pluginId} tokenLen=${tokenForLog.length} tokenHead=${tokenForLog.slice(0, 12)} tokenTail=${tokenForLog.slice(-8)} mintedEqualsCached=${refreshed === session.pluginAuthToken}`
23899
23930
  );
23931
+ if (process.env.CODESPACES === "true") ensureClaudeOnboarded();
23900
23932
  let beads = null;
23901
23933
  const getBeads = () => beads;
23902
23934
  const beadsReady = provisionBeadsForStart({
@@ -24312,9 +24344,9 @@ async function autoLinkAfterPair(opts) {
24312
24344
  }
24313
24345
 
24314
24346
  // src/commands/pair-auto.ts
24315
- var fs39 = __toESM(require("fs"));
24316
- var os30 = __toESM(require("os"));
24317
- var path47 = __toESM(require("path"));
24347
+ var fs40 = __toESM(require("fs"));
24348
+ var os31 = __toESM(require("os"));
24349
+ var path48 = __toESM(require("path"));
24318
24350
  var import_crypto7 = require("crypto");
24319
24351
 
24320
24352
  // src/commands/start-infra-only.ts
@@ -24509,12 +24541,12 @@ function readTokenFromArgs(args2) {
24509
24541
  }
24510
24542
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
24511
24543
  if (fileFlag) {
24512
- const path54 = fileFlag.slice("--token-file=".length);
24544
+ const path55 = fileFlag.slice("--token-file=".length);
24513
24545
  try {
24514
- const content = fs39.readFileSync(path54, "utf8").trim();
24515
- if (content.length === 0) fail(`--token-file ${path54} is empty`);
24546
+ const content = fs40.readFileSync(path55, "utf8").trim();
24547
+ if (content.length === 0) fail(`--token-file ${path55} is empty`);
24516
24548
  try {
24517
- fs39.unlinkSync(path54);
24549
+ fs40.unlinkSync(path55);
24518
24550
  } catch {
24519
24551
  }
24520
24552
  return content;
@@ -24540,7 +24572,7 @@ async function claimOnce(token, pluginId) {
24540
24572
  pluginId,
24541
24573
  ideName: "codeam-cli (codespace)",
24542
24574
  ideVersion: process.env.npm_package_version ?? "unknown",
24543
- hostname: os30.hostname(),
24575
+ hostname: os31.hostname(),
24544
24576
  codespaceName: process.env.CODESPACE_NAME ?? "",
24545
24577
  // Current git branch of the codespace's working directory, so the
24546
24578
  // backend can populate `PairedSession.branch` for the codespace pair.
@@ -24597,7 +24629,7 @@ async function claim(token, pluginId) {
24597
24629
  }
24598
24630
  }
24599
24631
  function pairAutoLockPath() {
24600
- return path47.join(os30.homedir(), ".codeam", "pair-auto.lock");
24632
+ return path48.join(os31.homedir(), ".codeam", "pair-auto.lock");
24601
24633
  }
24602
24634
  function isLivePairAuto(pid) {
24603
24635
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
@@ -24607,7 +24639,7 @@ function isLivePairAuto(pid) {
24607
24639
  if (e.code !== "EPERM") return false;
24608
24640
  }
24609
24641
  try {
24610
- return fs39.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
24642
+ return fs40.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
24611
24643
  } catch {
24612
24644
  return true;
24613
24645
  }
@@ -24615,19 +24647,19 @@ function isLivePairAuto(pid) {
24615
24647
  function acquireSingletonLock() {
24616
24648
  const lockPath = pairAutoLockPath();
24617
24649
  try {
24618
- fs39.mkdirSync(path47.dirname(lockPath), { recursive: true });
24650
+ fs40.mkdirSync(path48.dirname(lockPath), { recursive: true });
24619
24651
  try {
24620
- fs39.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
24652
+ fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
24621
24653
  } catch (e) {
24622
24654
  if (e.code !== "EEXIST") throw e;
24623
- const holder = Number(fs39.readFileSync(lockPath, "utf8").trim());
24655
+ const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
24624
24656
  if (isLivePairAuto(holder)) return false;
24625
- fs39.writeFileSync(lockPath, String(process.pid));
24657
+ fs40.writeFileSync(lockPath, String(process.pid));
24626
24658
  }
24627
24659
  process.once("exit", () => {
24628
24660
  try {
24629
- if (fs39.existsSync(lockPath) && Number(fs39.readFileSync(lockPath, "utf8").trim()) === process.pid) {
24630
- fs39.unlinkSync(lockPath);
24661
+ if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
24662
+ fs40.unlinkSync(lockPath);
24631
24663
  }
24632
24664
  } catch {
24633
24665
  }
@@ -24826,7 +24858,7 @@ var import_picocolors10 = __toESM(require("picocolors"));
24826
24858
  var import_child_process22 = require("child_process");
24827
24859
  var import_util4 = require("util");
24828
24860
  var import_picocolors8 = __toESM(require("picocolors"));
24829
- var path48 = __toESM(require("path"));
24861
+ var path49 = __toESM(require("path"));
24830
24862
  var execFileP5 = (0, import_util4.promisify)(import_child_process22.execFile);
24831
24863
  var MAX_BUFFER = 8 * 1024 * 1024;
24832
24864
  function resetStdinForChild() {
@@ -25315,7 +25347,7 @@ var GitHubCodespacesProvider = class {
25315
25347
  });
25316
25348
  }
25317
25349
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
25318
- const remoteDir = path48.posix.dirname(remotePath);
25350
+ const remoteDir = path49.posix.dirname(remotePath);
25319
25351
  const parts = [
25320
25352
  `mkdir -p ${shellQuote(remoteDir)}`,
25321
25353
  `cat > ${shellQuote(remotePath)}`
@@ -25385,7 +25417,7 @@ function shellQuote(s) {
25385
25417
  // src/services/providers/gitpod.ts
25386
25418
  var import_child_process23 = require("child_process");
25387
25419
  var import_util5 = require("util");
25388
- var path49 = __toESM(require("path"));
25420
+ var path50 = __toESM(require("path"));
25389
25421
  var import_picocolors9 = __toESM(require("picocolors"));
25390
25422
  var execFileP6 = (0, import_util5.promisify)(import_child_process23.execFile);
25391
25423
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -25625,7 +25657,7 @@ var GitpodProvider = class {
25625
25657
  });
25626
25658
  }
25627
25659
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
25628
- const remoteDir = path49.posix.dirname(remotePath);
25660
+ const remoteDir = path50.posix.dirname(remotePath);
25629
25661
  const parts = [
25630
25662
  `mkdir -p ${shellQuote2(remoteDir)}`,
25631
25663
  `cat > ${shellQuote2(remotePath)}`
@@ -25661,7 +25693,7 @@ function shellQuote2(s) {
25661
25693
  // src/services/providers/gitlab-workspaces.ts
25662
25694
  var import_child_process24 = require("child_process");
25663
25695
  var import_util6 = require("util");
25664
- var path50 = __toESM(require("path"));
25696
+ var path51 = __toESM(require("path"));
25665
25697
  var execFileP7 = (0, import_util6.promisify)(import_child_process24.execFile);
25666
25698
  var MAX_BUFFER3 = 8 * 1024 * 1024;
25667
25699
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -25921,7 +25953,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
25921
25953
  }
25922
25954
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
25923
25955
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
25924
- const remoteDir = path50.posix.dirname(remotePath);
25956
+ const remoteDir = path51.posix.dirname(remotePath);
25925
25957
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
25926
25958
  if (options.mode != null) {
25927
25959
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -25989,7 +26021,7 @@ function shellQuote3(s) {
25989
26021
  // src/services/providers/railway.ts
25990
26022
  var import_child_process25 = require("child_process");
25991
26023
  var import_util7 = require("util");
25992
- var path51 = __toESM(require("path"));
26024
+ var path52 = __toESM(require("path"));
25993
26025
  var execFileP8 = (0, import_util7.promisify)(import_child_process25.execFile);
25994
26026
  var MAX_BUFFER4 = 8 * 1024 * 1024;
25995
26027
  function resetStdinForChild4() {
@@ -26225,7 +26257,7 @@ var RailwayProvider = class {
26225
26257
  if (!projectId || !serviceId) {
26226
26258
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
26227
26259
  }
26228
- const remoteDir = path51.posix.dirname(remotePath);
26260
+ const remoteDir = path52.posix.dirname(remotePath);
26229
26261
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
26230
26262
  if (options.mode != null) {
26231
26263
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -26768,8 +26800,8 @@ async function stopWorkspaceFromLocal(target) {
26768
26800
  var import_node_dns = require("dns");
26769
26801
  var import_node_util4 = require("util");
26770
26802
  var import_node_crypto8 = require("crypto");
26771
- var fs40 = __toESM(require("fs"));
26772
- var path52 = __toESM(require("path"));
26803
+ var fs41 = __toESM(require("fs"));
26804
+ var path53 = __toESM(require("path"));
26773
26805
  var import_picocolors12 = __toESM(require("picocolors"));
26774
26806
  var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
26775
26807
  async function checkDns(apiBase) {
@@ -26825,13 +26857,13 @@ async function checkHealth(apiBase) {
26825
26857
  }
26826
26858
  }
26827
26859
  function checkConfigDir() {
26828
- const dir = path52.join(require("os").homedir(), ".codeam");
26860
+ const dir = path53.join(require("os").homedir(), ".codeam");
26829
26861
  try {
26830
- fs40.mkdirSync(dir, { recursive: true, mode: 448 });
26831
- const probe = path52.join(dir, ".doctor-probe");
26832
- fs40.writeFileSync(probe, "ok", { mode: 384 });
26833
- const read = fs40.readFileSync(probe, "utf8");
26834
- fs40.unlinkSync(probe);
26862
+ fs41.mkdirSync(dir, { recursive: true, mode: 448 });
26863
+ const probe = path53.join(dir, ".doctor-probe");
26864
+ fs41.writeFileSync(probe, "ok", { mode: 384 });
26865
+ const read = fs41.readFileSync(probe, "utf8");
26866
+ fs41.unlinkSync(probe);
26835
26867
  if (read !== "ok") throw new Error("write/read round-trip mismatch");
26836
26868
  return {
26837
26869
  id: "config-dir",
@@ -26871,9 +26903,9 @@ function checkSessions() {
26871
26903
  }
26872
26904
  }
26873
26905
  function checkAgentBinaries() {
26874
- const os32 = createOsStrategy();
26906
+ const os33 = createOsStrategy();
26875
26907
  return getEnabledAgents().map((meta) => {
26876
- const found = os32.findInPath(meta.binaryName);
26908
+ const found = os33.findInPath(meta.binaryName);
26877
26909
  return {
26878
26910
  id: `agent-${meta.id}`,
26879
26911
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -26895,7 +26927,7 @@ function checkNodePty() {
26895
26927
  detail: "not required on this platform"
26896
26928
  };
26897
26929
  }
26898
- const vendoredPath = path52.join(__dirname, "vendor", "node-pty");
26930
+ const vendoredPath = path53.join(__dirname, "vendor", "node-pty");
26899
26931
  for (const target of [vendoredPath, "node-pty"]) {
26900
26932
  try {
26901
26933
  require(target);
@@ -26937,7 +26969,7 @@ function checkChokidar() {
26937
26969
  }
26938
26970
  async function doctor(args2 = []) {
26939
26971
  const json = args2.includes("--json");
26940
- const cliVersion = true ? "2.39.9" : "0.0.0-dev";
26972
+ const cliVersion = true ? "2.39.10" : "0.0.0-dev";
26941
26973
  const apiBase = resolveApiBaseUrl();
26942
26974
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
26943
26975
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -27136,7 +27168,7 @@ async function completion(args2) {
27136
27168
  // src/commands/version.ts
27137
27169
  var import_picocolors13 = __toESM(require("picocolors"));
27138
27170
  function version2() {
27139
- const v = true ? "2.39.9" : "unknown";
27171
+ const v = true ? "2.39.10" : "unknown";
27140
27172
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
27141
27173
  }
27142
27174
 
@@ -27264,9 +27296,9 @@ function tryShowSubcommandHelp(cmd, args2) {
27264
27296
  var _subcommandHelpKeys = Object.keys(HELPS);
27265
27297
 
27266
27298
  // src/lib/updateNotifier.ts
27267
- var fs41 = __toESM(require("fs"));
27268
- var os31 = __toESM(require("os"));
27269
- var path53 = __toESM(require("path"));
27299
+ var fs42 = __toESM(require("fs"));
27300
+ var os32 = __toESM(require("os"));
27301
+ var path54 = __toESM(require("path"));
27270
27302
  var https8 = __toESM(require("https"));
27271
27303
  var import_node_child_process12 = require("child_process");
27272
27304
  var import_picocolors16 = __toESM(require("picocolors"));
@@ -27275,12 +27307,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
27275
27307
  var TTL_MS = 24 * 60 * 60 * 1e3;
27276
27308
  var REQUEST_TIMEOUT_MS = 1500;
27277
27309
  function cachePath() {
27278
- const dir = path53.join(os31.homedir(), ".codeam");
27279
- return path53.join(dir, "update-check.json");
27310
+ const dir = path54.join(os32.homedir(), ".codeam");
27311
+ return path54.join(dir, "update-check.json");
27280
27312
  }
27281
27313
  function readCache() {
27282
27314
  try {
27283
- const raw = fs41.readFileSync(cachePath(), "utf8");
27315
+ const raw = fs42.readFileSync(cachePath(), "utf8");
27284
27316
  const parsed = JSON.parse(raw);
27285
27317
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
27286
27318
  return parsed;
@@ -27291,10 +27323,10 @@ function readCache() {
27291
27323
  function writeCache(cache) {
27292
27324
  try {
27293
27325
  const file = cachePath();
27294
- fs41.mkdirSync(path53.dirname(file), { recursive: true });
27326
+ fs42.mkdirSync(path54.dirname(file), { recursive: true });
27295
27327
  const tmp = `${file}.${process.pid}.tmp`;
27296
- fs41.writeFileSync(tmp, JSON.stringify(cache));
27297
- fs41.renameSync(tmp, file);
27328
+ fs42.writeFileSync(tmp, JSON.stringify(cache));
27329
+ fs42.renameSync(tmp, file);
27298
27330
  } catch {
27299
27331
  }
27300
27332
  }
@@ -27368,8 +27400,8 @@ function isLinkedInstall() {
27368
27400
  timeout: 2e3
27369
27401
  }).trim();
27370
27402
  if (!root) return false;
27371
- const pkgPath = path53.join(root, PKG_NAME);
27372
- return fs41.lstatSync(pkgPath).isSymbolicLink();
27403
+ const pkgPath = path54.join(root, PKG_NAME);
27404
+ return fs42.lstatSync(pkgPath).isSymbolicLink();
27373
27405
  } catch {
27374
27406
  return false;
27375
27407
  }
@@ -27405,7 +27437,7 @@ function maybeAutoUpdate(currentVersion, latest) {
27405
27437
  return;
27406
27438
  }
27407
27439
  try {
27408
- fs41.unlinkSync(cachePath());
27440
+ fs42.unlinkSync(cachePath());
27409
27441
  } catch {
27410
27442
  }
27411
27443
  process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
@@ -27422,7 +27454,7 @@ function checkForUpdates() {
27422
27454
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
27423
27455
  if (process.env.CI) return;
27424
27456
  if (!process.stdout.isTTY) return;
27425
- const current = true ? "2.39.9" : null;
27457
+ const current = true ? "2.39.10" : null;
27426
27458
  if (!current) return;
27427
27459
  const cache = readCache();
27428
27460
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.39.9",
3
+ "version": "2.39.10",
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",