codeam-cli 2.12.16 → 2.13.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,24 @@ 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.12.17] — 2026-05-16
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Submit multi-line composer prompts; document new commands + env vars
12
+ - **vsc-plugin:** Replace placeholder activity bar icon with branded </> mark
13
+
14
+ ## [2.12.16] — 2026-05-15
15
+
16
+ ### Documentation
17
+
18
+ - **meta:** Mention Codex support across CLI/VS Code/JetBrains/README
19
+
20
+ ### Fixed
21
+
22
+ - **cli:** Scope codeam <agent> restore to that agent's most-recent session
23
+ - **cli:** Detect Codex shell-approval prompts as a select_prompt
24
+
7
25
  ## [2.12.14] — 2026-05-14
8
26
 
9
27
  ### Fixed
package/README.md CHANGED
@@ -43,15 +43,18 @@ That's it. Open the [CodeAgent Mobile app](https://codeagent-mobile.com), enter
43
43
 
44
44
  | Command | What it does |
45
45
  |---|---|
46
- | `codeam` | Start Claude Code in the current directory, with mobile control |
47
- | `codeam codex` | Start OpenAI Codex in the current directory, with mobile control |
48
- | `codeam pair` | Pair a new mobile device (6-digit code or QR) |
46
+ | `codeam` | Start the active agent in the current directory, with mobile control |
47
+ | `codeam <agent>` | Start a specific agent `codeam claude`, `codeam codex`, |
48
+ | `codeam pair` | Pair a new mobile device (6-character code or QR, interactive agent picker) |
49
+ | `codeam pair --agent <id>` | Pair non-interactively for a specific agent (`claude`, `codex`, …) — useful in scripts |
49
50
  | `codeam sessions` | List all paired devices |
51
+ | `codeam sessions switch` | Choose which paired session the next `codeam` invocation will use |
52
+ | `codeam sessions delete <session-id>` | Forget a specific paired session (leaves the others intact) |
50
53
  | `codeam status` | Show connection status |
51
54
  | `codeam logout` | Remove all paired sessions |
52
55
  | `codeam deploy` | Provision a cloud workspace (GitHub Codespaces) and pair it to your phone |
53
- | `codeam deploy ls` | List the cloud workspaces you've deployed (and which still have a session running) |
54
- | `codeam deploy stop` | Pick a deployed workspace and stop its codeam session (and optionally the workspace itself) |
56
+ | `codeam deploy ls` (alias `list`) | List the cloud workspaces you've deployed (and which still have a session running) |
57
+ | `codeam deploy stop` (alias `remove`) | Pick a deployed workspace and stop its codeam session (and optionally the workspace itself) |
55
58
  | `codeam --version`, `-v` | Print the installed CLI version |
56
59
  | `codeam --help`, `-h` | Show usage and the full command list |
57
60
 
@@ -106,7 +109,25 @@ Adding more cloud backends (Gitpod, Coder, your own SSH host, …) is a single n
106
109
 
107
110
  | Variable | Default | Effect |
108
111
  |---|---|---|
109
- | `CODEAM_DISABLE_UPDATE_CHECK` | unset | Set to `1` to suppress the "update available" banner. The check also auto-skips on non-TTY stdout, in CI, and during tests. |
112
+ | `CODEAM_API_URL` | `https://codeagent-mobile-api.vercel.app` | Override the backend relay URL. Useful for hitting a staging environment or self-hosted backend. |
113
+ | `CODEAM_DISABLE_UPDATE_CHECK` | unset | Set to `1` to suppress the "update available" banner. The check also auto-skips on non-TTY stdout, when `CI=true`, and during tests. |
114
+ | `CODEAM_AUTO_TOKEN` | unset | One-shot pairing token consumed by `codeam pair-auto`. Used by the `codeam deploy` bootstrap; see *Advanced / scripted pairing* below. |
115
+
116
+ ---
117
+
118
+ ## Advanced / scripted pairing
119
+
120
+ For automation (CI, Codespaces bootstraps, container entry-points) `codeam` ships a non-interactive pairing command:
121
+
122
+ ```bash
123
+ codeam pair-auto --token=<one-shot-pairing-token>
124
+ # or
125
+ codeam pair-auto --token-file=/path/to/token
126
+ # or pass the token via env:
127
+ CODEAM_AUTO_TOKEN=<token> codeam pair-auto
128
+ ```
129
+
130
+ This is the same path `codeam deploy` uses inside a freshly-provisioned Codespace to pair the cloud session to your phone with zero interactive prompts. End users on a laptop should keep using the interactive `codeam pair`.
110
131
 
111
132
  ---
112
133
 
package/dist/index.js CHANGED
@@ -1689,7 +1689,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
1689
1689
  // package.json
1690
1690
  var package_default = {
1691
1691
  name: "codeam-cli",
1692
- version: "2.12.16",
1692
+ version: "2.13.0",
1693
1693
  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.",
1694
1694
  type: "commonjs",
1695
1695
  main: "dist/index.js",
@@ -1817,6 +1817,12 @@ var https = __toESM(require("https"));
1817
1817
  var http = __toESM(require("http"));
1818
1818
  var os2 = __toESM(require("os"));
1819
1819
 
1820
+ // src/lib/backend-headers.ts
1821
+ function vercelBypassHeader() {
1822
+ const token = process.env.CODEAM_VERCEL_BYPASS;
1823
+ return token ? { "x-vercel-protection-bypass": token } : {};
1824
+ }
1825
+
1820
1826
  // src/lib/poll-delay.ts
1821
1827
  var MAX_DELAY_MS = 3e4;
1822
1828
  function computePollDelay({ baseMs, failures }) {
@@ -1915,7 +1921,8 @@ async function _postJson(url, body) {
1915
1921
  method: "POST",
1916
1922
  headers: {
1917
1923
  "Content-Type": "application/json",
1918
- "Content-Length": Buffer.byteLength(data)
1924
+ "Content-Length": Buffer.byteLength(data),
1925
+ ...vercelBypassHeader()
1919
1926
  },
1920
1927
  timeout: 1e4
1921
1928
  },
@@ -1957,6 +1964,7 @@ async function _getJson(url) {
1957
1964
  port: u2.port || (u2.protocol === "https:" ? 443 : 80),
1958
1965
  path: u2.pathname + u2.search,
1959
1966
  method: "GET",
1967
+ headers: { ...vercelBypassHeader() },
1960
1968
  timeout: 1e4
1961
1969
  },
1962
1970
  (res) => {
@@ -2111,7 +2119,7 @@ var CommandRelayService = class {
2111
2119
  port: url.port || (url.protocol === "https:" ? 443 : 80),
2112
2120
  path: `${url.pathname}${url.search}`,
2113
2121
  method: "GET",
2114
- headers: { Accept: "text/event-stream", "Cache-Control": "no-cache" },
2122
+ headers: { Accept: "text/event-stream", "Cache-Control": "no-cache", ...vercelBypassHeader() },
2115
2123
  timeout: 35e3
2116
2124
  },
2117
2125
  (res) => {
@@ -4832,8 +4840,17 @@ var AgentService = class {
4832
4840
  * the pre-batch (empty/previous) state → Enter submits nothing and the text
4833
4841
  * stays visible-but-unsubmitted in the input field.
4834
4842
  *
4835
- * Sending '\r' in a separate write() 50 ms later guarantees it arrives on
4843
+ * Sending '\r' in a separate write() ~50 ms later guarantees it arrives on
4836
4844
  * a fresh event-loop tick, after React has flushed the text into input state.
4845
+ *
4846
+ * The delay scales with line count: Smart Composer outputs are ~500–1500
4847
+ * chars with embedded `\n`s (Task / Context / Steps blocks). Ink's input
4848
+ * field re-flows multi-line content per render and the 50 ms baseline that
4849
+ * worked for single-line prompts isn't enough headroom — the text lands in
4850
+ * the field but `\r` submits stale state and the prompt sits there until
4851
+ * the user hits Enter manually. Adding ~40 ms per extra line (capped at
4852
+ * 300 ms) keeps short prompts snappy while giving multi-line composer
4853
+ * outputs the time they need to settle.
4837
4854
  */
4838
4855
  sendCommand(text) {
4839
4856
  if (!this.strategy) {
@@ -4848,7 +4865,9 @@ var AgentService = class {
4848
4865
  const s = this.strategy;
4849
4866
  log.trace("claude", `sendCommand text=${text.length}B`);
4850
4867
  s.write(text);
4851
- setTimeout(() => s.write("\r"), 50);
4868
+ const lineCount = text.split("\n").length;
4869
+ const delay = Math.min(300, 50 + (lineCount - 1) * 40);
4870
+ setTimeout(() => s.write("\r"), delay);
4852
4871
  }
4853
4872
  /**
4854
4873
  * Navigate a React Ink selector to the given 0-based target index and confirm.
@@ -6457,7 +6476,8 @@ var ChunkEmitter = class {
6457
6476
  // it can route legacy translations / 426 us when we're
6458
6477
  // too far behind. Bumped to 2.0.0 with the discriminated-
6459
6478
  // chunk + delta-chrome refactor in this release.
6460
- "X-Codeam-Protocol-Version": "2.0.0"
6479
+ "X-Codeam-Protocol-Version": "2.0.0",
6480
+ ...vercelBypassHeader()
6461
6481
  };
6462
6482
  if (opts.pluginAuthToken) {
6463
6483
  this.headers["X-Plugin-Auth-Token"] = opts.pluginAuthToken;
@@ -6972,7 +6992,8 @@ function post(endpoint, body) {
6972
6992
  method: "POST",
6973
6993
  headers: {
6974
6994
  "Content-Type": "application/json",
6975
- "Content-Length": Buffer.byteLength(payload)
6995
+ "Content-Length": Buffer.byteLength(payload),
6996
+ ...vercelBypassHeader()
6976
6997
  },
6977
6998
  timeout: 15e3
6978
6999
  },
@@ -8416,7 +8437,7 @@ async function claim(token, pluginId) {
8416
8437
  };
8417
8438
  const res = await fetch(url, {
8418
8439
  method: "POST",
8419
- headers: { "Content-Type": "application/json" },
8440
+ headers: { "Content-Type": "application/json", ...vercelBypassHeader() },
8420
8441
  body: JSON.stringify(body)
8421
8442
  });
8422
8443
  const json = await res.json();
@@ -10504,7 +10525,7 @@ async function stopWorkspaceFromLocal(target) {
10504
10525
  // src/commands/version.ts
10505
10526
  var import_picocolors11 = __toESM(require("picocolors"));
10506
10527
  function version() {
10507
- const v = true ? "2.12.16" : "unknown";
10528
+ const v = true ? "2.13.0" : "unknown";
10508
10529
  console.log(`${import_picocolors11.default.bold("codeam-cli")} ${import_picocolors11.default.cyan(v)}`);
10509
10530
  }
10510
10531
 
@@ -10513,24 +10534,28 @@ var import_picocolors12 = __toESM(require("picocolors"));
10513
10534
  function help() {
10514
10535
  const lines = [
10515
10536
  "",
10516
- ` ${import_picocolors12.default.bold(import_picocolors12.default.magenta("codeam-cli"))} ${import_picocolors12.default.dim("\u2014 Claude Code remote control")}`,
10537
+ ` ${import_picocolors12.default.bold(import_picocolors12.default.magenta("codeam-cli"))} ${import_picocolors12.default.dim("\u2014 remote-control AI coding agents from your phone")}`,
10517
10538
  "",
10518
10539
  ` ${import_picocolors12.default.bold("Usage")}`,
10519
10540
  ` ${import_picocolors12.default.cyan("codeam")} ${import_picocolors12.default.dim("[command]")}`,
10520
10541
  "",
10521
10542
  ` ${import_picocolors12.default.bold("Commands")}`,
10522
- ` ${import_picocolors12.default.white("codeam")} ${import_picocolors12.default.dim("start Claude Code with mobile control")}`,
10523
- ` ${import_picocolors12.default.white("codeam pair")} ${import_picocolors12.default.dim("pair a new mobile device")}`,
10524
- ` ${import_picocolors12.default.white("codeam sessions")} ${import_picocolors12.default.dim("list paired devices")}`,
10525
- ` ${import_picocolors12.default.white("codeam status")} ${import_picocolors12.default.dim("show connection info")}`,
10526
- ` ${import_picocolors12.default.white("codeam logout")} ${import_picocolors12.default.dim("remove all paired sessions")}`,
10527
- ` ${import_picocolors12.default.white("codeam deploy")} ${import_picocolors12.default.dim("provision a cloud workspace (Codespaces) and pair it")}`,
10528
- ` ${import_picocolors12.default.white("codeam deploy ls")} ${import_picocolors12.default.dim("list deployed cloud workspaces")}`,
10529
- ` ${import_picocolors12.default.white("codeam deploy stop")} ${import_picocolors12.default.dim("stop a deployed workspace session")}`,
10543
+ ` ${import_picocolors12.default.white("codeam")} ${import_picocolors12.default.dim("start the active agent with mobile control")}`,
10544
+ ` ${import_picocolors12.default.white("codeam <agent>")} ${import_picocolors12.default.dim("start a specific agent \u2014 e.g. claude, codex")}`,
10545
+ ` ${import_picocolors12.default.white("codeam pair")} ${import_picocolors12.default.dim("pair a new mobile device (interactive)")}`,
10546
+ ` ${import_picocolors12.default.white("codeam pair --agent <id>")} ${import_picocolors12.default.dim("pair non-interactively for a specific agent")}`,
10547
+ ` ${import_picocolors12.default.white("codeam sessions")} ${import_picocolors12.default.dim("list paired devices")}`,
10548
+ ` ${import_picocolors12.default.white("codeam sessions switch")} ${import_picocolors12.default.dim("switch the active paired session")}`,
10549
+ ` ${import_picocolors12.default.white("codeam sessions delete <id>")} ${import_picocolors12.default.dim("remove a specific paired session")}`,
10550
+ ` ${import_picocolors12.default.white("codeam status")} ${import_picocolors12.default.dim("show connection info")}`,
10551
+ ` ${import_picocolors12.default.white("codeam logout")} ${import_picocolors12.default.dim("remove all paired sessions")}`,
10552
+ ` ${import_picocolors12.default.white("codeam deploy")} ${import_picocolors12.default.dim("provision a cloud workspace (Codespaces) and pair it")}`,
10553
+ ` ${import_picocolors12.default.white("codeam deploy ls | list")} ${import_picocolors12.default.dim("list deployed cloud workspaces")}`,
10554
+ ` ${import_picocolors12.default.white("codeam deploy stop | remove")} ${import_picocolors12.default.dim("stop a deployed workspace session")}`,
10530
10555
  "",
10531
10556
  ` ${import_picocolors12.default.bold("Flags")}`,
10532
- ` ${import_picocolors12.default.white("-v, --version")} ${import_picocolors12.default.dim("print the CLI version")}`,
10533
- ` ${import_picocolors12.default.white("-h, --help")} ${import_picocolors12.default.dim("show this help")}`,
10557
+ ` ${import_picocolors12.default.white("-v, --version")} ${import_picocolors12.default.dim("print the CLI version")}`,
10558
+ ` ${import_picocolors12.default.white("-h, --help")} ${import_picocolors12.default.dim("show this help")}`,
10534
10559
  "",
10535
10560
  ` ${import_picocolors12.default.bold("Links")}`,
10536
10561
  ` ${import_picocolors12.default.dim("Docs:")} ${import_picocolors12.default.green("https://www.codeagent-mobile.com")}`,
@@ -10639,7 +10664,7 @@ function checkForUpdates() {
10639
10664
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
10640
10665
  if (process.env.CI) return;
10641
10666
  if (!process.stdout.isTTY) return;
10642
- const current = true ? "2.12.16" : null;
10667
+ const current = true ? "2.13.0" : null;
10643
10668
  if (!current) return;
10644
10669
  const cache = readCache();
10645
10670
  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.12.16",
3
+ "version": "2.13.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",