codeam-cli 2.7.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.
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.7.0] — 2026-05-08
8
+
9
+ ### Added
10
+
11
+ - **cli:** Codeam pair-auto subcommand for in-codespace auto-pairing
12
+
7
13
  ## [2.6.0] — 2026-05-08
8
14
 
9
15
  ### Added
package/dist/index.js CHANGED
@@ -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.7.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",
@@ -7038,13 +7038,15 @@ function readTokenFromArgs(args2) {
7038
7038
  }
7039
7039
  async function claim(token, pluginId) {
7040
7040
  const url = `${API_BASE5}/api/pairing/claim-auto-token`;
7041
+ const codespaceName = process.env.CODESPACE_NAME ?? "";
7042
+ const isCodespace = codespaceName.length > 0;
7041
7043
  const body = {
7042
7044
  token,
7043
7045
  pluginId,
7044
- ideName: "codeam-cli (codespace)",
7046
+ ideName: isCodespace ? "codeam-cli (codespace)" : "codeam-cli",
7045
7047
  ideVersion: process.env.npm_package_version ?? "unknown",
7046
7048
  hostname: os9.hostname(),
7047
- codespaceName: process.env.CODESPACE_NAME ?? ""
7049
+ codespaceName
7048
7050
  };
7049
7051
  const res = await fetch(url, {
7050
7052
  method: "POST",
@@ -7083,6 +7085,111 @@ async function pairAuto(args2) {
7083
7085
  await start();
7084
7086
  }
7085
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
+
7086
7193
  // src/commands/sessions.ts
7087
7194
  var import_picocolors4 = __toESM(require("picocolors"));
7088
7195
  async function sessions(args2) {
@@ -9318,7 +9425,7 @@ async function stopWorkspaceFromLocal(target) {
9318
9425
  // src/commands/version.ts
9319
9426
  var import_picocolors11 = __toESM(require("picocolors"));
9320
9427
  function version() {
9321
- const v = true ? "2.7.0" : "unknown";
9428
+ const v = true ? "2.8.0" : "unknown";
9322
9429
  console.log(`${import_picocolors11.default.bold("codeam-cli")} ${import_picocolors11.default.cyan(v)}`);
9323
9430
  }
9324
9431
 
@@ -9453,7 +9560,7 @@ function checkForUpdates() {
9453
9560
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
9454
9561
  if (process.env.CI) return;
9455
9562
  if (!process.stdout.isTTY) return;
9456
- const current = true ? "2.7.0" : null;
9563
+ const current = true ? "2.8.0" : null;
9457
9564
  if (!current) return;
9458
9565
  const cache = readCache();
9459
9566
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -9485,6 +9592,8 @@ async function main() {
9485
9592
  return pair();
9486
9593
  case "pair-auto":
9487
9594
  return pairAuto(args);
9595
+ case "plugin-bridge":
9596
+ return pluginBridge();
9488
9597
  case "sessions":
9489
9598
  return sessions(args);
9490
9599
  case "status":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.7.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",