adb-ready 0.5.1 → 0.6.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.
@@ -26,7 +26,7 @@ it. ADB Ready does not open an MCP network listener.
26
26
 
27
27
  ## Connect an agent
28
28
 
29
- Preview the exact project change first, then apply it:
29
+ Preview the exact project changes first, then apply them:
30
30
 
31
31
  ```bash
32
32
  adb-ready agent setup codex --dry-run
@@ -35,7 +35,28 @@ adb-ready agent setup codex
35
35
 
36
36
  Replace `codex` with `claude-code`, `cursor`, or `vscode`. Existing unrelated
37
37
  configuration is preserved. An existing `adb-ready` entry with different
38
- settings is reported as a conflict and is never replaced automatically.
38
+ settings is reported as a conflict and is never replaced automatically. The
39
+ same setup installs ADB Ready's version-matched Agent Skill at
40
+ `.agents/skills/adb-ready/SKILL.md`, or `.claude/skills/adb-ready/SKILL.md` for
41
+ Claude Code. A custom skill is never overwritten; generated older versions are
42
+ updated atomically with the MCP configuration.
43
+
44
+ Narrow tool discovery when an agent needs only one workflow:
45
+
46
+ ```bash
47
+ adb-ready agent setup codex --mcp-profile debug
48
+ ```
49
+
50
+ | Profile | Intended work |
51
+ | --- | --- |
52
+ | `full` | Complete backward-compatible tool surface; the default |
53
+ | `session` | Target readiness, app lifecycle, and durable development sessions |
54
+ | `ui` | Target readiness, app lifecycle, semantic UI automation, and screenshots |
55
+ | `debug` | Target readiness, app lifecycle, current/saved evidence, and failure diagnosis |
56
+
57
+ Profiles reduce accidental tool selection and client context size; they are not
58
+ an authorization boundary. Start a server directly with `adb-ready mcp
59
+ --mcp-profile ui` when configuration is managed outside `agent setup`.
39
60
 
40
61
  ### Codex
41
62
 
@@ -49,15 +70,16 @@ default_tools_approval_mode = "writes"
49
70
  ```
50
71
 
51
72
  Codex CLI, the Codex IDE extension, and the ChatGPT desktop app share Codex MCP
52
- configuration. See the [official Codex MCP guide](https://learn.chatgpt.com/docs/extend/mcp).
73
+ configuration. Codex loads project `.codex/config.toml` only after the project
74
+ is trusted; ADB Ready never changes trust on the user's behalf. See the
75
+ [official Codex configuration guide](https://developers.openai.com/codex/config-basic).
53
76
 
54
77
  ### Claude Code
55
78
 
56
- Run this from the project root:
79
+ Run the project setup from the project root:
57
80
 
58
81
  ```bash
59
- claude mcp add --scope project adb-ready -- node ./node_modules/adb-ready/dist/cli.js mcp
60
- claude mcp get adb-ready
82
+ adb-ready agent setup claude-code
61
83
  ```
62
84
 
63
85
  Claude Code stores project-scoped servers in `.mcp.json` and asks users to
@@ -126,16 +148,17 @@ starts in the Android project root.
126
148
 
127
149
  Ask the agent to follow this sequence:
128
150
 
129
- 1. Call `doctor` when host or ADB health is unknown.
130
- 2. Call `ensure_ready`; provide an exact device serial, configured alias, or
151
+ 1. Call `get_capabilities` and stay within the active profile.
152
+ 2. Call `doctor` when host or ADB health is unknown.
153
+ 3. Call `ensure_ready`; provide an exact device serial, configured alias, or
131
154
  transport ID when more than one ready target exists.
132
- 3. Start the configured stack with `start_dev_session` when it is not already
155
+ 4. Start the configured stack with `start_dev_session` when it is not already
133
156
  running; retain its task handle and poll `get_dev_session` without holding a
134
157
  tool call open.
135
- 4. Resolve the project app with `resolve_app`.
136
- 5. Use `inspect_app` or `inspect_ui` for bounded current evidence.
137
- 6. Perform one typed action, then inspect again instead of assuming success.
138
- 7. Use `get_session_problems` or `compile_debug_context` for an existing
158
+ 5. Resolve the project app with `resolve_app`.
159
+ 6. Use `inspect_app` or `inspect_ui` for bounded current evidence.
160
+ 7. Perform one typed action, then inspect again instead of assuming success.
161
+ 8. Use `get_session_problems` or `compile_debug_context` for an existing
139
162
  development session.
140
163
 
141
164
  The first successful `ensure_ready` binds one target to that MCP connection and
@@ -156,17 +179,18 @@ UI Automation service per target.
156
179
 
157
180
  | Capability | MCP tools |
158
181
  | --- | --- |
159
- | Host and target readiness | `doctor`, `list_targets`, `ensure_ready` |
182
+ | Discovery and readiness | `get_capabilities`, `doctor`, `list_targets`, `ensure_ready` |
160
183
  | Durable development lifecycle | `start_dev_session`, `get_dev_session`, `stop_dev_session` |
161
184
  | App identity and lifecycle | `resolve_app`, `install_app`, `launch_app`, `restart_app`, `open_url` |
162
- | Current evidence | `inspect_app`, `inspect_ui`, `capture_screenshot` |
163
- | Safe UI queries and actions | `audit_ui`, `get_ui`, `find_ui`, `assert_ui`, `compare_ui`, `tap_ui`, `long_press_ui`, `scroll_ui`, `swipe_ui`, `fill_ui`, `clear_ui`, `type_text_ui`, `press_key_ui`, `wait_for_ui` |
185
+ | Current evidence | `inspect_app`, `inspect_failures`, `inspect_ui`, `capture_screenshot` |
186
+ | Safe UI queries and actions | `audit_ui`, `get_ui`, `find_ui`, `assert_ui`, `compare_ui`, `tap_ui`, `long_press_ui`, `scroll_ui`, `swipe_ui`, `fill_ui`, `clear_ui`, `type_text_ui`, `press_key_ui`, `wait_for_ui`, `inspect_keyboard`, `dismiss_keyboard`, `inspect_permission_dialog`, `respond_to_permission_dialog` |
164
187
  | Saved diagnostics | `list_sessions`, `get_session_problems`, `compile_debug_context` |
165
188
 
166
189
  MCP resources keep larger read-only context outside tool calls:
167
190
 
168
191
  | Resource | Content |
169
192
  | --- | --- |
193
+ | `adb-ready://capabilities` | active profile, profile tool membership, and long-running task compatibility |
170
194
  | `adb-ready://targets` | current target inventory and this connection's bound target |
171
195
  | `adb-ready://sessions` | bounded saved-session manifests |
172
196
  | `adb-ready://sessions/{sessionId}` | one session manifest |
@@ -176,13 +200,33 @@ MCP resources keep larger read-only context outside tool calls:
176
200
  Every tool advertises an output schema and returns the same versioned result
177
201
  envelope used by CLI JSON output. Screenshot capture additionally returns MCP
178
202
  `image` content so a vision-capable agent can inspect the pixels directly; the
179
- verified project-local PNG remains the evidence source of record.
203
+ verified project-local PNG remains the evidence source of record. Agent
204
+ screenshots default to a 1024×1024 maximum and 4 MiB base64 content budget, with
205
+ explicit crop/dimension controls and a deliberate `fullResolution` opt-in.
206
+ Standard MCP annotations describe read-only, destructive, idempotent, and
207
+ open-world behavior. The namespaced `dev.adbready/tool` metadata adds profile,
208
+ category, target-binding, mutation, and sensitive-data signals. Annotations are
209
+ advisory for clients; ADB Ready still enforces the operation at runtime.
180
210
 
181
211
  The npm package also ships `schema/agent-tools-v1.json`, generated from the
182
212
  server's real `tools/list` response during every build. Integrations can inspect
183
213
  version-matched input and output schemas plus safety annotations without
184
214
  starting ADB.
185
215
 
216
+ The package also ships `skills/adb-ready/SKILL.md`. It is generated from the
217
+ same real `tools/list` contract during the build, so its workflow cannot name a
218
+ tool missing from that package version. The skill teaches task order and safety;
219
+ the MCP server remains the controlled execution surface.
220
+
221
+ ## Long-running task compatibility
222
+
223
+ ADB Ready does not advertise the MCP Tasks extension yet. Its durable
224
+ `start_dev_session`, `get_dev_session`, and `stop_dev_session` handles remain
225
+ available across supported clients and reconnects. `get_capabilities` reports
226
+ this compatibility path explicitly. Native Tasks will be advertised only after
227
+ capability negotiation and end-to-end interoperability are proven in at least
228
+ two supported clients; unnegotiated clients never receive a Tasks claim.
229
+
186
230
  `list_sessions` is project-scoped by default and supports status, preset,
187
231
  recency, and result-count filters. When more matches remain, pass its opaque
188
232
  `nextCursor` back as `cursor`; an expired cursor fails explicitly instead of
@@ -197,6 +241,9 @@ silently restarting the list.
197
241
  - UI hierarchy and app inspection are marked sensitive and remain bounded.
198
242
  - UI references are checked against a fresh hierarchy digest before mutation;
199
243
  stale references are rejected.
244
+ - Secret UI text is referenced by local environment-variable name rather than
245
+ sent in MCP arguments; Unicode input is capability-checked before mutation
246
+ and restores the prior Android IME.
200
247
  - Data clearing and uninstall are intentionally absent from the agent surface.
201
248
  - Tool annotations help clients request approval, but ADB Ready enforces its
202
249
  own target, path, and destructive-action rules.
@@ -123,6 +123,7 @@ Capture a PNG directly from the selected target:
123
123
  ```bash
124
124
  adb-ready capture screenshot
125
125
  adb-ready capture screenshot --out artifacts/login.png
126
+ adb-ready capture screenshot --crop 120,300,840,900 --max-width 640
126
127
  ```
127
128
 
128
129
  Capture a bounded MP4 recording:
@@ -146,7 +147,10 @@ instead of publishing unusable evidence; create visible activity and retry.
146
147
 
147
148
  Some multi-display Android builds, including foldables, emit a short textual
148
149
  warning before the screenshot bytes. ADB Ready removes only a bounded text
149
- preamble and still requires a valid PNG signature before publishing the file.
150
+ preamble and still decodes the complete PNG, verifies its chunks and checksums,
151
+ and validates its dimensions before publishing the file. `--crop` uses source
152
+ pixels in `X,Y,WIDTH,HEIGHT` order. `--max-width` and `--max-height` preserve
153
+ aspect ratio and never upscale.
150
154
 
151
155
  The result contains:
152
156
 
@@ -154,12 +158,21 @@ The result contains:
154
158
  - media type and byte size;
155
159
  - measured duration and video frame count for recordings;
156
160
  - SHA-256 digest;
161
+ - capture timestamp, source/output dimensions, effective crop, PNG encoding,
162
+ and whether crop or resize intentionally truncated the original frame;
157
163
  - selected target and capture-command provenance.
158
164
 
159
165
  Binary data is stored as a file rather than embedded into JSON or AI context.
160
166
  Screenshots and recordings can contain private information; ADB Ready does not
161
167
  upload or implicitly attach them to diagnostic context.
162
168
 
169
+ MCP screenshot results are different by design: `capture_screenshot` returns
170
+ image content to the requesting client, so it defaults to a proportional
171
+ 1024×1024 maximum and a 4 MiB base64 content budget. Agents may provide a
172
+ smaller `crop`, `maxWidth`, or `maxHeight`. `fullResolution: true` is an
173
+ explicit escape hatch for clients that can safely accept the complete image;
174
+ it cannot be combined with dimension limits.
175
+
163
176
  ## Target selection and automation
164
177
 
165
178
  All commands accept the standard target selectors:
@@ -158,7 +158,7 @@ leaving a development server open:
158
158
 
159
159
  ```bash
160
160
  adb-ready run --preset expo --run-timeout 10m -- \
161
- maestro '--device={target.serial}' test .maestro/smoke.yaml
161
+ maestro test .maestro/smoke.yaml
162
162
  ```
163
163
 
164
164
  ADB Ready selects and exclusively leases one target, prepares the configured
@@ -168,9 +168,23 @@ retries a failed product assertion as if it were an infrastructure failure.
168
168
 
169
169
  The literal `{target.serial}` inside a verification argument is replaced only
170
170
  after ADB Ready selects and leases the target. The child also receives the
171
- same value as `ANDROID_SERIAL` and `ADB_READY_TARGET_SERIAL`. This keeps tools
172
- such as Maestro pinned explicitly without invoking a shell; tools that already
173
- honor `ANDROID_SERIAL`, including common Gradle/ADB workflows, need no placeholder.
171
+ same value as `ANDROID_SERIAL` and `ADB_READY_TARGET_SERIAL`, plus a private
172
+ `ADB_READY_VERIFIER_OUTPUT_DIR` for native artifacts. Tools that already honor
173
+ `ANDROID_SERIAL`, including common Gradle/ADB workflows, need no placeholder.
174
+
175
+ For a direct `maestro test` command, ADB Ready uses Maestro's supported global
176
+ `--device` option to bind the leased serial. Unless the command already names
177
+ them, it also requests Maestro JUnit, test-output, and debug-output files. An
178
+ explicit Maestro device that differs from the leased target fails before
179
+ Maestro starts; ADB Ready never silently retargets it.
180
+
181
+ Android CLI does not expose a single `journey run` command or a stable Journey
182
+ report format. Journeys are evaluated by an agent using the installed Android
183
+ CLI skill. ADB Ready therefore does not invent such a command. It keeps the
184
+ agent workflow target-bound through MCP, and when a finite verifier invokes
185
+ the official `android layout` or `android screen capture` primitives directly,
186
+ ADB Ready supplies their supported `--device` and `--output` options. The
187
+ Journey XML remains owned by Android CLI and the agent.
174
188
 
175
189
  Every executed run prints the path to a project-local evidence directory under
176
190
  `.adb-ready/artifacts/`. Its manifest references the structured result,
@@ -196,7 +210,7 @@ adb-ready run \
196
210
  --artifact android/app/build/outputs/apk/debug/app-debug.apk \
197
211
  --package com.example.app \
198
212
  --run-timeout 10m \
199
- -- maestro '--device={target.serial}' test .maestro/smoke.yaml
213
+ -- maestro test .maestro/smoke.yaml
200
214
 
201
215
  adb-ready run --avd Pixel_9_API_36 --deploy --variant debug -- \
202
216
  ./gradlew connectedDebugAndroidTest
@@ -225,8 +239,18 @@ line-oriented `artifact_*`, `deployment_*`, and `emulator_*` fields; `--json`
225
239
  and `--ndjson` retain the complete structured automation data.
226
240
 
227
241
  The evidence manifest also includes the verifier's bounded, redacted native
228
- stdout and stderr. Preparation failures still publish the same result,
229
- problems, JUnit, and evidence contract after owned-resource cleanup.
242
+ stdout and stderr. Supported native JUnit, screenshots, videos, logs, JSON,
243
+ and HTML reports are copied under `verifier-native/`, checksummed, marked
244
+ sensitive, and bounded to 100 files, 20 MiB per file, and 50 MiB total.
245
+ Symlinks and unsupported file types are never followed. Text artifacts are
246
+ redacted; binary screenshots and video remain local sensitive evidence.
247
+ Preparation failures still publish the same result, problems, JUnit, and
248
+ evidence contract after owned-resource cleanup.
249
+
250
+ Structured results classify the verifier independently as `passed`,
251
+ `assertion-failed`, `tool-failed`, `target-failed`, `timed-out`, `cancelled`,
252
+ or `unavailable`. This classification uses process and session state, not
253
+ fragile parsing of human log messages.
230
254
 
231
255
  ## CI example
232
256
 
@@ -62,6 +62,40 @@ and never promoted to application problems. A configured `app.android.package`
62
62
  or `dev --package APP_ID` scopes the stream directly; Expo sessions retarget it
63
63
  to the package that Android resolves for the verified launch URL.
64
64
 
65
+ ## Correlated crash, ANR, and native evidence
66
+
67
+ Inspect one installed application across Android's available failure sources:
68
+
69
+ ```bash
70
+ adb-ready inspect failures com.example.app
71
+ adb-ready inspect failures --package com.example.app --since 30m --max-records 25 --json
72
+ ```
73
+
74
+ This read-only workflow verifies the selected package and target, records the
75
+ UID and current PID when Android exposes them, uses the target's own clock and
76
+ UTC offset, then correlates a bounded recent window from:
77
+
78
+ - package-scoped `ApplicationExitInfo` exposed by ActivityManager;
79
+ - UID-scoped `main`, `system`, and `crash` logcat buffers;
80
+ - exact package/process matches in supported app crash, native crash, and ANR
81
+ DropBox tags.
82
+
83
+ Java/Kotlin exceptions, native crashes, React Native fatal errors, and ANRs are
84
+ classified separately. Stable numeric `ApplicationExitInfo` reason codes drive
85
+ classification; its human description remains evidence rather than a parsing
86
+ contract. Old exits outside `--since` and DropBox blocks for other packages are
87
+ excluded. Matching evidence from different Android sources is returned as one
88
+ incident with `corroboratedBy`, rather than inflating one crash into multiple
89
+ findings. The default window is 15 minutes and default result limit is 20;
90
+ accepted bounds are one second to seven days and 1 to 100 incidents.
91
+
92
+ Android versions and OEM builds do not expose every source equally. The result
93
+ contains an availability, record count, truncation state, and limitation for
94
+ each source. Missing history or a DropBox permission denial does not become a
95
+ false application failure, and unrelated system/process failures are never
96
+ promoted into the selected app's findings. Returned evidence is sensitive and
97
+ redacted before retention or rendering.
98
+
65
99
  ## Session history
66
100
 
67
101
  Development sessions incrementally persist redacted NDJSON and an atomic
@@ -39,6 +39,12 @@ selection fails. An MCP connection binds one target and refuses a silent
39
39
  switch. UI references include the current hierarchy digest and are revalidated
40
40
  immediately before mutation.
41
41
 
42
+ MCP profiles narrow discovery for a workflow and reduce accidental tool
43
+ selection, but they are not an authorization boundary. Every exposed operation
44
+ still applies its own target, path, input, ownership, and destructive-action
45
+ checks. Tool annotations and namespaced sensitivity metadata help clients choose
46
+ approval policy; they are hints, not security enforcement.
47
+
42
48
  ### Unsafe file mutation
43
49
 
44
50
  Capture and setup paths are constrained to the project, checked for unsafe
@@ -52,6 +58,20 @@ redacted. Pairing codes use protected input or stdin and never enter process
52
58
  arguments. Screenshots and UI hierarchies require explicit calls and never join
53
59
  AI context automatically.
54
60
 
61
+ Screenshot capture rejects malformed PNG structure, invalid checksums,
62
+ unsupported encodings, and excessive source dimensions before publishing a
63
+ file. MCP image results are cropped or proportionally bounded by default and
64
+ must fit an encoded payload budget; full-resolution delivery is an explicit
65
+ client choice. These controls bound transport and context size, not the visual
66
+ sensitivity of the selected pixels.
67
+
68
+ Failure inspection accepts only a verified installed package, binds every
69
+ probe to the same target, uses package-scoped exit history and log filtering,
70
+ and retains DropBox blocks only when an exact package or package-process line
71
+ matches. Unavailable or permission-limited sources are reported rather than
72
+ replaced by target-wide evidence. Source bytes, time windows, record counts,
73
+ and returned excerpts are bounded and redacted.
74
+
55
75
  ### Unbounded or misleading automation
56
76
 
57
77
  Process output, recordings, UI trees, session storage, context, retries, and
@@ -59,6 +79,12 @@ waits are bounded. Results distinguish process acceptance (`ok`) from observed
59
79
  postconditions (`verified`). An unchanged UI is reported as a verification gap,
60
80
  not silently upgraded to verified success.
61
81
 
82
+ Keyboard dismissal requires two independent Android visibility signals to
83
+ agree before Back is sent and after it completes. Runtime-permission responses
84
+ require one recognized PermissionController dialog and one exact resource ID;
85
+ localized labels, generic system dialogs, biometric prompts, notification
86
+ setup, and ambiguous OEM states are never accepted speculatively.
87
+
62
88
  ### Network exposure
63
89
 
64
90
  The 0.2 MCP server uses stdio and opens no listener. ADB itself may connect to a
@@ -73,6 +99,13 @@ ADB Ready's isolation boundary.
73
99
  - autonomous destructive recovery;
74
100
  - automatic screenshot or UI-text upload.
75
101
 
102
+ Protected UI text is accepted from CLI stdin or by environment-variable name
103
+ through MCP. It is not placed in host argv, result envelopes, plans, journals,
104
+ screenshots created by the action, or AI context. It still exists transiently
105
+ in ADB Ready memory and the child-process pipe, and the selected Android target,
106
+ input method, app, or OEM auditing may observe it. ADB Ready does not claim to
107
+ turn a normal visible field or an untrusted target into a secure channel.
108
+
76
109
  ## Residual risk
77
110
 
78
111
  A trusted ADB server can control connected Android targets, and an approved AI
@@ -34,6 +34,11 @@ adb-ready context --since 5m --only problems,recovery,logs
34
34
  | `UI_HIERARCHY_BUSY` | Another process held the selected target's single UI Automation service through the UI timeout | Let that capture finish or increase the UI timeout, then retry |
35
35
  | `UI_HIERARCHY_LOCK_UNAVAILABLE` | The per-user coordination directory is not writable | Restore write access to the ADB Ready state directory, then retry |
36
36
  | `UI_NOT_IDLE` | Android UI Automator could not observe a quiet accessibility window | Pause continuous UI changes or navigate to a stable screen, then retry |
37
+ | `UI_UNICODE_INPUT_UNAVAILABLE` | Unicode/multiline input was requested but ADBKeyBoard is not installed and enabled | Install a compatible official ADBKeyBoard release, enable it in Android settings, and retry; ADB Ready will not enable an IME silently |
38
+ | `UI_INPUT_METHOD_UNKNOWN` | Android did not expose the current IME, so it cannot be restored safely | Select a keyboard on the target before retrying Unicode input |
39
+ | `UI_KEYBOARD_STATE_AMBIGUOUS` | InputMethodManager and WindowInsets disagree about keyboard visibility | Wait for the transition to settle, then inspect again; ADB Ready will not press Back while state is uncertain |
40
+ | `UI_KEYBOARD_STATE_UNSUPPORTED` | The Android build omitted one of the two required keyboard signals | Dismiss the keyboard in the app or use a target that exposes both dumpsys states |
41
+ | `UI_PERMISSION_DIALOG_UNSUPPORTED` | The current PermissionController or OEM dialog is not one exact supported runtime-permission prompt | Handle the dialog manually; notification, biometric, Settings, and unknown OEM dialogs are not auto-accepted |
37
42
  | `SESSION_RECOVERY_FAILED` | The bounded target/port recovery budget was exhausted | Inspect `problems`, network state, and saved recovery events |
38
43
  | `SESSION_PERSISTENCE_FAILED` | The private session record could not be written | Check user-state directory permissions and capacity |
39
44
  | `FRAMEWORK_LAUNCHER_NOT_FOUND` | The detected Flutter or Gradle project has no runnable launcher | Install Flutter and expose `flutter` on PATH, or restore the project's checked-in Gradle Wrapper |
@@ -135,6 +140,37 @@ Resolve the user-action problem, then start a new session. Increase the recovery
135
140
  budget only when the environment is known to need more time; do not use an
136
141
  unbounded timeout.
137
142
 
143
+ ## Screenshot capture is rejected
144
+
145
+ `SCREENSHOT_BOUNDS_INVALID` means the requested `--crop X,Y,WIDTH,HEIGHT` lies
146
+ outside the decoded source image. Capture once without a crop and read the
147
+ reported `image.source` dimensions, then retry with coordinates inside them.
148
+
149
+ `SCREENSHOT_PAYLOAD_TOO_LARGE` protects an MCP client from an unexpectedly
150
+ large image. Crop the relevant region or lower `maxWidth`/`maxHeight`; use
151
+ `fullResolution: true` only when the client can deliberately accept it.
152
+
153
+ `SCREENSHOT_INVALID` or `SCREENSHOT_ENCODING_UNSUPPORTED` means ADB did not
154
+ produce a complete standard non-interlaced 8-bit PNG. Confirm that the selected
155
+ display is available and not blocked by a secure surface, then retry without
156
+ assuming that a PNG signature alone proves usable evidence.
157
+
158
+ ## Failure inspection has unavailable sources
159
+
160
+ `adb-ready inspect failures APP_ID` succeeds when the app and target are
161
+ verified even if an optional Android evidence source is absent. Read the
162
+ `sources` list: each entry distinguishes available, truncated,
163
+ permission-limited, and unsupported evidence.
164
+ The top-level `truncated` flag means the requested incident limit bounded the
165
+ combined result; a source-level flag means Android output or log retention was
166
+ bounded before correlation.
167
+
168
+ Application exit history requires Android 11/API 30 or a compatible OEM
169
+ backport. DropBox visibility varies by Android build and shell permissions.
170
+ ADB Ready does not substitute unrelated target-wide crashes. Use a recent
171
+ `--since` window, reproduce the failure, and retry; use focused `adb-ready logs`
172
+ when the app is still running and live output is required.
173
+
138
174
  ## Report a reproducible issue
139
175
 
140
176
  For ordinary bugs, open a GitHub issue with the ADB Ready version, host/runtime,
@@ -30,6 +30,33 @@ parallel, and selector processing or input does not hold the capture lock. If
30
30
  another process does not finish within the configured UI timeout, the command
31
31
  returns `UI_HIERARCHY_BUSY` instead of misreporting an inaccessible screen.
32
32
 
33
+ Choose an acquisition profile when the default one-shot observation is not the
34
+ right tradeoff:
35
+
36
+ ```bash
37
+ adb-ready inspect ui --acquisition balanced
38
+ adb-ready inspect ui --acquisition fast --interactive-only
39
+ adb-ready inspect ui --acquisition strict
40
+ ```
41
+
42
+ - `balanced` takes one fresh platform-idle snapshot within the normal bounded
43
+ UI timeout and is the default.
44
+ - `fast` keeps the same safe target-scoped platform backend but limits the
45
+ attempt to three seconds. It reports a timeout or non-idle screen instead of
46
+ pretending that an empty result is a valid screen.
47
+ - `strict` requires two consecutive matching hierarchy digests within at most
48
+ three captures. A continuously changing screen returns
49
+ `UI_HIERARCHY_UNSTABLE`.
50
+
51
+ Every successful structured snapshot reports its observation time, duration,
52
+ attempt count, stability status, source and idle strategy, requested filters,
53
+ node limits, truncation, observed display bounds and rotation, and detected
54
+ semantic limitations. An empty hierarchy is an explicit `UI_HIERARCHY_EMPTY`
55
+ failure. WebView, Compose, and Flutter
56
+ markers are reported only when their corresponding platform view is actually
57
+ observed; they describe framework accessibility boundaries rather than guessing
58
+ why an otherwise unreadable window failed.
59
+
33
60
  ## Audit one screen for people and agents
34
61
 
35
62
  ```bash
@@ -92,6 +119,7 @@ field happens to be focused:
92
119
  adb-ready ui get 'id=com.example:id/email' --json
93
120
  adb-ready ui fill 'id=com.example:id/email' 'person@example.com'
94
121
  adb-ready ui fill 'id=com.example:id/search' 'pixel' --submit
122
+ adb-ready ui fill 'id=com.example:id/name' 'Příliš žluťoučký 🦊' --input-mode unicode
95
123
  adb-ready ui clear 'id=com.example:id/search'
96
124
  ```
97
125
 
@@ -128,9 +156,84 @@ node whose `scrollable` property is true; without a selector it uses the screen.
128
156
  Supported keys are `back`, `home`, `enter`, `menu`, `volume-up`, and
129
157
  `volume-down`.
130
158
 
131
- Android's text-input command passes through a device shell. ADB Ready therefore
132
- accepts only 1–256 ASCII letters, numbers, spaces, and `._@+,:/-`. Unsupported
133
- characters are rejected instead of being reinterpreted by a shell.
159
+ Text input is bounded to 1–256 Unicode code points and 4096 UTF-8 bytes. The
160
+ default `--input-mode auto` uses Android's built-in `input text` only for the
161
+ conservative ASCII set of letters, numbers, spaces, and `._@+,:/-`. Use
162
+ `--input-mode ascii` to require that path explicitly.
163
+
164
+ Unicode, emoji, RTL, CJK, and multiline input use the open-source
165
+ [ADBKeyBoard](https://github.com/senzhk/ADBKeyBoard) broadcast contract because
166
+ Android's built-in input command does not reliably represent those values. The
167
+ IME must already be installed and enabled on the selected target. ADB Ready
168
+ checks that contract before touching the screen, temporarily selects the IME,
169
+ and restores the exact previous IME in a `finally` path. It never downloads,
170
+ installs, enables, or leaves a keyboard selected silently. If the helper or a
171
+ restorable current IME is unavailable, the action fails before typing.
172
+
173
+ Some apps drop text delivered too quickly. Pace either backend by Unicode code
174
+ point with a whole-millisecond delay from 0 to 2000:
175
+
176
+ ```bash
177
+ adb-ready ui type 'مرحبا بالعالم' --input-mode unicode --typing-delay 40
178
+ ```
179
+
180
+ ### Protected input
181
+
182
+ Do not put passwords or tokens in a command argument. Pipe one value to stdin:
183
+
184
+ ```bash
185
+ printf '%s' "$TEST_PASSWORD" |
186
+ adb-ready ui fill 'id=com.example:id/password' --secret-stdin --submit
187
+ ```
188
+
189
+ `--secret-stdin` reads at most 4096 bytes to EOF, removes one final line ending,
190
+ and preserves embedded newlines. Plaintext is excluded from host process
191
+ arguments, operation plans, terminal output, structured results, event
192
+ journals, screenshots created by this action, and AI context. The value exists
193
+ only in process memory and the pipe used to deliver it to the selected target.
194
+ For Unicode, the on-device shell receives base64 rather than plaintext.
195
+
196
+ This is a bounded host-side guarantee, not a secure-input claim about Android
197
+ or the app: the selected IME and target receive the value, a normal visible
198
+ field may display it, and device/OEM auditing can observe shell activity. Use a
199
+ password field and assert a non-secret postcondition. A protected field cannot
200
+ expose its value for exact verification, so ADB Ready returns
201
+ `text-not-observable` rather than inventing success.
202
+
203
+ ## Keyboard and runtime-permission dialogs
204
+
205
+ Inspect or dismiss the software keyboard without sending a blind Back action:
206
+
207
+ ```bash
208
+ adb-ready ui keyboard status --json
209
+ adb-ready ui keyboard dismiss
210
+ ```
211
+
212
+ ADB Ready requires Android's InputMethodManager `mInputShown` state and its
213
+ WindowInsets `type=ime` visibility to both exist and agree. `dismiss` sends Back
214
+ only after both report visible, then reads both services again and succeeds only
215
+ after both report hidden. An already hidden keyboard is a verified no-op.
216
+ Missing or conflicting signals return `UI_KEYBOARD_STATE_UNSUPPORTED` or
217
+ `UI_KEYBOARD_STATE_AMBIGUOUS`; ADB Ready does not guess from inset height or
218
+ press Back against an unknown screen.
219
+
220
+ Inspect one standard Android runtime-permission prompt before choosing an exact
221
+ decision:
222
+
223
+ ```bash
224
+ adb-ready ui permission inspect --json
225
+ adb-ready ui permission respond allow-while-using
226
+ adb-ready ui permission respond allow-once --dry-run --json
227
+ adb-ready ui permission respond deny
228
+ ```
229
+
230
+ Inspection returns only the decisions actually present on the current dialog.
231
+ Responses match PermissionController package and resource IDs, never translated
232
+ button labels or coordinates copied from another device. A fresh hierarchy must
233
+ show that the specific prompt changed or disappeared after the tap. Multiple,
234
+ unknown, or OEM-specific states fail closed. Notification permission setup,
235
+ biometric prompts, Settings mutation, and generic system-dialog acceptance are
236
+ intentionally outside this workflow.
134
237
 
135
238
  ## Find, assert, compare, and wait
136
239
 
@@ -143,8 +246,9 @@ adb-ready ui assert 'text=Loading' --state gone
143
246
  adb-ready ui compare 7c4a31b8d2ef0000000000000000000000000000000000000000000000000000
144
247
  ```
145
248
 
146
- `compare` consumes the complete digest returned by inspection or another UI
147
- action and reports whether the current hierarchy changed.
249
+ The CLI `compare` command consumes the complete digest returned by inspection
250
+ or another UI action and reports whether the current hierarchy changed. It
251
+ does not persist the earlier sensitive hierarchy.
148
252
 
149
253
  Waits use exact, explicit selectors:
150
254
 
@@ -186,11 +290,31 @@ the next state is known.
186
290
  ## AI agents
187
291
 
188
292
  The MCP server exposes the same intent-level workflow through `audit_ui`, `get_ui`,
189
- `find_ui`, `fill_ui`, `clear_ui`, `scroll_ui`, `assert_ui`, and `compare_ui`.
293
+ `find_ui`, `fill_ui`, `clear_ui`, `scroll_ui`, `assert_ui`, `compare_ui`,
294
+ `inspect_keyboard`, `dismiss_keyboard`, `inspect_permission_dialog`, and
295
+ `respond_to_permission_dialog`.
190
296
  Its structured selectors can match exact values, prefixes, or substrings and
191
297
  qualify enabled/actionable state. An optional one-based occurrence is accepted
192
298
  only when repeated nodes are intentional. Arguments are schema-validated, each
193
299
  MCP connection stays bound to one target, and no raw ADB or shell tool is
194
300
  exposed.
195
301
 
302
+ `type_text_ui` and `fill_ui` accept `inputMode` and `typingDelayMs`. For a
303
+ secret, set `secretEnv` to the *name* of an environment variable already passed
304
+ to the local MCP server and omit `text`. ADB Ready reads the value locally; the
305
+ MCP request, tool result, and retained agent conversation contain only the
306
+ variable name. Supplying both fields, neither field, or a missing/empty variable
307
+ fails before device mutation.
308
+
309
+ `inspect_ui` retains at most eight sensitive snapshots in memory for that MCP
310
+ connection only. `compare_ui` accepts one of those complete digests and returns
311
+ a bounded semantic diff: added, removed, updated, and moved nodes with current
312
+ selector context. `changed` describes the requested filtered view, while
313
+ `digestChanged` also reveals changes outside that view. Unchanged screens return
314
+ empty change lists. Bases expire
315
+ after five minutes and are never written to disk; missing or expired digests
316
+ require a fresh `inspect_ui`. A diff is rejected rather than guessed when its
317
+ target, display bounds or rotation, hierarchy filters, acquisition contract, or
318
+ completeness differs from the base.
319
+
196
320
  [Connect an agent →](./agent-integration.md)
package/llms.txt CHANGED
@@ -8,13 +8,14 @@
8
8
  - Diagnose: `adb-ready doctor`
9
9
  - Start a session: `adb-ready dev`
10
10
  - Machine output: `adb-ready COMMAND --json --non-interactive`
11
- - MCP stdio server: `node ./node_modules/adb-ready/dist/cli.js mcp`
12
- - Agent setup: `adb-ready agent setup CLIENT --dry-run`
13
- - MCP resources: `adb-ready://targets` and `adb-ready://sessions`
11
+ - MCP stdio server: `node ./node_modules/adb-ready/dist/cli.js mcp [--mcp-profile PROFILE]`
12
+ - Agent setup plus version-matched Agent Skill: `adb-ready agent setup CLIENT --dry-run`
13
+ - Finite verifier with normalized evidence: `adb-ready run -- maestro test FLOW`
14
+ - MCP resources: `adb-ready://capabilities`, `adb-ready://targets`, and `adb-ready://sessions`
14
15
 
15
16
  ## Agent contract
16
17
 
17
- 1. Call `ensure_ready` before target-bound MCP tools.
18
+ 1. Call `get_capabilities`, then `ensure_ready` before target-bound MCP tools.
18
19
  2. Keep the bound target for the whole connection and pass the `targetHandle`
19
20
  returned by `ensure_ready` to target-bound tools.
20
21
  3. Use `start_dev_session`, then poll `get_dev_session` by its opaque handle;
@@ -29,6 +30,9 @@
29
30
  8. Use `list_sessions` filters and its `nextCursor` before requesting saved
30
31
  session problems or context.
31
32
  9. Never substitute a raw shell or ADB call for a missing typed tool.
33
+ 10. MCP Tasks are not advertised; use the durable start/get/stop session tools.
34
+ 11. For a finite verification job, use `run`; consume its structured verifier
35
+ outcome and retained `verifier-native/` references instead of parsing prose.
32
36
 
33
37
  ## Documentation
34
38
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adb-ready",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Agent-ready Android CLI for reliable ADB sessions, app automation, and verified evidence.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -17,6 +17,7 @@
17
17
  "LICENSE",
18
18
  "llms.txt",
19
19
  "schema",
20
+ "skills",
20
21
  "README.md"
21
22
  ],
22
23
  "engines": {
@@ -25,6 +26,7 @@
25
26
  "packageManager": "bun@1.3.11",
26
27
  "scripts": {
27
28
  "dev": "bun run src/cli.ts",
29
+ "what": "runpalette",
28
30
  "build": "bun run scripts/build.mjs",
29
31
  "docs:check": "bun run scripts/docs-check.mjs",
30
32
  "typecheck": "tsc --noEmit",
@@ -97,6 +99,7 @@
97
99
  "@yarnpkg/cli-dist": "4.18.0",
98
100
  "npm": "12.0.2",
99
101
  "publint": "0.3.24",
102
+ "runpalette": "0.3.0",
100
103
  "tinyexec": "1.3.1",
101
104
  "typescript": "7.0.2",
102
105
  "yarn": "1.22.22"