codeam-cli 2.39.83 → 2.39.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,17 @@ 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.83] — 2026-06-22
8
+
9
+ ### Added
10
+
11
+ - **cli:** Install + authenticate gh on bare self-hosted boxes
12
+ - **cli:** Synchronous auto-upgrade for link/pair on stale CLIs
13
+
14
+ ### Fixed
15
+
16
+ - **cli:** Persist git credentials + commit identity for self-hosted workspaces
17
+
7
18
  ## [2.39.82] — 2026-06-22
8
19
 
9
20
  ### Fixed
package/dist/index.js CHANGED
@@ -5390,7 +5390,7 @@ function readAnonId() {
5390
5390
  }
5391
5391
  function superProperties() {
5392
5392
  return {
5393
- cliVersion: true ? "2.39.83" : "0.0.0-dev",
5393
+ cliVersion: true ? "2.39.84" : "0.0.0-dev",
5394
5394
  nodeVersion: process.version,
5395
5395
  platform: process.platform,
5396
5396
  arch: process.arch,
@@ -5549,7 +5549,7 @@ var os4 = __toESM(require("os"));
5549
5549
  // package.json
5550
5550
  var package_default = {
5551
5551
  name: "codeam-cli",
5552
- version: "2.39.83",
5552
+ version: "2.39.84",
5553
5553
  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.",
5554
5554
  type: "commonjs",
5555
5555
  main: "dist/index.js",
@@ -11078,12 +11078,12 @@ function isAvailable() {
11078
11078
  }
11079
11079
  function augmentPath() {
11080
11080
  const dirs = probeInstallDirs();
11081
- const sep5 = path14.delimiter;
11081
+ const sep6 = path14.delimiter;
11082
11082
  const current = process.env.PATH ?? "";
11083
- const existing = new Set(current.split(sep5).filter(Boolean));
11083
+ const existing = new Set(current.split(sep6).filter(Boolean));
11084
11084
  const additions = dirs.filter((d3) => !existing.has(d3));
11085
11085
  if (additions.length === 0) return;
11086
- process.env.PATH = additions.join(sep5) + sep5 + current;
11086
+ process.env.PATH = additions.join(sep6) + sep6 + current;
11087
11087
  }
11088
11088
  function runInstaller() {
11089
11089
  const isWindows = process.platform === "win32";
@@ -11200,13 +11200,34 @@ function readClaudeAgentState() {
11200
11200
  }
11201
11201
 
11202
11202
  // src/agents/claude/link.ts
11203
+ function validateClaudeToken(token) {
11204
+ if (token.method !== "oauth") return { status: "unknown" };
11205
+ let oauth;
11206
+ try {
11207
+ const parsed = JSON.parse(token.credential);
11208
+ const inner = parsed.claudeAiOauth;
11209
+ oauth = inner && typeof inner === "object" ? inner : parsed;
11210
+ } catch {
11211
+ return { status: "unknown" };
11212
+ }
11213
+ const expiresAt = typeof oauth.expiresAt === "number" ? oauth.expiresAt : null;
11214
+ if (expiresAt === null) return { status: "unknown" };
11215
+ if (expiresAt >= Date.now()) return { status: "valid" };
11216
+ const hasRefresh = typeof oauth.refreshToken === "string" && oauth.refreshToken.length > 0;
11217
+ if (hasRefresh) return { status: "unknown" };
11218
+ return {
11219
+ status: "expired",
11220
+ reason: "Your local Claude session has expired with no refresh token."
11221
+ };
11222
+ }
11203
11223
  function claudeCredentialLocator() {
11204
11224
  return {
11205
11225
  publicId: "claude_code",
11206
11226
  vendor: "Anthropic",
11207
11227
  hint: "~/.claude/.credentials.json or the macOS Keychain",
11208
11228
  watchPaths: claudeCredentialsPaths,
11209
- extract: extractLocalClaudeToken
11229
+ extract: extractLocalClaudeToken,
11230
+ validate: validateClaudeToken
11210
11231
  };
11211
11232
  }
11212
11233
  function claudeLoginLauncher() {
@@ -12470,6 +12491,13 @@ var import_node_child_process6 = require("child_process");
12470
12491
  var fs19 = __toESM(require("fs"));
12471
12492
  var os18 = __toESM(require("os"));
12472
12493
  var path24 = __toESM(require("path"));
12494
+
12495
+ // src/agents/strategy.ts
12496
+ function validateNonEmptyCredential(token) {
12497
+ return { status: token.credential.trim().length > 0 ? "valid" : "unknown" };
12498
+ }
12499
+
12500
+ // src/agents/coderabbit/link.ts
12473
12501
  function authPath() {
12474
12502
  return path24.join(os18.homedir(), ".coderabbit", "auth.json");
12475
12503
  }
@@ -12486,7 +12514,8 @@ function coderabbitCredentialLocator() {
12486
12514
  vendor: "CodeRabbit",
12487
12515
  hint: "~/.coderabbit/auth.json",
12488
12516
  watchPaths: () => [authPath()],
12489
- extract: extractLocalCoderabbitToken
12517
+ extract: extractLocalCoderabbitToken,
12518
+ validate: validateNonEmptyCredential
12490
12519
  };
12491
12520
  }
12492
12521
  function coderabbitLoginLauncher(os40) {
@@ -12651,7 +12680,8 @@ function cursorCredentialLocator() {
12651
12680
  vendor: "Cursor",
12652
12681
  hint: "~/.cursor/auth.json",
12653
12682
  watchPaths: cursorCredentialsPaths,
12654
- extract: extractLocalCursorToken
12683
+ extract: extractLocalCursorToken,
12684
+ validate: validateNonEmptyCredential
12655
12685
  };
12656
12686
  }
12657
12687
  function cursorLoginLauncher(os40) {
@@ -12837,7 +12867,8 @@ function aiderCredentialLocator() {
12837
12867
  vendor: "Aider",
12838
12868
  hint: "ANTHROPIC_API_KEY / OPENAI_API_KEY env var or ~/.aider.conf.yml",
12839
12869
  watchPaths: aiderCredentialsPaths,
12840
- extract: extractLocalAiderToken
12870
+ extract: extractLocalAiderToken,
12871
+ validate: validateNonEmptyCredential
12841
12872
  };
12842
12873
  }
12843
12874
  function aiderLoginLauncher(os40) {
@@ -17140,6 +17171,7 @@ async function configureGitCredentials(dest, repoRef, cloneToken) {
17140
17171
  }
17141
17172
  const env = nonInteractiveGitEnv();
17142
17173
  const git2 = (args2) => execFileP5("git", ["-C", dest, ...args2], { timeout: 3e4, env });
17174
+ const credFilePosix = credFile.split(path42.sep).join("/");
17143
17175
  await git2(["config", "--local", "--replace-all", "credential.helper", ""]).catch(() => {
17144
17176
  });
17145
17177
  await git2([
@@ -17147,7 +17179,7 @@ async function configureGitCredentials(dest, repoRef, cloneToken) {
17147
17179
  "--local",
17148
17180
  "--add",
17149
17181
  "credential.helper",
17150
- `store --file=${credFile}`
17182
+ `store --file=${credFilePosix}`
17151
17183
  ]).catch(() => {
17152
17184
  });
17153
17185
  await git2(["remote", "set-url", "origin", repoCloneUrl(repoRef)]).catch(() => {
@@ -17319,16 +17351,17 @@ async function ensureGhCli(runner, token, deps = {}) {
17319
17351
  if (runner.which("gh")) return "gh";
17320
17352
  const arch2 = ghArch();
17321
17353
  const platform3 = process.platform;
17322
- if (arch2 === null || platform3 !== "linux" && platform3 !== "darwin") {
17354
+ if (arch2 === null || platform3 !== "linux" && platform3 !== "darwin" && platform3 !== "win32") {
17323
17355
  log.warn("host-agent", `gh auto-install unsupported on ${platform3}/${process.arch} \u2014 skipping`);
17324
17356
  return null;
17325
17357
  }
17358
+ const osToken = platform3 === "darwin" ? "macOS" : platform3 === "win32" ? "windows" : "linux";
17359
+ const ext = platform3 === "linux" ? "tar.gz" : "zip";
17360
+ const binaryName = platform3 === "win32" ? "gh.exe" : "gh";
17326
17361
  const downloadFn = deps.downloadFn ?? download;
17327
17362
  const resolveVersionFn = deps.resolveVersionFn ?? resolveLatestGhVersion;
17328
17363
  try {
17329
17364
  const version3 = await resolveVersionFn(token);
17330
- const osToken = platform3 === "darwin" ? "macOS" : "linux";
17331
- const ext = platform3 === "darwin" ? "zip" : "tar.gz";
17332
17365
  const asset = `gh_${version3}_${osToken}_${arch2}`;
17333
17366
  const url = `https://github.com/cli/cli/releases/download/v${version3}/${asset}.${ext}`;
17334
17367
  const tmpRoot = fs38.mkdtempSync(path44.join(os31.tmpdir(), "codeam-gh-"));
@@ -17337,26 +17370,19 @@ async function ensureGhCli(runner, token, deps = {}) {
17337
17370
  log.warn("host-agent", "gh download failed \u2014 skipping (git pull/push still work via the credential helper)");
17338
17371
  return null;
17339
17372
  }
17340
- let extractCode = null;
17341
- if (platform3 === "darwin") {
17342
- const r = await runner.run("unzip", ["-o", archive, "-d", tmpRoot], { timeoutMs: 6e4 });
17343
- extractCode = r.code;
17344
- } else {
17345
- const r = await runner.run("tar", ["-xzf", archive, "-C", tmpRoot], { timeoutMs: 6e4 });
17346
- extractCode = r.code;
17347
- }
17348
- if (extractCode !== 0) {
17349
- log.warn("host-agent", `gh archive extraction failed (code=${String(extractCode)}) \u2014 skipping`);
17373
+ const extract = await runner.run("tar", ["-xf", archive, "-C", tmpRoot], { timeoutMs: 6e4 });
17374
+ if (extract.code !== 0) {
17375
+ log.warn("host-agent", `gh archive extraction failed (code=${String(extract.code)}) \u2014 skipping`);
17350
17376
  return null;
17351
17377
  }
17352
- const extractedBin = path44.join(tmpRoot, asset, "bin", "gh");
17378
+ const extractedBin = path44.join(tmpRoot, asset, "bin", binaryName);
17353
17379
  if (!fs38.existsSync(extractedBin)) {
17354
17380
  log.warn("host-agent", "gh binary not found in the extracted archive \u2014 skipping");
17355
17381
  return null;
17356
17382
  }
17357
17383
  const binDir = codeamBinDir();
17358
17384
  fs38.mkdirSync(binDir, { recursive: true });
17359
- const target = path44.join(binDir, "gh");
17385
+ const target = path44.join(binDir, binaryName);
17360
17386
  fs38.copyFileSync(extractedBin, target);
17361
17387
  fs38.chmodSync(target, 493);
17362
17388
  log.info("host-agent", `gh installed to ${target} (v${version3})`);
@@ -17391,7 +17417,8 @@ async function ensureGhAuth(runner, ghCmd, token) {
17391
17417
  var defaultGitToolingRunner = {
17392
17418
  which(cmd) {
17393
17419
  try {
17394
- (0, import_node_child_process12.execFileSync)("which", [cmd], { stdio: "ignore" });
17420
+ const probe = process.platform === "win32" ? "where" : "which";
17421
+ (0, import_node_child_process12.execFileSync)(probe, [cmd], { stdio: "ignore" });
17395
17422
  return true;
17396
17423
  } catch {
17397
17424
  return false;
@@ -17677,7 +17704,7 @@ async function autoUpgradeBeforeCriticalCommand() {
17677
17704
  if (process.env.NODE_ENV === "test") return;
17678
17705
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17679
17706
  if (process.env.CI) return;
17680
- const current = true ? "2.39.83" : null;
17707
+ const current = true ? "2.39.84" : null;
17681
17708
  if (!current) return;
17682
17709
  const cache = readCache();
17683
17710
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17694,7 +17721,7 @@ function checkForUpdates() {
17694
17721
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17695
17722
  if (process.env.CI) return;
17696
17723
  if (!process.stdout.isTTY) return;
17697
- const current = true ? "2.39.83" : null;
17724
+ const current = true ? "2.39.84" : null;
17698
17725
  if (!current) return;
17699
17726
  const cache = readCache();
17700
17727
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -18132,7 +18159,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process14.s
18132
18159
  detached: false
18133
18160
  });
18134
18161
  function currentCliVersion() {
18135
- return true ? "2.39.83" : null;
18162
+ return true ? "2.39.84" : null;
18136
18163
  }
18137
18164
  function runCmd(cmd, args2, timeoutMs) {
18138
18165
  return new Promise((resolve7) => {
@@ -18548,7 +18575,7 @@ var HostAgentSupervisor = class {
18548
18575
  report("preparing", "configuring git tooling");
18549
18576
  const ghCmd = await ensureGhCli(defaultGitToolingRunner, payload.cloneToken);
18550
18577
  if (ghCmd) {
18551
- childEnv.PATH = `${codeamBinDir()}:${childEnv.PATH}`;
18578
+ childEnv.PATH = `${codeamBinDir()}${path46.delimiter}${childEnv.PATH}`;
18552
18579
  await ensureGhAuth(defaultGitToolingRunner, ghCmd, payload.cloneToken);
18553
18580
  }
18554
18581
  } catch (e) {
@@ -28937,7 +28964,7 @@ function checkChokidar() {
28937
28964
  }
28938
28965
  async function doctor(args2 = []) {
28939
28966
  const json = args2.includes("--json");
28940
- const cliVersion = true ? "2.39.83" : "0.0.0-dev";
28967
+ const cliVersion = true ? "2.39.84" : "0.0.0-dev";
28941
28968
  const apiBase2 = resolveApiBaseUrl();
28942
28969
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
28943
28970
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -29136,7 +29163,7 @@ async function completion(args2) {
29136
29163
  // src/commands/version.ts
29137
29164
  var import_picocolors14 = __toESM(require("picocolors"));
29138
29165
  function version2() {
29139
- const v = true ? "2.39.83" : "unknown";
29166
+ const v = true ? "2.39.84" : "unknown";
29140
29167
  console.log(`${import_picocolors14.default.bold("codeam-cli")} ${import_picocolors14.default.cyan(v)}`);
29141
29168
  }
29142
29169
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.39.83",
3
+ "version": "2.39.84",
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",