codeam-cli 2.4.0 → 2.4.2
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/README.md +22 -0
- package/dist/index.js +248 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,28 @@ That's it. Open the [CodeAgent Mobile app](https://codeagent-mobile.com), enter
|
|
|
46
46
|
| `codeam sessions` | List all paired devices |
|
|
47
47
|
| `codeam status` | Show connection status |
|
|
48
48
|
| `codeam logout` | Remove all paired sessions |
|
|
49
|
+
| `codeam deploy` | Provision a cloud workspace (GitHub Codespaces) and pair it to your phone |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## `codeam deploy` — drive a cloud workspace from your phone
|
|
54
|
+
|
|
55
|
+
Don't want to keep your laptop running while you control Claude from the train? `codeam deploy` spins up a fresh **GitHub Codespace** for any of your repos, installs Claude Code + `codeam-cli` inside it, copies your local Claude credentials so you skip the re-auth (or runs `claude login` interactively if you don't have a local config yet), and finishes by streaming `codeam pair` from inside the codespace — so you get a pairing code on this terminal already wired to the remote workspace.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
codeam deploy
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
That's it. You'll be guided through:
|
|
62
|
+
|
|
63
|
+
1. **Pick a provider** (GitHub Codespaces today; more coming).
|
|
64
|
+
2. **Pick a repo** from your account.
|
|
65
|
+
3. **Wait ~1 minute** while the codespace boots and tools install.
|
|
66
|
+
4. **Scan the QR / enter the code** on the CodeAgent Mobile app — same flow as `codeam pair`, only the agent is now running in the cloud.
|
|
67
|
+
|
|
68
|
+
Requirements: the [GitHub CLI (`gh`)](https://cli.github.com/) installed and authenticated (`gh auth login`). The deploy flow re-uses `gh`'s OAuth — we don't ask for a separate token.
|
|
69
|
+
|
|
70
|
+
Adding more cloud backends (Gitpod, Coder, your own SSH host, …) is a single new file in `apps/cli/src/services/providers/` — the `CloudProvider` interface keeps it pluggable.
|
|
49
71
|
|
|
50
72
|
---
|
|
51
73
|
|
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.2",
|
|
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: {
|
|
@@ -5080,11 +5080,12 @@ async function logout() {
|
|
|
5080
5080
|
var fs8 = __toESM(require("fs"));
|
|
5081
5081
|
var os6 = __toESM(require("os"));
|
|
5082
5082
|
var path8 = __toESM(require("path"));
|
|
5083
|
-
var
|
|
5083
|
+
var import_picocolors8 = __toESM(require("picocolors"));
|
|
5084
5084
|
|
|
5085
5085
|
// src/services/providers/github-codespaces.ts
|
|
5086
5086
|
var import_child_process5 = require("child_process");
|
|
5087
5087
|
var import_util2 = require("util");
|
|
5088
|
+
var import_picocolors7 = __toESM(require("picocolors"));
|
|
5088
5089
|
var execFileP2 = (0, import_util2.promisify)(import_child_process5.execFile);
|
|
5089
5090
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
5090
5091
|
var GitHubCodespacesProvider = class {
|
|
@@ -5096,16 +5097,21 @@ var GitHubCodespacesProvider = class {
|
|
|
5096
5097
|
try {
|
|
5097
5098
|
await execFileP2("gh", ["--version"], { maxBuffer: MAX_BUFFER });
|
|
5098
5099
|
} catch {
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5100
|
+
await this.tryInstallGh();
|
|
5101
|
+
try {
|
|
5102
|
+
await execFileP2("gh", ["--version"], { maxBuffer: MAX_BUFFER });
|
|
5103
|
+
} catch {
|
|
5104
|
+
throw new Error(
|
|
5105
|
+
[
|
|
5106
|
+
"GitHub CLI (`gh`) is still not on PATH.",
|
|
5107
|
+
"Install it manually with:",
|
|
5108
|
+
" \u2022 macOS: brew install gh",
|
|
5109
|
+
" \u2022 Linux: https://github.com/cli/cli/blob/trunk/docs/install_linux.md",
|
|
5110
|
+
" \u2022 Windows: winget install --id GitHub.cli",
|
|
5111
|
+
"Then run `codeam deploy` again."
|
|
5112
|
+
].join("\n")
|
|
5113
|
+
);
|
|
5114
|
+
}
|
|
5109
5115
|
}
|
|
5110
5116
|
try {
|
|
5111
5117
|
await execFileP2("gh", ["auth", "status"], { maxBuffer: MAX_BUFFER });
|
|
@@ -5123,6 +5129,95 @@ var GitHubCodespacesProvider = class {
|
|
|
5123
5129
|
proc.on("error", reject);
|
|
5124
5130
|
});
|
|
5125
5131
|
}
|
|
5132
|
+
/**
|
|
5133
|
+
* Try to install the `gh` CLI for the user. Opt-in via a confirm
|
|
5134
|
+
* prompt — we never run `brew` / `winget` / `apt` without explicit
|
|
5135
|
+
* consent. Strategy per platform:
|
|
5136
|
+
*
|
|
5137
|
+
* - macOS: `brew install gh` (requires Homebrew)
|
|
5138
|
+
* - Windows: `winget install --id GitHub.cli -e --silent`
|
|
5139
|
+
* - Linux: too many distros / package managers to be safe; we
|
|
5140
|
+
* point the user at the official install doc instead.
|
|
5141
|
+
*
|
|
5142
|
+
* Stdio is inherited so any sudo / authentication prompt the package
|
|
5143
|
+
* manager surfaces (e.g. macOS keychain, Windows UAC) lands in this
|
|
5144
|
+
* terminal. On failure or an unsupported platform we just return —
|
|
5145
|
+
* the caller will re-check `gh --version` and surface the manual-
|
|
5146
|
+
* install error if it's still missing.
|
|
5147
|
+
*/
|
|
5148
|
+
async tryInstallGh() {
|
|
5149
|
+
const platform = process.platform;
|
|
5150
|
+
wt(
|
|
5151
|
+
`GitHub CLI (${import_picocolors7.default.cyan("gh")}) is required for Codespaces deploys but isn't on your PATH.`,
|
|
5152
|
+
"Heads up"
|
|
5153
|
+
);
|
|
5154
|
+
if (platform === "linux") {
|
|
5155
|
+
wt(
|
|
5156
|
+
[
|
|
5157
|
+
"On Linux, please install gh from the official guide:",
|
|
5158
|
+
" https://github.com/cli/cli/blob/trunk/docs/install_linux.md",
|
|
5159
|
+
"Re-run `codeam deploy` once it is on your PATH."
|
|
5160
|
+
].join("\n"),
|
|
5161
|
+
"Install gh on Linux"
|
|
5162
|
+
);
|
|
5163
|
+
return;
|
|
5164
|
+
}
|
|
5165
|
+
let installCmd = null;
|
|
5166
|
+
if (platform === "darwin") {
|
|
5167
|
+
try {
|
|
5168
|
+
await execFileP2("brew", ["--version"], { maxBuffer: MAX_BUFFER });
|
|
5169
|
+
} catch {
|
|
5170
|
+
wt(
|
|
5171
|
+
[
|
|
5172
|
+
"Homebrew (`brew`) is not installed.",
|
|
5173
|
+
"Install it from https://brew.sh and re-run `codeam deploy`,",
|
|
5174
|
+
"or install gh manually: https://cli.github.com/"
|
|
5175
|
+
].join("\n"),
|
|
5176
|
+
"Cannot auto-install on macOS"
|
|
5177
|
+
);
|
|
5178
|
+
return;
|
|
5179
|
+
}
|
|
5180
|
+
installCmd = {
|
|
5181
|
+
exe: "brew",
|
|
5182
|
+
args: ["install", "gh"],
|
|
5183
|
+
describe: "brew install gh"
|
|
5184
|
+
};
|
|
5185
|
+
} else if (platform === "win32") {
|
|
5186
|
+
try {
|
|
5187
|
+
await execFileP2("winget", ["--version"], { maxBuffer: MAX_BUFFER });
|
|
5188
|
+
} catch {
|
|
5189
|
+
wt(
|
|
5190
|
+
[
|
|
5191
|
+
"winget is not available on this machine.",
|
|
5192
|
+
"Install gh manually: https://github.com/cli/cli/releases/latest"
|
|
5193
|
+
].join("\n"),
|
|
5194
|
+
"Cannot auto-install on Windows"
|
|
5195
|
+
);
|
|
5196
|
+
return;
|
|
5197
|
+
}
|
|
5198
|
+
installCmd = {
|
|
5199
|
+
exe: "winget",
|
|
5200
|
+
args: ["install", "--id", "GitHub.cli", "-e", "--silent"],
|
|
5201
|
+
describe: "winget install --id GitHub.cli"
|
|
5202
|
+
};
|
|
5203
|
+
} else {
|
|
5204
|
+
return;
|
|
5205
|
+
}
|
|
5206
|
+
const proceed = await ot2({
|
|
5207
|
+
message: `Run ${import_picocolors7.default.cyan(installCmd.describe)} now?`,
|
|
5208
|
+
initialValue: true
|
|
5209
|
+
});
|
|
5210
|
+
if (q(proceed) || !proceed) return;
|
|
5211
|
+
const installStep = fe();
|
|
5212
|
+
installStep.start(`Installing gh via ${installCmd.describe}\u2026`);
|
|
5213
|
+
const ok = await new Promise((resolve2) => {
|
|
5214
|
+
const proc = (0, import_child_process5.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
|
|
5215
|
+
proc.on("exit", (code) => resolve2(code === 0));
|
|
5216
|
+
proc.on("error", () => resolve2(false));
|
|
5217
|
+
});
|
|
5218
|
+
if (ok) installStep.stop("\u2713 gh installed");
|
|
5219
|
+
else installStep.stop("\u2717 gh install failed");
|
|
5220
|
+
}
|
|
5126
5221
|
async listProjects() {
|
|
5127
5222
|
const { stdout } = await execFileP2(
|
|
5128
5223
|
"gh",
|
|
@@ -5146,10 +5241,51 @@ var GitHubCodespacesProvider = class {
|
|
|
5146
5241
|
private: !!r.isPrivate
|
|
5147
5242
|
}));
|
|
5148
5243
|
}
|
|
5149
|
-
|
|
5244
|
+
/**
|
|
5245
|
+
* Return the machine types available to the user for this repo. The
|
|
5246
|
+
* `gh api /repos/.../codespaces/machines` endpoint reports CPU / RAM /
|
|
5247
|
+
* storage, so we hand all three to the picker for a clean label.
|
|
5248
|
+
*
|
|
5249
|
+
* We filter out anything below 8 GB RAM — Claude Code wants headroom
|
|
5250
|
+
* for `tsc`, build tools, and parallel test runners; the 4 GB tier
|
|
5251
|
+
* (when available) is too tight in practice.
|
|
5252
|
+
*/
|
|
5253
|
+
async listMachineTypes(projectId) {
|
|
5254
|
+
try {
|
|
5255
|
+
const { stdout } = await execFileP2(
|
|
5256
|
+
"gh",
|
|
5257
|
+
["api", `/repos/${projectId}/codespaces/machines`],
|
|
5258
|
+
{ maxBuffer: MAX_BUFFER }
|
|
5259
|
+
);
|
|
5260
|
+
const data = JSON.parse(stdout);
|
|
5261
|
+
const machines = data.machines ?? [];
|
|
5262
|
+
const GB = 1024 ** 3;
|
|
5263
|
+
return machines.map((m) => {
|
|
5264
|
+
const memoryGb = m.memory_in_bytes ? Math.round(m.memory_in_bytes / GB) : 0;
|
|
5265
|
+
const storageGb = m.storage_in_bytes ? Math.round(m.storage_in_bytes / GB) : void 0;
|
|
5266
|
+
const parts = [];
|
|
5267
|
+
if (m.cpus) parts.push(`${m.cpus} ${m.cpus === 1 ? "core" : "cores"}`);
|
|
5268
|
+
if (memoryGb) parts.push(`${memoryGb} GB RAM`);
|
|
5269
|
+
if (storageGb) parts.push(`${storageGb} GB storage`);
|
|
5270
|
+
return {
|
|
5271
|
+
id: m.name,
|
|
5272
|
+
label: m.display_name ?? (parts.join(" \xB7 ") || m.name),
|
|
5273
|
+
memoryGb,
|
|
5274
|
+
cpus: m.cpus,
|
|
5275
|
+
storageGb
|
|
5276
|
+
};
|
|
5277
|
+
}).filter((m) => m.memoryGb >= 8).sort((a, b) => a.memoryGb - b.memoryGb || (a.cpus ?? 0) - (b.cpus ?? 0));
|
|
5278
|
+
} catch {
|
|
5279
|
+
return [];
|
|
5280
|
+
}
|
|
5281
|
+
}
|
|
5282
|
+
async createWorkspace(projectId, machineTypeId) {
|
|
5283
|
+
const machine = machineTypeId ?? await this.pickDefaultMachine(projectId);
|
|
5284
|
+
const args2 = ["codespace", "create", "-R", projectId, "--default-permissions"];
|
|
5285
|
+
if (machine) args2.push("-m", machine);
|
|
5150
5286
|
const { stdout } = await execFileP2(
|
|
5151
5287
|
"gh",
|
|
5152
|
-
|
|
5288
|
+
args2,
|
|
5153
5289
|
{ maxBuffer: MAX_BUFFER, timeout: 12e4 }
|
|
5154
5290
|
);
|
|
5155
5291
|
const name = stdout.trim().split("\n").filter(Boolean).pop() ?? "";
|
|
@@ -5163,6 +5299,27 @@ var GitHubCodespacesProvider = class {
|
|
|
5163
5299
|
webUrl: `https://github.com/codespaces/${name}`
|
|
5164
5300
|
};
|
|
5165
5301
|
}
|
|
5302
|
+
/**
|
|
5303
|
+
* Fallback machine picker for when the orchestrator didn't ask the
|
|
5304
|
+
* user — defaults to the cheapest 8 GB tier (`basicLinux32gb`) and
|
|
5305
|
+
* walks up only if the repo restricts that tier. Returns `null` if
|
|
5306
|
+
* the API call fails entirely; the caller will then omit `-m` and
|
|
5307
|
+
* let `gh` use the repo/org default.
|
|
5308
|
+
*/
|
|
5309
|
+
async pickDefaultMachine(projectId) {
|
|
5310
|
+
const machines = await this.listMachineTypes(projectId);
|
|
5311
|
+
if (machines.length === 0) return null;
|
|
5312
|
+
const preferenceOrder = [
|
|
5313
|
+
"basicLinux32gb",
|
|
5314
|
+
"standardLinux32gb",
|
|
5315
|
+
"premiumLinux",
|
|
5316
|
+
"largePremiumLinux"
|
|
5317
|
+
];
|
|
5318
|
+
for (const pref of preferenceOrder) {
|
|
5319
|
+
if (machines.some((m) => m.id === pref)) return pref;
|
|
5320
|
+
}
|
|
5321
|
+
return machines[0].id;
|
|
5322
|
+
}
|
|
5166
5323
|
async waitUntilAvailable(name) {
|
|
5167
5324
|
const deadline = Date.now() + 5 * 60 * 1e3;
|
|
5168
5325
|
while (Date.now() < deadline) {
|
|
@@ -5231,7 +5388,7 @@ var PROVIDERS = [
|
|
|
5231
5388
|
// src/commands/deploy.ts
|
|
5232
5389
|
async function deploy() {
|
|
5233
5390
|
console.log();
|
|
5234
|
-
mt(
|
|
5391
|
+
mt(import_picocolors8.default.bgMagenta(import_picocolors8.default.white(" codeam deploy ")));
|
|
5235
5392
|
const provider = await pickProvider();
|
|
5236
5393
|
if (!provider) {
|
|
5237
5394
|
pt("No provider selected.");
|
|
@@ -5275,11 +5432,43 @@ async function deploy() {
|
|
|
5275
5432
|
process.exit(0);
|
|
5276
5433
|
}
|
|
5277
5434
|
const project = projects.find((proj) => proj.id === projectId);
|
|
5435
|
+
let machineTypeId;
|
|
5436
|
+
if (provider.listMachineTypes) {
|
|
5437
|
+
const machineStep = fe();
|
|
5438
|
+
machineStep.start("Loading machine types\u2026");
|
|
5439
|
+
let machines = [];
|
|
5440
|
+
try {
|
|
5441
|
+
machines = await provider.listMachineTypes(project.id);
|
|
5442
|
+
machineStep.stop(
|
|
5443
|
+
machines.length > 0 ? `\u2713 ${machines.length} machine type${machines.length === 1 ? "" : "s"} available` : "\xB7 No machine types reported (using provider default)"
|
|
5444
|
+
);
|
|
5445
|
+
} catch {
|
|
5446
|
+
machineStep.stop("\xB7 Could not list machine types \u2014 using provider default");
|
|
5447
|
+
}
|
|
5448
|
+
if (machines.length > 1) {
|
|
5449
|
+
const picked = await _t({
|
|
5450
|
+
message: "Pick a machine size (starts at 8 GB RAM):",
|
|
5451
|
+
initialValue: machines[0].id,
|
|
5452
|
+
options: machines.map((m) => ({
|
|
5453
|
+
value: m.id,
|
|
5454
|
+
label: m.label,
|
|
5455
|
+
hint: `${m.memoryGb} GB RAM`
|
|
5456
|
+
}))
|
|
5457
|
+
});
|
|
5458
|
+
if (q(picked)) {
|
|
5459
|
+
pt("Cancelled.");
|
|
5460
|
+
process.exit(0);
|
|
5461
|
+
}
|
|
5462
|
+
machineTypeId = picked;
|
|
5463
|
+
} else if (machines.length === 1) {
|
|
5464
|
+
machineTypeId = machines[0].id;
|
|
5465
|
+
}
|
|
5466
|
+
}
|
|
5278
5467
|
const createStep = fe();
|
|
5279
5468
|
createStep.start(`Creating workspace for ${project.fullName}\u2026`);
|
|
5280
5469
|
let workspace;
|
|
5281
5470
|
try {
|
|
5282
|
-
workspace = await provider.createWorkspace(project.id);
|
|
5471
|
+
workspace = await provider.createWorkspace(project.id, machineTypeId);
|
|
5283
5472
|
createStep.stop(`\u2713 Workspace ready: ${workspace.displayName ?? workspace.id}`);
|
|
5284
5473
|
} catch (err) {
|
|
5285
5474
|
createStep.stop(`\u2717 Workspace creation failed`);
|
|
@@ -5299,21 +5488,36 @@ async function deploy() {
|
|
|
5299
5488
|
}
|
|
5300
5489
|
claudeStep.stop("\u2713 Claude CLI installed");
|
|
5301
5490
|
const localClaudeDir = path8.join(os6.homedir(), ".claude");
|
|
5302
|
-
|
|
5491
|
+
const haveLocalClaude = fs8.existsSync(localClaudeDir) && fs8.statSync(localClaudeDir).isDirectory();
|
|
5492
|
+
if (haveLocalClaude) {
|
|
5303
5493
|
const copyStep = fe();
|
|
5304
5494
|
copyStep.start("Copying local Claude config to workspace\u2026");
|
|
5305
5495
|
try {
|
|
5306
5496
|
await provider.uploadDirectory(workspace.id, localClaudeDir, "/home/codespace/.claude");
|
|
5307
5497
|
copyStep.stop("\u2713 Claude config copied \u2014 no re-auth needed");
|
|
5308
5498
|
} catch (err) {
|
|
5309
|
-
copyStep.stop("\u26A0 Could not copy Claude config \u2014
|
|
5499
|
+
copyStep.stop("\u26A0 Could not copy Claude config \u2014 falling back to remote login");
|
|
5310
5500
|
void err;
|
|
5501
|
+
await runRemoteClaudeLogin(provider, workspace.id);
|
|
5311
5502
|
}
|
|
5312
5503
|
} else {
|
|
5313
5504
|
wt(
|
|
5314
|
-
|
|
5315
|
-
|
|
5505
|
+
[
|
|
5506
|
+
"No local ~/.claude config found.",
|
|
5507
|
+
"We can run `claude login` inside the workspace right now \u2014 the URL",
|
|
5508
|
+
"will print here, you open it in your browser, paste the code back,",
|
|
5509
|
+
"and the workspace gets authenticated. (Skip if you'd rather do it",
|
|
5510
|
+
"manually later from inside the codespace.)"
|
|
5511
|
+
].join("\n"),
|
|
5512
|
+
"Claude credentials"
|
|
5316
5513
|
);
|
|
5514
|
+
const proceed = await ot2({
|
|
5515
|
+
message: "Run `claude login` on the workspace now?",
|
|
5516
|
+
initialValue: true
|
|
5517
|
+
});
|
|
5518
|
+
if (!q(proceed) && proceed) {
|
|
5519
|
+
await runRemoteClaudeLogin(provider, workspace.id);
|
|
5520
|
+
}
|
|
5317
5521
|
}
|
|
5318
5522
|
const cliStep = fe();
|
|
5319
5523
|
cliStep.start("Installing codeam-cli on workspace\u2026");
|
|
@@ -5326,8 +5530,8 @@ async function deploy() {
|
|
|
5326
5530
|
cliStep.stop("\u2713 codeam-cli installed");
|
|
5327
5531
|
wt(
|
|
5328
5532
|
[
|
|
5329
|
-
`Workspace: ${
|
|
5330
|
-
workspace.webUrl ? `Web: ${
|
|
5533
|
+
`Workspace: ${import_picocolors8.default.cyan(workspace.displayName ?? workspace.id)}`,
|
|
5534
|
+
workspace.webUrl ? `Web: ${import_picocolors8.default.cyan(workspace.webUrl)}` : "",
|
|
5331
5535
|
"",
|
|
5332
5536
|
"Starting `codeam pair` on the workspace.",
|
|
5333
5537
|
"Scan the QR code below with the CodeAgent Mobile app to finish pairing."
|
|
@@ -5336,9 +5540,28 @@ async function deploy() {
|
|
|
5336
5540
|
);
|
|
5337
5541
|
const code = (await provider.streamCommand(workspace.id, "codeam pair")).code;
|
|
5338
5542
|
if (code === 0) {
|
|
5339
|
-
gt(
|
|
5543
|
+
gt(import_picocolors8.default.green(`\u2713 Workspace deployed and paired. Drive from your phone, anywhere.`));
|
|
5340
5544
|
} else {
|
|
5341
|
-
gt(
|
|
5545
|
+
gt(import_picocolors8.default.yellow(`Pairing exited with code ${code}. Run "codeam pair" inside the codespace if needed.`));
|
|
5546
|
+
}
|
|
5547
|
+
}
|
|
5548
|
+
async function runRemoteClaudeLogin(provider, workspaceId) {
|
|
5549
|
+
wt(
|
|
5550
|
+
[
|
|
5551
|
+
"A login URL will print below. Open it in your local browser, sign in,",
|
|
5552
|
+
"and paste any code Claude asks for back into this terminal."
|
|
5553
|
+
].join("\n"),
|
|
5554
|
+
"Authenticating Claude on workspace"
|
|
5555
|
+
);
|
|
5556
|
+
const result = await provider.streamCommand(
|
|
5557
|
+
workspaceId,
|
|
5558
|
+
'bash -lc "claude login || claude /login || true"'
|
|
5559
|
+
);
|
|
5560
|
+
if (result.code !== 0) {
|
|
5561
|
+
wt(
|
|
5562
|
+
"claude login exited non-zero. You can re-run it manually inside the codespace later.",
|
|
5563
|
+
"Heads up"
|
|
5564
|
+
);
|
|
5342
5565
|
}
|
|
5343
5566
|
}
|
|
5344
5567
|
async function pickProvider() {
|
|
@@ -5348,7 +5571,7 @@ async function pickProvider() {
|
|
|
5348
5571
|
message: "Where do you want to deploy?",
|
|
5349
5572
|
options: PROVIDERS.map((prov) => ({
|
|
5350
5573
|
value: prov.id,
|
|
5351
|
-
label: prov.available ? prov.displayName : `${prov.displayName} ${
|
|
5574
|
+
label: prov.available ? prov.displayName : `${prov.displayName} ${import_picocolors8.default.dim("(coming soon)")}`,
|
|
5352
5575
|
hint: prov.tagline
|
|
5353
5576
|
}))
|
|
5354
5577
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
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": {
|