codeam-cli 2.4.6 → 2.4.7
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 +6 -0
- package/dist/index.js +126 -8
- package/package.json +1 -1
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.4.5] — 2026-05-03
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Clearer guidance when gh refresh hits multi-account browser (v2.4.5)
|
|
12
|
+
|
|
7
13
|
## [2.4.4] — 2026-05-03
|
|
8
14
|
|
|
9
15
|
### 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.7",
|
|
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: {
|
|
@@ -5077,15 +5077,18 @@ async function logout() {
|
|
|
5077
5077
|
}
|
|
5078
5078
|
|
|
5079
5079
|
// src/commands/deploy.ts
|
|
5080
|
+
var import_child_process6 = require("child_process");
|
|
5080
5081
|
var fs8 = __toESM(require("fs"));
|
|
5081
5082
|
var os6 = __toESM(require("os"));
|
|
5082
|
-
var
|
|
5083
|
+
var path9 = __toESM(require("path"));
|
|
5084
|
+
var import_util3 = require("util");
|
|
5083
5085
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
5084
5086
|
|
|
5085
5087
|
// src/services/providers/github-codespaces.ts
|
|
5086
5088
|
var import_child_process5 = require("child_process");
|
|
5087
5089
|
var import_util2 = require("util");
|
|
5088
5090
|
var import_picocolors7 = __toESM(require("picocolors"));
|
|
5091
|
+
var path8 = __toESM(require("path"));
|
|
5089
5092
|
var execFileP2 = (0, import_util2.promisify)(import_child_process5.execFile);
|
|
5090
5093
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
5091
5094
|
function resetStdinForChild() {
|
|
@@ -5471,7 +5474,12 @@ var GitHubCodespacesProvider = class {
|
|
|
5471
5474
|
proc.on("error", reject);
|
|
5472
5475
|
});
|
|
5473
5476
|
}
|
|
5474
|
-
async uploadDirectory(workspaceId, localDir, remoteDir) {
|
|
5477
|
+
async uploadDirectory(workspaceId, localDir, remoteDir, options = {}) {
|
|
5478
|
+
const tarArgs = ["-czf", "-", "-C", localDir];
|
|
5479
|
+
for (const pattern of options.exclude ?? []) {
|
|
5480
|
+
tarArgs.push(`--exclude=${pattern}`);
|
|
5481
|
+
}
|
|
5482
|
+
tarArgs.push(".");
|
|
5475
5483
|
const sshArgs = [
|
|
5476
5484
|
"codespace",
|
|
5477
5485
|
"ssh",
|
|
@@ -5481,7 +5489,7 @@ var GitHubCodespacesProvider = class {
|
|
|
5481
5489
|
`mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
|
|
5482
5490
|
];
|
|
5483
5491
|
await new Promise((resolve2, reject) => {
|
|
5484
|
-
const tar = (0, import_child_process5.spawn)("tar",
|
|
5492
|
+
const tar = (0, import_child_process5.spawn)("tar", tarArgs, {
|
|
5485
5493
|
stdio: ["ignore", "pipe", "pipe"]
|
|
5486
5494
|
});
|
|
5487
5495
|
const ssh = (0, import_child_process5.spawn)("gh", sshArgs, {
|
|
@@ -5507,6 +5515,35 @@ var GitHubCodespacesProvider = class {
|
|
|
5507
5515
|
});
|
|
5508
5516
|
});
|
|
5509
5517
|
}
|
|
5518
|
+
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
5519
|
+
const remoteDir = path8.posix.dirname(remotePath);
|
|
5520
|
+
const parts = [
|
|
5521
|
+
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
5522
|
+
`cat > ${shellQuote(remotePath)}`
|
|
5523
|
+
];
|
|
5524
|
+
if (options.mode != null) {
|
|
5525
|
+
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote(remotePath)}`);
|
|
5526
|
+
}
|
|
5527
|
+
const cmd = parts.join(" && ");
|
|
5528
|
+
await new Promise((resolve2, reject) => {
|
|
5529
|
+
const proc = (0, import_child_process5.spawn)(
|
|
5530
|
+
"gh",
|
|
5531
|
+
["codespace", "ssh", "-c", workspaceId, "--", cmd],
|
|
5532
|
+
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
5533
|
+
);
|
|
5534
|
+
let stderr = "";
|
|
5535
|
+
proc.stderr?.on("data", (d3) => {
|
|
5536
|
+
stderr += d3.toString();
|
|
5537
|
+
});
|
|
5538
|
+
proc.on("error", reject);
|
|
5539
|
+
proc.on("exit", (code) => {
|
|
5540
|
+
if (code === 0) resolve2();
|
|
5541
|
+
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
5542
|
+
});
|
|
5543
|
+
proc.stdin?.write(contents);
|
|
5544
|
+
proc.stdin?.end();
|
|
5545
|
+
});
|
|
5546
|
+
}
|
|
5510
5547
|
async listExistingWorkspaces(projectId) {
|
|
5511
5548
|
try {
|
|
5512
5549
|
const { stdout } = await execFileP2(
|
|
@@ -5565,6 +5602,7 @@ var PROVIDERS = [
|
|
|
5565
5602
|
];
|
|
5566
5603
|
|
|
5567
5604
|
// src/commands/deploy.ts
|
|
5605
|
+
var execFileP3 = (0, import_util3.promisify)(import_child_process6.execFile);
|
|
5568
5606
|
async function deploy() {
|
|
5569
5607
|
console.log();
|
|
5570
5608
|
mt(import_picocolors8.default.bgMagenta(import_picocolors8.default.white(" codeam deploy ")));
|
|
@@ -5711,19 +5749,74 @@ async function deploy() {
|
|
|
5711
5749
|
process.exit(1);
|
|
5712
5750
|
}
|
|
5713
5751
|
claudeStep.stop("\u2713 Claude CLI installed");
|
|
5714
|
-
const localClaudeDir =
|
|
5752
|
+
const localClaudeDir = path9.join(os6.homedir(), ".claude");
|
|
5715
5753
|
const haveLocalClaude = fs8.existsSync(localClaudeDir) && fs8.statSync(localClaudeDir).isDirectory();
|
|
5716
5754
|
if (haveLocalClaude) {
|
|
5717
5755
|
const copyStep = fe();
|
|
5718
5756
|
copyStep.start("Copying local Claude config to workspace\u2026");
|
|
5757
|
+
let configUploaded = false;
|
|
5719
5758
|
try {
|
|
5720
|
-
await provider.uploadDirectory(
|
|
5721
|
-
|
|
5759
|
+
await provider.uploadDirectory(
|
|
5760
|
+
workspace.id,
|
|
5761
|
+
localClaudeDir,
|
|
5762
|
+
"/home/codespace/.claude",
|
|
5763
|
+
{
|
|
5764
|
+
exclude: [
|
|
5765
|
+
"./projects",
|
|
5766
|
+
// per-project conversation history (often 700MB+)
|
|
5767
|
+
"./file-history",
|
|
5768
|
+
// per-project file diffs
|
|
5769
|
+
"./downloads",
|
|
5770
|
+
// downloaded artifacts
|
|
5771
|
+
"./image-cache",
|
|
5772
|
+
// cached images
|
|
5773
|
+
"./paste-cache",
|
|
5774
|
+
// clipboard/paste cache
|
|
5775
|
+
"./backups",
|
|
5776
|
+
// local backups
|
|
5777
|
+
"./shell-snapshots",
|
|
5778
|
+
// shell history snapshots
|
|
5779
|
+
"./telemetry",
|
|
5780
|
+
// analytics dumps
|
|
5781
|
+
"./statsig",
|
|
5782
|
+
// feature-flag cache
|
|
5783
|
+
"./cache",
|
|
5784
|
+
// generic cache dir
|
|
5785
|
+
"./history.jsonl",
|
|
5786
|
+
// global REPL history
|
|
5787
|
+
"./ide",
|
|
5788
|
+
// local IDE bridge state
|
|
5789
|
+
"./todos",
|
|
5790
|
+
// local todo state
|
|
5791
|
+
"./tasks"
|
|
5792
|
+
// local task state
|
|
5793
|
+
]
|
|
5794
|
+
}
|
|
5795
|
+
);
|
|
5796
|
+
configUploaded = true;
|
|
5797
|
+
copyStep.stop("\u2713 Claude config uploaded");
|
|
5722
5798
|
} catch (err) {
|
|
5723
|
-
copyStep.stop("\u26A0 Could not
|
|
5799
|
+
copyStep.stop("\u26A0 Could not upload Claude config \u2014 falling back to remote login");
|
|
5724
5800
|
void err;
|
|
5725
5801
|
await runRemoteClaudeLogin(provider, workspace.id);
|
|
5726
5802
|
}
|
|
5803
|
+
if (configUploaded) {
|
|
5804
|
+
const credStep = fe();
|
|
5805
|
+
credStep.start("Bridging Claude credentials\u2026");
|
|
5806
|
+
const bridged = await bridgeClaudeCredentials(provider, workspace.id, localClaudeDir);
|
|
5807
|
+
switch (bridged) {
|
|
5808
|
+
case "flat-file":
|
|
5809
|
+
credStep.stop("\u2713 Credentials in tar \u2014 no re-auth needed");
|
|
5810
|
+
break;
|
|
5811
|
+
case "macos-keychain":
|
|
5812
|
+
credStep.stop("\u2713 Credentials extracted from macOS Keychain \u2014 no re-auth needed");
|
|
5813
|
+
break;
|
|
5814
|
+
case "none":
|
|
5815
|
+
credStep.stop("\u26A0 No transferable Claude credentials found \u2014 falling back to remote login");
|
|
5816
|
+
await runRemoteClaudeLogin(provider, workspace.id);
|
|
5817
|
+
break;
|
|
5818
|
+
}
|
|
5819
|
+
}
|
|
5727
5820
|
} else {
|
|
5728
5821
|
wt(
|
|
5729
5822
|
[
|
|
@@ -5788,6 +5881,31 @@ async function runRemoteClaudeLogin(provider, workspaceId) {
|
|
|
5788
5881
|
);
|
|
5789
5882
|
}
|
|
5790
5883
|
}
|
|
5884
|
+
async function bridgeClaudeCredentials(provider, workspaceId, localClaudeDir) {
|
|
5885
|
+
const fileBased = path9.join(localClaudeDir, ".credentials.json");
|
|
5886
|
+
if (fs8.existsSync(fileBased)) return "flat-file";
|
|
5887
|
+
if (process.platform === "darwin") {
|
|
5888
|
+
try {
|
|
5889
|
+
const { stdout } = await execFileP3(
|
|
5890
|
+
"security",
|
|
5891
|
+
["find-generic-password", "-s", "Claude Code-credentials", "-w"],
|
|
5892
|
+
{ maxBuffer: 1024 * 1024 }
|
|
5893
|
+
);
|
|
5894
|
+
const json = stdout.trim();
|
|
5895
|
+
if (json.length === 0) return "none";
|
|
5896
|
+
await provider.uploadFile(
|
|
5897
|
+
workspaceId,
|
|
5898
|
+
"/home/codespace/.claude/.credentials.json",
|
|
5899
|
+
json,
|
|
5900
|
+
{ mode: 384 }
|
|
5901
|
+
);
|
|
5902
|
+
return "macos-keychain";
|
|
5903
|
+
} catch {
|
|
5904
|
+
return "none";
|
|
5905
|
+
}
|
|
5906
|
+
}
|
|
5907
|
+
return "none";
|
|
5908
|
+
}
|
|
5791
5909
|
function formatLastUsed(iso) {
|
|
5792
5910
|
if (!iso) return "";
|
|
5793
5911
|
const t2 = Date.parse(iso);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.7",
|
|
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": {
|