codeam-cli 2.6.0 → 2.8.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 +25 -0
  2. package/dist/index.js +217 -24
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,31 @@ 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.7.0] — 2026-05-08
8
+
9
+ ### Added
10
+
11
+ - **cli:** Codeam pair-auto subcommand for in-codespace auto-pairing
12
+
13
+ ## [2.6.0] — 2026-05-08
14
+
15
+ ### Added
16
+
17
+ - **vsc-plugin:** Replay X-Plugin-Auth-Token + delta conversation upload
18
+ - **jetbrains-plugin:** Full parity with CLI — auth token, missing handlers, chunk emissions
19
+
20
+ ### CI
21
+
22
+ - **release:** Make verifyPlugin non-fatal so JetBrains release ships
23
+
24
+ ### Chore
25
+
26
+ - **cli:** Bump source version to 2.6.0 for unified release line
27
+
28
+ ### Fixed
29
+
30
+ - **shared:** Selector detector locks onto trust-dialog text without a cursor
31
+
7
32
  ## [2.5.4] — 2026-05-07
8
33
 
9
34
  ### Fixed
package/dist/index.js CHANGED
@@ -519,8 +519,8 @@ var require_windowsPtyAgent = __commonJS({
519
519
  "use strict";
520
520
  Object.defineProperty(exports2, "__esModule", { value: true });
521
521
  exports2.argsToCommandLine = exports2.WindowsPtyAgent = void 0;
522
- var fs12 = require("fs");
523
- var os11 = require("os");
522
+ var fs13 = require("fs");
523
+ var os12 = require("os");
524
524
  var path19 = require("path");
525
525
  var child_process_1 = require("child_process");
526
526
  var net_1 = require("net");
@@ -578,7 +578,7 @@ var require_windowsPtyAgent = __commonJS({
578
578
  this._outSocket.on("connect", function() {
579
579
  _this._outSocket.emit("ready_datapipe");
580
580
  });
581
- var inSocketFD = fs12.openSync(term.conin, "w");
581
+ var inSocketFD = fs13.openSync(term.conin, "w");
582
582
  this._inSocket = new net_1.Socket({
583
583
  fd: inSocketFD,
584
584
  readable: false,
@@ -702,7 +702,7 @@ var require_windowsPtyAgent = __commonJS({
702
702
  configurable: true
703
703
  });
704
704
  WindowsPtyAgent2.prototype._getWindowsBuildNumber = function() {
705
- var osVersion = /(\d+)\.(\d+)\.(\d+)/g.exec(os11.release());
705
+ var osVersion = /(\d+)\.(\d+)\.(\d+)/g.exec(os12.release());
706
706
  var buildNumber = 0;
707
707
  if (osVersion && osVersion.length === 4) {
708
708
  buildNumber = parseInt(osVersion[3]);
@@ -1012,7 +1012,7 @@ var require_unixTerminal = __commonJS({
1012
1012
  })();
1013
1013
  Object.defineProperty(exports2, "__esModule", { value: true });
1014
1014
  exports2.UnixTerminal = void 0;
1015
- var fs12 = require("fs");
1015
+ var fs13 = require("fs");
1016
1016
  var path19 = require("path");
1017
1017
  var tty = require("tty");
1018
1018
  var terminal_1 = require_terminal();
@@ -1275,7 +1275,7 @@ var require_unixTerminal = __commonJS({
1275
1275
  return;
1276
1276
  }
1277
1277
  var task = this._writeQueue[0];
1278
- fs12.write(this._fd, task.buffer, task.offset, function(err, written) {
1278
+ fs13.write(this._fd, task.buffer, task.offset, function(err, written) {
1279
1279
  if (err) {
1280
1280
  if ("code" in err && err.code === "EAGAIN") {
1281
1281
  _this._writeImmediate = setImmediate(function() {
@@ -1477,7 +1477,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
1477
1477
  // package.json
1478
1478
  var package_default = {
1479
1479
  name: "codeam-cli",
1480
- version: "2.6.0",
1480
+ version: "2.8.0",
1481
1481
  description: "Remote control Claude Code (and other AI coding agents) from your mobile phone. Pair your device, send prompts, stream responses in real-time, and approve commands \u2014 from anywhere.",
1482
1482
  type: "commonjs",
1483
1483
  main: "dist/index.js",
@@ -7001,6 +7001,195 @@ async function pair() {
7001
7001
  await start();
7002
7002
  }
7003
7003
 
7004
+ // src/commands/pair-auto.ts
7005
+ var fs10 = __toESM(require("fs"));
7006
+ var os9 = __toESM(require("os"));
7007
+ var import_crypto3 = require("crypto");
7008
+ var API_BASE5 = process.env.CODEAM_API_URL ?? "https://codeagent-mobile-api.vercel.app";
7009
+ function fail(msg) {
7010
+ console.error(`
7011
+ ${msg}
7012
+ `);
7013
+ process.exit(1);
7014
+ }
7015
+ function readTokenFromArgs(args2) {
7016
+ const inline = args2.find((a) => a.startsWith("--token="));
7017
+ if (inline) {
7018
+ const value = inline.slice("--token=".length).trim();
7019
+ if (value.length > 0) return value;
7020
+ }
7021
+ const fileFlag = args2.find((a) => a.startsWith("--token-file="));
7022
+ if (fileFlag) {
7023
+ const path19 = fileFlag.slice("--token-file=".length);
7024
+ try {
7025
+ const content = fs10.readFileSync(path19, "utf8").trim();
7026
+ if (content.length === 0) fail(`--token-file ${path19} is empty`);
7027
+ try {
7028
+ fs10.unlinkSync(path19);
7029
+ } catch {
7030
+ }
7031
+ return content;
7032
+ } catch (err) {
7033
+ fail(`Could not read --token-file: ${err.message}`);
7034
+ }
7035
+ }
7036
+ if (process.env.CODEAM_AUTO_TOKEN) return process.env.CODEAM_AUTO_TOKEN;
7037
+ fail("codeam pair-auto requires --token-file=<path>, --token=<value>, or CODEAM_AUTO_TOKEN env");
7038
+ }
7039
+ async function claim(token, pluginId) {
7040
+ const url = `${API_BASE5}/api/pairing/claim-auto-token`;
7041
+ const codespaceName = process.env.CODESPACE_NAME ?? "";
7042
+ const isCodespace = codespaceName.length > 0;
7043
+ const body = {
7044
+ token,
7045
+ pluginId,
7046
+ ideName: isCodespace ? "codeam-cli (codespace)" : "codeam-cli",
7047
+ ideVersion: process.env.npm_package_version ?? "unknown",
7048
+ hostname: os9.hostname(),
7049
+ codespaceName
7050
+ };
7051
+ const res = await fetch(url, {
7052
+ method: "POST",
7053
+ headers: { "Content-Type": "application/json" },
7054
+ body: JSON.stringify(body)
7055
+ });
7056
+ const json = await res.json();
7057
+ if (!res.ok || !("success" in json) || !json.success) {
7058
+ const errBody = json;
7059
+ const code = errBody?.error?.code ?? `HTTP_${res.status}`;
7060
+ const msg = errBody?.error?.message ?? `Server returned ${res.status}`;
7061
+ fail(`Auto-pair failed (${code}): ${msg}`);
7062
+ }
7063
+ const ok = json;
7064
+ if (!ok.data?.sessionId) {
7065
+ fail("Auto-pair response missing sessionId");
7066
+ }
7067
+ return ok.data;
7068
+ }
7069
+ async function pairAuto(args2) {
7070
+ const token = readTokenFromArgs(args2);
7071
+ const pluginId = (0, import_crypto3.randomUUID)();
7072
+ console.log(" Claiming pairing token\u2026");
7073
+ const claimed = await claim(token, pluginId);
7074
+ addSession({
7075
+ id: claimed.sessionId,
7076
+ pluginId,
7077
+ userName: claimed.user.name,
7078
+ userEmail: claimed.user.email,
7079
+ plan: claimed.user.plan,
7080
+ pairedAt: Date.now(),
7081
+ pluginAuthToken: claimed.pluginAuthToken
7082
+ });
7083
+ console.log(` Paired with ${claimed.user.name} (${claimed.user.plan})`);
7084
+ console.log(" Starting agent loop\u2026");
7085
+ await start();
7086
+ }
7087
+
7088
+ // src/commands/plugin-bridge.ts
7089
+ async function pluginBridge() {
7090
+ const sessionId = process.env.CODEAM_BRIDGE_SESSION_ID;
7091
+ const pluginId = process.env.CODEAM_BRIDGE_PLUGIN_ID;
7092
+ const pluginAuthToken = process.env.CODEAM_BRIDGE_PLUGIN_AUTH_TOKEN;
7093
+ if (!sessionId || !pluginId || !pluginAuthToken) {
7094
+ console.error(
7095
+ "[plugin-bridge] missing CODEAM_BRIDGE_SESSION_ID / CODEAM_BRIDGE_PLUGIN_ID / CODEAM_BRIDGE_PLUGIN_AUTH_TOKEN env"
7096
+ );
7097
+ process.exit(1);
7098
+ }
7099
+ const cwd = process.cwd();
7100
+ const historySvc = new HistoryService(pluginId, cwd);
7101
+ const keepAliveCtx = { inCodespace: false, codespaceName: void 0 };
7102
+ const { apply: setKeepAlive2 } = buildKeepAlive(keepAliveCtx);
7103
+ const outputSvc = new OutputService(
7104
+ sessionId,
7105
+ pluginId,
7106
+ (conversationId) => historySvc.setCurrentConversationId(conversationId),
7107
+ (reset) => historySvc.setRateLimitReset(reset),
7108
+ () => {
7109
+ if (historySvc.isQuotaStale()) fetchQuotaUsage(historySvc);
7110
+ setTimeout(() => {
7111
+ historySvc.uploadDelta().catch(() => {
7112
+ });
7113
+ }, 400);
7114
+ },
7115
+ () => {
7116
+ const prevCount = historySvc.getCurrentMessageCount();
7117
+ historySvc.waitForNewUserMessage(prevCount).then((userText) => outputSvc.startTerminalTurn(userText ?? void 0)).catch(() => outputSvc.startTerminalTurn(void 0));
7118
+ },
7119
+ pluginAuthToken
7120
+ );
7121
+ const claude = new ClaudeService({
7122
+ cwd,
7123
+ onData(raw) {
7124
+ outputSvc.push(raw);
7125
+ },
7126
+ onExit(code) {
7127
+ outputSvc.dispose();
7128
+ process.exit(code);
7129
+ }
7130
+ });
7131
+ const relayStub = new CommandRelayService(pluginId, async () => {
7132
+ });
7133
+ const ctx = {
7134
+ outputSvc,
7135
+ claude,
7136
+ historySvc,
7137
+ relay: relayStub,
7138
+ setKeepAlive: setKeepAlive2,
7139
+ keepAliveCtx
7140
+ };
7141
+ function shutdown(code) {
7142
+ try {
7143
+ claude.kill();
7144
+ } catch {
7145
+ }
7146
+ try {
7147
+ outputSvc.dispose();
7148
+ } catch {
7149
+ }
7150
+ process.exit(code);
7151
+ }
7152
+ process.once("SIGINT", () => shutdown(0));
7153
+ process.once("SIGTERM", () => shutdown(0));
7154
+ await claude.spawn();
7155
+ await outputSvc.startTerminalTurn();
7156
+ let buffer = "";
7157
+ process.stdin.setEncoding("utf8");
7158
+ process.stdin.on("data", (chunk) => {
7159
+ buffer += chunk;
7160
+ let idx;
7161
+ while ((idx = buffer.indexOf("\n")) !== -1) {
7162
+ const line = buffer.slice(0, idx).trim();
7163
+ buffer = buffer.slice(idx + 1);
7164
+ if (!line) continue;
7165
+ try {
7166
+ const raw = JSON.parse(line);
7167
+ if (typeof raw?.id !== "string" || typeof raw?.type !== "string") continue;
7168
+ const cmd = {
7169
+ id: raw.id,
7170
+ type: raw.type,
7171
+ sessionId,
7172
+ // always the plugin's session — ignore any value from the host
7173
+ payload: raw.payload ?? {}
7174
+ };
7175
+ dispatchCommand(ctx, cmd).catch(() => {
7176
+ });
7177
+ } catch {
7178
+ }
7179
+ }
7180
+ });
7181
+ process.stdin.on("end", () => shutdown(0));
7182
+ setTimeout(() => {
7183
+ historySvc.detectCurrentConversation();
7184
+ historySvc.load().catch(() => {
7185
+ });
7186
+ const currentId = historySvc.getCurrentConversationId();
7187
+ if (currentId) historySvc.loadConversation(currentId).catch(() => {
7188
+ });
7189
+ }, 2e3);
7190
+ setTimeout(() => fetchQuotaUsage(historySvc), 5e3);
7191
+ }
7192
+
7004
7193
  // src/commands/sessions.ts
7005
7194
  var import_picocolors4 = __toESM(require("picocolors"));
7006
7195
  async function sessions(args2) {
@@ -7102,8 +7291,8 @@ async function logout() {
7102
7291
 
7103
7292
  // src/commands/deploy.ts
7104
7293
  var import_child_process12 = require("child_process");
7105
- var fs10 = __toESM(require("fs"));
7106
- var os9 = __toESM(require("os"));
7294
+ var fs11 = __toESM(require("fs"));
7295
+ var os10 = __toESM(require("os"));
7107
7296
  var path17 = __toESM(require("path"));
7108
7297
  var import_util6 = require("util");
7109
7298
  var import_picocolors9 = __toESM(require("picocolors"));
@@ -8703,7 +8892,7 @@ async function deploy() {
8703
8892
  process.exit(1);
8704
8893
  }
8705
8894
  }
8706
- const localClaudeDir = path17.join(os9.homedir(), ".claude");
8895
+ const localClaudeDir = path17.join(os10.homedir(), ".claude");
8707
8896
  const localCredsKind = await detectLocalClaudeCredentials(localClaudeDir);
8708
8897
  let bridged = "none";
8709
8898
  if (localCredsKind !== "none") {
@@ -8747,7 +8936,7 @@ async function deploy() {
8747
8936
  process.exit(1);
8748
8937
  }
8749
8938
  claudeStep.stop("\u2713 Claude CLI installed");
8750
- const haveLocalClaude = fs10.existsSync(localClaudeDir) && fs10.statSync(localClaudeDir).isDirectory();
8939
+ const haveLocalClaude = fs11.existsSync(localClaudeDir) && fs11.statSync(localClaudeDir).isDirectory();
8751
8940
  if (haveLocalClaude) {
8752
8941
  const copyStep = fe();
8753
8942
  copyStep.start("Copying local Claude config to workspace\u2026");
@@ -8801,10 +8990,10 @@ async function deploy() {
8801
8990
  }
8802
8991
  }
8803
8992
  if (bridged !== "none") {
8804
- const localClaudeJson = path17.join(os9.homedir(), ".claude.json");
8805
- if (fs10.existsSync(localClaudeJson)) {
8993
+ const localClaudeJson = path17.join(os10.homedir(), ".claude.json");
8994
+ if (fs11.existsSync(localClaudeJson)) {
8806
8995
  try {
8807
- const contents = fs10.readFileSync(localClaudeJson);
8996
+ const contents = fs11.readFileSync(localClaudeJson);
8808
8997
  await provider.uploadFile(
8809
8998
  workspace.id,
8810
8999
  "/home/codespace/.claude.json",
@@ -8994,7 +9183,7 @@ async function runRemoteClaudeLogin(provider, workspaceId) {
8994
9183
  }
8995
9184
  }
8996
9185
  async function detectLocalClaudeCredentials(localClaudeDir) {
8997
- if (fs10.existsSync(path17.join(localClaudeDir, ".credentials.json"))) {
9186
+ if (fs11.existsSync(path17.join(localClaudeDir, ".credentials.json"))) {
8998
9187
  return "flat-file";
8999
9188
  }
9000
9189
  if (process.platform === "darwin") {
@@ -9028,7 +9217,7 @@ async function verifyClaudeAuth(provider, workspaceId) {
9028
9217
  }
9029
9218
  async function bridgeClaudeCredentials(provider, workspaceId, localClaudeDir) {
9030
9219
  const fileBased = path17.join(localClaudeDir, ".credentials.json");
9031
- if (fs10.existsSync(fileBased)) return "flat-file";
9220
+ if (fs11.existsSync(fileBased)) return "flat-file";
9032
9221
  if (process.platform === "darwin") {
9033
9222
  try {
9034
9223
  const { stdout } = await execFileP6(
@@ -9236,7 +9425,7 @@ async function stopWorkspaceFromLocal(target) {
9236
9425
  // src/commands/version.ts
9237
9426
  var import_picocolors11 = __toESM(require("picocolors"));
9238
9427
  function version() {
9239
- const v = true ? "2.6.0" : "unknown";
9428
+ const v = true ? "2.8.0" : "unknown";
9240
9429
  console.log(`${import_picocolors11.default.bold("codeam-cli")} ${import_picocolors11.default.cyan(v)}`);
9241
9430
  }
9242
9431
 
@@ -9273,8 +9462,8 @@ function help() {
9273
9462
  }
9274
9463
 
9275
9464
  // src/lib/updateNotifier.ts
9276
- var fs11 = __toESM(require("fs"));
9277
- var os10 = __toESM(require("os"));
9465
+ var fs12 = __toESM(require("fs"));
9466
+ var os11 = __toESM(require("os"));
9278
9467
  var path18 = __toESM(require("path"));
9279
9468
  var https5 = __toESM(require("https"));
9280
9469
  var import_picocolors13 = __toESM(require("picocolors"));
@@ -9283,12 +9472,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
9283
9472
  var TTL_MS = 24 * 60 * 60 * 1e3;
9284
9473
  var REQUEST_TIMEOUT_MS = 1500;
9285
9474
  function cachePath() {
9286
- const dir = path18.join(os10.homedir(), ".codeam");
9475
+ const dir = path18.join(os11.homedir(), ".codeam");
9287
9476
  return path18.join(dir, "update-check.json");
9288
9477
  }
9289
9478
  function readCache() {
9290
9479
  try {
9291
- const raw = fs11.readFileSync(cachePath(), "utf8");
9480
+ const raw = fs12.readFileSync(cachePath(), "utf8");
9292
9481
  const parsed = JSON.parse(raw);
9293
9482
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
9294
9483
  return parsed;
@@ -9299,8 +9488,8 @@ function readCache() {
9299
9488
  function writeCache(cache) {
9300
9489
  try {
9301
9490
  const file = cachePath();
9302
- fs11.mkdirSync(path18.dirname(file), { recursive: true });
9303
- fs11.writeFileSync(file, JSON.stringify(cache));
9491
+ fs12.mkdirSync(path18.dirname(file), { recursive: true });
9492
+ fs12.writeFileSync(file, JSON.stringify(cache));
9304
9493
  } catch {
9305
9494
  }
9306
9495
  }
@@ -9371,7 +9560,7 @@ function checkForUpdates() {
9371
9560
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
9372
9561
  if (process.env.CI) return;
9373
9562
  if (!process.stdout.isTTY) return;
9374
- const current = true ? "2.6.0" : null;
9563
+ const current = true ? "2.8.0" : null;
9375
9564
  if (!current) return;
9376
9565
  const cache = readCache();
9377
9566
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -9401,6 +9590,10 @@ async function main() {
9401
9590
  return help();
9402
9591
  case "pair":
9403
9592
  return pair();
9593
+ case "pair-auto":
9594
+ return pairAuto(args);
9595
+ case "plugin-bridge":
9596
+ return pluginBridge();
9404
9597
  case "sessions":
9405
9598
  return sessions(args);
9406
9599
  case "status":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.6.0",
3
+ "version": "2.8.0",
4
4
  "description": "Remote control Claude Code (and other AI coding agents) from your mobile phone. Pair your device, send prompts, stream responses in real-time, and approve commands — from anywhere.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",