codeam-cli 2.4.2 → 2.4.4
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 +18 -0
- package/dist/index.js +77 -18
- package/package.json +1 -1
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.4.2] — 2026-05-03
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Codespace machine picker + auto-install gh; deploy doc (v2.4.2)
|
|
12
|
+
|
|
13
|
+
## [2.4.1] — 2026-05-03
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **cli:** Interactive `claude login` fallback when no local config (v2.4.1)
|
|
18
|
+
|
|
19
|
+
## [2.4.0] — 2026-05-03
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **cli:** `codeam deploy` — provision a paired cloud workspace in one command (v2.4.0)
|
|
24
|
+
|
|
7
25
|
## [2.2.2] — 2026-05-02
|
|
8
26
|
|
|
9
27
|
### Fixed
|
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.
|
|
182
|
+
version: "2.4.4",
|
|
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: {
|
|
@@ -5088,6 +5088,14 @@ var import_util2 = require("util");
|
|
|
5088
5088
|
var import_picocolors7 = __toESM(require("picocolors"));
|
|
5089
5089
|
var execFileP2 = (0, import_util2.promisify)(import_child_process5.execFile);
|
|
5090
5090
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
5091
|
+
function resetStdinForChild() {
|
|
5092
|
+
if (process.stdin.isTTY) {
|
|
5093
|
+
try {
|
|
5094
|
+
process.stdin.setRawMode(false);
|
|
5095
|
+
} catch {
|
|
5096
|
+
}
|
|
5097
|
+
}
|
|
5098
|
+
}
|
|
5091
5099
|
var GitHubCodespacesProvider = class {
|
|
5092
5100
|
id = "github-codespaces";
|
|
5093
5101
|
displayName = "GitHub Codespaces";
|
|
@@ -5113,21 +5121,72 @@ var GitHubCodespacesProvider = class {
|
|
|
5113
5121
|
);
|
|
5114
5122
|
}
|
|
5115
5123
|
}
|
|
5124
|
+
let isAuthed = false;
|
|
5116
5125
|
try {
|
|
5117
5126
|
await execFileP2("gh", ["auth", "status"], { maxBuffer: MAX_BUFFER });
|
|
5118
|
-
|
|
5127
|
+
isAuthed = true;
|
|
5119
5128
|
} catch {
|
|
5120
5129
|
}
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5130
|
+
if (!isAuthed) {
|
|
5131
|
+
resetStdinForChild();
|
|
5132
|
+
await new Promise((resolve2, reject) => {
|
|
5133
|
+
const proc = (0, import_child_process5.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
|
|
5134
|
+
stdio: "inherit"
|
|
5135
|
+
});
|
|
5136
|
+
proc.on("exit", (code) => {
|
|
5137
|
+
if (code === 0) resolve2();
|
|
5138
|
+
else reject(new Error("gh auth login failed."));
|
|
5139
|
+
});
|
|
5140
|
+
proc.on("error", reject);
|
|
5124
5141
|
});
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5142
|
+
return;
|
|
5143
|
+
}
|
|
5144
|
+
const hasScope = await this.hasCodespaceScope();
|
|
5145
|
+
if (!hasScope) {
|
|
5146
|
+
wt(
|
|
5147
|
+
[
|
|
5148
|
+
"Your existing GitHub login is missing the `codespace` scope.",
|
|
5149
|
+
"I'll run `gh auth refresh` to add it \u2014 your browser will open",
|
|
5150
|
+
"for a one-tap approval."
|
|
5151
|
+
].join("\n"),
|
|
5152
|
+
"One more permission needed"
|
|
5153
|
+
);
|
|
5154
|
+
resetStdinForChild();
|
|
5155
|
+
await new Promise((resolve2, reject) => {
|
|
5156
|
+
const proc = (0, import_child_process5.spawn)(
|
|
5157
|
+
"gh",
|
|
5158
|
+
["auth", "refresh", "-h", "github.com", "-s", "codespace"],
|
|
5159
|
+
{ stdio: "inherit" }
|
|
5160
|
+
);
|
|
5161
|
+
proc.on("exit", (code) => {
|
|
5162
|
+
if (code === 0) resolve2();
|
|
5163
|
+
else reject(new Error("gh auth refresh failed \u2014 re-run `gh auth refresh -h github.com -s codespace` manually."));
|
|
5164
|
+
});
|
|
5165
|
+
proc.on("error", reject);
|
|
5128
5166
|
});
|
|
5129
|
-
|
|
5130
|
-
|
|
5167
|
+
}
|
|
5168
|
+
}
|
|
5169
|
+
/**
|
|
5170
|
+
* Check whether the current `gh` token includes the `codespace`
|
|
5171
|
+
* OAuth scope. We hit `/user` with `-i` so GitHub echoes the granted
|
|
5172
|
+
* scopes back in the `X-OAuth-Scopes` response header — the most
|
|
5173
|
+
* authoritative source (more reliable than scraping `gh auth status`,
|
|
5174
|
+
* whose format has shifted across `gh` versions).
|
|
5175
|
+
*/
|
|
5176
|
+
async hasCodespaceScope() {
|
|
5177
|
+
try {
|
|
5178
|
+
const { stdout } = await execFileP2(
|
|
5179
|
+
"gh",
|
|
5180
|
+
["api", "-i", "user"],
|
|
5181
|
+
{ maxBuffer: MAX_BUFFER }
|
|
5182
|
+
);
|
|
5183
|
+
const m = stdout.match(/^x-oauth-scopes:\s*(.+)$/im);
|
|
5184
|
+
if (!m) return false;
|
|
5185
|
+
const scopes = m[1].split(",").map((s) => s.trim().toLowerCase());
|
|
5186
|
+
return scopes.includes("codespace");
|
|
5187
|
+
} catch {
|
|
5188
|
+
return false;
|
|
5189
|
+
}
|
|
5131
5190
|
}
|
|
5132
5191
|
/**
|
|
5133
5192
|
* Try to install the `gh` CLI for the user. Opt-in via a confirm
|
|
@@ -5208,15 +5267,15 @@ var GitHubCodespacesProvider = class {
|
|
|
5208
5267
|
initialValue: true
|
|
5209
5268
|
});
|
|
5210
5269
|
if (q(proceed) || !proceed) return;
|
|
5211
|
-
|
|
5212
|
-
|
|
5270
|
+
O2.step(`Installing gh via ${installCmd.describe}\u2026`);
|
|
5271
|
+
resetStdinForChild();
|
|
5213
5272
|
const ok = await new Promise((resolve2) => {
|
|
5214
5273
|
const proc = (0, import_child_process5.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
|
|
5215
5274
|
proc.on("exit", (code) => resolve2(code === 0));
|
|
5216
5275
|
proc.on("error", () => resolve2(false));
|
|
5217
5276
|
});
|
|
5218
|
-
if (ok)
|
|
5219
|
-
else
|
|
5277
|
+
if (ok) O2.success("gh installed");
|
|
5278
|
+
else O2.error("gh install failed");
|
|
5220
5279
|
}
|
|
5221
5280
|
async listProjects() {
|
|
5222
5281
|
const { stdout } = await execFileP2(
|
|
@@ -5357,6 +5416,7 @@ var GitHubCodespacesProvider = class {
|
|
|
5357
5416
|
}
|
|
5358
5417
|
}
|
|
5359
5418
|
async streamCommand(workspaceId, command2) {
|
|
5419
|
+
resetStdinForChild();
|
|
5360
5420
|
return new Promise((resolve2, reject) => {
|
|
5361
5421
|
const proc = (0, import_child_process5.spawn)(
|
|
5362
5422
|
"gh",
|
|
@@ -5394,13 +5454,12 @@ async function deploy() {
|
|
|
5394
5454
|
pt("No provider selected.");
|
|
5395
5455
|
process.exit(0);
|
|
5396
5456
|
}
|
|
5397
|
-
|
|
5398
|
-
authStep.start(`Authorizing with ${provider.displayName}\u2026`);
|
|
5457
|
+
O2.step(`Authorizing with ${provider.displayName}\u2026`);
|
|
5399
5458
|
try {
|
|
5400
5459
|
await provider.authorize();
|
|
5401
|
-
|
|
5460
|
+
O2.success(`Authorized with ${provider.displayName}`);
|
|
5402
5461
|
} catch (err) {
|
|
5403
|
-
|
|
5462
|
+
O2.error("Authorization failed");
|
|
5404
5463
|
pt(err instanceof Error ? err.message : String(err));
|
|
5405
5464
|
process.exit(1);
|
|
5406
5465
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.4",
|
|
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": {
|