codeam-cli 2.16.2 → 2.17.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 +21 -0
- package/dist/index.js +125 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,27 @@ 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.16.2] — 2026-05-22
|
|
8
|
+
|
|
9
|
+
### Chore
|
|
10
|
+
|
|
11
|
+
- **meta:** Expand issue templates with question + documentation forms
|
|
12
|
+
|
|
13
|
+
### Documentation
|
|
14
|
+
|
|
15
|
+
- **shared:** Correct prod URL in api-url history comment
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **cli:** Codeam link — auto-install, multi-probe creds, file-watcher login
|
|
20
|
+
- **cli:** Windows EPERM crash from chokidar watching user-profile junctions (#43)
|
|
21
|
+
|
|
22
|
+
## [2.16.1] — 2026-05-21
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **cli:** Codeam link — auto-install, multi-probe creds, file-watcher login (#42)
|
|
27
|
+
|
|
7
28
|
## [2.16.0] — 2026-05-21
|
|
8
29
|
|
|
9
30
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -424,7 +424,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
424
424
|
// package.json
|
|
425
425
|
var package_default = {
|
|
426
426
|
name: "codeam-cli",
|
|
427
|
-
version: "2.
|
|
427
|
+
version: "2.17.0",
|
|
428
428
|
description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
|
|
429
429
|
type: "commonjs",
|
|
430
430
|
main: "dist/index.js",
|
|
@@ -8592,8 +8592,9 @@ async function promptForAgent(initialValue) {
|
|
|
8592
8592
|
// src/commands/pair.ts
|
|
8593
8593
|
async function pair(args2 = []) {
|
|
8594
8594
|
const config = loadCliConfig();
|
|
8595
|
+
const dryRun = args2.includes("--dry-run");
|
|
8595
8596
|
const flagAgent = parseAgentFlag(args2);
|
|
8596
|
-
const agentId = flagAgent ?? await promptForAgent(config.preferredAgent ?? "claude");
|
|
8597
|
+
const agentId = dryRun ? flagAgent ?? config.preferredAgent ?? "claude" : flagAgent ?? await promptForAgent(config.preferredAgent ?? "claude");
|
|
8597
8598
|
showIntro();
|
|
8598
8599
|
const pluginId = (0, import_crypto4.randomUUID)();
|
|
8599
8600
|
const spin = dist_exports.spinner();
|
|
@@ -8605,6 +8606,20 @@ async function pair(args2 = []) {
|
|
|
8605
8606
|
process.exit(1);
|
|
8606
8607
|
}
|
|
8607
8608
|
spin.stop("Got pairing code");
|
|
8609
|
+
if (dryRun) {
|
|
8610
|
+
const codeOk = typeof result.code === "string" && result.code.trim().length > 0;
|
|
8611
|
+
const expiresOk = typeof result.expiresAt === "number" && result.expiresAt > 0;
|
|
8612
|
+
if (!codeOk || !expiresOk) {
|
|
8613
|
+
showError(
|
|
8614
|
+
`Pair dry-run: backend response shape unexpected (codeType=${typeof result.code}, codeEmpty=${!codeOk}, expiresType=${typeof result.expiresAt}, expiresPositive=${expiresOk}).`
|
|
8615
|
+
);
|
|
8616
|
+
process.exit(1);
|
|
8617
|
+
}
|
|
8618
|
+
showSuccess(
|
|
8619
|
+
`Pair dry-run OK \u2014 backend reachable, response shape valid (codeLength=${result.code.length}, expiresAt=${result.expiresAt}, agent=${agentId}).`
|
|
8620
|
+
);
|
|
8621
|
+
process.exit(0);
|
|
8622
|
+
}
|
|
8608
8623
|
showPairingCode(result.code);
|
|
8609
8624
|
console.log(import_picocolors3.default.dim(" Scan the QR code or enter the code in CodeAgent Mobile."));
|
|
8610
8625
|
console.log("");
|
|
@@ -10920,11 +10935,12 @@ function parseLinkArgs(args2) {
|
|
|
10920
10935
|
);
|
|
10921
10936
|
}
|
|
10922
10937
|
const reuseExisting = args2.includes("--reuse-existing");
|
|
10938
|
+
const dryRun = args2.includes("--dry-run");
|
|
10923
10939
|
const apiKeyArg = args2.find((a) => a.startsWith("--api-key="));
|
|
10924
10940
|
const apiKey = apiKeyArg ? apiKeyArg.slice("--api-key=".length) : null;
|
|
10925
10941
|
const tokenFileArg = args2.find((a) => a.startsWith("--token-file="));
|
|
10926
10942
|
const tokenFile = tokenFileArg ? tokenFileArg.slice("--token-file=".length) : null;
|
|
10927
|
-
return { agent: normalised, reuseExisting, apiKey, tokenFile };
|
|
10943
|
+
return { agent: normalised, reuseExisting, apiKey, tokenFile, dryRun };
|
|
10928
10944
|
}
|
|
10929
10945
|
async function link(args2 = []) {
|
|
10930
10946
|
const parsed = parseLinkArgs(args2);
|
|
@@ -10934,6 +10950,10 @@ async function link(args2 = []) {
|
|
|
10934
10950
|
import_picocolors11.default.bold(` Link ${meta.displayName}`) + import_picocolors11.default.dim(` \xB7 ${meta.vendor}`)
|
|
10935
10951
|
);
|
|
10936
10952
|
console.log("");
|
|
10953
|
+
if (parsed.dryRun) {
|
|
10954
|
+
await linkDryRunPreflight(meta);
|
|
10955
|
+
return;
|
|
10956
|
+
}
|
|
10937
10957
|
const pluginId = (0, import_node_crypto.randomUUID)();
|
|
10938
10958
|
const spin = dist_exports.spinner();
|
|
10939
10959
|
spin.start("Requesting pairing code...");
|
|
@@ -11153,11 +11173,42 @@ async function uploadAndSucceed(meta, paired, pluginId, token) {
|
|
|
11153
11173
|
);
|
|
11154
11174
|
console.log("");
|
|
11155
11175
|
}
|
|
11176
|
+
async function linkDryRunPreflight(meta) {
|
|
11177
|
+
const spin = dist_exports.spinner();
|
|
11178
|
+
spin.start(`Probing ${meta.publicId} link endpoint...`);
|
|
11179
|
+
const result = await postLinkCredential({
|
|
11180
|
+
agentId: meta.publicId,
|
|
11181
|
+
sessionId: "dryrun-session",
|
|
11182
|
+
pluginId: "dryrun-plugin",
|
|
11183
|
+
pluginAuthToken: "dryrun-token",
|
|
11184
|
+
method: "oauth",
|
|
11185
|
+
credential: "dryrun-credential"
|
|
11186
|
+
});
|
|
11187
|
+
if (result.ok) {
|
|
11188
|
+
spin.stop("Unexpected 2xx");
|
|
11189
|
+
showError(
|
|
11190
|
+
"Link dry-run: backend accepted a stub credential (2xx). PluginAuthGuard appears to be disabled \u2014 investigate api-v2."
|
|
11191
|
+
);
|
|
11192
|
+
process.exit(1);
|
|
11193
|
+
}
|
|
11194
|
+
if (result.status === 401) {
|
|
11195
|
+
spin.stop("Endpoint OK");
|
|
11196
|
+
showSuccess(
|
|
11197
|
+
`Link dry-run OK \u2014 /api/plugin/agents/${meta.publicId}/link reachable and auth-gated (401 as expected).`
|
|
11198
|
+
);
|
|
11199
|
+
process.exit(0);
|
|
11200
|
+
}
|
|
11201
|
+
spin.stop("Failed");
|
|
11202
|
+
showError(
|
|
11203
|
+
`Link dry-run: unexpected response from /api/plugin/agents/${meta.publicId}/link (status=${result.status}, message=${result.message}). Expected 401.`
|
|
11204
|
+
);
|
|
11205
|
+
process.exit(1);
|
|
11206
|
+
}
|
|
11156
11207
|
|
|
11157
11208
|
// src/commands/version.ts
|
|
11158
11209
|
var import_picocolors12 = __toESM(require("picocolors"));
|
|
11159
11210
|
function version() {
|
|
11160
|
-
const v = true ? "2.
|
|
11211
|
+
const v = true ? "2.17.0" : "unknown";
|
|
11161
11212
|
console.log(`${import_picocolors12.default.bold("codeam-cli")} ${import_picocolors12.default.cyan(v)}`);
|
|
11162
11213
|
}
|
|
11163
11214
|
|
|
@@ -11198,12 +11249,74 @@ function help() {
|
|
|
11198
11249
|
process.stdout.write(lines.join("\n") + "\n");
|
|
11199
11250
|
}
|
|
11200
11251
|
|
|
11252
|
+
// src/commands/subcommand-help.ts
|
|
11253
|
+
var import_picocolors14 = __toESM(require("picocolors"));
|
|
11254
|
+
var HELPS = {
|
|
11255
|
+
pair: () => print([
|
|
11256
|
+
` ${import_picocolors14.default.bold("codeam pair")} ${import_picocolors14.default.dim("\u2014 pair a mobile device with this CLI")}`,
|
|
11257
|
+
"",
|
|
11258
|
+
` ${import_picocolors14.default.cyan("codeam pair")} ${import_picocolors14.default.dim("interactive pairing (prompts for the agent)")}`,
|
|
11259
|
+
` ${import_picocolors14.default.cyan("codeam pair --agent <id>")} ${import_picocolors14.default.dim("pair non-interactively (agent: claude | codex)")}`,
|
|
11260
|
+
` ${import_picocolors14.default.cyan("codeam pair --dry-run")} ${import_picocolors14.default.dim("request a pairing code, validate the response, exit")}`
|
|
11261
|
+
]),
|
|
11262
|
+
"pair-auto": () => print([
|
|
11263
|
+
` ${import_picocolors14.default.bold("codeam pair-auto")} ${import_picocolors14.default.dim("\u2014 non-interactive variant of pair for scripted setups")}`,
|
|
11264
|
+
"",
|
|
11265
|
+
` ${import_picocolors14.default.cyan("codeam pair-auto --agent <id>")} ${import_picocolors14.default.dim("pair using the supplied agent id; exit on success or timeout")}`
|
|
11266
|
+
]),
|
|
11267
|
+
link: () => print([
|
|
11268
|
+
` ${import_picocolors14.default.bold("codeam link <agent>")} ${import_picocolors14.default.dim("\u2014 upload a local agent token (Claude or Codex) to your vault")}`,
|
|
11269
|
+
"",
|
|
11270
|
+
` ${import_picocolors14.default.cyan("codeam link claude")}`,
|
|
11271
|
+
` ${import_picocolors14.default.cyan("codeam link codex")}`,
|
|
11272
|
+
"",
|
|
11273
|
+
` ${import_picocolors14.default.white("--api-key=<key>")} ${import_picocolors14.default.dim("paste an API key directly (skip the local auth flow)")}`,
|
|
11274
|
+
` ${import_picocolors14.default.white("--reuse-existing")} ${import_picocolors14.default.dim("upload existing creds without re-launching the agent login")}`,
|
|
11275
|
+
` ${import_picocolors14.default.white("--token-file=<path>")} ${import_picocolors14.default.dim("manual credential blob path for unusual vendor locations")}`,
|
|
11276
|
+
` ${import_picocolors14.default.white("--dry-run")} ${import_picocolors14.default.dim("probe the /api/plugin/agents/<agent>/link endpoint and exit")}`
|
|
11277
|
+
]),
|
|
11278
|
+
sessions: () => print([
|
|
11279
|
+
` ${import_picocolors14.default.bold("codeam sessions")} ${import_picocolors14.default.dim("\u2014 list, switch, or delete paired mobile sessions")}`,
|
|
11280
|
+
"",
|
|
11281
|
+
` ${import_picocolors14.default.cyan("codeam sessions")} ${import_picocolors14.default.dim("list all paired sessions on this machine")}`,
|
|
11282
|
+
` ${import_picocolors14.default.cyan("codeam sessions switch")} ${import_picocolors14.default.dim("interactively switch the active session")}`,
|
|
11283
|
+
` ${import_picocolors14.default.cyan("codeam sessions delete <id>")} ${import_picocolors14.default.dim("remove a specific paired session")}`
|
|
11284
|
+
]),
|
|
11285
|
+
deploy: () => print([
|
|
11286
|
+
` ${import_picocolors14.default.bold("codeam deploy")} ${import_picocolors14.default.dim("\u2014 provision a cloud workspace (GitHub Codespaces) and pair it")}`,
|
|
11287
|
+
"",
|
|
11288
|
+
` ${import_picocolors14.default.cyan("codeam deploy")} ${import_picocolors14.default.dim("start a new deploy (prompts for repo + agent)")}`,
|
|
11289
|
+
` ${import_picocolors14.default.cyan("codeam deploy ls | list")} ${import_picocolors14.default.dim("list deployed cloud workspaces")}`,
|
|
11290
|
+
` ${import_picocolors14.default.cyan("codeam deploy stop | remove")} ${import_picocolors14.default.dim("pick a workspace and stop its codeam-pair session")}`
|
|
11291
|
+
]),
|
|
11292
|
+
status: () => print([
|
|
11293
|
+
` ${import_picocolors14.default.bold("codeam status")} ${import_picocolors14.default.dim("\u2014 show the active session, agent, and connection info")}`
|
|
11294
|
+
]),
|
|
11295
|
+
logout: () => print([
|
|
11296
|
+
` ${import_picocolors14.default.bold("codeam logout")} ${import_picocolors14.default.dim("\u2014 remove every paired session from this machine")}`
|
|
11297
|
+
])
|
|
11298
|
+
};
|
|
11299
|
+
function print(lines) {
|
|
11300
|
+
process.stdout.write(["", ...lines, ""].join("\n") + "\n");
|
|
11301
|
+
}
|
|
11302
|
+
function isHelpFlag(arg) {
|
|
11303
|
+
return arg === "--help" || arg === "-h";
|
|
11304
|
+
}
|
|
11305
|
+
function tryShowSubcommandHelp(cmd, args2) {
|
|
11306
|
+
if (!isHelpFlag(args2[0])) return false;
|
|
11307
|
+
const renderer = HELPS[cmd];
|
|
11308
|
+
if (!renderer) return false;
|
|
11309
|
+
renderer();
|
|
11310
|
+
return true;
|
|
11311
|
+
}
|
|
11312
|
+
var _subcommandHelpKeys = Object.keys(HELPS);
|
|
11313
|
+
|
|
11201
11314
|
// src/lib/updateNotifier.ts
|
|
11202
11315
|
var fs19 = __toESM(require("fs"));
|
|
11203
11316
|
var os18 = __toESM(require("os"));
|
|
11204
11317
|
var path27 = __toESM(require("path"));
|
|
11205
11318
|
var https7 = __toESM(require("https"));
|
|
11206
|
-
var
|
|
11319
|
+
var import_picocolors15 = __toESM(require("picocolors"));
|
|
11207
11320
|
var PKG_NAME = "codeam-cli";
|
|
11208
11321
|
var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
11209
11322
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -11282,11 +11395,11 @@ function fetchLatest() {
|
|
|
11282
11395
|
}
|
|
11283
11396
|
function notifyIfStale(currentVersion, latest) {
|
|
11284
11397
|
if (compareSemver(latest, currentVersion) <= 0) return;
|
|
11285
|
-
const arrow =
|
|
11286
|
-
const cmd =
|
|
11398
|
+
const arrow = import_picocolors15.default.dim("\u2192");
|
|
11399
|
+
const cmd = import_picocolors15.default.cyan("npm install -g codeam-cli");
|
|
11287
11400
|
const lines = [
|
|
11288
11401
|
"",
|
|
11289
|
-
` ${
|
|
11402
|
+
` ${import_picocolors15.default.yellow("\u25CF")} ${import_picocolors15.default.bold("Update available")} ${import_picocolors15.default.dim(currentVersion)} ${arrow} ${import_picocolors15.default.green(latest)}`,
|
|
11290
11403
|
` Run ${cmd} to upgrade.`,
|
|
11291
11404
|
""
|
|
11292
11405
|
];
|
|
@@ -11297,7 +11410,7 @@ function checkForUpdates() {
|
|
|
11297
11410
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
11298
11411
|
if (process.env.CI) return;
|
|
11299
11412
|
if (!process.stdout.isTTY) return;
|
|
11300
|
-
const current = true ? "2.
|
|
11413
|
+
const current = true ? "2.17.0" : null;
|
|
11301
11414
|
if (!current) return;
|
|
11302
11415
|
const cache = readCache();
|
|
11303
11416
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -11316,6 +11429,9 @@ var [, , command, ...args] = process.argv;
|
|
|
11316
11429
|
async function main() {
|
|
11317
11430
|
const isMetaCommand = command === "--version" || command === "-v" || command === "version" || command === "--help" || command === "-h" || command === "help";
|
|
11318
11431
|
if (!isMetaCommand) checkForUpdates();
|
|
11432
|
+
if (typeof command === "string" && tryShowSubcommandHelp(command, args)) {
|
|
11433
|
+
return;
|
|
11434
|
+
}
|
|
11319
11435
|
switch (command) {
|
|
11320
11436
|
case "--version":
|
|
11321
11437
|
case "-v":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.17.0",
|
|
4
4
|
"description": "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device — async. The terminal companion for CodeAgent Mobile.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/index.js",
|