vibeview 0.24.0 → 0.25.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/README.md +2 -0
- package/dist/{chunk-MVNMGB6I.js → chunk-GEKYHEWU.js} +224 -100
- package/dist/{chunk-2WNJYNDW.js → chunk-RFFCCPGZ.js} +5 -0
- package/dist/cli.js +175 -124
- package/dist/{server-KIJCEN6T.js → server-6EUBLXKE.js} +88 -5
- package/dist/{upload-app-BXXKH65S.js → upload-app-E32EZXYQ.js} +1 -1
- package/package.json +1 -1
- package/skills/vibeview-agent/SKILL.md +11 -1
package/dist/cli.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
formatDevicesHuman,
|
|
13
13
|
formatDuration,
|
|
14
14
|
killOwnedMetro,
|
|
15
|
+
listBuilds,
|
|
15
16
|
loadDevConfig,
|
|
16
17
|
newTransitionState,
|
|
17
18
|
printOutcomeLine,
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
readDevState,
|
|
20
21
|
readMetroState,
|
|
21
22
|
runAgentVerb
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-GEKYHEWU.js";
|
|
23
24
|
import {
|
|
24
25
|
ApiClient,
|
|
25
26
|
EXIT_INFRA_ERROR,
|
|
@@ -32,7 +33,7 @@ import {
|
|
|
32
33
|
resolveAuth,
|
|
33
34
|
saveConfig,
|
|
34
35
|
uploadApp
|
|
35
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-RFFCCPGZ.js";
|
|
36
37
|
|
|
37
38
|
// src/cli.ts
|
|
38
39
|
import { createRequire } from "module";
|
|
@@ -881,8 +882,52 @@ async function listApps(options) {
|
|
|
881
882
|
console.log();
|
|
882
883
|
}
|
|
883
884
|
|
|
884
|
-
// src/commands/
|
|
885
|
+
// src/commands/stop.ts
|
|
885
886
|
import chalk8 from "chalk";
|
|
887
|
+
async function stopCommand(sessionId, opts, deps) {
|
|
888
|
+
const id = sessionId?.trim();
|
|
889
|
+
if (!id) throw new UsageError("a session id is required: vibeview stop <session-id>");
|
|
890
|
+
const { token, baseUrl } = resolveAuth(opts);
|
|
891
|
+
const d = deps ?? { stopSession: (s) => new ApiClient(baseUrl, token).stopSession(s) };
|
|
892
|
+
try {
|
|
893
|
+
await d.stopSession(id);
|
|
894
|
+
} catch (err) {
|
|
895
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
896
|
+
if (opts.json) console.log(JSON.stringify({ stopped: false, session_id: id, message }));
|
|
897
|
+
console.error(chalk8.red(`error: ${message}`));
|
|
898
|
+
process.exitCode = 1;
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
const state = readDevState(process.cwd());
|
|
902
|
+
let devPid = null;
|
|
903
|
+
if (state && state.session_id === id) {
|
|
904
|
+
devPid = state.pid;
|
|
905
|
+
try {
|
|
906
|
+
process.kill(state.pid, "SIGTERM");
|
|
907
|
+
} catch (err) {
|
|
908
|
+
if (err.code !== "ESRCH") throw err;
|
|
909
|
+
}
|
|
910
|
+
clearDevState(process.cwd());
|
|
911
|
+
killOwnedMetro(process.cwd());
|
|
912
|
+
}
|
|
913
|
+
if (opts.json) {
|
|
914
|
+
console.log(
|
|
915
|
+
JSON.stringify({
|
|
916
|
+
stopped: true,
|
|
917
|
+
session_id: id,
|
|
918
|
+
...devPid !== null ? { pid: devPid } : {}
|
|
919
|
+
})
|
|
920
|
+
);
|
|
921
|
+
} else {
|
|
922
|
+
console.error(
|
|
923
|
+
`Stopped session ${id}${devPid !== null ? ` (and this project's dev process, pid ${devPid})` : ""}.`
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
process.exitCode = 0;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// src/commands/create-test.ts
|
|
930
|
+
import chalk9 from "chalk";
|
|
886
931
|
import { existsSync, readFileSync } from "fs";
|
|
887
932
|
async function readStdin() {
|
|
888
933
|
return new Promise((resolve, reject) => {
|
|
@@ -973,19 +1018,19 @@ async function createTest(options) {
|
|
|
973
1018
|
);
|
|
974
1019
|
} else {
|
|
975
1020
|
console.log(`
|
|
976
|
-
${
|
|
1021
|
+
${chalk9.cyan(result.public_id)} ${result.name}`);
|
|
977
1022
|
if (result.app_name) {
|
|
978
|
-
console.log(` ${
|
|
1023
|
+
console.log(` ${chalk9.dim(`App: ${result.app_name}`)}`);
|
|
979
1024
|
}
|
|
980
1025
|
if (result.platform) {
|
|
981
|
-
console.log(` ${
|
|
1026
|
+
console.log(` ${chalk9.dim(`Platform: ${result.platform}`)}`);
|
|
982
1027
|
}
|
|
983
|
-
console.log(` ${
|
|
984
|
-
console.log(
|
|
1028
|
+
console.log(` ${chalk9.dim(`Steps: ${steps.length}`)}`);
|
|
1029
|
+
console.log(chalk9.dim(` ${baseUrl}/tests?tab=standalone
|
|
985
1030
|
`));
|
|
986
1031
|
}
|
|
987
1032
|
} catch (err) {
|
|
988
|
-
console.error(
|
|
1033
|
+
console.error(chalk9.red(err instanceof Error ? err.message : "Failed to create test"));
|
|
989
1034
|
process.exit(EXIT_INFRA_ERROR);
|
|
990
1035
|
}
|
|
991
1036
|
}
|
|
@@ -1067,7 +1112,7 @@ async function logout() {
|
|
|
1067
1112
|
}
|
|
1068
1113
|
|
|
1069
1114
|
// src/commands/dev-status.ts
|
|
1070
|
-
import
|
|
1115
|
+
import chalk10 from "chalk";
|
|
1071
1116
|
async function devStatus(opts) {
|
|
1072
1117
|
const state = readDevState(process.cwd());
|
|
1073
1118
|
if (!state) {
|
|
@@ -1112,7 +1157,7 @@ async function devStatus(opts) {
|
|
|
1112
1157
|
console.error(` url: ${state.page_url}`);
|
|
1113
1158
|
console.error(` started: ${state.started_at}`);
|
|
1114
1159
|
}
|
|
1115
|
-
if (metro) console.error(
|
|
1160
|
+
if (metro) console.error(chalk10.dim(`Metro: pid ${metro.pid} on :${metro.port} (CLI-owned)`));
|
|
1116
1161
|
process.exit(0);
|
|
1117
1162
|
}
|
|
1118
1163
|
|
|
@@ -1148,12 +1193,12 @@ async function devStop(opts) {
|
|
|
1148
1193
|
}
|
|
1149
1194
|
|
|
1150
1195
|
// src/commands/dev-reload.ts
|
|
1151
|
-
import
|
|
1196
|
+
import chalk11 from "chalk";
|
|
1152
1197
|
function fail(opts, code, message, exit) {
|
|
1153
1198
|
if (opts.json) {
|
|
1154
1199
|
console.log(JSON.stringify({ reloaded: false, code, message }));
|
|
1155
1200
|
} else {
|
|
1156
|
-
console.error(
|
|
1201
|
+
console.error(chalk11.red(`error: ${message}`));
|
|
1157
1202
|
}
|
|
1158
1203
|
process.exit(exit);
|
|
1159
1204
|
}
|
|
@@ -1206,7 +1251,7 @@ async function devReload(opts) {
|
|
|
1206
1251
|
api,
|
|
1207
1252
|
// Build output and the "reloaded in" line are human output: stderr, so
|
|
1208
1253
|
// stdout stays reserved for the --json result.
|
|
1209
|
-
log: (line) => console.error(
|
|
1254
|
+
log: (line) => console.error(chalk11.dim(line))
|
|
1210
1255
|
});
|
|
1211
1256
|
const started = Date.now();
|
|
1212
1257
|
try {
|
|
@@ -1227,22 +1272,22 @@ async function devReload(opts) {
|
|
|
1227
1272
|
}
|
|
1228
1273
|
|
|
1229
1274
|
// src/commands/builds.ts
|
|
1230
|
-
import
|
|
1275
|
+
import chalk13 from "chalk";
|
|
1231
1276
|
|
|
1232
1277
|
// src/lib/formatters/builds.ts
|
|
1233
|
-
import
|
|
1278
|
+
import chalk12 from "chalk";
|
|
1234
1279
|
var HEADERS = ["ID", "PLATFORM", "STATUS", "CREATED", "COST", "APP"];
|
|
1235
1280
|
function formatCostCell(costMicro) {
|
|
1236
1281
|
return costMicro > 0 ? `$${(costMicro / 1e6).toFixed(2)}` : "";
|
|
1237
1282
|
}
|
|
1238
1283
|
var STATUS_COLOR = {
|
|
1239
|
-
succeeded:
|
|
1240
|
-
failed:
|
|
1241
|
-
timed_out:
|
|
1242
|
-
infra_failed:
|
|
1243
|
-
canceled:
|
|
1244
|
-
running:
|
|
1245
|
-
queued:
|
|
1284
|
+
succeeded: chalk12.green,
|
|
1285
|
+
failed: chalk12.red,
|
|
1286
|
+
timed_out: chalk12.red,
|
|
1287
|
+
infra_failed: chalk12.red,
|
|
1288
|
+
canceled: chalk12.dim,
|
|
1289
|
+
running: chalk12.yellow,
|
|
1290
|
+
queued: chalk12.dim
|
|
1246
1291
|
};
|
|
1247
1292
|
function formatBuildsHuman(builds2) {
|
|
1248
1293
|
if (builds2.length === 0) {
|
|
@@ -1259,7 +1304,7 @@ function formatBuildsHuman(builds2) {
|
|
|
1259
1304
|
const widths = HEADERS.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
1260
1305
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
1261
1306
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
1262
|
-
const lines = [
|
|
1307
|
+
const lines = [chalk12.bold(join3(padCells(HEADERS)))];
|
|
1263
1308
|
for (const row of rows) {
|
|
1264
1309
|
const padded = padCells(row);
|
|
1265
1310
|
const colorFn = STATUS_COLOR[row[2]] ?? ((s) => s);
|
|
@@ -1318,7 +1363,7 @@ async function buildsLogs(id, opts, deps) {
|
|
|
1318
1363
|
console.log(JSON.stringify(logs));
|
|
1319
1364
|
} else {
|
|
1320
1365
|
if (logs.content) process.stdout.write(logs.content);
|
|
1321
|
-
console.error(
|
|
1366
|
+
console.error(chalk13.dim(`status: ${logs.status}`));
|
|
1322
1367
|
}
|
|
1323
1368
|
process.exitCode = 0;
|
|
1324
1369
|
return;
|
|
@@ -1415,7 +1460,7 @@ async function buildsDownload(id, opts, deps) {
|
|
|
1415
1460
|
if (opts.json) {
|
|
1416
1461
|
console.log(JSON.stringify(result));
|
|
1417
1462
|
} else {
|
|
1418
|
-
console.log(
|
|
1463
|
+
console.log(chalk13.green(`\u2713 saved ${result.path}`));
|
|
1419
1464
|
}
|
|
1420
1465
|
process.exitCode = 0;
|
|
1421
1466
|
} catch (err) {
|
|
@@ -1432,7 +1477,7 @@ async function buildsCancel(id, opts, deps) {
|
|
|
1432
1477
|
if (opts.json) {
|
|
1433
1478
|
console.log(JSON.stringify(build));
|
|
1434
1479
|
} else {
|
|
1435
|
-
console.log(`${
|
|
1480
|
+
console.log(`${chalk13.cyan(build.id)} ${build.status}`);
|
|
1436
1481
|
}
|
|
1437
1482
|
process.exitCode = 0;
|
|
1438
1483
|
} catch (err) {
|
|
@@ -1449,7 +1494,7 @@ async function buildsDeleteArtifact(id, opts, deps) {
|
|
|
1449
1494
|
if (opts.json) {
|
|
1450
1495
|
console.log(JSON.stringify(result));
|
|
1451
1496
|
} else {
|
|
1452
|
-
console.log(
|
|
1497
|
+
console.log(chalk13.green(`\u2713 deleted artifact for ${id}`));
|
|
1453
1498
|
}
|
|
1454
1499
|
process.exitCode = 0;
|
|
1455
1500
|
} catch (err) {
|
|
@@ -1460,11 +1505,11 @@ async function buildsDeleteArtifact(id, opts, deps) {
|
|
|
1460
1505
|
function printError(opts, err) {
|
|
1461
1506
|
const message = err instanceof Error ? err.message : String(err);
|
|
1462
1507
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
1463
|
-
console.error(
|
|
1508
|
+
console.error(chalk13.red(`error: ${message}`));
|
|
1464
1509
|
}
|
|
1465
1510
|
|
|
1466
1511
|
// src/commands/submit.ts
|
|
1467
|
-
import
|
|
1512
|
+
import chalk14 from "chalk";
|
|
1468
1513
|
function defaultDeps2(client) {
|
|
1469
1514
|
return {
|
|
1470
1515
|
createSubmission: client.createSubmission.bind(client),
|
|
@@ -1487,7 +1532,7 @@ function submitConfigFor(cwd, platform) {
|
|
|
1487
1532
|
cfg = loadDevConfig(cwd);
|
|
1488
1533
|
} catch (err) {
|
|
1489
1534
|
console.error(
|
|
1490
|
-
|
|
1535
|
+
chalk14.yellow(
|
|
1491
1536
|
`warning: vibeview.json could not be read \u2014 ignoring submit defaults (${err instanceof Error ? err.message : String(err)})`
|
|
1492
1537
|
)
|
|
1493
1538
|
);
|
|
@@ -1635,12 +1680,12 @@ async function submitCommand(opts, deps) {
|
|
|
1635
1680
|
return;
|
|
1636
1681
|
}
|
|
1637
1682
|
if (!opts.json) {
|
|
1638
|
-
console.error(` ${
|
|
1683
|
+
console.error(` ${chalk14.cyan(sub.id)} ${chalk14.dim(`[${sub.platform}]`)}`);
|
|
1639
1684
|
}
|
|
1640
1685
|
const final = await followSubmission(sub, opts, d);
|
|
1641
1686
|
if (!opts.json && final.status === "succeeded" && (final.release_status ?? releaseStatus) === "draft") {
|
|
1642
1687
|
console.error(
|
|
1643
|
-
|
|
1688
|
+
chalk14.dim("release status: draft \u2014 activate it from the Play Console when ready")
|
|
1644
1689
|
);
|
|
1645
1690
|
}
|
|
1646
1691
|
process.exitCode = final.status === "succeeded" ? 0 : 1;
|
|
@@ -1664,11 +1709,11 @@ async function checkStore(platform, androidFamily, ascKey2, opts, deps) {
|
|
|
1664
1709
|
});
|
|
1665
1710
|
emit(opts.json, { event: "preflight", ...result });
|
|
1666
1711
|
if (!opts.json) {
|
|
1667
|
-
const mark = result.ready ?
|
|
1712
|
+
const mark = result.ready ? chalk14.green("\u2713") : chalk14.red("\u2717");
|
|
1668
1713
|
console.error(`${mark} ${result.message}`);
|
|
1669
1714
|
if (result.ready) {
|
|
1670
1715
|
console.error(
|
|
1671
|
-
|
|
1716
|
+
chalk14.dim(
|
|
1672
1717
|
` next: vibeview build --cloud --production --platform ${platform}, then vibeview submit --platform ${platform} --latest`
|
|
1673
1718
|
)
|
|
1674
1719
|
);
|
|
@@ -1717,14 +1762,14 @@ async function followSubmission(created, opts, deps) {
|
|
|
1717
1762
|
if (opts.json) {
|
|
1718
1763
|
emit(opts.json, { event: "status", id: created.id, status: "queued" });
|
|
1719
1764
|
} else {
|
|
1720
|
-
console.error(
|
|
1765
|
+
console.error(chalk14.dim("\u23F3 queued \u2014 waiting for a submission slot"));
|
|
1721
1766
|
}
|
|
1722
1767
|
} else if (log.status === "running" && !printedRunning) {
|
|
1723
1768
|
printedRunning = true;
|
|
1724
1769
|
if (opts.json) {
|
|
1725
1770
|
emit(opts.json, { event: "status", id: created.id, status: "running" });
|
|
1726
1771
|
} else {
|
|
1727
|
-
console.error(`${
|
|
1772
|
+
console.error(`${chalk14.cyan("\u25B6")} submitting`);
|
|
1728
1773
|
}
|
|
1729
1774
|
}
|
|
1730
1775
|
if (log.content) {
|
|
@@ -1766,7 +1811,7 @@ The submission continues server-side \u2014 see its outcome on the Builds page i
|
|
|
1766
1811
|
});
|
|
1767
1812
|
if (!opts.json) {
|
|
1768
1813
|
const ok = final.status === "succeeded";
|
|
1769
|
-
const mark = ok ?
|
|
1814
|
+
const mark = ok ? chalk14.green("\u2713") : chalk14.red("\u2717");
|
|
1770
1815
|
const duration = formatDuration(final.started_at, final.finished_at);
|
|
1771
1816
|
let line = `${mark} ${final.status}`;
|
|
1772
1817
|
if (duration) line += ` (${duration})`;
|
|
@@ -1778,11 +1823,11 @@ The submission continues server-side \u2014 see its outcome on the Builds page i
|
|
|
1778
1823
|
function printError2(opts, err) {
|
|
1779
1824
|
const message = err instanceof Error ? err.message : String(err);
|
|
1780
1825
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
1781
|
-
console.error(
|
|
1826
|
+
console.error(chalk14.red(`error: ${message}`));
|
|
1782
1827
|
}
|
|
1783
1828
|
|
|
1784
1829
|
// src/commands/versions.ts
|
|
1785
|
-
import
|
|
1830
|
+
import chalk15 from "chalk";
|
|
1786
1831
|
function defaultDeps3(client) {
|
|
1787
1832
|
return {
|
|
1788
1833
|
listAppVersions: client.listAppVersions.bind(client),
|
|
@@ -1832,7 +1877,7 @@ async function versionsSet(buildNumber, opts, deps) {
|
|
|
1832
1877
|
console.log(JSON.stringify(version));
|
|
1833
1878
|
} else {
|
|
1834
1879
|
console.log(
|
|
1835
|
-
|
|
1880
|
+
chalk15.green(`\u2713 ${version.platform} build number set to ${version.build_number}`) + chalk15.dim(
|
|
1836
1881
|
" \u2014 the next autoIncrement production build gets " + (version.build_number + 1)
|
|
1837
1882
|
)
|
|
1838
1883
|
);
|
|
@@ -1852,18 +1897,18 @@ function formatVersionsHuman(versions2) {
|
|
|
1852
1897
|
const widths = HEADERS2.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
1853
1898
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
1854
1899
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
1855
|
-
const lines = [
|
|
1900
|
+
const lines = [chalk15.bold(join3(padCells(HEADERS2)))];
|
|
1856
1901
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
1857
1902
|
return lines.join("\n") + "\n";
|
|
1858
1903
|
}
|
|
1859
1904
|
function printError3(opts, err) {
|
|
1860
1905
|
const message = err instanceof Error ? err.message : String(err);
|
|
1861
1906
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
1862
|
-
console.error(
|
|
1907
|
+
console.error(chalk15.red(`error: ${message}`));
|
|
1863
1908
|
}
|
|
1864
1909
|
|
|
1865
1910
|
// src/commands/whoami.ts
|
|
1866
|
-
import
|
|
1911
|
+
import chalk16 from "chalk";
|
|
1867
1912
|
function defaultDeps4(opts) {
|
|
1868
1913
|
const { token, baseUrl } = resolveAuth(opts);
|
|
1869
1914
|
const client = new ApiClient(baseUrl, token);
|
|
@@ -1885,27 +1930,27 @@ async function whoAmI(opts, deps) {
|
|
|
1885
1930
|
process.exitCode = 0;
|
|
1886
1931
|
return;
|
|
1887
1932
|
}
|
|
1888
|
-
console.log(`${
|
|
1933
|
+
console.log(`${chalk16.bold("Logged in as")} ${me.email}`);
|
|
1889
1934
|
if (me.memberships.length === 1) {
|
|
1890
|
-
console.log(`${
|
|
1935
|
+
console.log(`${chalk16.bold("Organization")} ${me.memberships[0].organization_name}`);
|
|
1891
1936
|
} else if (me.memberships.length > 1) {
|
|
1892
|
-
console.log(
|
|
1937
|
+
console.log(chalk16.bold("Organizations"));
|
|
1893
1938
|
for (const m of me.memberships) {
|
|
1894
1939
|
console.log(` ${m.organization_name} (${m.role})`);
|
|
1895
1940
|
}
|
|
1896
1941
|
}
|
|
1897
|
-
console.log(`${
|
|
1898
|
-
console.log(`${
|
|
1899
|
-
console.log(`${
|
|
1942
|
+
console.log(`${chalk16.bold("Member role")} ${me.role ?? "\u2014"}`);
|
|
1943
|
+
console.log(`${chalk16.bold("Token role")} ${me.token_role ?? "\u2014 (session auth)"}`);
|
|
1944
|
+
console.log(`${chalk16.bold("Effective role")} ${effective ?? "\u2014"}`);
|
|
1900
1945
|
if (me.is_superadmin) {
|
|
1901
|
-
console.log(
|
|
1946
|
+
console.log(chalk16.dim("Superadmin (platform-wide; does not raise the org role above)"));
|
|
1902
1947
|
}
|
|
1903
1948
|
if (me.role === "admin" && me.token_role && me.token_role !== "admin") {
|
|
1904
1949
|
console.log(
|
|
1905
|
-
|
|
1950
|
+
chalk16.yellow(
|
|
1906
1951
|
`
|
|
1907
|
-
Your account is admin, but this CLI token is ${me.token_role}. The effective role is the lower of the two, so admin-only commands (such as ${
|
|
1908
|
-
Create an admin API token in the dashboard and use ${
|
|
1952
|
+
Your account is admin, but this CLI token is ${me.token_role}. The effective role is the lower of the two, so admin-only commands (such as ${chalk16.bold("vibeview env set")}) will fail with a permissions error.
|
|
1953
|
+
Create an admin API token in the dashboard and use ${chalk16.bold("--token")} or ${chalk16.bold("VIBEVIEW_API_TOKEN")}.`
|
|
1909
1954
|
)
|
|
1910
1955
|
);
|
|
1911
1956
|
}
|
|
@@ -1915,7 +1960,7 @@ Create an admin API token in the dashboard and use ${chalk15.bold("--token")} or
|
|
|
1915
1960
|
if (opts.json) {
|
|
1916
1961
|
console.log(JSON.stringify({ event: "error", message }));
|
|
1917
1962
|
}
|
|
1918
|
-
console.error(
|
|
1963
|
+
console.error(chalk16.red(`error: ${message}`));
|
|
1919
1964
|
process.exitCode = 1;
|
|
1920
1965
|
}
|
|
1921
1966
|
}
|
|
@@ -1923,7 +1968,7 @@ Create an admin API token in the dashboard and use ${chalk15.bold("--token")} or
|
|
|
1923
1968
|
// src/commands/env.ts
|
|
1924
1969
|
import { chmod, open as open2, readFile as readFileAsync } from "fs/promises";
|
|
1925
1970
|
import { basename } from "path";
|
|
1926
|
-
import
|
|
1971
|
+
import chalk17 from "chalk";
|
|
1927
1972
|
import { password } from "@inquirer/prompts";
|
|
1928
1973
|
|
|
1929
1974
|
// src/lib/gitignore.ts
|
|
@@ -1979,7 +2024,7 @@ function defaultDeps5(client) {
|
|
|
1979
2024
|
isIgnored: (path) => isGitIgnored(path),
|
|
1980
2025
|
writeFile: writeSecureFile,
|
|
1981
2026
|
readFile: (path) => readFileAsync(path),
|
|
1982
|
-
warn: (message) => console.error(
|
|
2027
|
+
warn: (message) => console.error(chalk17.yellow(`warning: ${message}`))
|
|
1983
2028
|
};
|
|
1984
2029
|
}
|
|
1985
2030
|
async function envList(opts, deps) {
|
|
@@ -2011,7 +2056,7 @@ function formatEnvVarsHuman(variables) {
|
|
|
2011
2056
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2012
2057
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2013
2058
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2014
|
-
const lines = [
|
|
2059
|
+
const lines = [chalk17.bold(join3(padCells(HEADERS3)))];
|
|
2015
2060
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2016
2061
|
return lines.join("\n") + "\n";
|
|
2017
2062
|
}
|
|
@@ -2061,7 +2106,7 @@ function printSetResult(opts, result) {
|
|
|
2061
2106
|
if (opts.json) {
|
|
2062
2107
|
console.log(JSON.stringify(result));
|
|
2063
2108
|
} else {
|
|
2064
|
-
console.log(
|
|
2109
|
+
console.log(chalk17.green(`\u2713 set ${result.name} (${result.visibility})`));
|
|
2065
2110
|
}
|
|
2066
2111
|
}
|
|
2067
2112
|
async function envRm(name, opts, deps) {
|
|
@@ -2071,7 +2116,7 @@ async function envRm(name, opts, deps) {
|
|
|
2071
2116
|
if (opts.json) {
|
|
2072
2117
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2073
2118
|
} else {
|
|
2074
|
-
console.log(
|
|
2119
|
+
console.log(chalk17.green(`\u2713 removed ${name}`));
|
|
2075
2120
|
}
|
|
2076
2121
|
process.exitCode = 0;
|
|
2077
2122
|
} catch (err) {
|
|
@@ -2103,7 +2148,7 @@ async function envPull(opts, deps) {
|
|
|
2103
2148
|
if (opts.json) {
|
|
2104
2149
|
console.log(JSON.stringify({ event: "pulled", path: outPath, count: variables.length }));
|
|
2105
2150
|
} else {
|
|
2106
|
-
console.log(
|
|
2151
|
+
console.log(chalk17.green(`\u2713 wrote ${variables.length} variable(s) to ${outPath}`));
|
|
2107
2152
|
}
|
|
2108
2153
|
process.exitCode = 0;
|
|
2109
2154
|
} catch (err) {
|
|
@@ -2142,7 +2187,7 @@ function escapeEnvValue(value) {
|
|
|
2142
2187
|
function printError4(opts, err) {
|
|
2143
2188
|
const message = err instanceof Error ? err.message : String(err);
|
|
2144
2189
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
2145
|
-
console.error(
|
|
2190
|
+
console.error(chalk17.red(`error: ${message}`));
|
|
2146
2191
|
}
|
|
2147
2192
|
|
|
2148
2193
|
// src/commands/credentials.ts
|
|
@@ -2154,7 +2199,7 @@ import {
|
|
|
2154
2199
|
} from "fs/promises";
|
|
2155
2200
|
import { mkdirSync } from "fs";
|
|
2156
2201
|
import { basename as basename2, extname, join } from "path";
|
|
2157
|
-
import
|
|
2202
|
+
import chalk18 from "chalk";
|
|
2158
2203
|
import { input, password as password2 } from "@inquirer/prompts";
|
|
2159
2204
|
function clientFor2(opts) {
|
|
2160
2205
|
const { token, baseUrl } = resolveAuth(opts);
|
|
@@ -2227,7 +2272,7 @@ function defaultDeps6(client) {
|
|
|
2227
2272
|
mkdir: (dir) => mkdirSync(dir, { recursive: true }),
|
|
2228
2273
|
writeFile: (path, data, mode) => writeFileAsync(path, data, mode !== void 0 ? { mode } : void 0),
|
|
2229
2274
|
chmod: (path, mode) => chmodAsync(path, mode),
|
|
2230
|
-
warn: (message) => console.error(
|
|
2275
|
+
warn: (message) => console.error(chalk18.yellow(`warning: ${message}`))
|
|
2231
2276
|
};
|
|
2232
2277
|
}
|
|
2233
2278
|
var ANDROID_KIND = "android_keystore";
|
|
@@ -2296,7 +2341,7 @@ async function credentialsAdd(opts, deps) {
|
|
|
2296
2341
|
if (opts.json) {
|
|
2297
2342
|
console.log(JSON.stringify(result));
|
|
2298
2343
|
} else {
|
|
2299
|
-
console.log(
|
|
2344
|
+
console.log(chalk18.green(`\u2713 added ${result.name} (${result.platform})`));
|
|
2300
2345
|
}
|
|
2301
2346
|
process.exitCode = 0;
|
|
2302
2347
|
} catch (err) {
|
|
@@ -2354,20 +2399,20 @@ async function credentialsGenerate(opts, deps) {
|
|
|
2354
2399
|
}
|
|
2355
2400
|
if (opts.json) {
|
|
2356
2401
|
} else {
|
|
2357
|
-
console.log(
|
|
2402
|
+
console.log(chalk18.green(`\u2713 generated ${result.name} (android)`));
|
|
2358
2403
|
console.log("");
|
|
2359
|
-
console.log(` Keystore saved to: ${
|
|
2360
|
-
console.log(` Key alias: ${
|
|
2361
|
-
console.log(` Store password: ${
|
|
2362
|
-
console.log(` Key password: ${
|
|
2404
|
+
console.log(` Keystore saved to: ${chalk18.bold(savedTo)}`);
|
|
2405
|
+
console.log(` Key alias: ${chalk18.bold(result.key_alias)}`);
|
|
2406
|
+
console.log(` Store password: ${chalk18.bold(result.store_password)}`);
|
|
2407
|
+
console.log(` Key password: ${chalk18.bold(result.key_password)}`);
|
|
2363
2408
|
console.log("");
|
|
2364
2409
|
console.log(
|
|
2365
|
-
|
|
2410
|
+
chalk18.yellow(
|
|
2366
2411
|
" These are shown ONCE \u2014 VibeView cannot recover the keystore file or its passwords. Back them up somewhere safe."
|
|
2367
2412
|
)
|
|
2368
2413
|
);
|
|
2369
2414
|
console.log(
|
|
2370
|
-
|
|
2415
|
+
chalk18.yellow(
|
|
2371
2416
|
" The credential is already uploaded and active for android and androidtv production builds."
|
|
2372
2417
|
)
|
|
2373
2418
|
);
|
|
@@ -2393,19 +2438,19 @@ async function generateAppleCredential(platform, opts, d) {
|
|
|
2393
2438
|
if (opts.json) {
|
|
2394
2439
|
console.log(JSON.stringify(result));
|
|
2395
2440
|
} else {
|
|
2396
|
-
console.log(
|
|
2441
|
+
console.log(chalk18.green(`\u2713 generated ${result.name} (${result.platform})`));
|
|
2397
2442
|
console.log("");
|
|
2398
|
-
console.log(` Scope: ${
|
|
2443
|
+
console.log(` Scope: ${chalk18.bold(result.app_public_id ?? "org-wide")}`);
|
|
2399
2444
|
const expires = formatExpires(result);
|
|
2400
2445
|
if (expires) {
|
|
2401
|
-
console.log(` Expires: ${
|
|
2446
|
+
console.log(` Expires: ${chalk18.bold(expires)}`);
|
|
2402
2447
|
}
|
|
2403
2448
|
console.log("");
|
|
2404
2449
|
console.log(
|
|
2405
2450
|
` The certificate and provisioning profile are stored with VibeView and already active for ${result.platform} production builds.`
|
|
2406
2451
|
);
|
|
2407
2452
|
console.log(
|
|
2408
|
-
` Run ${
|
|
2453
|
+
` Run ${chalk18.bold(`vibeview credentials download ${result.name}`)} if you need the files locally.`
|
|
2409
2454
|
);
|
|
2410
2455
|
}
|
|
2411
2456
|
process.exitCode = 0;
|
|
@@ -2471,17 +2516,17 @@ async function credentialsDownload(name, opts, deps) {
|
|
|
2471
2516
|
await d.chmod(path, 384);
|
|
2472
2517
|
}
|
|
2473
2518
|
if (!opts.json) {
|
|
2474
|
-
console.log(
|
|
2519
|
+
console.log(chalk18.green(`\u2713 downloaded ${material.name} (${material.platform})`));
|
|
2475
2520
|
console.log("");
|
|
2476
|
-
console.log(` Saved to: ${
|
|
2521
|
+
console.log(` Saved to: ${chalk18.bold(savedTo)}`);
|
|
2477
2522
|
if (profileSavedTo !== null) {
|
|
2478
|
-
console.log(` Profile: ${
|
|
2523
|
+
console.log(` Profile: ${chalk18.bold(profileSavedTo)}`);
|
|
2479
2524
|
}
|
|
2480
2525
|
for (const [key, value] of Object.entries(material.passwords)) {
|
|
2481
|
-
console.log(` ${key}: ${
|
|
2526
|
+
console.log(` ${key}: ${chalk18.bold(value)}`);
|
|
2482
2527
|
}
|
|
2483
2528
|
console.log("");
|
|
2484
|
-
console.log(
|
|
2529
|
+
console.log(chalk18.yellow(" This download is recorded in your organization's audit log."));
|
|
2485
2530
|
}
|
|
2486
2531
|
process.exitCode = 0;
|
|
2487
2532
|
} catch (err) {
|
|
@@ -2512,13 +2557,13 @@ async function ascKeyAdd(opts, deps) {
|
|
|
2512
2557
|
if (opts.json) {
|
|
2513
2558
|
console.log(JSON.stringify(result));
|
|
2514
2559
|
} else {
|
|
2515
|
-
console.log(
|
|
2560
|
+
console.log(chalk18.green(`\u2713 added App Store Connect key ${result.name}`));
|
|
2516
2561
|
console.log("");
|
|
2517
|
-
console.log(` Key ID: ${
|
|
2518
|
-
console.log(` Issuer ID: ${
|
|
2562
|
+
console.log(` Key ID: ${chalk18.bold(result.key_id)}`);
|
|
2563
|
+
console.log(` Issuer ID: ${chalk18.bold(result.issuer_id)}`);
|
|
2519
2564
|
console.log("");
|
|
2520
2565
|
console.log(
|
|
2521
|
-
|
|
2566
|
+
chalk18.yellow(
|
|
2522
2567
|
" The .p8 is stored encrypted and will never be shown again \u2014 keep your own copy somewhere safe."
|
|
2523
2568
|
)
|
|
2524
2569
|
);
|
|
@@ -2553,7 +2598,7 @@ function formatAscKeysHuman(keys) {
|
|
|
2553
2598
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2554
2599
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2555
2600
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2556
|
-
const lines = [
|
|
2601
|
+
const lines = [chalk18.bold(join3(padCells(HEADERS3)))];
|
|
2557
2602
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2558
2603
|
return lines.join("\n") + "\n";
|
|
2559
2604
|
}
|
|
@@ -2564,7 +2609,7 @@ async function ascKeyRm(name, opts, deps) {
|
|
|
2564
2609
|
if (opts.json) {
|
|
2565
2610
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2566
2611
|
} else {
|
|
2567
|
-
console.log(
|
|
2612
|
+
console.log(chalk18.green(`\u2713 removed App Store Connect key ${name}`));
|
|
2568
2613
|
}
|
|
2569
2614
|
process.exitCode = 0;
|
|
2570
2615
|
} catch (err) {
|
|
@@ -2589,12 +2634,12 @@ async function playKeyAdd(opts, deps) {
|
|
|
2589
2634
|
if (opts.json) {
|
|
2590
2635
|
console.log(JSON.stringify(result));
|
|
2591
2636
|
} else {
|
|
2592
|
-
console.log(
|
|
2637
|
+
console.log(chalk18.green(`\u2713 added Google Play key ${result.name}`));
|
|
2593
2638
|
console.log("");
|
|
2594
|
-
console.log(` Service account: ${
|
|
2639
|
+
console.log(` Service account: ${chalk18.bold(result.client_email)}`);
|
|
2595
2640
|
console.log("");
|
|
2596
2641
|
console.log(
|
|
2597
|
-
|
|
2642
|
+
chalk18.yellow(
|
|
2598
2643
|
" The JSON key is stored encrypted and will never be shown again \u2014 keep your own copy somewhere safe."
|
|
2599
2644
|
)
|
|
2600
2645
|
);
|
|
@@ -2629,7 +2674,7 @@ function formatPlayKeysHuman(keys) {
|
|
|
2629
2674
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2630
2675
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2631
2676
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2632
|
-
const lines = [
|
|
2677
|
+
const lines = [chalk18.bold(join3(padCells(HEADERS3)))];
|
|
2633
2678
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2634
2679
|
return lines.join("\n") + "\n";
|
|
2635
2680
|
}
|
|
@@ -2640,7 +2685,7 @@ async function playKeyRm(name, opts, deps) {
|
|
|
2640
2685
|
if (opts.json) {
|
|
2641
2686
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2642
2687
|
} else {
|
|
2643
|
-
console.log(
|
|
2688
|
+
console.log(chalk18.green(`\u2713 removed Google Play key ${name}`));
|
|
2644
2689
|
}
|
|
2645
2690
|
process.exitCode = 0;
|
|
2646
2691
|
} catch (err) {
|
|
@@ -2709,7 +2754,7 @@ function formatCredentialsHuman(credentials2) {
|
|
|
2709
2754
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2710
2755
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2711
2756
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2712
|
-
const lines = [
|
|
2757
|
+
const lines = [chalk18.bold(join3(padCells(HEADERS3)))];
|
|
2713
2758
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2714
2759
|
return lines.join("\n") + "\n";
|
|
2715
2760
|
}
|
|
@@ -2720,7 +2765,7 @@ async function credentialsRm(name, opts, deps) {
|
|
|
2720
2765
|
if (opts.json) {
|
|
2721
2766
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2722
2767
|
} else {
|
|
2723
|
-
console.log(
|
|
2768
|
+
console.log(chalk18.green(`\u2713 removed ${name}`));
|
|
2724
2769
|
}
|
|
2725
2770
|
process.exitCode = 0;
|
|
2726
2771
|
} catch (err) {
|
|
@@ -2732,16 +2777,16 @@ function printKeystoreWriteFailure(opts, err, result) {
|
|
|
2732
2777
|
const message = err instanceof Error ? err.message : String(err);
|
|
2733
2778
|
if (opts.json) {
|
|
2734
2779
|
console.log(JSON.stringify({ event: "error", message }));
|
|
2735
|
-
console.error(
|
|
2780
|
+
console.error(chalk18.red(`error: ${message}`));
|
|
2736
2781
|
return;
|
|
2737
2782
|
}
|
|
2738
|
-
console.error(
|
|
2783
|
+
console.error(chalk18.red(`error: ${message}`));
|
|
2739
2784
|
console.error(
|
|
2740
|
-
|
|
2785
|
+
chalk18.red(
|
|
2741
2786
|
`The keystore could NOT be saved locally, but the credential "${result.name}" WAS created server-side and its key material can never be re-fetched.`
|
|
2742
2787
|
)
|
|
2743
2788
|
);
|
|
2744
|
-
console.error(
|
|
2789
|
+
console.error(chalk18.red("Recover it NOW from the values below \u2014 they will not be shown again:"));
|
|
2745
2790
|
console.error("");
|
|
2746
2791
|
console.error(` Key alias: ${result.key_alias}`);
|
|
2747
2792
|
console.error(` Store password: ${result.store_password}`);
|
|
@@ -2755,11 +2800,11 @@ function printKeystoreWriteFailure(opts, err, result) {
|
|
|
2755
2800
|
function printError5(opts, err) {
|
|
2756
2801
|
const message = err instanceof Error ? err.message : String(err);
|
|
2757
2802
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
2758
|
-
console.error(
|
|
2803
|
+
console.error(chalk18.red(`error: ${message}`));
|
|
2759
2804
|
}
|
|
2760
2805
|
|
|
2761
2806
|
// src/commands/webhooks.ts
|
|
2762
|
-
import
|
|
2807
|
+
import chalk19 from "chalk";
|
|
2763
2808
|
function clientFor3(opts) {
|
|
2764
2809
|
const { token, baseUrl } = resolveAuth(opts);
|
|
2765
2810
|
return new ApiClient(baseUrl, token);
|
|
@@ -2790,14 +2835,14 @@ async function webhooksAdd(opts, deps) {
|
|
|
2790
2835
|
if (opts.json) {
|
|
2791
2836
|
console.log(JSON.stringify(result));
|
|
2792
2837
|
} else {
|
|
2793
|
-
console.log(
|
|
2838
|
+
console.log(chalk19.green(`\u2713 added ${result.id} ${result.url}`));
|
|
2794
2839
|
console.log("");
|
|
2795
|
-
console.log(` Signing secret: ${
|
|
2840
|
+
console.log(` Signing secret: ${chalk19.bold(result.secret)}`);
|
|
2796
2841
|
if (opts.secret !== void 0) {
|
|
2797
|
-
console.log(
|
|
2842
|
+
console.log(chalk19.yellow(" (This is the secret you provided.)"));
|
|
2798
2843
|
}
|
|
2799
2844
|
console.log(
|
|
2800
|
-
|
|
2845
|
+
chalk19.yellow(" This secret is shown ONCE and cannot be retrieved again \u2014 store it now.")
|
|
2801
2846
|
);
|
|
2802
2847
|
}
|
|
2803
2848
|
process.exitCode = 0;
|
|
@@ -2828,7 +2873,7 @@ function formatWebhooksHuman(webhooks2) {
|
|
|
2828
2873
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2829
2874
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2830
2875
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2831
|
-
const lines = [
|
|
2876
|
+
const lines = [chalk19.bold(join3(padCells(HEADERS3)))];
|
|
2832
2877
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2833
2878
|
return lines.join("\n") + "\n";
|
|
2834
2879
|
}
|
|
@@ -2854,7 +2899,7 @@ async function webhooksRm(id, opts, deps) {
|
|
|
2854
2899
|
if (opts.json) {
|
|
2855
2900
|
console.log(JSON.stringify({ event: "deleted", id }));
|
|
2856
2901
|
} else {
|
|
2857
|
-
console.log(
|
|
2902
|
+
console.log(chalk19.green(`\u2713 removed ${id}`));
|
|
2858
2903
|
}
|
|
2859
2904
|
process.exitCode = 0;
|
|
2860
2905
|
} catch (err) {
|
|
@@ -2887,13 +2932,13 @@ async function webhooksTest(id, opts, deps) {
|
|
|
2887
2932
|
if (opts.json) console.log(JSON.stringify(ld));
|
|
2888
2933
|
if (ld.status === "succeeded") {
|
|
2889
2934
|
if (!opts.json) {
|
|
2890
|
-
console.log(
|
|
2935
|
+
console.log(chalk19.green(`\u2713 Delivered (HTTP ${ld.response_code})`));
|
|
2891
2936
|
}
|
|
2892
2937
|
process.exitCode = 0;
|
|
2893
2938
|
} else {
|
|
2894
2939
|
if (!opts.json) {
|
|
2895
2940
|
const code = ld.response_code != null ? `HTTP ${ld.response_code}` : "no response";
|
|
2896
|
-
console.error(
|
|
2941
|
+
console.error(chalk19.red(`\u2717 Failed (${code}) at ${ld.at}`));
|
|
2897
2942
|
}
|
|
2898
2943
|
process.exitCode = 1;
|
|
2899
2944
|
}
|
|
@@ -2902,7 +2947,7 @@ async function webhooksTest(id, opts, deps) {
|
|
|
2902
2947
|
}
|
|
2903
2948
|
if (opts.json) console.log(JSON.stringify({ status: "pending" }));
|
|
2904
2949
|
console.error(
|
|
2905
|
-
|
|
2950
|
+
chalk19.yellow(
|
|
2906
2951
|
`Delivery still pending after ${TEST_POLL_BUDGET_MS / 1e3}s \u2014 check \`vibeview webhooks list\` later for the result.`
|
|
2907
2952
|
)
|
|
2908
2953
|
);
|
|
@@ -2915,7 +2960,7 @@ async function webhooksTest(id, opts, deps) {
|
|
|
2915
2960
|
function printError6(opts, err) {
|
|
2916
2961
|
const message = err instanceof Error ? err.message : String(err);
|
|
2917
2962
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
2918
|
-
console.error(
|
|
2963
|
+
console.error(chalk19.red(`error: ${message}`));
|
|
2919
2964
|
}
|
|
2920
2965
|
|
|
2921
2966
|
// src/commands/list-devices.ts
|
|
@@ -3015,7 +3060,7 @@ import { dirname, join as join2 } from "path";
|
|
|
3015
3060
|
import { fileURLToPath } from "url";
|
|
3016
3061
|
import { spawnSync } from "child_process";
|
|
3017
3062
|
import { confirm } from "@inquirer/prompts";
|
|
3018
|
-
import
|
|
3063
|
+
import chalk20 from "chalk";
|
|
3019
3064
|
function resolveShippedSkillPath(fromDir) {
|
|
3020
3065
|
for (const rel of ["..", join2("..", "..")]) {
|
|
3021
3066
|
const candidate = join2(fromDir, rel, "skills", "vibeview-agent", "SKILL.md");
|
|
@@ -3043,23 +3088,23 @@ function registerMcp() {
|
|
|
3043
3088
|
encoding: "utf8"
|
|
3044
3089
|
});
|
|
3045
3090
|
if (res.status === 0) {
|
|
3046
|
-
console.log(
|
|
3091
|
+
console.log(chalk20.green("\u2713 MCP server registered with Claude Code (claude mcp add vibeview)"));
|
|
3047
3092
|
return;
|
|
3048
3093
|
}
|
|
3049
3094
|
const out = `${res.stderr ?? ""}${res.stdout ?? ""}`;
|
|
3050
3095
|
if (out.includes("already exists")) {
|
|
3051
|
-
console.log(
|
|
3096
|
+
console.log(chalk20.dim("MCP server already registered with Claude Code \u2014 nothing to do"));
|
|
3052
3097
|
return;
|
|
3053
3098
|
}
|
|
3054
|
-
console.error(
|
|
3055
|
-
console.error(
|
|
3099
|
+
console.error(chalk20.yellow(`\u26A0 could not register the MCP server: ${out.trim() || res.error}`));
|
|
3100
|
+
console.error(chalk20.yellow(" register it manually: claude mcp add vibeview -- vibeview mcp"));
|
|
3056
3101
|
}
|
|
3057
3102
|
async function agentSetup(opts) {
|
|
3058
3103
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
3059
3104
|
const shipped = resolveShippedSkillPath(moduleDir);
|
|
3060
3105
|
if (!shipped) {
|
|
3061
3106
|
console.error(
|
|
3062
|
-
|
|
3107
|
+
chalk20.red(
|
|
3063
3108
|
"error: could not find the packaged skill (skills/vibeview-agent/SKILL.md) \u2014 is this a complete install of the vibeview package?"
|
|
3064
3109
|
)
|
|
3065
3110
|
);
|
|
@@ -3068,9 +3113,9 @@ async function agentSetup(opts) {
|
|
|
3068
3113
|
}
|
|
3069
3114
|
const targetDir = skillInstallDir(opts.project ?? false, process.cwd(), homedir());
|
|
3070
3115
|
const result = installSkill(shipped, targetDir);
|
|
3071
|
-
console.log(
|
|
3116
|
+
console.log(chalk20.green(`\u2713 vibeview-agent skill ${result}: ${join2(targetDir, "SKILL.md")}`));
|
|
3072
3117
|
console.log(
|
|
3073
|
-
|
|
3118
|
+
chalk20.dim(
|
|
3074
3119
|
opts.project ? " Claude Code discovers it automatically for anyone working in this project." : " Claude Code discovers it automatically in every project on this machine."
|
|
3075
3120
|
)
|
|
3076
3121
|
);
|
|
@@ -3078,7 +3123,7 @@ async function agentSetup(opts) {
|
|
|
3078
3123
|
if (!claudeCliAvailable()) {
|
|
3079
3124
|
if (opts.mcp === true) {
|
|
3080
3125
|
console.error(
|
|
3081
|
-
|
|
3126
|
+
chalk20.yellow(
|
|
3082
3127
|
"\u26A0 claude CLI not found \u2014 install Claude Code, then run: claude mcp add vibeview -- vibeview mcp"
|
|
3083
3128
|
)
|
|
3084
3129
|
);
|
|
@@ -3092,7 +3137,7 @@ async function agentSetup(opts) {
|
|
|
3092
3137
|
}
|
|
3093
3138
|
console.log(
|
|
3094
3139
|
`
|
|
3095
|
-
Suggested line for your project's ${
|
|
3140
|
+
Suggested line for your project's ${chalk20.bold("CLAUDE.md")} (or ${chalk20.bold(
|
|
3096
3141
|
"AGENTS.md"
|
|
3097
3142
|
)} for other agents):
|
|
3098
3143
|
`
|
|
@@ -3100,7 +3145,7 @@ Suggested line for your project's ${chalk19.bold("CLAUDE.md")} (or ${chalk19.bol
|
|
|
3100
3145
|
console.log(` ${CLAUDE_MD_SUGGESTION}
|
|
3101
3146
|
`);
|
|
3102
3147
|
console.log(
|
|
3103
|
-
|
|
3148
|
+
chalk20.dim(
|
|
3104
3149
|
"Other agents (Cursor, Copilot, Codex, ...): install the same skill from GitHub with\n npx skills add vibeview/skills\nor point them at the skill file above, or add the MCP server per client \u2014\nsee https://vibeview.io/docs/agent-control"
|
|
3105
3150
|
)
|
|
3106
3151
|
);
|
|
@@ -3222,6 +3267,9 @@ program.command("list-suites").description("List available test suites").option(
|
|
|
3222
3267
|
[]
|
|
3223
3268
|
).option("--match <mode>", "When multiple --tag flags: any (default) or all", "any").action((opts) => listSuites(opts));
|
|
3224
3269
|
program.command("list-apps").description("List apps in your organization").option("--token <token>", "API token").option("--output <format>", "Output format: human, json", "human").action((opts) => listApps(opts));
|
|
3270
|
+
program.command("list-builds <app>").description(
|
|
3271
|
+
"List an app's uploaded builds, newest first: id, version, platform, debug/release, upload time and note (the ids `dev --build <id>` and `run-test --build` take)"
|
|
3272
|
+
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print the builds as a JSON array", false).action((app, opts) => listBuilds(app, opts));
|
|
3225
3273
|
program.command("list-devices").description("List devices registered with the platform (filterable by type and category)").option("--token <token>", "API token").option("--output <format>", "Output format: human, json", "human").option("--type <type>", "Filter by device type: ios, android, roku").option("--category <category>", "Filter by category: phone, tablet, tv").option("--status <status>", "Filter by status: available, busy, offline").option(
|
|
3226
3274
|
"--models",
|
|
3227
3275
|
"List the device models you can start instead (the names `dev --model` takes)",
|
|
@@ -3250,8 +3298,8 @@ program.command("dev").description(
|
|
|
3250
3298
|
"Run the dev session in the background; prints session info and exits (see `dev-status`, `dev-stop`, and `dev-reload` for Roku)",
|
|
3251
3299
|
false
|
|
3252
3300
|
).option(
|
|
3253
|
-
"--build",
|
|
3254
|
-
"
|
|
3301
|
+
"--build [id]",
|
|
3302
|
+
"Bare: build and upload first (uses platforms.<platform>.build from vibeview.json). With an id: run that uploaded debug build instead of the newest one (see `vibeview list-builds <app>`)",
|
|
3255
3303
|
false
|
|
3256
3304
|
).option(
|
|
3257
3305
|
"--watch [seconds]",
|
|
@@ -3387,13 +3435,16 @@ webhooks.command("rm <id>").description("Remove a webhook endpoint (rotate the s
|
|
|
3387
3435
|
webhooks.command("test <id>").description("Send a ping delivery and wait up to 60s for the result").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print the final delivery result as one JSON line", false).action((id, opts) => webhooksTest(id, opts));
|
|
3388
3436
|
program.command("dev-status").description("Show the status of a `vibeview dev --detach` session in this project").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print as one JSON line", false).action((opts) => devStatus(opts));
|
|
3389
3437
|
program.command("dev-stop").description("Stop a `vibeview dev --detach` session in this project").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print as one JSON line", false).action((opts) => devStop(opts));
|
|
3438
|
+
program.command("stop <session-id>").description(
|
|
3439
|
+
"Stop any session by id \u2014 e.g. one started from the API, the sandbox, or a collaboration link (`dev-stop` stops this project's detached dev session without an id)"
|
|
3440
|
+
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print the result as one JSON line", false).action((sessionId, opts) => stopCommand(sessionId, opts));
|
|
3390
3441
|
program.command("dev-reload").description(
|
|
3391
3442
|
"Roku only: re-package, upload and reload the channel into this project's `vibeview dev --detach` session (the `r` key of the foreground loop)"
|
|
3392
3443
|
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print as one JSON line", false).action((opts) => devReload(opts));
|
|
3393
3444
|
program.command("mcp").description(
|
|
3394
3445
|
"Run an MCP stdio server exposing the agent verbs (tap, swipe, type, ...) plus dev_start/dev_stop/dev_reload as tools"
|
|
3395
3446
|
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").action(async (opts) => {
|
|
3396
|
-
const { runMcpServer } = await import("./server-
|
|
3447
|
+
const { runMcpServer } = await import("./server-6EUBLXKE.js");
|
|
3397
3448
|
await runMcpServer(opts);
|
|
3398
3449
|
});
|
|
3399
3450
|
program.command("agent-setup").description(
|