adb-ready 0.5.0 → 0.5.1
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 +19 -1
- package/README.md +2 -0
- package/dist/cli.js +270 -64
- package/docs/getting-started.md +6 -1
- package/docs/targets-and-wireless.md +4 -0
- package/package.json +1 -1
- package/schema/agent-tools-v1.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,23 @@ breaking changes.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.5.1] - 2026-09-25
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Add a first-device guide under Start that walks new users through USB,
|
|
17
|
+
Android 11+ Wireless debugging, or an existing emulator before handing off
|
|
18
|
+
to the normal verified devices, pairing, or connection workflow.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Make interactive selection unmistakable with one directional cursor and a
|
|
23
|
+
high-contrast active row, while retaining explicit no-color and ASCII
|
|
24
|
+
fallbacks and removing distracting markers from inactive choices.
|
|
25
|
+
- Group session launch, planning, bounded verification, wireless connection,
|
|
26
|
+
and pairing under one focused Start workflow instead of scattering entry
|
|
27
|
+
actions across unrelated top-level categories.
|
|
28
|
+
|
|
12
29
|
## [0.5.0] - 2026-09-21
|
|
13
30
|
|
|
14
31
|
### Fixed
|
|
@@ -406,7 +423,8 @@ breaking changes.
|
|
|
406
423
|
explainable configuration precedence.
|
|
407
424
|
- Human, plain, JSON, and NDJSON output across Node, Bun, and Deno entrypoints.
|
|
408
425
|
|
|
409
|
-
[Unreleased]: https://github.com/Adam014/adb-ready/compare/v0.5.
|
|
426
|
+
[Unreleased]: https://github.com/Adam014/adb-ready/compare/v0.5.1...HEAD
|
|
427
|
+
[0.5.1]: https://github.com/Adam014/adb-ready/compare/v0.5.0...v0.5.1
|
|
410
428
|
[0.5.0]: https://github.com/Adam014/adb-ready/compare/v0.4.1...v0.5.0
|
|
411
429
|
[0.4.1]: https://github.com/Adam014/adb-ready/compare/v0.4.0...v0.4.1
|
|
412
430
|
[0.4.0]: https://github.com/Adam014/adb-ready/compare/v0.3.5...v0.4.0
|
package/README.md
CHANGED
|
@@ -71,6 +71,8 @@ them or require an ADB Ready account, hosted service, or model API key.
|
|
|
71
71
|
|
|
72
72
|
Running `adb-ready` without a command opens the interactive workflow home.
|
|
73
73
|
`adbr` is the shorter alias for the same CLI.
|
|
74
|
+
New to Android device setup? Open **Start → Set up first device** for a guided
|
|
75
|
+
USB, Wireless debugging, or emulator path.
|
|
74
76
|
The home and its focused menus adapt to the detected terminal width and height,
|
|
75
77
|
including narrow split panes and short terminals, without relying on scrolling
|
|
76
78
|
to reveal an action.
|
package/dist/cli.js
CHANGED
|
@@ -3304,7 +3304,7 @@ import process15 from "node:process";
|
|
|
3304
3304
|
// package.json
|
|
3305
3305
|
var package_default = {
|
|
3306
3306
|
name: "adb-ready",
|
|
3307
|
-
version: "0.5.
|
|
3307
|
+
version: "0.5.1",
|
|
3308
3308
|
description: "Agent-ready Android CLI for reliable ADB sessions, app automation, and verified evidence.",
|
|
3309
3309
|
private: false,
|
|
3310
3310
|
type: "module",
|
|
@@ -41609,7 +41609,7 @@ async function pruneSessions(options) {
|
|
|
41609
41609
|
if (!listed.ok)
|
|
41610
41610
|
return;
|
|
41611
41611
|
const completed = listed.value.filter(({ status }) => status !== "running").sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
41612
|
-
const cutoff = Date.
|
|
41612
|
+
const cutoff = (options.clock ?? (() => new Date))().getTime() - maxAgeDays * 24 * 60 * 60 * 1000;
|
|
41613
41613
|
const groups = new Map;
|
|
41614
41614
|
for (const manifest of completed) {
|
|
41615
41615
|
const key = manifest.projectFingerprint ?? "legacy-unscoped";
|
|
@@ -43635,7 +43635,8 @@ async function runDev(options, config4 = {}, dependencies = {}, signal) {
|
|
|
43635
43635
|
projectRoot: options.cwd
|
|
43636
43636
|
}, {
|
|
43637
43637
|
...options.sessionStore,
|
|
43638
|
-
projectRoot: options.sessionStore.projectRoot ?? options.cwd
|
|
43638
|
+
projectRoot: options.sessionStore.projectRoot ?? options.cwd,
|
|
43639
|
+
...dependencies.clock === undefined ? {} : { clock: dependencies.clock }
|
|
43639
43640
|
});
|
|
43640
43641
|
} catch {
|
|
43641
43642
|
problems.push({
|
|
@@ -51402,10 +51403,14 @@ function symbols(capabilities) {
|
|
|
51402
51403
|
function color(code, value, capabilities) {
|
|
51403
51404
|
return capabilities.color ? `\x1B[${String(code)}m${value}\x1B[0m` : value;
|
|
51404
51405
|
}
|
|
51406
|
+
function selected(value, capabilities) {
|
|
51407
|
+
return capabilities.color ? `\x1B[1;7m${value}\x1B[0m` : value;
|
|
51408
|
+
}
|
|
51405
51409
|
var style = {
|
|
51406
51410
|
accent: (value, capabilities) => color(36, value, capabilities),
|
|
51407
51411
|
dim: (value, capabilities) => color(2, value, capabilities),
|
|
51408
51412
|
failure: (value, capabilities) => color(31, value, capabilities),
|
|
51413
|
+
selected,
|
|
51409
51414
|
strong: (value, capabilities) => color(1, value, capabilities),
|
|
51410
51415
|
success: (value, capabilities) => color(32, value, capabilities),
|
|
51411
51416
|
warning: (value, capabilities) => color(33, value, capabilities)
|
|
@@ -51465,7 +51470,7 @@ function initialIndex(options) {
|
|
|
51465
51470
|
}
|
|
51466
51471
|
return options.findIndex((option) => option.disabled !== true);
|
|
51467
51472
|
}
|
|
51468
|
-
function renderMenu(options,
|
|
51473
|
+
function renderMenu(options, selected2, previousLineCount, frame) {
|
|
51469
51474
|
const { capabilities, sink } = options;
|
|
51470
51475
|
const glyphs = symbols(capabilities);
|
|
51471
51476
|
const availableColumns = Math.max(19, capabilities.columns - 1);
|
|
@@ -51481,14 +51486,15 @@ function renderMenu(options, selected, previousLineCount, frame) {
|
|
|
51481
51486
|
const lines = [...options.preamble?.(frame) ?? []];
|
|
51482
51487
|
lines.push(`${style.dim(top, capabilities)} ${style.strong(truncate(sanitizeTerminalText(options.title), Math.max(8, availableColumns - 4)), capabilities)}`);
|
|
51483
51488
|
options.options.forEach((option, index) => {
|
|
51484
|
-
const isSelected = index ===
|
|
51485
|
-
const pointer = isSelected ? style.accent(
|
|
51486
|
-
const number8 =
|
|
51489
|
+
const isSelected = index === selected2;
|
|
51490
|
+
const pointer = isSelected ? style.accent(capabilities.unicode ? "›" : ">", capabilities) : option.disabled === true ? style.dim(glyphs.skipped, capabilities) : " ";
|
|
51491
|
+
const number8 = `[${String(index + 1)}]`;
|
|
51487
51492
|
const disabled = option.disabled === true ? " · unavailable" : "";
|
|
51488
51493
|
const recommended = option.recommended === true ? " · recommended" : "";
|
|
51489
51494
|
const label = truncate(`${sanitizeTerminalText(option.label)}${disabled}${recommended}`, Math.max(8, availableColumns - 10));
|
|
51490
|
-
const
|
|
51491
|
-
|
|
51495
|
+
const row = `${number8} ${label}`;
|
|
51496
|
+
const styledRow = option.disabled === true ? style.dim(row, capabilities) : isSelected ? style.selected(row, capabilities) : `${style.dim(number8, capabilities)} ${label}`;
|
|
51497
|
+
lines.push(` ${pointer} ${styledRow}`);
|
|
51492
51498
|
if (isSelected && option.description !== undefined) {
|
|
51493
51499
|
for (const description of wrap(option.description, Math.max(10, availableColumns - 9))) {
|
|
51494
51500
|
lines.push(` ${style.accent(rail, capabilities)} ${style.dim(description, capabilities)}`);
|
|
@@ -51512,8 +51518,8 @@ async function selectOne(options) {
|
|
|
51512
51518
|
if (!options.capabilities.interactive || options.input.setRawMode === undefined) {
|
|
51513
51519
|
return { kind: "unavailable" };
|
|
51514
51520
|
}
|
|
51515
|
-
let
|
|
51516
|
-
if (
|
|
51521
|
+
let selected2 = initialIndex(options.options);
|
|
51522
|
+
if (selected2 === -1) {
|
|
51517
51523
|
return { kind: "unavailable" };
|
|
51518
51524
|
}
|
|
51519
51525
|
return await new Promise((resolve) => {
|
|
@@ -51556,7 +51562,7 @@ async function selectOne(options) {
|
|
|
51556
51562
|
resolve(result);
|
|
51557
51563
|
};
|
|
51558
51564
|
const draw = () => {
|
|
51559
|
-
lineCount = renderMenu(options,
|
|
51565
|
+
lineCount = renderMenu(options, selected2, lineCount, frame);
|
|
51560
51566
|
};
|
|
51561
51567
|
const onAbort = () => settle3({ kind: "cancelled", reason: "signal" });
|
|
51562
51568
|
const cancelEscape = () => {
|
|
@@ -51571,13 +51577,13 @@ async function selectOne(options) {
|
|
|
51571
51577
|
}
|
|
51572
51578
|
if (bufferedInput.startsWith("\x1B[A")) {
|
|
51573
51579
|
bufferedInput = bufferedInput.slice(3);
|
|
51574
|
-
|
|
51580
|
+
selected2 = nextEnabled(options.options, selected2, -1);
|
|
51575
51581
|
draw();
|
|
51576
51582
|
continue;
|
|
51577
51583
|
}
|
|
51578
51584
|
if (bufferedInput.startsWith("\x1B[B")) {
|
|
51579
51585
|
bufferedInput = bufferedInput.slice(3);
|
|
51580
|
-
|
|
51586
|
+
selected2 = nextEnabled(options.options, selected2, 1);
|
|
51581
51587
|
draw();
|
|
51582
51588
|
continue;
|
|
51583
51589
|
}
|
|
@@ -51593,7 +51599,7 @@ async function selectOne(options) {
|
|
|
51593
51599
|
bufferedInput = bufferedInput.slice(1);
|
|
51594
51600
|
if (character === "\r" || character === `
|
|
51595
51601
|
`) {
|
|
51596
|
-
const selectedOption = options.options[
|
|
51602
|
+
const selectedOption = options.options[selected2];
|
|
51597
51603
|
if (selectedOption !== undefined && selectedOption.disabled !== true) {
|
|
51598
51604
|
settle3({ kind: "selected", value: selectedOption.value });
|
|
51599
51605
|
}
|
|
@@ -51602,7 +51608,7 @@ async function selectOne(options) {
|
|
|
51602
51608
|
if (character !== undefined && /^[1-9]$/u.test(character)) {
|
|
51603
51609
|
const index = Number(character) - 1;
|
|
51604
51610
|
if (options.options[index] !== undefined && options.options[index]?.disabled !== true) {
|
|
51605
|
-
|
|
51611
|
+
selected2 = index;
|
|
51606
51612
|
draw();
|
|
51607
51613
|
}
|
|
51608
51614
|
}
|
|
@@ -51788,6 +51794,190 @@ function startDevControls(options) {
|
|
|
51788
51794
|
return { dispose, stopRequested };
|
|
51789
51795
|
}
|
|
51790
51796
|
|
|
51797
|
+
// src/ui/device-setup.ts
|
|
51798
|
+
function wrap2(value, width) {
|
|
51799
|
+
const words = sanitizeTerminalText(value).split(" ");
|
|
51800
|
+
const lines = [];
|
|
51801
|
+
let current = "";
|
|
51802
|
+
for (const word of words) {
|
|
51803
|
+
const candidate = current === "" ? word : `${current} ${word}`;
|
|
51804
|
+
if (candidate.length <= width) {
|
|
51805
|
+
current = candidate;
|
|
51806
|
+
continue;
|
|
51807
|
+
}
|
|
51808
|
+
if (current !== "")
|
|
51809
|
+
lines.push(current);
|
|
51810
|
+
current = word;
|
|
51811
|
+
}
|
|
51812
|
+
if (current !== "")
|
|
51813
|
+
lines.push(current);
|
|
51814
|
+
return lines;
|
|
51815
|
+
}
|
|
51816
|
+
function guide(title, steps, capabilities) {
|
|
51817
|
+
const width = Math.max(18, capabilities.columns - 8);
|
|
51818
|
+
const rail = capabilities.unicode ? "│" : "|";
|
|
51819
|
+
const lines = [style.accent(`DEVICE SETUP · ${title}`, capabilities), ""];
|
|
51820
|
+
for (const [index, step] of steps.entries()) {
|
|
51821
|
+
const prefix = `${String(index + 1)}. `;
|
|
51822
|
+
const wrapped = wrap2(step, Math.max(12, width - prefix.length));
|
|
51823
|
+
for (const [lineIndex, line] of wrapped.entries()) {
|
|
51824
|
+
const marker = lineIndex === 0 ? prefix : " ".repeat(prefix.length);
|
|
51825
|
+
lines.push(`${style.dim(rail, capabilities)} ${marker}${line}`);
|
|
51826
|
+
}
|
|
51827
|
+
}
|
|
51828
|
+
lines.push("");
|
|
51829
|
+
return lines;
|
|
51830
|
+
}
|
|
51831
|
+
function intro(title, detail2, capabilities) {
|
|
51832
|
+
return [
|
|
51833
|
+
style.accent(`DEVICE SETUP · ${title}`, capabilities),
|
|
51834
|
+
...wrap2(detail2, Math.max(18, capabilities.columns - 4)).map((line) => style.dim(line, capabilities)),
|
|
51835
|
+
""
|
|
51836
|
+
];
|
|
51837
|
+
}
|
|
51838
|
+
async function nextStep(options, title, steps, action, label) {
|
|
51839
|
+
const selected2 = await selectOne({
|
|
51840
|
+
title: "READY FOR ADB READY?",
|
|
51841
|
+
options: [
|
|
51842
|
+
{
|
|
51843
|
+
value: action,
|
|
51844
|
+
label,
|
|
51845
|
+
description: "ADB Ready will verify the target before using it.",
|
|
51846
|
+
recommended: true
|
|
51847
|
+
},
|
|
51848
|
+
{ value: "back", label: "Choose another method" }
|
|
51849
|
+
],
|
|
51850
|
+
input: options.input,
|
|
51851
|
+
sink: options.sink,
|
|
51852
|
+
capabilities: options.capabilities,
|
|
51853
|
+
preamble: () => guide(title, steps, options.capabilities),
|
|
51854
|
+
escapeLabel: "back",
|
|
51855
|
+
...options.signal === undefined ? {} : { signal: options.signal }
|
|
51856
|
+
});
|
|
51857
|
+
if (selected2.kind !== "selected")
|
|
51858
|
+
return selected2;
|
|
51859
|
+
return selected2.value === "back" ? { kind: "back" } : { kind: "action", action: selected2.value };
|
|
51860
|
+
}
|
|
51861
|
+
async function showDeviceSetup(options) {
|
|
51862
|
+
while (true) {
|
|
51863
|
+
const target = await selectOne({
|
|
51864
|
+
title: "SET UP YOUR FIRST ANDROID TARGET",
|
|
51865
|
+
options: [
|
|
51866
|
+
{
|
|
51867
|
+
value: "physical",
|
|
51868
|
+
label: "Physical Android device",
|
|
51869
|
+
description: "Connect a phone, tablet, foldable, watch, TV, car, or XR target.",
|
|
51870
|
+
recommended: true
|
|
51871
|
+
},
|
|
51872
|
+
{
|
|
51873
|
+
value: "emulator",
|
|
51874
|
+
label: "Android emulator",
|
|
51875
|
+
description: "Use an existing Android Virtual Device on this computer."
|
|
51876
|
+
}
|
|
51877
|
+
],
|
|
51878
|
+
input: options.input,
|
|
51879
|
+
sink: options.sink,
|
|
51880
|
+
capabilities: options.capabilities,
|
|
51881
|
+
preamble: () => intro("ANDROID", "Choose how this project will reach its development target.", options.capabilities),
|
|
51882
|
+
escapeLabel: "home",
|
|
51883
|
+
...options.signal === undefined ? {} : { signal: options.signal }
|
|
51884
|
+
});
|
|
51885
|
+
if (target.kind !== "selected")
|
|
51886
|
+
return target;
|
|
51887
|
+
if (target.value === "emulator") {
|
|
51888
|
+
const result = await nextStep(options, "ANDROID EMULATOR", [
|
|
51889
|
+
"Open Android Studio, then open Device Manager.",
|
|
51890
|
+
"Start an existing Android Virtual Device and wait for its home screen.",
|
|
51891
|
+
"Continue here; ADB Ready will list and verify the running emulator."
|
|
51892
|
+
], "devices", "Verify running emulator");
|
|
51893
|
+
if (result.kind === "back")
|
|
51894
|
+
continue;
|
|
51895
|
+
return result;
|
|
51896
|
+
}
|
|
51897
|
+
while (true) {
|
|
51898
|
+
const method = await selectOne({
|
|
51899
|
+
title: "HOW SHOULD THIS DEVICE CONNECT?",
|
|
51900
|
+
options: [
|
|
51901
|
+
{
|
|
51902
|
+
value: "usb",
|
|
51903
|
+
label: "USB cable",
|
|
51904
|
+
description: "The most direct first connection; Android asks you to trust this computer.",
|
|
51905
|
+
recommended: true
|
|
51906
|
+
},
|
|
51907
|
+
{
|
|
51908
|
+
value: "wireless",
|
|
51909
|
+
label: "Wireless debugging",
|
|
51910
|
+
description: "Pair Android 11 or newer over the same trusted network."
|
|
51911
|
+
}
|
|
51912
|
+
],
|
|
51913
|
+
input: options.input,
|
|
51914
|
+
sink: options.sink,
|
|
51915
|
+
capabilities: options.capabilities,
|
|
51916
|
+
preamble: () => [style.accent("DEVICE SETUP · PHYSICAL DEVICE", options.capabilities), ""],
|
|
51917
|
+
escapeLabel: "back",
|
|
51918
|
+
...options.signal === undefined ? {} : { signal: options.signal }
|
|
51919
|
+
});
|
|
51920
|
+
if (method.kind !== "selected") {
|
|
51921
|
+
if (method.kind === "cancelled" && method.reason === "escape")
|
|
51922
|
+
break;
|
|
51923
|
+
return method;
|
|
51924
|
+
}
|
|
51925
|
+
if (method.value === "usb") {
|
|
51926
|
+
const result2 = await nextStep(options, "USB", [
|
|
51927
|
+
"On Android, open Settings > About phone and tap Build number seven times. Manufacturer paths can vary; Settings search can find Build number.",
|
|
51928
|
+
"Open Developer options and enable USB debugging.",
|
|
51929
|
+
"Connect a data-capable USB cable, unlock the device, and approve the RSA trust prompt."
|
|
51930
|
+
], "devices", "Verify USB device");
|
|
51931
|
+
if (result2.kind === "back")
|
|
51932
|
+
continue;
|
|
51933
|
+
return result2;
|
|
51934
|
+
}
|
|
51935
|
+
const wireless = await selectOne({
|
|
51936
|
+
title: "WIRELESS DEBUGGING",
|
|
51937
|
+
options: [
|
|
51938
|
+
{
|
|
51939
|
+
value: "pair",
|
|
51940
|
+
label: "Pair this computer",
|
|
51941
|
+
description: "Use Android's temporary six-digit pairing code.",
|
|
51942
|
+
recommended: true
|
|
51943
|
+
},
|
|
51944
|
+
{
|
|
51945
|
+
value: "connect",
|
|
51946
|
+
label: "Connect an already paired device",
|
|
51947
|
+
description: "Discover and verify a device this computer already trusts."
|
|
51948
|
+
}
|
|
51949
|
+
],
|
|
51950
|
+
input: options.input,
|
|
51951
|
+
sink: options.sink,
|
|
51952
|
+
capabilities: options.capabilities,
|
|
51953
|
+
preamble: () => guide("WIRELESS", [
|
|
51954
|
+
"Keep the computer and Android device on the same trusted network.",
|
|
51955
|
+
"On Android 11 or newer, open Developer options > Wireless debugging and turn it on."
|
|
51956
|
+
], options.capabilities),
|
|
51957
|
+
escapeLabel: "back",
|
|
51958
|
+
...options.signal === undefined ? {} : { signal: options.signal }
|
|
51959
|
+
});
|
|
51960
|
+
if (wireless.kind !== "selected") {
|
|
51961
|
+
if (wireless.kind === "cancelled" && wireless.reason === "escape")
|
|
51962
|
+
continue;
|
|
51963
|
+
return wireless;
|
|
51964
|
+
}
|
|
51965
|
+
const result = await nextStep(options, wireless.value === "pair" ? "PAIR WIRELESSLY" : "CONNECT WIRELESSLY", wireless.value === "pair" ? [
|
|
51966
|
+
"In Wireless debugging, choose Pair device with pairing code.",
|
|
51967
|
+
"Keep that screen open. Its pairing address and six-digit code are temporary.",
|
|
51968
|
+
"Continue here; the code is read through a hidden prompt and is never placed in shell history."
|
|
51969
|
+
] : [
|
|
51970
|
+
"Keep Wireless debugging enabled and stay on the same trusted network.",
|
|
51971
|
+
"Return to the main Wireless debugging screen; its connection port normally differs from the pairing port.",
|
|
51972
|
+
"Continue here; ADB Ready will discover and verify the connected target."
|
|
51973
|
+
], wireless.value, wireless.value === "pair" ? "Start secure pairing" : "Find and connect device");
|
|
51974
|
+
if (result.kind === "back")
|
|
51975
|
+
continue;
|
|
51976
|
+
return result;
|
|
51977
|
+
}
|
|
51978
|
+
}
|
|
51979
|
+
}
|
|
51980
|
+
|
|
51791
51981
|
// src/ui/ascii-scene.ts
|
|
51792
51982
|
var FACE_SHADES = ".,:;=+*#%@";
|
|
51793
51983
|
var LINK_PATH = [
|
|
@@ -52011,16 +52201,11 @@ async function showHomeScreen(options) {
|
|
|
52011
52201
|
clearInteractiveScreen(options.sink, options.capabilities);
|
|
52012
52202
|
const rootOptions = [
|
|
52013
52203
|
{
|
|
52014
|
-
value: "
|
|
52015
|
-
label: "Start
|
|
52016
|
-
description: "
|
|
52204
|
+
value: "start",
|
|
52205
|
+
label: "Start",
|
|
52206
|
+
description: "Develop, connect a device, or run a bounded verification.",
|
|
52017
52207
|
recommended: true
|
|
52018
52208
|
},
|
|
52019
|
-
{
|
|
52020
|
-
value: "automation",
|
|
52021
|
-
label: "Test & automate",
|
|
52022
|
-
description: "Preview readiness, run bounded checks, and keep evidence."
|
|
52023
|
-
},
|
|
52024
52209
|
{
|
|
52025
52210
|
value: "device",
|
|
52026
52211
|
label: "Device & app",
|
|
@@ -52039,7 +52224,28 @@ async function showHomeScreen(options) {
|
|
|
52039
52224
|
{ value: "exit", label: "Exit", description: "Close ADB Ready." }
|
|
52040
52225
|
];
|
|
52041
52226
|
const sectionOptions = {
|
|
52042
|
-
|
|
52227
|
+
start: [
|
|
52228
|
+
{
|
|
52229
|
+
value: "dev",
|
|
52230
|
+
label: "Development session",
|
|
52231
|
+
description: "Prepare one target, ports, logs, and your project command.",
|
|
52232
|
+
recommended: true
|
|
52233
|
+
},
|
|
52234
|
+
{
|
|
52235
|
+
value: "setup-device",
|
|
52236
|
+
label: "Set up first device",
|
|
52237
|
+
description: "Follow a guided USB, Wireless debugging, or emulator setup."
|
|
52238
|
+
},
|
|
52239
|
+
{
|
|
52240
|
+
value: "connect",
|
|
52241
|
+
label: "Connect wirelessly",
|
|
52242
|
+
description: "Discover and verify an already paired Wireless debugging target."
|
|
52243
|
+
},
|
|
52244
|
+
{
|
|
52245
|
+
value: "pair",
|
|
52246
|
+
label: "Pair a new device",
|
|
52247
|
+
description: "Pair safely with Android's temporary six-digit code."
|
|
52248
|
+
},
|
|
52043
52249
|
{
|
|
52044
52250
|
value: "dev-plan",
|
|
52045
52251
|
label: "Preview project plan",
|
|
@@ -52049,16 +52255,6 @@ async function showHomeScreen(options) {
|
|
|
52049
52255
|
value: "run-help",
|
|
52050
52256
|
label: "Run a bounded verification",
|
|
52051
52257
|
description: "See how to gate a test on readiness and retain its evidence."
|
|
52052
|
-
},
|
|
52053
|
-
{
|
|
52054
|
-
value: "sessions",
|
|
52055
|
-
label: "Review recent runs",
|
|
52056
|
-
description: "Find completed, failed, or interrupted project sessions."
|
|
52057
|
-
},
|
|
52058
|
-
{
|
|
52059
|
-
value: "context",
|
|
52060
|
-
label: "Create AI debug context",
|
|
52061
|
-
description: "Compile the latest run into a compact redacted brief."
|
|
52062
52258
|
}
|
|
52063
52259
|
],
|
|
52064
52260
|
device: [
|
|
@@ -52076,16 +52272,6 @@ async function showHomeScreen(options) {
|
|
|
52076
52272
|
value: "app-restart",
|
|
52077
52273
|
label: "Restart project app",
|
|
52078
52274
|
description: "Verify a clean stop and launch on the selected target."
|
|
52079
|
-
},
|
|
52080
|
-
{
|
|
52081
|
-
value: "connect",
|
|
52082
|
-
label: "Connect wirelessly",
|
|
52083
|
-
description: "Discover and verify an already paired Wireless debugging target."
|
|
52084
|
-
},
|
|
52085
|
-
{
|
|
52086
|
-
value: "pair",
|
|
52087
|
-
label: "Pair a new target",
|
|
52088
|
-
description: "Pair safely with Android's temporary six-digit code."
|
|
52089
52275
|
}
|
|
52090
52276
|
],
|
|
52091
52277
|
debug: [
|
|
@@ -52157,7 +52343,7 @@ async function showHomeScreen(options) {
|
|
|
52157
52343
|
const visibleOptions = density === "minimal" ? currentOptions.map(({ description: _description, ...option }) => option) : currentOptions;
|
|
52158
52344
|
const numericShortcut = `1-${String(Math.min(currentOptions.length, 9))} jump`;
|
|
52159
52345
|
const selection2 = await selectOne({
|
|
52160
|
-
title: atRoot ? "WHAT DO YOU WANT TO DO?" : `HOME / ${section === "
|
|
52346
|
+
title: atRoot ? "WHAT DO YOU WANT TO DO?" : `HOME / ${section === "start" ? "START" : section === "device" ? "DEVICE & APP" : section === "debug" ? "DEBUG & EVIDENCE" : "PROJECT & SETUP"}`,
|
|
52161
52347
|
options: visibleOptions,
|
|
52162
52348
|
input: options.input,
|
|
52163
52349
|
sink: options.sink,
|
|
@@ -52188,7 +52374,7 @@ async function showHomeScreen(options) {
|
|
|
52188
52374
|
}
|
|
52189
52375
|
return { kind: "cancelled", reason: selection2.reason };
|
|
52190
52376
|
}
|
|
52191
|
-
if (atRoot && selection2.value !== "
|
|
52377
|
+
if (atRoot && selection2.value !== "exit") {
|
|
52192
52378
|
section = selection2.value;
|
|
52193
52379
|
continue;
|
|
52194
52380
|
}
|
|
@@ -54463,14 +54649,14 @@ function parseArguments(argv) {
|
|
|
54463
54649
|
} else if (uiAction === "swipe" || uiAction === "scroll") {
|
|
54464
54650
|
const direction = uiOperands[0];
|
|
54465
54651
|
if ((uiOperands.length === 1 || uiAction === "scroll" && uiOperands.length === 2) && direction !== undefined && new Set(["down", "left", "right", "up"]).has(direction)) {
|
|
54466
|
-
const
|
|
54467
|
-
if (uiAction === "scroll" && uiOperands.length === 2 &&
|
|
54652
|
+
const selected2 = selector(uiOperands[1]);
|
|
54653
|
+
if (uiAction === "scroll" && uiOperands.length === 2 && selected2 === undefined) {
|
|
54468
54654
|
return failure4("CLI_USAGE", "ui scroll accepts an optional valid selector after direction.");
|
|
54469
54655
|
}
|
|
54470
54656
|
uiRequest = uiAction === "scroll" ? {
|
|
54471
54657
|
action: "scroll",
|
|
54472
54658
|
direction,
|
|
54473
|
-
...
|
|
54659
|
+
...selected2 === undefined ? {} : { selector: selected2 }
|
|
54474
54660
|
} : { action: "swipe", direction };
|
|
54475
54661
|
} else if (uiAction === "swipe" && uiOperands.length === 4) {
|
|
54476
54662
|
const values2 = uiOperands.map(coordinate);
|
|
@@ -54489,13 +54675,13 @@ function parseArguments(argv) {
|
|
|
54489
54675
|
}
|
|
54490
54676
|
} else if (uiAction === "type" || uiAction === "fill") {
|
|
54491
54677
|
if (uiAction === "fill") {
|
|
54492
|
-
const
|
|
54493
|
-
if (uiOperands.length !== 2 ||
|
|
54678
|
+
const selected2 = selector(uiOperands[0]);
|
|
54679
|
+
if (uiOperands.length !== 2 || selected2 === undefined) {
|
|
54494
54680
|
return failure4("CLI_USAGE", "ui fill requires one valid selector and one text value.");
|
|
54495
54681
|
}
|
|
54496
54682
|
uiRequest = {
|
|
54497
54683
|
action: "fill",
|
|
54498
|
-
selector:
|
|
54684
|
+
selector: selected2,
|
|
54499
54685
|
text: uiOperands[1] ?? "",
|
|
54500
54686
|
...uiSubmit ? { submit: true } : {}
|
|
54501
54687
|
};
|
|
@@ -54515,13 +54701,13 @@ function parseArguments(argv) {
|
|
|
54515
54701
|
}
|
|
54516
54702
|
uiRequest = { action: "press", key: key2 };
|
|
54517
54703
|
} else if (uiAction === "find" || uiAction === "get" || uiAction === "assert" || uiAction === "clear") {
|
|
54518
|
-
const
|
|
54519
|
-
if (uiOperands.length !== 1 ||
|
|
54704
|
+
const selected2 = selector(uiOperands[0]);
|
|
54705
|
+
if (uiOperands.length !== 1 || selected2 === undefined) {
|
|
54520
54706
|
return failure4("CLI_USAGE", `ui ${uiAction} requires one valid selector.`);
|
|
54521
54707
|
}
|
|
54522
|
-
uiRequest = uiAction === "find" ? { action: "find", selector:
|
|
54708
|
+
uiRequest = uiAction === "find" ? { action: "find", selector: selected2 } : uiAction === "get" ? { action: "get", selector: selected2 } : uiAction === "clear" ? { action: "clear", selector: selected2 } : {
|
|
54523
54709
|
action: "assert",
|
|
54524
|
-
selector:
|
|
54710
|
+
selector: selected2,
|
|
54525
54711
|
...uiWaitState === undefined ? {} : { state: uiWaitState }
|
|
54526
54712
|
};
|
|
54527
54713
|
} else if (uiAction === "compare") {
|
|
@@ -55260,6 +55446,26 @@ async function runInteractiveSession(io, dependencies, terminal2, signal) {
|
|
|
55260
55446
|
if (home.action === "exit") {
|
|
55261
55447
|
return 0 /* Success */;
|
|
55262
55448
|
}
|
|
55449
|
+
if (home.action === "setup-device") {
|
|
55450
|
+
clearInteractiveScreen(io.error, terminal2);
|
|
55451
|
+
const setup = await showDeviceSetup({
|
|
55452
|
+
input: io.input,
|
|
55453
|
+
sink: io.error,
|
|
55454
|
+
capabilities: terminal2,
|
|
55455
|
+
...signal === undefined ? {} : { signal }
|
|
55456
|
+
});
|
|
55457
|
+
if (setup.kind === "cancelled" && setup.reason !== "escape") {
|
|
55458
|
+
return 130 /* Interrupted */;
|
|
55459
|
+
}
|
|
55460
|
+
if (setup.kind === "action") {
|
|
55461
|
+
clearInteractiveScreen(io.error, terminal2);
|
|
55462
|
+
await runCliInternal([setup.action], io, dependencies, signal);
|
|
55463
|
+
}
|
|
55464
|
+
if (signal?.aborted === true)
|
|
55465
|
+
return 130 /* Interrupted */;
|
|
55466
|
+
presentation = "menu";
|
|
55467
|
+
continue;
|
|
55468
|
+
}
|
|
55263
55469
|
const actionArguments = {
|
|
55264
55470
|
"app-info": ["app", "info"],
|
|
55265
55471
|
"app-restart": ["app", "restart"],
|
|
@@ -55702,13 +55908,13 @@ async function runCliInternal(argv, io, dependencies = {}, signal) {
|
|
|
55702
55908
|
}
|
|
55703
55909
|
}
|
|
55704
55910
|
const shouldPrompt = options.select || (options.command === "app" && options.appAction !== "resolve" || options.command === "apps" || options.command === "capture" || options.command === "dev" || options.command === "run" || options.command === "inspect" || options.command === "logs" || options.command === "open" || options.command === "ui") && errorCapabilities.interactive && inventory.result.data?.selected === undefined && selectable.length !== 1;
|
|
55705
|
-
const
|
|
55706
|
-
if (!
|
|
55911
|
+
const selected2 = shouldPrompt ? await selectDevice(inventory, io, errorCapabilities, lastTarget, signal) : inventory;
|
|
55912
|
+
if (!selected2.result.ok || selected2.result.data?.selected === undefined) {
|
|
55707
55913
|
if (shouldPrompt) {
|
|
55708
55914
|
if (autonomousRun) {
|
|
55709
|
-
return await finishAutonomousFailure([...
|
|
55915
|
+
return await finishAutonomousFailure([...selected2.result.problems], selected2.exitCode);
|
|
55710
55916
|
}
|
|
55711
|
-
renderResult({ ...
|
|
55917
|
+
renderResult({ ...selected2.result, command: options.command }, {
|
|
55712
55918
|
format: "human",
|
|
55713
55919
|
capabilities: errorCapabilities,
|
|
55714
55920
|
sink: io.error,
|
|
@@ -55716,10 +55922,10 @@ async function runCliInternal(argv, io, dependencies = {}, signal) {
|
|
|
55716
55922
|
});
|
|
55717
55923
|
await preparedAvd?.release(signal);
|
|
55718
55924
|
preparedAvd = undefined;
|
|
55719
|
-
return
|
|
55925
|
+
return selected2.exitCode;
|
|
55720
55926
|
}
|
|
55721
55927
|
} else {
|
|
55722
|
-
preparedSelection =
|
|
55928
|
+
preparedSelection = selected2.result.data.selected;
|
|
55723
55929
|
const transport = preparedSelection.transport;
|
|
55724
55930
|
if (options.avdName !== undefined || transport.transportId === undefined) {
|
|
55725
55931
|
config4.targetSelector = transport.serial;
|
|
@@ -56332,4 +56538,4 @@ try {
|
|
|
56332
56538
|
process16.removeListener("SIGTERM", abort);
|
|
56333
56539
|
}
|
|
56334
56540
|
|
|
56335
|
-
//# debugId=
|
|
56541
|
+
//# debugId=3D497281264093F564756E2164756E21
|
package/docs/getting-started.md
CHANGED
|
@@ -28,7 +28,12 @@ npx adb-ready doctor
|
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
Run `npx adb-ready` without a command for the interactive workflow home. Its
|
|
31
|
-
layout automatically switches to a compact form in narrow terminal panes.
|
|
31
|
+
layout automatically switches to a compact form in narrow terminal panes. Open
|
|
32
|
+
**Start** for development sessions, bounded verification, wireless connection,
|
|
33
|
+
pairing, or **Set up first device**. The guided setup walks through a physical
|
|
34
|
+
Android device over USB, Android 11+ Wireless debugging, or an existing Android
|
|
35
|
+
emulator, then hands off to the normal verified target workflow. The remaining
|
|
36
|
+
sections keep device operations, debugging, and project setup separate.
|
|
32
37
|
|
|
33
38
|
The full source build can be tested from a repository checkout:
|
|
34
39
|
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
ADB Ready models USB devices, emulators, TCP transports, and TLS Wireless
|
|
4
4
|
debugging transports behind one deterministic selection contract.
|
|
5
5
|
|
|
6
|
+
For a first connection, run `adb-ready` and open **Start → Set up first
|
|
7
|
+
device**. The interactive guide explains the Android-side steps, then reuses the
|
|
8
|
+
same verified `devices`, `pair`, or `connect` workflow documented below.
|
|
9
|
+
|
|
6
10
|
## Inspect visible targets
|
|
7
11
|
|
|
8
12
|
```bash
|
package/package.json
CHANGED