codeam-cli 2.4.21 → 2.4.23

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,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.4.21] — 2026-05-03
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Only run keep-alive heartbeat inside a Codespace (v2.4.21)
12
+
13
+ ## [2.4.20] — 2026-05-03
14
+
15
+ ### Added
16
+
17
+ - **cli:** Handle set_keep_alive command from apps' Settings modal (v2.4.20)
18
+
7
19
  ## [2.4.19] — 2026-05-03
8
20
 
9
21
  ### Added
package/dist/index.js CHANGED
@@ -179,7 +179,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
179
179
  // package.json
180
180
  var package_default = {
181
181
  name: "codeam-cli",
182
- version: "2.4.21",
182
+ version: "2.4.23",
183
183
  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.",
184
184
  main: "dist/index.js",
185
185
  bin: {
@@ -2793,6 +2793,18 @@ except Exception:sys.exit(0)
2793
2793
  claude.kill();
2794
2794
  } catch {
2795
2795
  }
2796
+ const codespaceName = process.env.CODESPACE_NAME;
2797
+ if (codespaceName && process.env.CODESPACES === "true") {
2798
+ try {
2799
+ const stopProc = (0, import_child_process4.spawn)(
2800
+ "bash",
2801
+ ["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(codespaceName)} >/dev/null 2>&1 || true`],
2802
+ { detached: true, stdio: "ignore" }
2803
+ );
2804
+ stopProc.unref();
2805
+ } catch {
2806
+ }
2807
+ }
2796
2808
  try {
2797
2809
  const proc = (0, import_child_process4.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
2798
2810
  detached: true,
@@ -5383,6 +5395,40 @@ var GitHubCodespacesProvider = class {
5383
5395
  if (ok) O2.success("gh installed");
5384
5396
  else O2.error("gh install failed");
5385
5397
  }
5398
+ /**
5399
+ * Re-run `gh auth refresh` with broader scopes so `gh repo list`
5400
+ * can return repos in orgs the user belongs to (and team repos
5401
+ * accessible via membership). The default codespace scope set
5402
+ * (`codespace,repo,read:user`) already covers the user's own
5403
+ * repos and most personal collaborator repos, but org repos and
5404
+ * private team repos require `read:org`. We add `read:org` here
5405
+ * and re-issue.
5406
+ */
5407
+ async expandListScopes() {
5408
+ wt(
5409
+ [
5410
+ "We'll re-authorize `gh` with broader scopes so org and team",
5411
+ "repositories show up in the list. A browser will open for",
5412
+ "a one-tap approval."
5413
+ ].join("\n"),
5414
+ "Expanding GitHub scopes"
5415
+ );
5416
+ resetStdinForChild();
5417
+ await new Promise((resolve2, reject) => {
5418
+ const proc = (0, import_child_process5.spawn)(
5419
+ "gh",
5420
+ ["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
5421
+ { stdio: "inherit" }
5422
+ );
5423
+ proc.on("exit", (code) => {
5424
+ if (code === 0) resolve2();
5425
+ else reject(new Error(
5426
+ "gh auth refresh failed. Re-run `gh auth refresh -h github.com -s repo,read:org` manually."
5427
+ ));
5428
+ });
5429
+ proc.on("error", reject);
5430
+ });
5431
+ }
5386
5432
  async listProjects() {
5387
5433
  const { stdout } = await execFileP2(
5388
5434
  "gh",
@@ -5674,34 +5720,54 @@ async function deploy() {
5674
5720
  pt(err instanceof Error ? err.message : String(err));
5675
5721
  process.exit(1);
5676
5722
  }
5677
- const listStep = fe();
5678
- listStep.start("Loading your projects\u2026");
5679
- let projects = [];
5680
- try {
5681
- projects = await provider.listProjects();
5682
- listStep.stop(`\u2713 ${projects.length} project${projects.length === 1 ? "" : "s"} available`);
5683
- } catch (err) {
5684
- listStep.stop(`\u2717 Could not list projects`);
5685
- pt(err instanceof Error ? err.message : String(err));
5686
- process.exit(1);
5687
- }
5688
- if (projects.length === 0) {
5689
- pt("No projects found on the account.");
5690
- process.exit(0);
5691
- }
5692
- const projectId = await _t({
5693
- message: "Select a project to deploy:",
5694
- options: projects.slice(0, 50).map((proj) => ({
5723
+ const EXPAND_SCOPES = "__expand_scopes__";
5724
+ let project = null;
5725
+ while (!project) {
5726
+ const listStep = fe();
5727
+ listStep.start("Loading your projects\u2026");
5728
+ let projects = [];
5729
+ try {
5730
+ projects = await provider.listProjects();
5731
+ listStep.stop(`\u2713 ${projects.length} project${projects.length === 1 ? "" : "s"} available`);
5732
+ } catch (err) {
5733
+ listStep.stop(`\u2717 Could not list projects`);
5734
+ pt(err instanceof Error ? err.message : String(err));
5735
+ process.exit(1);
5736
+ }
5737
+ const options = projects.slice(0, 50).map((proj) => ({
5695
5738
  value: proj.id,
5696
5739
  label: proj.fullName,
5697
5740
  hint: proj.description ? proj.description.slice(0, 80) : proj.private ? "private" : "public"
5698
- }))
5699
- });
5700
- if (q(projectId) || typeof projectId !== "string") {
5701
- pt("Cancelled.");
5702
- process.exit(0);
5741
+ }));
5742
+ if (provider.expandListScopes) {
5743
+ options.push({
5744
+ value: EXPAND_SCOPES,
5745
+ label: import_picocolors8.default.cyan("+ Don't see your project? Expand scopes\u2026"),
5746
+ hint: "Re-authorize with broader scopes (org / team repos)"
5747
+ });
5748
+ }
5749
+ if (options.length === 0) {
5750
+ pt("No projects found on the account.");
5751
+ process.exit(0);
5752
+ }
5753
+ const projectId = await _t({
5754
+ message: "Select a project to deploy:",
5755
+ options
5756
+ });
5757
+ if (q(projectId) || typeof projectId !== "string") {
5758
+ pt("Cancelled.");
5759
+ process.exit(0);
5760
+ }
5761
+ if (projectId === EXPAND_SCOPES) {
5762
+ try {
5763
+ await provider.expandListScopes();
5764
+ } catch (err) {
5765
+ O2.warn(err instanceof Error ? err.message : String(err));
5766
+ }
5767
+ continue;
5768
+ }
5769
+ project = projects.find((proj) => proj.id === projectId) ?? null;
5703
5770
  }
5704
- const project = projects.find((proj) => proj.id === projectId);
5705
5771
  let workspace = null;
5706
5772
  if (provider.listExistingWorkspaces && provider.startWorkspace) {
5707
5773
  const existingStep = fe();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.4.21",
3
+ "version": "2.4.23",
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
  "main": "dist/index.js",
6
6
  "bin": {