@ulpi/browse 2.3.3 → 2.3.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ulpi/browse",
3
- "version": "2.3.3",
3
+ "version": "2.3.4",
4
4
  "homepage": "https://browse.ulpi.io",
5
5
  "repository": {
6
6
  "type": "git",
@@ -2,19 +2,96 @@
2
2
  name: browse
3
3
  version: 3.5.0
4
4
  description: |
5
- Fast web browsing and web app testing for AI coding agents via persistent headless Chromium daemon.
6
- Browse any URL, read page content, click elements, fill forms, run JavaScript, take screenshots,
7
- inspect CSS/DOM, capture console/network logs, and more. Ideal for verifying local dev servers,
8
- testing UI changes, and validating web app behavior end-to-end. ~100ms per command after
9
- first call. Works with Claude Code, Cursor, Cline, Windsurf, and any agent that can run Bash.
10
- No MCP, no Chrome extension — just fast CLI.
5
+ Fast web browsing, web app testing, and native app automation for AI coding agents.
6
+ Persistent headless Chromium for web. Android, iOS, and macOS app automation via accessibility APIs.
7
+ Browse URLs, read content, click elements, fill forms, run JavaScript, take screenshots,
8
+ automate native apps all through the same CLI and @ref workflow. ~100ms per command.
9
+ Auto-installs Android toolchain. Works with Claude Code, Cursor, Cline, Windsurf, and any agent that can run Bash.
11
10
  allowed-tools:
12
11
  - Bash
13
12
  - Read
14
13
 
15
14
  ---
16
15
 
17
- # browse: Persistent Browser for AI Coding Agents
16
+ # browse: Browser & Native App Automation for AI Agents
17
+
18
+ ## Target Decision — ALWAYS check this first
19
+
20
+ Before running any browse command, decide the correct target:
21
+
22
+ | User wants to... | Target | Command pattern |
23
+ |---|---|---|
24
+ | Open a URL, test a website, scrape web content | **Browser** (default) | `browse goto <url>` |
25
+ | Test a local dev server (`localhost`) | **Browser** | `browse goto http://localhost:3000` |
26
+ | Interact with an iOS app (Settings, Safari, custom app) | **iOS Simulator** | `browse --platform ios --app <bundleId> <cmd>` |
27
+ | Interact with an Android app (Settings, Chrome, custom app) | **Android Emulator** | `browse --platform android --app <package> <cmd>` |
28
+ | Interact with a macOS desktop app (System Settings, TextEdit) | **macOS App** | `browse --app <name> <cmd>` |
29
+ | Install and test an iOS .app or .ipa file | **iOS Simulator** | `browse sim start --platform ios --app ./MyApp.app --visible` |
30
+ | Install and test an Android .apk file | **Android Emulator** | `browse sim start --platform android --app ./app.apk --visible` |
31
+
32
+ **Key rules:**
33
+ - **No `--platform` or `--app` flag** → browser target (Chromium). Use `goto` to navigate.
34
+ - **`--app` without `--platform`** → macOS app automation. App must be running.
35
+ - **`--platform ios --app`** → iOS Simulator. Use `browse sim start` first if not running.
36
+ - **`--platform android --app`** → Android Emulator. Use `browse sim start` first if not running.
37
+ - **Native app targets do NOT support**: `goto`, `js`, `eval`, `tabs`, `cookies`, `route`, `har`. These are browser-only.
38
+ - **All targets support**: `snapshot`, `text`, `tap`, `fill`, `type`, `press`, `swipe`, `screenshot`.
39
+ - **If unsure which target to use, ASK the user.** "Should I open this in the browser, or do you want me to use the iOS/Android/macOS app?" Don't guess — wrong target = wasted work.
40
+
41
+ ### Native App Quick Start
42
+
43
+ ```bash
44
+ # iOS — boot simulator, open Settings, interact
45
+ browse sim start --platform ios --app com.apple.Preferences --visible
46
+ browse --platform ios --app com.apple.Preferences snapshot -i
47
+ browse --platform ios --app com.apple.Preferences tap @e3
48
+
49
+ # Android — boot emulator (auto-installs toolchain), open Settings, interact
50
+ browse sim start --platform android --app com.android.settings --visible
51
+ browse --platform android --app com.android.settings snapshot -i
52
+ browse --platform android --app com.android.settings tap @e3
53
+
54
+ # macOS — no sim needed, app must be running
55
+ browse --app "System Settings" snapshot -i
56
+ browse --app "System Settings" tap @e5
57
+
58
+ # Install and test your own app from a file
59
+ browse sim start --platform ios --app ./build/MyApp.app --visible # .app bundle
60
+ browse sim start --platform ios --app ./MyApp.ipa --visible # .ipa archive
61
+ browse sim start --platform android --app ./app-debug.apk --visible # .apk file
62
+
63
+ # Switch app targets (iOS: instant reconfigure, Android: driver restart)
64
+ browse --platform ios --app com.apple.mobilesafari snapshot -i
65
+ browse sim start --platform android --app com.google.android.dialer --visible
66
+
67
+ # Enable platforms (install dependencies, build drivers — run once)
68
+ browse enable android # Auto-installs adb, JDK, SDK, emulator, driver
69
+ browse enable ios # Builds iOS runner (needs Xcode)
70
+ browse enable macos # Builds browse-ax bridge
71
+ browse enable all # All platforms
72
+ ```
73
+
74
+ ### Common iOS Bundle IDs
75
+ | App | Bundle ID |
76
+ |-----|-----------|
77
+ | Settings | `com.apple.Preferences` |
78
+ | Safari | `com.apple.mobilesafari` |
79
+ | Maps | `com.apple.Maps` |
80
+ | Photos | `com.apple.mobileslideshow` |
81
+ | Calendar | `com.apple.mobilecal` |
82
+
83
+ ### Common Android Package Names
84
+ | App | Package Name |
85
+ |-----|-------------|
86
+ | Settings | `com.android.settings` |
87
+ | Chrome | `com.android.chrome` |
88
+ | Dialer | `com.google.android.dialer` |
89
+ | Messages | `com.google.android.apps.messaging` |
90
+ | Calculator | `com.google.android.calculator` |
91
+
92
+ ---
93
+
94
+ ## Browser Quick Start
18
95
 
19
96
  Persistent headless Chromium daemon. First call auto-starts the server (~3s).
20
97
  Every subsequent call: ~100-200ms. Auto-shuts down after 30 min idle.
@@ -190,7 +267,7 @@ Refs are invalidated on navigation — run `snapshot` again after `goto`.
190
267
 
191
268
  ### Native App Automation
192
269
  ```
193
- browse sim start --platform ios|android --app <id> [--visible] Start simulator/emulator + app
270
+ browse sim start --platform ios|android --app <id-or-path> [--visible] Start + install/launch app
194
271
  browse sim stop --platform ios|android Stop simulator/emulator
195
272
  browse sim status --platform ios|android Check runner status
196
273
  browse --platform ios --app <bundleId> <command> Target iOS app
@@ -198,6 +275,8 @@ browse --platform android --app <package> <command> Target Android a
198
275
  browse --app <name> <command> Target macOS app
199
276
  ```
200
277
 
278
+ The `--app` flag accepts a bundle ID, package name, **or file path** (.app/.ipa/.apk). File paths auto-install the app into the simulator/emulator.
279
+
201
280
  Supported commands on all app platforms: `snapshot`, `text`, `tap`, `fill`, `type`, `press`, `swipe`, `screenshot`.
202
281
  macOS also supports modifier combos: `browse --app TextEdit press "cmd+n"`.
203
282
  Android auto-installs adb, Java, SDK, and emulator on first use (macOS via Homebrew).
@@ -0,0 +1,299 @@
1
+ ---
2
+ name: browse-qa
3
+ description: |
4
+ AI QA agent powered by browse. Validates features, runs exploratory testing, and generates
5
+ automated regression tests across web, iOS, Android, and macOS. Accepts work from any source:
6
+ Jira stories, Linear tickets, GitHub issues, plain English descriptions, or acceptance criteria.
7
+ Outputs a reusable browse flow file that can be rerun for regression testing.
8
+ Use when the user says "QA this", "test this feature", "validate this story", "check this works",
9
+ or provides a ticket ID/URL to verify.
10
+ allowed-tools:
11
+ - Bash
12
+ - Read
13
+ - Write
14
+ ---
15
+
16
+ # browse-qa: AI QA Agent
17
+
18
+ QA any feature across web, iOS, Android, and macOS. Accept a spec from anywhere, test it live, generate automated regression tests.
19
+
20
+ ## When to Use
21
+
22
+ - User says "QA this", "test this feature", "validate this story", "check this works"
23
+ - User provides a Jira ticket, Linear issue, GitHub issue, or any feature description
24
+ - User wants to verify acceptance criteria against a live app or website
25
+ - User wants to generate automated tests from a manual QA session
26
+ - User asks for exploratory testing of a feature or page
27
+
28
+ ## Input Sources
29
+
30
+ The spec can come from:
31
+
32
+ 1. **Jira MCP** — if `mcp__jira__*` tools are available, fetch the ticket:
33
+ ```
34
+ mcp__jira__get_issue({ issueKey: "PROJ-123" })
35
+ ```
36
+ 2. **Linear MCP** — if `mcp__linear__*` tools are available
37
+ 3. **GitHub issue** — use browse to read the issue page
38
+ 4. **Plain text** — user describes what to test
39
+ 5. **File** — user points to a spec file
40
+ 6. **URL** — user provides a ticket URL (use browse to read it)
41
+
42
+ ## Workflow
43
+
44
+ ### Phase 1: Understand What to QA
45
+
46
+ 1. **Get the spec** — from MCP, user text, or URL
47
+ 2. **Break it down** into concrete, testable scenarios:
48
+ - What is the feature?
49
+ - Where does it live? (URL, app, platform)
50
+ - What are the acceptance criteria?
51
+ - What should happen? What should NOT happen?
52
+ - Edge cases: empty input, invalid data, boundary values
53
+ 3. **Present the QA plan**:
54
+ ```
55
+ QA plan for [feature]:
56
+
57
+ Target: [URL / app / platform]
58
+
59
+ Scenarios:
60
+ 1. [Happy path] — expected: [outcome]
61
+ 2. [Edge case] — expected: [outcome]
62
+ 3. [Error case] — expected: [outcome]
63
+ 4. [Boundary] — expected: [outcome]
64
+ ```
65
+ 4. **Confirm with user** before executing
66
+
67
+ ### Phase 2: Decide the Target
68
+
69
+ | Spec mentions... | Target | Setup |
70
+ |---|---|---|
71
+ | URL, website, web page, localhost | **Browser** | `browse --headed goto <url>` |
72
+ | iOS app, iPhone, iPad, Swift | **iOS Simulator** | `browse sim start --platform ios --app <id> --visible` |
73
+ | Android app, Kotlin, phone | **Android Emulator** | `browse sim start --platform android --app <id> --visible` |
74
+ | macOS app, desktop app | **macOS** | `browse --app <name>` |
75
+ | User has a .app/.ipa build to test | **iOS Simulator** | `browse sim start --platform ios --app ./path/to/App.app --visible` |
76
+ | User has an .apk build to test | **Android Emulator** | `browse sim start --platform android --app ./path/to/app.apk --visible` |
77
+ | Ambiguous ("our app", "the app") | **Ask the user** | "Which platform? Do you have a build file (.app/.ipa/.apk)?" |
78
+
79
+ **If unsure, always ask.** Don't guess the platform. If the user has a build artifact, ask for the file path.
80
+
81
+ ### Phase 3: Execute QA
82
+
83
+ 1. **Start recording** — every command becomes part of the regression test:
84
+ ```bash
85
+ browse record start
86
+ ```
87
+
88
+ 2. **For each scenario**, follow this pattern:
89
+
90
+ **Navigate:**
91
+ ```bash
92
+ browse goto <url> # web
93
+ browse wait --network-idle # web
94
+ browse --platform ios --app <id> snapshot -i # native
95
+ ```
96
+
97
+ **Interact:**
98
+ ```bash
99
+ browse snapshot -i # find elements
100
+ browse click @e3 # click
101
+ browse fill @e4 "test value" # fill
102
+ browse press Enter # submit
103
+ browse swipe up # scroll (native)
104
+ ```
105
+
106
+ **Verify — this is the critical part:**
107
+ ```bash
108
+ browse text # check visible text contains expected content
109
+ browse snapshot -i # check element exists/state
110
+ browse js "document.querySelector('.success')?.textContent" # specific check
111
+ browse count ".error-message" # check error count
112
+ browse screenshot .browse/sessions/default/scenario-1.png
113
+ ```
114
+
115
+ 3. **Report each scenario immediately:**
116
+ ```
117
+ ✓ Scenario 1: Valid discount code
118
+ Verified: price updated from AED 500 to AED 400
119
+ Screenshot: .browse/sessions/default/scenario-1.png
120
+
121
+ ✗ Scenario 2: Invalid discount code
122
+ Expected: error message "Invalid code"
123
+ Actual: no error shown, page unchanged
124
+ Screenshot: .browse/sessions/default/scenario-2.png
125
+ ```
126
+
127
+ ### Phase 4: Exploratory Testing
128
+
129
+ After testing the stated scenarios, do exploratory testing:
130
+
131
+ - **Try unexpected inputs** — special characters, very long text, HTML injection
132
+ - **Test responsiveness** — `browse emulate "iPhone 14"` then recheck
133
+ - **Check edge states** — empty cart, logged out, slow network (`browse offline on`)
134
+ - **Verify error handling** — what happens when things go wrong?
135
+ - **Check accessibility** — `browse a11y-audit` on key pages
136
+
137
+ Report any additional findings as bugs, not scenario failures.
138
+
139
+ ### Phase 5: Generate Regression Tests
140
+
141
+ For complex features, generate **multiple flow files** — one per logical scenario or user journey. Each should be independently runnable.
142
+
143
+ **Strategy:** Start recording before each scenario group, stop and save after it completes. Then start a new recording for the next group.
144
+
145
+ ```bash
146
+ # Scenario group 1: Happy path
147
+ browse record start
148
+ # ... execute happy path steps ...
149
+ browse record stop
150
+ browse flow save checkout-happy-path
151
+
152
+ # Scenario group 2: Validation errors
153
+ browse record start
154
+ # ... execute validation error steps ...
155
+ browse record stop
156
+ browse flow save checkout-validation-errors
157
+
158
+ # Scenario group 3: Discount codes
159
+ browse record start
160
+ # ... execute discount code steps ...
161
+ browse record stop
162
+ browse flow save checkout-discount-codes
163
+ ```
164
+
165
+ **When to split into multiple flows:**
166
+ - Different user journeys (login → browse → checkout is 3 flows, not 1)
167
+ - Different personas (guest checkout vs logged-in checkout)
168
+ - Different error scenarios (each error type gets its own flow)
169
+ - Different platforms (web flow + iOS flow for the same feature)
170
+ - When a single flow would exceed ~20 steps
171
+
172
+ **When to keep as one flow:**
173
+ - Simple feature with 1-5 steps
174
+ - Linear flow with no branching
175
+ - Single acceptance criterion
176
+
177
+ Tell the user how to rerun:
178
+ ```
179
+ Regression tests saved:
180
+ .browse/flows/checkout-happy-path.yaml
181
+ .browse/flows/checkout-validation-errors.yaml
182
+ .browse/flows/checkout-discount-codes.yaml
183
+
184
+ Rerun all:
185
+ browse flow run checkout-happy-path
186
+ browse flow run checkout-validation-errors
187
+ browse flow run checkout-discount-codes
188
+
189
+ Or run individually:
190
+ browse flow run checkout-happy-path
191
+ ```
192
+
193
+ ### Phase 6: QA Report
194
+
195
+ ```
196
+ ## QA Report: [Feature Name]
197
+
198
+ **Source:** [Jira PROJ-123 / user description]
199
+ **Target:** [https://example.com / com.example.app on iOS]
200
+ **Tested:** [date]
201
+
202
+ ### Acceptance Criteria
203
+ | # | Criteria | Result | Evidence |
204
+ |---|----------|--------|----------|
205
+ | 1 | [criteria from spec] | ✓ PASS | [what was verified] |
206
+ | 2 | [criteria from spec] | ✗ FAIL | [expected vs actual] |
207
+
208
+ ### Exploratory Findings
209
+ | # | Finding | Severity | Details |
210
+ |---|---------|----------|---------|
211
+ | 1 | [issue found] | High | [description + screenshot] |
212
+ | 2 | [edge case] | Low | [description] |
213
+
214
+ ### Regression Tests
215
+ | Flow | Steps | Rerun |
216
+ |------|-------|-------|
217
+ | .browse/flows/<name-1>.yaml | [N] | browse flow run <name-1> |
218
+ | .browse/flows/<name-2>.yaml | [N] | browse flow run <name-2> |
219
+
220
+ ### Screenshots
221
+ [list of screenshots taken during QA]
222
+
223
+ ### Verdict
224
+ [PASS / FAIL / PASS WITH ISSUES]
225
+ [Summary of what works, what doesn't, and recommended actions]
226
+ ```
227
+
228
+ ## Rules
229
+
230
+ 1. **Always record** — `browse record start` before any testing. Every QA session should produce a regression test.
231
+ 2. **Verify, don't just navigate** — the value of QA is checking outcomes, not clicking around. Use `browse text`, `browse count`, `browse js` to verify.
232
+ 3. **Screenshot at every checkpoint** — evidence for the report and useful for debugging failures.
233
+ 4. **Test the unhappy path** — edge cases, errors, and boundaries are where bugs hide.
234
+ 5. **Ask when ambiguous** — if the spec doesn't say where to test or what "correct" looks like, ask.
235
+ 6. **Name flows after the feature** — `checkout-discount`, `user-registration`, `search-filters`. Not `test1`.
236
+ 7. **Split complex features into multiple flows** — one flow per logical scenario or user journey. A checkout feature might produce `checkout-happy-path.yaml`, `checkout-discount-code.yaml`, `checkout-validation-errors.yaml`. Each flow should be independently runnable.
237
+ 8. **Report honestly** — if something doesn't work, say so clearly. Don't gloss over failures.
238
+
239
+ ## Native App QA
240
+
241
+ Same workflow, native commands:
242
+
243
+ ```bash
244
+ # iOS — from bundle ID (app already installed)
245
+ browse sim start --platform ios --app com.example.myapp --visible
246
+
247
+ # iOS — install from .app or .ipa build file
248
+ browse sim start --platform ios --app ./build/MyApp.app --visible
249
+ browse sim start --platform ios --app ./MyApp.ipa --visible
250
+
251
+ # Android — install from .apk build file
252
+ browse sim start --platform android --app ./app/build/outputs/apk/debug/app-debug.apk --visible
253
+
254
+ # Then QA as normal
255
+ browse record start
256
+ browse --platform ios --app com.example.myapp snapshot -i
257
+ browse --platform ios --app com.example.myapp tap @e3
258
+ browse --platform ios --app com.example.myapp fill @e5 "test"
259
+ browse --platform ios --app com.example.myapp press return
260
+ browse --platform ios --app com.example.myapp screenshot .browse/sessions/default/ios-test.png
261
+ browse record stop
262
+ browse flow save ios-feature-qa
263
+ ```
264
+
265
+ ## Examples
266
+
267
+ ### Example 1: Jira Story
268
+
269
+ **User:** "QA SHOP-789"
270
+
271
+ **Agent:**
272
+ 1. `mcp__jira__get_issue({ issueKey: "SHOP-789" })` → "Add discount code field to checkout. Valid codes reduce price. Invalid codes show error."
273
+ 2. Plans: happy path (valid code), error path (invalid), edge case (empty submit), boundary (expired code)
274
+ 3. Opens checkout page in headed browser
275
+ 4. Tests each scenario, screenshots at each step
276
+ 5. Finds: valid code works, invalid code works, BUT empty submit crashes the page
277
+ 6. Reports: 3/4 PASS, 1 FAIL (empty submit bug), flow saved as `checkout-discount-qa`
278
+
279
+ ### Example 2: Plain English
280
+
281
+ **User:** "QA the search on mumzworld.com — make sure filters work"
282
+
283
+ **Agent:**
284
+ 1. Plans: search text, apply price filter, apply brand filter, clear filters, empty search
285
+ 2. Opens mumzworld.com in headed browser
286
+ 3. Tests each filter combination
287
+ 4. Reports results with screenshots
288
+ 5. Saves flow: `mumzworld-search-filters-qa`
289
+
290
+ ### Example 3: Mobile App
291
+
292
+ **User:** "QA the login flow on our iOS app, bundle is com.ourcompany.app"
293
+
294
+ **Agent:**
295
+ 1. Boots iOS Simulator with the app
296
+ 2. Plans: valid login, invalid password, empty fields, forgot password link
297
+ 3. Tests each scenario in the simulator
298
+ 4. Reports with screenshots
299
+ 5. Saves flow: `ios-login-qa`