driftx 0.1.0 → 0.1.2

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.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +216 -0
  3. package/dist/bin.js +842 -84
  4. package/dist/bin.js.map +1 -1
  5. package/driftx-plugin/skills/driftx/SKILL.md +514 -0
  6. package/ios-companion/DriftxCompanion/DriftxCompanionApp.swift +10 -0
  7. package/ios-companion/DriftxCompanion/Info.plist +22 -0
  8. package/ios-companion/DriftxCompanion.xcodeproj/project.pbxproj +376 -0
  9. package/ios-companion/DriftxCompanion.xcodeproj/xcshareddata/xcschemes/DriftxCompanionUITests.xcscheme +109 -0
  10. package/ios-companion/DriftxCompanionUITests/CompanionServer.swift +176 -0
  11. package/ios-companion/DriftxCompanionUITests/DriftxCompanionUITests.swift +15 -0
  12. package/ios-companion/DriftxCompanionUITests/HierarchyEndpoint.swift +140 -0
  13. package/ios-companion/DriftxCompanionUITests/Info.plist +22 -0
  14. package/ios-companion/DriftxCompanionUITests/InteractionEndpoint.swift +142 -0
  15. package/ios-companion/DriftxCompanionUITests/Router.swift +47 -0
  16. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/DriftxCompanion +0 -0
  17. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/DriftxCompanion.debug.dylib +0 -0
  18. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/Info.plist +0 -0
  19. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/PkgInfo +1 -0
  20. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/__preview.dylib +0 -0
  21. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/DriftxCompanionUITests-Runner +0 -0
  22. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/Testing.framework/Info.plist +0 -0
  23. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/Testing.framework/Testing +0 -0
  24. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/Testing.framework/_CodeSignature/CodeResources +168 -0
  25. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/Testing.framework/version.plist +18 -0
  26. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTAutomationSupport.framework/Info.plist +0 -0
  27. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTAutomationSupport.framework/XCTAutomationSupport +0 -0
  28. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTAutomationSupport.framework/_CodeSignature/CodeResources +113 -0
  29. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTAutomationSupport.framework/version.plist +18 -0
  30. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTest.framework/Info.plist +0 -0
  31. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTest.framework/XCTest +0 -0
  32. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTest.framework/_CodeSignature/CodeResources +817 -0
  33. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTest.framework/version.plist +18 -0
  34. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestCore.framework/Info.plist +0 -0
  35. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestCore.framework/XCTestCore +0 -0
  36. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestCore.framework/_CodeSignature/CodeResources +113 -0
  37. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestCore.framework/version.plist +18 -0
  38. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestSupport.framework/Info.plist +0 -0
  39. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestSupport.framework/XCTestSupport +0 -0
  40. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestSupport.framework/_CodeSignature/CodeResources +113 -0
  41. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestSupport.framework/version.plist +18 -0
  42. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUIAutomation.framework/Info.plist +0 -0
  43. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUIAutomation.framework/XCUIAutomation +0 -0
  44. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUIAutomation.framework/_CodeSignature/CodeResources +432 -0
  45. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUIAutomation.framework/version.plist +18 -0
  46. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUnit.framework/Info.plist +0 -0
  47. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUnit.framework/XCUnit +0 -0
  48. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUnit.framework/_CodeSignature/CodeResources +113 -0
  49. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUnit.framework/version.plist +18 -0
  50. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/libXCTestSwiftSupport.dylib +0 -0
  51. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Info.plist +254 -0
  52. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/PkgInfo +1 -0
  53. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/PlugIns/DriftxCompanionUITests.xctest/DriftxCompanionUITests +0 -0
  54. package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/PlugIns/DriftxCompanionUITests.xctest/Info.plist +0 -0
  55. package/ios-companion/prebuilt/DriftxCompanionUITests.xctestrun +135 -0
  56. package/ios-companion/prebuilt/build-info.json +6 -0
  57. package/package.json +19 -4
  58. package/driftx-plugin/skills/driftx.md +0 -299
@@ -0,0 +1,514 @@
1
+ ---
2
+ name: driftx
3
+ description: Visual comparison, accessibility audit, layout regression, and device interaction for mobile apps (Android, iOS, React Native). Use when the user asks to compare their app against a design, check accessibility, detect visual regressions, inspect the component tree, capture screenshots, or interact with a device/simulator (tap, type, swipe, navigate).
4
+ ---
5
+
6
+ # driftx — Visual Analysis for React Native & Android
7
+
8
+ Use driftx when the user wants to:
9
+ - Compare their running app against a design image (Figma export, mockup, etc.)
10
+ - Run an accessibility audit on the component tree
11
+ - Detect layout regressions between builds
12
+ - Inspect the React Native component tree on a device
13
+ - Capture a screenshot from a running simulator/emulator
14
+ - Interact with the app — tap buttons, type text, swipe, navigate back, open deep links
15
+ - Test a user flow end-to-end (navigate, interact, then verify visually)
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install -g driftx
21
+ ```
22
+
23
+ The iOS companion ships pre-built — no Xcode build step required on install.
24
+ driftx will notify you when a newer version is available.
25
+
26
+ ## Prerequisites
27
+
28
+ Run `driftx doctor` to verify the environment is set up correctly.
29
+
30
+ **Requirements:**
31
+ - **Metro bundler** must be running (`npx react-native start`) for tree inspection, tap resolution, and bundle ID auto-detection
32
+ - **Android**: `adb` available, emulator booted
33
+ - **iOS**: `xcrun simctl` available, simulator booted. The XCUITest companion auto-launches when needed.
34
+
35
+ ## Platform Support
36
+
37
+ driftx currently supports **simulators and emulators only**:
38
+ - **Android**: Emulators via `adb`
39
+ - **iOS**: Simulators via `xcrun simctl` + XCUITest companion
40
+
41
+ Physical device support is not yet available (requires code signing for XCUITest companion deployment and alternative screenshot tooling).
42
+
43
+ ## Global Flags
44
+
45
+ | Flag | Description |
46
+ |------|-------------|
47
+ | `-d, --device <id>` | Device ID or name. If omitted and multiple devices are booted, driftx shows a picker. |
48
+ | `--bundle-id <id>` | iOS app bundle identifier. Optional — auto-detected from Metro CDP target when Metro is running. |
49
+ | `--verbose` | Enable debug logging. Useful for diagnosing tap resolution, companion issues, or CDP connection problems. |
50
+ | `--format <type>` | Output format: `terminal`, `markdown`, `json` (default: `terminal`). |
51
+ | `--copy` | Copy output to clipboard. |
52
+
53
+ ## Commands Reference
54
+
55
+ ### `driftx compare` — Run visual analysis
56
+
57
+ The primary command. Compares a screenshot from a running device against a design image or baseline.
58
+
59
+ ```bash
60
+ # Compare against a design image
61
+ npx driftx compare --design path/to/design.png --format json
62
+
63
+ # Compare with specific device
64
+ npx driftx compare --design path/to/design.png --device "iPhone 16 Pro" --format json
65
+
66
+ # Use an existing screenshot instead of capturing
67
+ npx driftx compare --design path/to/design.png --screenshot path/to/screenshot.png --format json
68
+
69
+ # Run only specific analyses
70
+ npx driftx compare --design path/to/design.png --with pixel,a11y --format json
71
+
72
+ # Exclude specific analyses
73
+ npx driftx compare --design path/to/design.png --without pixel --format json
74
+
75
+ # Regression mode — compare against previous run (no design needed)
76
+ npx driftx compare --baseline --format json
77
+ ```
78
+
79
+ **Flags:**
80
+ | Flag | Description |
81
+ |------|-------------|
82
+ | `--design <path>` | Path to design image (PNG). Required unless `--baseline`. |
83
+ | `--screenshot <path>` | Use existing screenshot instead of capturing from device. |
84
+ | `--threshold <n>` | Pixel sensitivity threshold (0-1, default 0.1). |
85
+ | `--with <analyses>` | Comma-separated analyses to run (e.g., `pixel,a11y,regression`). |
86
+ | `--without <analyses>` | Analyses to exclude. |
87
+ | `--baseline` | Compare against previous run's screenshot. |
88
+ | `--format json` | **Always use this** for structured output. |
89
+
90
+ **Available analyses:**
91
+ | Analysis | What it does | Auto-enabled when |
92
+ |----------|-------------|-------------------|
93
+ | `pixel` | Pixel-level diff between screenshot and design | Design image provided |
94
+ | `a11y` | Accessibility audit — missing labels, small tap targets, images without alt text | Component tree available (device connected) |
95
+ | `regression` | Layout regression — diff against previous run | `--baseline` flag used |
96
+
97
+ **Smart defaults:** When no `--with`/`--without` is specified, analyses auto-enable based on available inputs. You don't need to specify `--with` unless you want to override.
98
+
99
+ ### `driftx inspect` — Inspect component tree
100
+
101
+ ```bash
102
+ npx driftx inspect --format json
103
+ npx driftx inspect --json # shorthand for --format json
104
+ npx driftx inspect --device "Pixel 8" --format json
105
+ ```
106
+
107
+ Returns the React Native component tree with component names, testIDs, text content, and bounds. Use this to discover tap targets before interacting — the tree shows all visible text, testIDs, and component names that `driftx tap` can target.
108
+
109
+ ### `driftx devices` — List connected devices
110
+
111
+ ```bash
112
+ npx driftx devices --format json
113
+ ```
114
+
115
+ Returns available simulators/emulators and their state (booted/offline). When multiple devices are booted and no `-d` flag is provided, driftx shows an interactive picker.
116
+
117
+ ### `driftx capture` — Capture screenshot
118
+
119
+ ```bash
120
+ npx driftx capture --output screenshot.png
121
+ npx driftx capture --device "iPhone 16 Pro" --output screenshot.png
122
+ ```
123
+
124
+ Captures a screenshot from the device and saves it to the specified path.
125
+
126
+ ### `driftx doctor` — Check prerequisites
127
+
128
+ ```bash
129
+ npx driftx doctor --format json
130
+ ```
131
+
132
+ Checks that adb, xcrun, Metro, etc. are available.
133
+
134
+ ### `driftx setup-claude` — Register as Claude Code plugin
135
+
136
+ ```bash
137
+ npx driftx setup-claude
138
+ ```
139
+
140
+ Registers driftx as a Claude Code plugin so the skill is available in all projects.
141
+
142
+ ## Output Interpretation
143
+
144
+ ### JSON format (CompareReport)
145
+
146
+ When using `--format json`, `driftx compare` outputs a `CompareReport`:
147
+
148
+ ```json
149
+ {
150
+ "report": {
151
+ "runId": "abc123",
152
+ "analyses": [
153
+ {
154
+ "analysisName": "pixel",
155
+ "findings": [...],
156
+ "summary": "Pixel diff: 2.100% — 3 regions (fail)",
157
+ "metadata": {
158
+ "diffPercentage": 2.1,
159
+ "diffPixels": 5000,
160
+ "totalPixels": 238000,
161
+ "regions": [...],
162
+ "passed": false
163
+ },
164
+ "durationMs": 450
165
+ },
166
+ {
167
+ "analysisName": "a11y",
168
+ "findings": [...],
169
+ "summary": "2 accessibility issues found",
170
+ "metadata": {
171
+ "totalChecked": 15,
172
+ "issuesByType": { "label": 1, "tapTarget": 1, "image": 0, "emptyText": 0 }
173
+ },
174
+ "durationMs": 5
175
+ }
176
+ ],
177
+ "findings": [...],
178
+ "summary": "...",
179
+ "durationMs": 460
180
+ },
181
+ "artifactDir": ".driftx/runs/abc123"
182
+ }
183
+ ```
184
+
185
+ Key fields to check:
186
+ - `report.analyses[].metadata.passed` — `false` means the analysis failed its threshold
187
+ - `report.analyses[].findings` — individual issues found
188
+ - `report.findings` — all findings merged across analyses
189
+ - `artifactDir` — where screenshots, diff masks, and region crops are saved
190
+
191
+ ### Artifacts
192
+
193
+ After a compare run, artifacts are saved to `.driftx/runs/<runId>/`:
194
+
195
+ | File | Description |
196
+ |------|-------------|
197
+ | `screenshot.png` | Captured screenshot |
198
+ | `design.png` | Copy of the design image |
199
+ | `diff-mask.png` | Visual overlay showing pixel differences |
200
+ | `regions/<id>.png` | Cropped images of each diff region |
201
+ | `regression-diff-mask.png` | Diff mask for regression analysis |
202
+ | `result.json` | Full CompareReport as JSON |
203
+ | `report.md` | Human-readable markdown report |
204
+
205
+ Read `report.md` for a formatted summary. Read `result.json` for structured data. View diff mask and region crops to understand what changed visually.
206
+
207
+ ### Finding categories
208
+
209
+ | Category | Source | Meaning |
210
+ |----------|--------|---------|
211
+ | `spacing`, `color`, `font`, `alignment`, `size`, `content`, `missing`, `extra` | pixel analysis | Visual differences between design and screenshot |
212
+ | `accessibility` | a11y analysis | Missing labels, small tap targets, images without alt text |
213
+ | `regression` | regression analysis | Layout changed from previous baseline |
214
+
215
+ ### Finding severity
216
+
217
+ - `critical` — major visual breakage
218
+ - `major` — noticeable difference (missing labels, significant pixel diff)
219
+ - `minor` — small issues (slightly small tap targets)
220
+ - `info` — informational (empty text nodes)
221
+
222
+ ## Interpreting Visual Differences
223
+
224
+ When comparing a design against a live app, **distinguish between structural issues and dynamic data**. Not every pixel difference is a bug.
225
+
226
+ ### Dynamic data (NOT issues)
227
+
228
+ These are expected to differ between a design mockup and a live app — do NOT report them as mismatches:
229
+
230
+ - **Counts and numbers** — "12 stops" vs "243 stops", "97" vs "99+", timestamps, dates
231
+ - **User-specific text** — names, email addresses, avatars, profile data
232
+ - **API-driven content** — store names, product titles, list items, map labels, notification badges
233
+ - **Images from a server** — map tiles, avatars, product images, thumbnails
234
+
235
+ ### Structural issues (REAL issues)
236
+
237
+ These are actual design deviations that should be reported:
238
+
239
+ - **Missing or extra UI elements** — buttons, cards, banners not in the design
240
+ - **Different labels/icons** — tab bar says "Settings" but design says "Account", wrong icon
241
+ - **Layout differences** — spacing, alignment, sizing that doesn't match the design
242
+ - **Typography changes** — bold vs regular, different font size, wrong color
243
+ - **Style differences** — wrong background color, border radius, shadows
244
+
245
+ ### How to present comparison results
246
+
247
+ When showing a design-vs-app comparison table, add a **Type** column:
248
+
249
+ ```
250
+ | Area | Design | App | Type | Match? |
251
+ |------|--------|-----|------|--------|
252
+ | Stop count | "12 stops" | "243 stops" | Dynamic data | OK |
253
+ | Tab labels | "Account" | "Settings" | Structural | Mismatch |
254
+ | Alert badge | 97 | 99+ | Dynamic data | OK |
255
+ | Action buttons | None | "View stops..." | Structural | Mismatch — extra element |
256
+ ```
257
+
258
+ Mark dynamic data rows as **OK** even if the values differ. Only flag structural differences as mismatches. Summarize by counting only structural mismatches, not dynamic data differences.
259
+
260
+ ## Workflow Patterns
261
+
262
+ ### Compare against a Figma design
263
+
264
+ If the user has a Figma MCP server connected, use it to export the frame as an image first, then run driftx:
265
+
266
+ 1. Use Figma MCP to get the design frame → save as PNG
267
+ 2. Run `npx driftx compare --design <saved-image-path> --format json`
268
+ 3. Read the JSON output to understand differences
269
+ 4. Read artifact files (diff mask, report.md) for visual context
270
+ 5. **Classify each difference** as dynamic data or structural issue
271
+ 6. Only suggest code fixes for structural issues
272
+
273
+ If no Figma MCP, ask the user to provide the design image path.
274
+
275
+ ### Accessibility audit
276
+
277
+ ```bash
278
+ npx driftx compare --design <path> --with a11y --format json
279
+ ```
280
+
281
+ Or without a design image (a11y only needs the component tree):
282
+ ```bash
283
+ npx driftx compare --baseline --with a11y --format json
284
+ ```
285
+
286
+ Review findings with `category: 'accessibility'` and suggest fixes (add accessibilityLabel, increase tap target size, etc.).
287
+
288
+ ### Regression detection
289
+
290
+ ```bash
291
+ npx driftx compare --baseline --format json
292
+ ```
293
+
294
+ Compares current app state against the most recent previous run. No design file needed. Useful after code changes to verify nothing broke visually.
295
+
296
+ ### Full audit (all analyses)
297
+
298
+ ```bash
299
+ npx driftx compare --design <path> --with pixel,a11y --format json
300
+ ```
301
+
302
+ Runs pixel diff and accessibility audit together.
303
+
304
+ ## Device Interaction
305
+
306
+ driftx can interact with the running app — tap buttons, type text, swipe, navigate.
307
+
308
+ **Critical rule: always verify interactions visually.** Before any interaction, capture a screenshot to understand the current screen state. After any interaction, capture another screenshot to verify it worked. Never assume an interaction succeeded without visual confirmation.
309
+
310
+ ### Recommended interaction pattern
311
+
312
+ 1. `npx driftx capture -o /tmp/before.png` — see what's on screen
313
+ 2. `npx driftx inspect --json` — find tap targets (text, testIDs, component names)
314
+ 3. `npx driftx tap "Submit"` — interact
315
+ 4. `npx driftx capture -o /tmp/after.png` — verify the result
316
+
317
+ ### How tap resolution works
318
+
319
+ When you run `driftx tap "Submit"`, the tool resolves the target through multiple strategies in order:
320
+
321
+ 1. **CDP tree** (React Native) — finds components by testID, name, or text with bounds
322
+ 2. **XCUITest companion hierarchy** (iOS) — accessibility elements with real screen bounds, fuzzy text matching (e.g., "Trips" matches "Trips, tab, 2 of 6")
323
+ 3. **XCUITest element query** (iOS) — searches staticTexts, buttons, links by label
324
+ 4. **CDP fiber measurement** — finds the React fiber by text, then calls `stateNode.measureInWindow()` to get actual screen coordinates
325
+
326
+ This means `driftx tap "Submit"` works even for React Native elements that have no accessibility label — the CDP fiber measurement will find and measure it directly.
327
+
328
+ ### `driftx tap <target>` — Tap a component
329
+
330
+ ```bash
331
+ # By testID, component name, or visible text
332
+ npx driftx tap login-btn
333
+ npx driftx tap LoginButton
334
+ npx driftx tap "Submit"
335
+
336
+ # By exact coordinates
337
+ npx driftx tap 150,300 --xy
338
+
339
+ # Target a specific device
340
+ npx driftx tap "Submit" --device "iPhone 16 Pro"
341
+ ```
342
+
343
+ The `--bundle-id` flag is optional — driftx auto-detects the app's bundle ID from the Metro CDP target when Metro is running.
344
+
345
+ ### `driftx type <target> <text>` — Type text into a field
346
+
347
+ ```bash
348
+ npx driftx type email-input "user@example.com"
349
+ ```
350
+
351
+ Taps the target first to focus it, then types.
352
+
353
+ ### `driftx swipe <direction>` — Swipe gesture
354
+
355
+ ```bash
356
+ npx driftx swipe up
357
+ npx driftx swipe down
358
+ npx driftx swipe left
359
+ npx driftx swipe right
360
+
361
+ # Custom distance (default: 300pt iOS, 600pt Android)
362
+ npx driftx swipe up --distance 200
363
+ ```
364
+
365
+ Default distance is 300pt on iOS and 600pt on Android. Always capture a screenshot before swiping to understand the screen layout and choose an appropriate distance, and after swiping to verify the result. If a swipe dismisses the app or triggers the home gesture, reduce the distance (e.g., `--distance 150`).
366
+
367
+ ### `driftx go-back` — Press back button
368
+
369
+ ```bash
370
+ npx driftx go-back
371
+ ```
372
+
373
+ ### `driftx open-url <url>` — Open a deep link
374
+
375
+ ```bash
376
+ npx driftx open-url "myapp://profile/123"
377
+ ```
378
+
379
+ ### Interaction Workflow
380
+
381
+ **Simple navigation test:**
382
+ 1. `npx driftx capture -o /tmp/start.png` — capture starting state
383
+ 2. `npx driftx inspect --json` — find available tap targets
384
+ 3. `npx driftx tap "Login"` — navigate
385
+ 4. `npx driftx capture -o /tmp/after-login.png` — verify navigation happened
386
+ 5. `npx driftx compare --design mockup.png --format json` — compare against design
387
+
388
+ **Form testing:**
389
+ 1. `npx driftx capture -o /tmp/form.png` — see the form
390
+ 2. `npx driftx type email-input "test@example.com"`
391
+ 3. `npx driftx type password-input "password123"`
392
+ 4. `npx driftx tap "Submit"`
393
+ 5. `npx driftx capture -o /tmp/after-submit.png` — verify submission result
394
+
395
+ **Scrolling to find content:**
396
+ 1. `npx driftx capture -o /tmp/before-scroll.png` — see what's visible
397
+ 2. `npx driftx swipe up` — scroll down
398
+ 3. `npx driftx capture -o /tmp/after-scroll.png` — verify new content is visible
399
+ 4. `npx driftx tap "Load More"` — tap newly visible element
400
+
401
+ ## Configuration
402
+
403
+ driftx uses `.driftxrc.json` in the project root. Run `npx driftx init` to create one. Key settings:
404
+
405
+ - `platform`: `"android"` or `"ios"`
406
+ - `metroPort`: Metro bundler port (default 8081)
407
+ - `threshold`: Pixel sensitivity (default 0.1)
408
+ - `diffThreshold`: Pass/fail percentage threshold (default 0.01)
409
+ - `analyses.default`: Default analyses to run
410
+ - `analyses.disabled`: Analyses to never run
411
+
412
+ ## Output Formatting Rules
413
+
414
+ **Always present results in a consistent, structured format.** Follow these rules strictly:
415
+
416
+ ### Results Table
417
+
418
+ Every analysis result — whether it has issues or not — must be shown in a table. Use this format for **each device**:
419
+
420
+ **When issues are found:**
421
+
422
+ ```
423
+ ### <Device Name> (<Platform>)
424
+
425
+ <N> components checked — <M> issues found.
426
+
427
+ | Severity | Issue | Component | Location |
428
+ |----------|-------|-----------|----------|
429
+ | Major | Missing accessibilityLabel | android.widget.Button | x:954 y:164 (105x105px) |
430
+ | Minor | Small tap target (36x36) | RCTText | x:10 y:200 (36x36px) |
431
+ ```
432
+
433
+ **When no issues are found:**
434
+
435
+ ```
436
+ ### <Device Name> (<Platform>)
437
+
438
+ <N> components checked — no issues found.
439
+
440
+ | Category | Count |
441
+ |----------|-------|
442
+ | Missing labels | 0 |
443
+ | Small tap targets | 0 |
444
+ | Images without alt text | 0 |
445
+ | Empty text nodes | 0 |
446
+ ```
447
+
448
+ **For pixel diff results:**
449
+
450
+ ```
451
+ ### <Device Name> (<Platform>)
452
+
453
+ | Metric | Value |
454
+ |--------|-------|
455
+ | Diff | 2.10% (5000 / 238000 pixels) |
456
+ | Regions | 3 |
457
+ | Duration | 450ms |
458
+ | Result | FAIL |
459
+
460
+ | # | Severity | Category | Component | Region |
461
+ |---|----------|----------|-----------|--------|
462
+ | 1 | Critical | spacing | LoginButton [login-btn] | (10,20) 100x50 |
463
+ ```
464
+
465
+ ### Next Actions
466
+
467
+ After presenting results, **always offer next actions using the AskUserQuestion tool with `options`**. This renders as a radio-button selection menu. Never present choices as plain numbered text.
468
+
469
+ Example — after a11y audit with issues:
470
+ ```
471
+ AskUserQuestion(
472
+ question: "What would you like to do next?",
473
+ options: [
474
+ "Capture a screenshot to visually identify the issue",
475
+ "Inspect the component tree to find the source component",
476
+ "Fix the issue (add accessibilityLabel)",
477
+ "Run the audit again after changes",
478
+ "Run on another device"
479
+ ]
480
+ )
481
+ ```
482
+
483
+ Example — after clean results (no issues):
484
+ ```
485
+ AskUserQuestion(
486
+ question: "What would you like to do next?",
487
+ options: [
488
+ "Run pixel diff against a design",
489
+ "Run regression test against previous baseline",
490
+ "Check another device",
491
+ "Inspect the component tree",
492
+ "Capture a screenshot"
493
+ ]
494
+ )
495
+ ```
496
+
497
+ Tailor the options to the context. Always use AskUserQuestion with options — never plain text lists.
498
+
499
+ ### General Rules
500
+
501
+ - **Consistent style across all devices** — if you show a table for one device, show a table for all
502
+ - **Always include the device name and platform** as a header
503
+ - **Always include component count** (from `metadata.totalChecked`)
504
+ - **Always offer next actions** as a numbered list
505
+ - **Read artifact files** (`report.md`, `result.json`) when you need more detail about findings
506
+
507
+ ## Error Handling
508
+
509
+ - If no booted device is found, suggest the user start a simulator/emulator
510
+ - If Metro is not running, suggest `npx react-native start` — Metro is required for tree inspection, tap-by-text, and bundle ID auto-detection
511
+ - If `driftx doctor` shows missing prerequisites, show the user which tools to install
512
+ - If compare fails with "Either --design or --baseline must be provided", one of those flags is required
513
+ - If tap returns `"Target not found"`, run `npx driftx inspect --json` to see available targets, or use `--xy` with coordinates from a screenshot
514
+ - If interactions fail with timeout, add `--verbose` to see debug logs for the companion and CDP connection
@@ -0,0 +1,10 @@
1
+ import SwiftUI
2
+
3
+ @main
4
+ struct DriftxCompanionApp: App {
5
+ var body: some Scene {
6
+ WindowGroup {
7
+ Text("DriftxCompanion")
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>en</string>
7
+ <key>CFBundleExecutable</key>
8
+ <string>$(EXECUTABLE_NAME)</string>
9
+ <key>CFBundleIdentifier</key>
10
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11
+ <key>CFBundleInfoDictionaryVersion</key>
12
+ <string>6.0</string>
13
+ <key>CFBundleName</key>
14
+ <string>$(PRODUCT_NAME)</string>
15
+ <key>CFBundlePackageType</key>
16
+ <string>APPL</string>
17
+ <key>CFBundleShortVersionString</key>
18
+ <string>1.0</string>
19
+ <key>CFBundleVersion</key>
20
+ <string>1</string>
21
+ </dict>
22
+ </plist>