codeam-cli 2.22.0 → 2.23.0

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 +240 -60
  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.22.1] — 2026-05-25
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Payload.agentId — accept any string, not just the public enum (#187)
12
+
13
+ ## [2.22.0] — 2026-05-25
14
+
15
+ ### Added
16
+
17
+ - **cli:** Handle request_link_credentials from backend auto-link (#186)
18
+
7
19
  ## [2.21.2] — 2026-05-25
8
20
 
9
21
  ### Fixed
package/dist/index.js CHANGED
@@ -441,7 +441,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
441
441
  // package.json
442
442
  var package_default = {
443
443
  name: "codeam-cli",
444
- version: "2.22.0",
444
+ version: "2.23.0",
445
445
  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.",
446
446
  type: "commonjs",
447
447
  main: "dist/index.js",
@@ -734,6 +734,34 @@ async function postLinkCredential(input) {
734
734
  };
735
735
  }
736
736
  }
737
+ async function postAiResult(input) {
738
+ const body = {
739
+ sessionId: input.sessionId,
740
+ pluginId: input.pluginId,
741
+ kind: input.kind,
742
+ summary: input.summary
743
+ };
744
+ if (input.turnId) body.turnId = input.turnId;
745
+ if (input.stats) body.stats = input.stats;
746
+ if (input.fileChangeId) body.fileChangeId = input.fileChangeId;
747
+ if (input.reasoning) body.reasoning = input.reasoning;
748
+ if (input.securityNote) body.securityNote = input.securityNote;
749
+ try {
750
+ await _transport.postJsonAuthed(
751
+ `${API_BASE}/api/plugin/ai-result`,
752
+ body,
753
+ input.pluginAuthToken
754
+ );
755
+ return { ok: true };
756
+ } catch (err) {
757
+ const e = err;
758
+ return {
759
+ ok: false,
760
+ status: typeof e.statusCode === "number" ? e.statusCode : 0,
761
+ message: e.message || "unknown"
762
+ };
763
+ }
764
+ }
737
765
  async function _postJsonAuthed(url, body, pluginAuthToken) {
738
766
  return new Promise((resolve5, reject) => {
739
767
  const data = JSON.stringify(body);
@@ -5740,7 +5768,7 @@ function readAnonId() {
5740
5768
  }
5741
5769
  function superProperties() {
5742
5770
  return {
5743
- cliVersion: true ? "2.22.0" : "0.0.0-dev",
5771
+ cliVersion: true ? "2.23.0" : "0.0.0-dev",
5744
5772
  nodeVersion: process.version,
5745
5773
  platform: process.platform,
5746
5774
  arch: process.arch,
@@ -9099,6 +9127,59 @@ async function fetchClaudeQuota() {
9099
9127
  });
9100
9128
  }
9101
9129
 
9130
+ // src/services/spawn-and-capture.ts
9131
+ var import_child_process6 = require("child_process");
9132
+ async function spawnAndCapture(cmd, args2, opts = {}) {
9133
+ const timeoutMs = opts.timeoutMs ?? 6e4;
9134
+ return new Promise((resolve5) => {
9135
+ let settled = false;
9136
+ const settle = (value) => {
9137
+ if (settled) return;
9138
+ settled = true;
9139
+ resolve5(value);
9140
+ };
9141
+ let child;
9142
+ try {
9143
+ child = (0, import_child_process6.spawn)(cmd, [...args2], {
9144
+ cwd: opts.cwd,
9145
+ env: opts.env ?? process.env,
9146
+ stdio: ["ignore", "pipe", "pipe"]
9147
+ });
9148
+ } catch {
9149
+ settle(null);
9150
+ return;
9151
+ }
9152
+ let stdout = "";
9153
+ child.stdout?.on("data", (chunk) => {
9154
+ stdout += chunk.toString("utf8");
9155
+ });
9156
+ child.stderr?.on("data", (chunk) => {
9157
+ opts.onStderr?.(chunk.toString("utf8"));
9158
+ });
9159
+ const timer = setTimeout(() => {
9160
+ try {
9161
+ child.kill("SIGKILL");
9162
+ } catch {
9163
+ }
9164
+ settle(null);
9165
+ }, timeoutMs);
9166
+ timer.unref();
9167
+ child.on("error", () => {
9168
+ clearTimeout(timer);
9169
+ settle(null);
9170
+ });
9171
+ child.on("exit", (code) => {
9172
+ clearTimeout(timer);
9173
+ if (code !== 0) {
9174
+ settle(null);
9175
+ return;
9176
+ }
9177
+ const trimmed = stdout.trim();
9178
+ settle(trimmed.length > 0 ? trimmed : null);
9179
+ });
9180
+ });
9181
+ }
9182
+
9102
9183
  // src/agents/claude/history.ts
9103
9184
  var fs9 = __toESM(require("fs"));
9104
9185
  var path12 = __toESM(require("path"));
@@ -9541,6 +9622,14 @@ var ClaudeRuntimeStrategy = class {
9541
9622
  loginLauncher() {
9542
9623
  return claudeLoginLauncher();
9543
9624
  }
9625
+ async generateOneShot(prompt, opts) {
9626
+ const launch = buildClaudeLaunch(["-p", prompt], this.os);
9627
+ if (!launch) return null;
9628
+ return spawnAndCapture(launch.cmd, launch.args, {
9629
+ cwd: opts?.cwd,
9630
+ timeoutMs: opts?.timeoutMs
9631
+ });
9632
+ }
9544
9633
  };
9545
9634
 
9546
9635
  // src/agents/claude/deploy.ts
@@ -9549,12 +9638,12 @@ var os13 = __toESM(require("os"));
9549
9638
  var path14 = __toESM(require("path"));
9550
9639
 
9551
9640
  // src/agents/claude/credentials.ts
9552
- var import_child_process6 = require("child_process");
9641
+ var import_child_process7 = require("child_process");
9553
9642
  var fs10 = __toESM(require("fs"));
9554
9643
  var os12 = __toESM(require("os"));
9555
9644
  var path13 = __toESM(require("path"));
9556
9645
  var import_util = require("util");
9557
- var execFileP2 = (0, import_util.promisify)(import_child_process6.execFile);
9646
+ var execFileP2 = (0, import_util.promisify)(import_child_process7.execFile);
9558
9647
  async function detectLocalClaudeCredentials() {
9559
9648
  const localClaudeDir = path13.join(os12.homedir(), ".claude");
9560
9649
  const flat = path13.join(localClaudeDir, ".credentials.json");
@@ -10424,6 +10513,15 @@ var CodexRuntimeStrategy = class {
10424
10513
  loginLauncher() {
10425
10514
  return codexLoginLauncher();
10426
10515
  }
10516
+ async generateOneShot(prompt, opts) {
10517
+ const binary = this.os.findInPath("codex");
10518
+ if (!binary) return null;
10519
+ const launch = this.os.buildLaunch(binary, ["exec", prompt]);
10520
+ return spawnAndCapture(launch.cmd, launch.args, {
10521
+ cwd: opts?.cwd,
10522
+ timeoutMs: opts?.timeoutMs
10523
+ });
10524
+ }
10427
10525
  };
10428
10526
  function resolveNpm(os26) {
10429
10527
  return os26.id === "win32" ? "npm.cmd" : "npm";
@@ -12206,7 +12304,7 @@ var HistoryService = class _HistoryService {
12206
12304
  };
12207
12305
 
12208
12306
  // src/services/file-watcher.service.ts
12209
- var import_child_process7 = require("child_process");
12307
+ var import_child_process8 = require("child_process");
12210
12308
  var fs21 = __toESM(require("fs"));
12211
12309
  var os22 = __toESM(require("os"));
12212
12310
  var path25 = __toESM(require("path"));
@@ -12744,7 +12842,7 @@ async function _runGitImpl(cwd, args2, opts = {}) {
12744
12842
  return new Promise((resolve5) => {
12745
12843
  let proc;
12746
12844
  try {
12747
- proc = (0, import_child_process7.spawn)("git", args2, { cwd, env: process.env });
12845
+ proc = (0, import_child_process8.spawn)("git", args2, { cwd, env: process.env });
12748
12846
  } catch {
12749
12847
  resolve5(null);
12750
12848
  return;
@@ -12776,7 +12874,7 @@ function _runGit(cwd, args2, opts = {}) {
12776
12874
  var import_crypto2 = require("crypto");
12777
12875
 
12778
12876
  // src/services/turn-files/git-changeset.ts
12779
- var import_child_process8 = require("child_process");
12877
+ var import_child_process9 = require("child_process");
12780
12878
  var path26 = __toESM(require("path"));
12781
12879
  async function collectRepoChangeset(opts) {
12782
12880
  const status2 = await runGit2(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
@@ -12859,7 +12957,7 @@ function defaultRunGit(cwd, args2) {
12859
12957
  return new Promise((resolve5) => {
12860
12958
  let proc;
12861
12959
  try {
12862
- proc = (0, import_child_process8.spawn)("git", args2, { cwd, env: process.env });
12960
+ proc = (0, import_child_process9.spawn)("git", args2, { cwd, env: process.env });
12863
12961
  } catch {
12864
12962
  resolve5(null);
12865
12963
  return;
@@ -13199,6 +13297,7 @@ var TurnFileAggregator = class {
13199
13297
  sessionId: entry.sessionId,
13200
13298
  pluginId: entry.pluginId,
13201
13299
  turnId: entry.turnId,
13300
+ agentId: this.opts.agentId,
13202
13301
  files: entry.files
13203
13302
  });
13204
13303
  try {
@@ -13711,13 +13810,13 @@ function fetchQuotaUsage(runtime, historySvc) {
13711
13810
  }
13712
13811
 
13713
13812
  // src/commands/start/keep-alive.ts
13714
- var import_child_process9 = require("child_process");
13813
+ var import_child_process10 = require("child_process");
13715
13814
  function buildKeepAlive(ctx) {
13716
13815
  let timer = null;
13717
13816
  async function setIdleTimeout(minutes) {
13718
13817
  if (!ctx.inCodespace || !ctx.codespaceName) return;
13719
13818
  await new Promise((resolve5) => {
13720
- const proc = (0, import_child_process9.spawn)(
13819
+ const proc = (0, import_child_process10.spawn)(
13721
13820
  "gh",
13722
13821
  [
13723
13822
  "api",
@@ -13758,7 +13857,7 @@ var fs27 = __toESM(require("fs"));
13758
13857
  var os23 = __toESM(require("os"));
13759
13858
  var path33 = __toESM(require("path"));
13760
13859
  var import_crypto5 = require("crypto");
13761
- var import_child_process13 = require("child_process");
13860
+ var import_child_process14 = require("child_process");
13762
13861
 
13763
13862
  // src/lib/payload.ts
13764
13863
  var import_zod2 = require("zod");
@@ -13817,11 +13916,33 @@ var startCommandSchema = import_zod2.z.object({
13817
13916
  action: import_zod2.z.enum(["approved", "rejected"]).optional(),
13818
13917
  // `request_link_credentials` — backend fires this from the
13819
13918
  // heartbeat handler when it notices the user is running an agent
13820
- // they haven't vaulted yet. We reuse the `codeam link` token-
13821
- // capture path to push the credential up; if extraction fails
13822
- // (no local auth, missing file), the handler no-ops silently
13823
- // no browser-login surprises during a normal `codeam pair`.
13824
- agentId: import_zod2.z.enum(["claude_code", "codex", "cursor", "aider", "coderabbit"]).optional()
13919
+ // they haven't vaulted yet. Also reused by `get_context` /
13920
+ // `list_models` payloads which carry the currently-selected
13921
+ // agent for that session. We accept any string here (rather than
13922
+ // a narrow enum) because the web sends internal ids ('claude')
13923
+ // while the auto-link backend sends public ids ('claude_code'),
13924
+ // and the consuming handlers normalize themselves.
13925
+ agentId: import_zod2.z.string().max(64).optional(),
13926
+ // `request_ai_summary` / `request_ai_insight` — backend fires
13927
+ // these on turn-end (+ file selection) when LinkedAgent.
13928
+ // aiInsightsEnabled is true. The CLI spawns the agent in
13929
+ // headless one-shot mode (`claude -p "..."` / `codex exec`) and
13930
+ // POSTs the response back to /api/plugin/ai-result.
13931
+ //
13932
+ // `prompt` (declared above for start_task) carries the LLM prompt
13933
+ // the backend pre-rendered with the diff context inlined; the
13934
+ // agent receives it verbatim. `turnId` keys the summary,
13935
+ // `fileChangeId` keys the per-file insight, `stats` is echoed
13936
+ // unchanged on the result POST so the backend doesn't have to
13937
+ // recompute (numbers came from file_changes; the agent only
13938
+ // writes the narrative).
13939
+ turnId: import_zod2.z.string().max(128).optional(),
13940
+ fileChangeId: import_zod2.z.string().max(128).optional(),
13941
+ stats: import_zod2.z.object({
13942
+ added: import_zod2.z.number().int(),
13943
+ removed: import_zod2.z.number().int(),
13944
+ complexityShift: import_zod2.z.number().int()
13945
+ }).optional()
13825
13946
  });
13826
13947
  function parsePayload2(schema, raw) {
13827
13948
  const result = schema.safeParse(raw);
@@ -13977,11 +14098,11 @@ async function writeProjectFile(rawPath, content) {
13977
14098
  }
13978
14099
 
13979
14100
  // src/services/project-ops.service.ts
13980
- var import_child_process10 = require("child_process");
14101
+ var import_child_process11 = require("child_process");
13981
14102
  var import_util2 = require("util");
13982
14103
  var fs24 = __toESM(require("fs/promises"));
13983
14104
  var path29 = __toESM(require("path"));
13984
- var execFileP3 = (0, import_util2.promisify)(import_child_process10.execFile);
14105
+ var execFileP3 = (0, import_util2.promisify)(import_child_process11.execFile);
13985
14106
  var PROJECT_IGNORE = /* @__PURE__ */ new Set([
13986
14107
  "node_modules",
13987
14108
  ".git",
@@ -14321,7 +14442,7 @@ async function jsSearchFiles(opts, cwd, cap) {
14321
14442
  }
14322
14443
 
14323
14444
  // src/services/terminal-ops.service.ts
14324
- var import_child_process11 = require("child_process");
14445
+ var import_child_process12 = require("child_process");
14325
14446
  var import_crypto4 = require("crypto");
14326
14447
  var import_path3 = __toESM(require("path"));
14327
14448
  var MAX_CONCURRENT_SESSIONS = 4;
@@ -14443,7 +14564,7 @@ function createPythonSession(id, shell, cwd, env, cols, rows) {
14443
14564
  }
14444
14565
  let child;
14445
14566
  try {
14446
- child = (0, import_child_process11.spawn)(python, ["-c", PYTHON_TERMINAL_HELPER, shell], {
14567
+ child = (0, import_child_process12.spawn)(python, ["-c", PYTHON_TERMINAL_HELPER, shell], {
14447
14568
  cwd,
14448
14569
  env: { ...env, COLUMNS: String(cols), LINES: String(rows) },
14449
14570
  stdio: ["pipe", "pipe", "pipe"]
@@ -14578,7 +14699,7 @@ function closeAllTerminals() {
14578
14699
  }
14579
14700
 
14580
14701
  // src/services/apply-file-review.service.ts
14581
- var import_child_process12 = require("child_process");
14702
+ var import_child_process13 = require("child_process");
14582
14703
  var fs25 = __toESM(require("fs"));
14583
14704
  var path31 = __toESM(require("path"));
14584
14705
  async function applyFileReview(workingDir, filePath, action) {
@@ -14620,7 +14741,7 @@ function runGit3(cwd, args2) {
14620
14741
  return new Promise((resolve5) => {
14621
14742
  let proc;
14622
14743
  try {
14623
- proc = (0, import_child_process12.spawn)("git", args2, { cwd, env: process.env });
14744
+ proc = (0, import_child_process13.spawn)("git", args2, { cwd, env: process.env });
14624
14745
  } catch (err) {
14625
14746
  resolve5({ ok: false, code: -1, stdout: "", stderr: err.message });
14626
14747
  return;
@@ -15151,7 +15272,7 @@ var sessionTerminated = (ctx) => {
15151
15272
  } catch {
15152
15273
  }
15153
15274
  try {
15154
- const proc = (0, import_child_process13.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
15275
+ const proc = (0, import_child_process14.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
15155
15276
  detached: true,
15156
15277
  stdio: "ignore"
15157
15278
  });
@@ -15173,7 +15294,7 @@ var shutdownSession = async (ctx, cmd) => {
15173
15294
  }
15174
15295
  if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
15175
15296
  try {
15176
- const stopProc = (0, import_child_process13.spawn)(
15297
+ const stopProc = (0, import_child_process14.spawn)(
15177
15298
  "bash",
15178
15299
  ["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
15179
15300
  { detached: true, stdio: "ignore" }
@@ -15183,7 +15304,7 @@ var shutdownSession = async (ctx, cmd) => {
15183
15304
  }
15184
15305
  }
15185
15306
  try {
15186
- const proc = (0, import_child_process13.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
15307
+ const proc = (0, import_child_process14.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
15187
15308
  detached: true,
15188
15309
  stdio: "ignore"
15189
15310
  });
@@ -15365,6 +15486,62 @@ var requestLinkCredentialsH = async (ctx, _cmd, parsed) => {
15365
15486
  log.trace("auto-link", `upload failed (${result.status}): ${result.message}`);
15366
15487
  }
15367
15488
  };
15489
+ var requestAiSummaryH = async (ctx, _cmd, parsed) => {
15490
+ if (!ctx.pluginAuthToken) return;
15491
+ if (typeof ctx.runtime.generateOneShot !== "function") return;
15492
+ if (!parsed.prompt || !parsed.turnId || !parsed.stats) {
15493
+ log.trace("ai-summary", "missing prompt/turnId/stats \u2014 skipping");
15494
+ return;
15495
+ }
15496
+ const text = await ctx.runtime.generateOneShot(parsed.prompt).catch((err) => {
15497
+ log.trace("ai-summary", "generateOneShot threw", err);
15498
+ return null;
15499
+ });
15500
+ if (!text) return;
15501
+ await postAiResult({
15502
+ sessionId: ctx.sessionId,
15503
+ pluginId: ctx.pluginId,
15504
+ pluginAuthToken: ctx.pluginAuthToken,
15505
+ kind: "summary",
15506
+ turnId: parsed.turnId,
15507
+ summary: text,
15508
+ stats: parsed.stats
15509
+ });
15510
+ };
15511
+ var requestAiInsightH = async (ctx, _cmd, parsed) => {
15512
+ if (!ctx.pluginAuthToken) return;
15513
+ if (typeof ctx.runtime.generateOneShot !== "function") return;
15514
+ if (!parsed.prompt || !parsed.fileChangeId) {
15515
+ log.trace("ai-insight", "missing prompt/fileChangeId \u2014 skipping");
15516
+ return;
15517
+ }
15518
+ const text = await ctx.runtime.generateOneShot(parsed.prompt).catch((err) => {
15519
+ log.trace("ai-insight", "generateOneShot threw", err);
15520
+ return null;
15521
+ });
15522
+ if (!text) return;
15523
+ const { summary, reasoning, securityNote } = parseInsightText(text);
15524
+ await postAiResult({
15525
+ sessionId: ctx.sessionId,
15526
+ pluginId: ctx.pluginId,
15527
+ pluginAuthToken: ctx.pluginAuthToken,
15528
+ kind: "insight",
15529
+ fileChangeId: parsed.fileChangeId,
15530
+ summary,
15531
+ reasoning,
15532
+ securityNote
15533
+ });
15534
+ };
15535
+ function parseInsightText(text) {
15536
+ const summaryMatch = text.match(/SUMMARY:\s*([\s\S]*?)(?=\n\s*(?:REASONING|SECURITY):|$)/i);
15537
+ const reasoningMatch = text.match(/REASONING:\s*([\s\S]*?)(?=\n\s*SECURITY:|$)/i);
15538
+ const securityMatch = text.match(/SECURITY:\s*([\s\S]*)/i);
15539
+ return {
15540
+ summary: (summaryMatch?.[1] ?? text).trim(),
15541
+ reasoning: (reasoningMatch?.[1] ?? text).trim(),
15542
+ securityNote: securityMatch?.[1]?.trim() || void 0
15543
+ };
15544
+ }
15368
15545
  var handlers = {
15369
15546
  start_task: startTask,
15370
15547
  provide_input: provideInput,
@@ -15397,7 +15574,9 @@ var handlers = {
15397
15574
  git_pull: gitPullH,
15398
15575
  git_resolve: gitResolveH,
15399
15576
  apply_file_review: applyFileReviewH,
15400
- request_link_credentials: requestLinkCredentialsH
15577
+ request_link_credentials: requestLinkCredentialsH,
15578
+ request_ai_summary: requestAiSummaryH,
15579
+ request_ai_insight: requestAiInsightH
15401
15580
  };
15402
15581
  async function dispatchCommand(ctx, cmd) {
15403
15582
  const parsed = parsePayload2(startCommandSchema, cmd.payload);
@@ -15492,6 +15671,7 @@ async function start(requestedAgent) {
15492
15671
  sessionId: session.id,
15493
15672
  pluginId,
15494
15673
  pluginAuthToken: session.pluginAuthToken,
15674
+ agentId: runtime.meta.id,
15495
15675
  dirtyTracker: dirtyTracker ?? void 0
15496
15676
  }) : null;
15497
15677
  let streamingEmitter = null;
@@ -15989,11 +16169,11 @@ async function logout() {
15989
16169
  var import_picocolors10 = __toESM(require("picocolors"));
15990
16170
 
15991
16171
  // src/services/providers/github-codespaces.ts
15992
- var import_child_process14 = require("child_process");
16172
+ var import_child_process15 = require("child_process");
15993
16173
  var import_util3 = require("util");
15994
16174
  var import_picocolors8 = __toESM(require("picocolors"));
15995
16175
  var path34 = __toESM(require("path"));
15996
- var execFileP4 = (0, import_util3.promisify)(import_child_process14.execFile);
16176
+ var execFileP4 = (0, import_util3.promisify)(import_child_process15.execFile);
15997
16177
  var MAX_BUFFER = 8 * 1024 * 1024;
15998
16178
  function resetStdinForChild() {
15999
16179
  if (process.stdin.isTTY) {
@@ -16037,7 +16217,7 @@ var GitHubCodespacesProvider = class {
16037
16217
  if (!isAuthed) {
16038
16218
  resetStdinForChild();
16039
16219
  await new Promise((resolve5, reject) => {
16040
- const proc = (0, import_child_process14.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
16220
+ const proc = (0, import_child_process15.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
16041
16221
  stdio: "inherit"
16042
16222
  });
16043
16223
  proc.on("exit", (code) => {
@@ -16071,7 +16251,7 @@ var GitHubCodespacesProvider = class {
16071
16251
  wt(noteLines.join("\n"), "One more permission needed");
16072
16252
  resetStdinForChild();
16073
16253
  const refreshCode = await new Promise((resolve5, reject) => {
16074
- const proc = (0, import_child_process14.spawn)(
16254
+ const proc = (0, import_child_process15.spawn)(
16075
16255
  "gh",
16076
16256
  ["auth", "refresh", "-h", "github.com", "-s", "codespace"],
16077
16257
  { stdio: "inherit" }
@@ -16221,7 +16401,7 @@ var GitHubCodespacesProvider = class {
16221
16401
  O2.step(`Installing gh via ${installCmd.describe}\u2026`);
16222
16402
  resetStdinForChild();
16223
16403
  const ok = await new Promise((resolve5) => {
16224
- const proc = (0, import_child_process14.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
16404
+ const proc = (0, import_child_process15.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
16225
16405
  proc.on("exit", (code) => resolve5(code === 0));
16226
16406
  proc.on("error", () => resolve5(false));
16227
16407
  });
@@ -16248,7 +16428,7 @@ var GitHubCodespacesProvider = class {
16248
16428
  );
16249
16429
  resetStdinForChild();
16250
16430
  await new Promise((resolve5, reject) => {
16251
- const proc = (0, import_child_process14.spawn)(
16431
+ const proc = (0, import_child_process15.spawn)(
16252
16432
  "gh",
16253
16433
  ["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
16254
16434
  { stdio: "inherit" }
@@ -16426,7 +16606,7 @@ var GitHubCodespacesProvider = class {
16426
16606
  async streamCommand(workspaceId, command2) {
16427
16607
  resetStdinForChild();
16428
16608
  return new Promise((resolve5, reject) => {
16429
- const proc = (0, import_child_process14.spawn)(
16609
+ const proc = (0, import_child_process15.spawn)(
16430
16610
  "gh",
16431
16611
  ["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
16432
16612
  { stdio: "inherit" }
@@ -16453,11 +16633,11 @@ var GitHubCodespacesProvider = class {
16453
16633
  `mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
16454
16634
  ];
16455
16635
  await new Promise((resolve5, reject) => {
16456
- const tar = (0, import_child_process14.spawn)("tar", tarArgs, {
16636
+ const tar = (0, import_child_process15.spawn)("tar", tarArgs, {
16457
16637
  stdio: ["ignore", "pipe", "pipe"],
16458
16638
  env: tarEnv
16459
16639
  });
16460
- const ssh = (0, import_child_process14.spawn)("gh", sshArgs, {
16640
+ const ssh = (0, import_child_process15.spawn)("gh", sshArgs, {
16461
16641
  stdio: [tar.stdout, "pipe", "pipe"]
16462
16642
  });
16463
16643
  let tarErr = "";
@@ -16491,7 +16671,7 @@ var GitHubCodespacesProvider = class {
16491
16671
  }
16492
16672
  const cmd = parts.join(" && ");
16493
16673
  await new Promise((resolve5, reject) => {
16494
- const proc = (0, import_child_process14.spawn)(
16674
+ const proc = (0, import_child_process15.spawn)(
16495
16675
  "gh",
16496
16676
  ["codespace", "ssh", "-c", workspaceId, "--", cmd],
16497
16677
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -16549,11 +16729,11 @@ function shellQuote(s) {
16549
16729
  }
16550
16730
 
16551
16731
  // src/services/providers/gitpod.ts
16552
- var import_child_process15 = require("child_process");
16732
+ var import_child_process16 = require("child_process");
16553
16733
  var import_util4 = require("util");
16554
16734
  var path35 = __toESM(require("path"));
16555
16735
  var import_picocolors9 = __toESM(require("picocolors"));
16556
- var execFileP5 = (0, import_util4.promisify)(import_child_process15.execFile);
16736
+ var execFileP5 = (0, import_util4.promisify)(import_child_process16.execFile);
16557
16737
  var MAX_BUFFER2 = 8 * 1024 * 1024;
16558
16738
  function resetStdinForChild2() {
16559
16739
  if (process.stdin.isTTY) {
@@ -16593,7 +16773,7 @@ var GitpodProvider = class {
16593
16773
  );
16594
16774
  resetStdinForChild2();
16595
16775
  await new Promise((resolve5, reject) => {
16596
- const proc = (0, import_child_process15.spawn)("gitpod", ["login"], { stdio: "inherit" });
16776
+ const proc = (0, import_child_process16.spawn)("gitpod", ["login"], { stdio: "inherit" });
16597
16777
  proc.on("exit", (code) => {
16598
16778
  if (code === 0) resolve5();
16599
16779
  else reject(new Error("gitpod login failed."));
@@ -16745,7 +16925,7 @@ var GitpodProvider = class {
16745
16925
  async streamCommand(workspaceId, command2) {
16746
16926
  resetStdinForChild2();
16747
16927
  return new Promise((resolve5, reject) => {
16748
- const proc = (0, import_child_process15.spawn)(
16928
+ const proc = (0, import_child_process16.spawn)(
16749
16929
  "gitpod",
16750
16930
  ["workspace", "ssh", workspaceId, "--", "-tt", command2],
16751
16931
  { stdio: "inherit" }
@@ -16765,11 +16945,11 @@ var GitpodProvider = class {
16765
16945
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
16766
16946
  const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
16767
16947
  await new Promise((resolve5, reject) => {
16768
- const tar = (0, import_child_process15.spawn)("tar", tarArgs, {
16948
+ const tar = (0, import_child_process16.spawn)("tar", tarArgs, {
16769
16949
  stdio: ["ignore", "pipe", "pipe"],
16770
16950
  env: tarEnv
16771
16951
  });
16772
- const ssh = (0, import_child_process15.spawn)(
16952
+ const ssh = (0, import_child_process16.spawn)(
16773
16953
  "gitpod",
16774
16954
  ["workspace", "ssh", workspaceId, "--", remoteCmd],
16775
16955
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -16801,7 +16981,7 @@ var GitpodProvider = class {
16801
16981
  }
16802
16982
  const cmd = parts.join(" && ");
16803
16983
  await new Promise((resolve5, reject) => {
16804
- const proc = (0, import_child_process15.spawn)(
16984
+ const proc = (0, import_child_process16.spawn)(
16805
16985
  "gitpod",
16806
16986
  ["workspace", "ssh", workspaceId, "--", cmd],
16807
16987
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -16825,10 +17005,10 @@ function shellQuote2(s) {
16825
17005
  }
16826
17006
 
16827
17007
  // src/services/providers/gitlab-workspaces.ts
16828
- var import_child_process16 = require("child_process");
17008
+ var import_child_process17 = require("child_process");
16829
17009
  var import_util5 = require("util");
16830
17010
  var path36 = __toESM(require("path"));
16831
- var execFileP6 = (0, import_util5.promisify)(import_child_process16.execFile);
17011
+ var execFileP6 = (0, import_util5.promisify)(import_child_process17.execFile);
16832
17012
  var MAX_BUFFER3 = 8 * 1024 * 1024;
16833
17013
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
16834
17014
  function resetStdinForChild3() {
@@ -16870,7 +17050,7 @@ var GitLabWorkspacesProvider = class {
16870
17050
  );
16871
17051
  resetStdinForChild3();
16872
17052
  await new Promise((resolve5, reject) => {
16873
- const proc = (0, import_child_process16.spawn)(
17053
+ const proc = (0, import_child_process17.spawn)(
16874
17054
  "glab",
16875
17055
  ["auth", "login", "--scopes", "api,read_user,read_repository"],
16876
17056
  { stdio: "inherit" }
@@ -17042,7 +17222,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
17042
17222
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
17043
17223
  resetStdinForChild3();
17044
17224
  return new Promise((resolve5, reject) => {
17045
- const proc = (0, import_child_process16.spawn)(
17225
+ const proc = (0, import_child_process17.spawn)(
17046
17226
  "ssh",
17047
17227
  ["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
17048
17228
  { stdio: "inherit" }
@@ -17063,8 +17243,8 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
17063
17243
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
17064
17244
  const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
17065
17245
  await new Promise((resolve5, reject) => {
17066
- const tar = (0, import_child_process16.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
17067
- const ssh = (0, import_child_process16.spawn)(
17246
+ const tar = (0, import_child_process17.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
17247
+ const ssh = (0, import_child_process17.spawn)(
17068
17248
  "ssh",
17069
17249
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
17070
17250
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -17094,7 +17274,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
17094
17274
  }
17095
17275
  const cmd = parts.join(" && ");
17096
17276
  await new Promise((resolve5, reject) => {
17097
- const proc = (0, import_child_process16.spawn)(
17277
+ const proc = (0, import_child_process17.spawn)(
17098
17278
  "ssh",
17099
17279
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
17100
17280
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -17153,10 +17333,10 @@ function shellQuote3(s) {
17153
17333
  }
17154
17334
 
17155
17335
  // src/services/providers/railway.ts
17156
- var import_child_process17 = require("child_process");
17336
+ var import_child_process18 = require("child_process");
17157
17337
  var import_util6 = require("util");
17158
17338
  var path37 = __toESM(require("path"));
17159
- var execFileP7 = (0, import_util6.promisify)(import_child_process17.execFile);
17339
+ var execFileP7 = (0, import_util6.promisify)(import_child_process18.execFile);
17160
17340
  var MAX_BUFFER4 = 8 * 1024 * 1024;
17161
17341
  function resetStdinForChild4() {
17162
17342
  if (process.stdin.isTTY) {
@@ -17197,7 +17377,7 @@ var RailwayProvider = class {
17197
17377
  );
17198
17378
  resetStdinForChild4();
17199
17379
  await new Promise((resolve5, reject) => {
17200
- const proc = (0, import_child_process17.spawn)("railway", ["login"], { stdio: "inherit" });
17380
+ const proc = (0, import_child_process18.spawn)("railway", ["login"], { stdio: "inherit" });
17201
17381
  proc.on("exit", (code) => {
17202
17382
  if (code === 0) resolve5();
17203
17383
  else reject(new Error("railway login failed."));
@@ -17340,7 +17520,7 @@ var RailwayProvider = class {
17340
17520
  }
17341
17521
  resetStdinForChild4();
17342
17522
  return new Promise((resolve5, reject) => {
17343
- const proc = (0, import_child_process17.spawn)(
17523
+ const proc = (0, import_child_process18.spawn)(
17344
17524
  "railway",
17345
17525
  ["shell", "--project", projectId, "--service", serviceId, "--command", command2],
17346
17526
  { stdio: "inherit" }
@@ -17364,8 +17544,8 @@ var RailwayProvider = class {
17364
17544
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
17365
17545
  const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
17366
17546
  await new Promise((resolve5, reject) => {
17367
- const tar = (0, import_child_process17.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
17368
- const sh = (0, import_child_process17.spawn)(
17547
+ const tar = (0, import_child_process18.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
17548
+ const sh = (0, import_child_process18.spawn)(
17369
17549
  "railway",
17370
17550
  ["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
17371
17551
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -17398,7 +17578,7 @@ var RailwayProvider = class {
17398
17578
  }
17399
17579
  const cmd = parts.join(" && ");
17400
17580
  await new Promise((resolve5, reject) => {
17401
- const proc = (0, import_child_process17.spawn)(
17581
+ const proc = (0, import_child_process18.spawn)(
17402
17582
  "railway",
17403
17583
  ["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
17404
17584
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -18103,7 +18283,7 @@ function checkChokidar() {
18103
18283
  }
18104
18284
  async function doctor(args2 = []) {
18105
18285
  const json = args2.includes("--json");
18106
- const cliVersion = true ? "2.22.0" : "0.0.0-dev";
18286
+ const cliVersion = true ? "2.23.0" : "0.0.0-dev";
18107
18287
  const apiBase = resolveApiBaseUrl();
18108
18288
  const diagnosticId = (0, import_node_crypto5.randomUUID)();
18109
18289
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -18302,7 +18482,7 @@ async function completion(args2) {
18302
18482
  // src/commands/version.ts
18303
18483
  var import_picocolors13 = __toESM(require("picocolors"));
18304
18484
  function version2() {
18305
- const v = true ? "2.22.0" : "unknown";
18485
+ const v = true ? "2.23.0" : "unknown";
18306
18486
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
18307
18487
  }
18308
18488
 
@@ -18530,7 +18710,7 @@ function checkForUpdates() {
18530
18710
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
18531
18711
  if (process.env.CI) return;
18532
18712
  if (!process.stdout.isTTY) return;
18533
- const current = true ? "2.22.0" : null;
18713
+ const current = true ? "2.23.0" : null;
18534
18714
  if (!current) return;
18535
18715
  const cache = readCache();
18536
18716
  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.22.0",
3
+ "version": "2.23.0",
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",