Skip to content

feat: replace Appium with Revyl CLI for mobile QA (v0.11.21.0)#488

Open
TenzinDhonyoe wants to merge 27 commits intogarrytan:mainfrom
TenzinDhonyoe:TenzinDhonyoe/qa-mobile-check
Open

feat: replace Appium with Revyl CLI for mobile QA (v0.11.21.0)#488
TenzinDhonyoe wants to merge 27 commits intogarrytan:mainfrom
TenzinDhonyoe:TenzinDhonyoe/qa-mobile-check

Conversation

@TenzinDhonyoe
Copy link

@TenzinDhonyoe TenzinDhonyoe commented Mar 25, 2026

Summary

  • Mobile QA now uses Revyl cloud devices instead of local Appium/iOS Simulator setup. Zero local dependencies — cloud-hosted iOS and Android with AI-grounded natural language targeting.
  • Revyl auth gatingrevyl auth status check at skill startup. Mobile QA auto-activates when Revyl is authenticated AND app.json/app.config.* is present. Web QA works regardless.
  • Modular resolver integrationgenerateRevylSetup and extended generateQAMethodology placed in scripts/resolvers/utility.ts + registered in scripts/resolvers/index.ts, aligned with upstream's modular resolver refactoring.
  • Hardened session management — keepalive checks detect dead sessions and restart, empty bundle ID detection asks user instead of proceeding silently.
  • Removed browse-mobile/ entirely — all Appium code deleted. Unused fast-xml-parser dependency removed.
  • Consistent screenshot paths — standardized to /tmp/mobile-screen.png across all templates.

Changes

Area What changed
scripts/resolvers/utility.ts New generateRevylSetup(), extended generateQAMethodology() with mobile step 3b
scripts/resolvers/index.ts Registered REVYL_SETUP in RESOLVERS map
scripts/gen-skill-docs.ts Merged with upstream modular resolver approach (local copies now dead code)
qa/SKILL.md.tmpl Added {{REVYL_SETUP}}, mobile command mapping, --mobile/--web platform param
qa-only/SKILL.md.tmpl Same Revyl integration
SKILL.md.tmpl (root) Updated mobile testing section with Revyl CLI examples
package.json Removed fast-xml-parser, bumped to 0.11.21.0
TODOS.md Browse-Mobile section marked as superseded by Revyl

Pre-Landing Review

Pre-landing review completed. Adversarial review found 5 issues:

  • 3 FIXABLE: applied (keepalive dead session check, empty bundle ID guard, screenshot path standardization)
  • 2 INVESTIGATE: informational (MCP→CLI migration incomplete if Revyl updates, revyl auth status exit code assumption)

Test plan

  • bun test passes (1 pre-existing failure in review.ts Codex path — not related to this branch)
  • bun run gen:skill-docs regenerates all SKILL.md files without error
  • Generated SKILL.md files contain Revyl setup and mobile methodology sections
  • No {{REVYL_SETUP}} unresolved placeholders in generated output

🤖 Generated with Claude Code

TenzinDhonyoe and others added 19 commits March 23, 2026 12:59
New module that implements the same HTTP command protocol as browse/
but backed by Appium WebDriver for mobile app automation. Enables
/qa to test Expo/React Native apps on iOS Simulator.

Key components:
- ref-system.ts: Parse Appium XML accessibility tree into @e refs
- mobile-driver.ts: WebDriverIO wrapper with click, fill, screenshot, snapshot
- server.ts: HTTP server (same protocol as browse — bearer auth, state file)
- cli.ts: CLI entry point + setup-check for dependency validation
- platform/ios.ts: iOS Simulator boot, device listing, app management

Tested against real Expo app (Gluco) — snapshot, click, fill, screenshot
all working. 43 tests passing, 0 failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
QA skills now auto-detect Expo/React Native projects and switch to
mobile mode. When app.json is found and browse-mobile is available:
- Automatically starts Appium if not running
- Boots iOS Simulator if needed
- Builds/installs app if not on simulator
- Navigates through Expo dev launcher to actual app
- Uses $BM instead of $B for all browse commands
- Falls back to ~"Label" selector for RN components missing accessibilityRole
- Flags missing accessibility props as QA findings

Web QA behavior is completely unchanged — mobile branches are gated
on detection.

Files changed:
- scripts/gen-skill-docs.ts: BROWSE_MOBILE_SETUP placeholder + mobile
  detection in QA methodology + Expo/RN framework guidance
- qa/SKILL.md.tmpl: mobile setup block + platform parameter
- qa-only/SKILL.md.tmpl: same mobile additions (report-only)
- SKILL.md.tmpl: Mobile Testing section with $BM command reference
- TODOS.md: 3 new items from eng review

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The compiled binary is 58MB (bundles entire Bun runtime + webdriverio).
Same pattern as browse/dist/ which is already gitignored.
Users build it locally via: bun build --compile browse-mobile/src/cli.ts --outfile browse-mobile/dist/browse-mobile

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The compiled binary couldn't find server.ts when deployed outside the
gstack repo. Now the CLI spawns itself with --server flag to run the
server in-process, same pattern as browse/. Works both in dev mode
(bun run cli.ts) and as compiled binary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…iled binary

Three fixes:
1. Switch from bun --compile (can't resolve webdriverio transitive deps)
   to bun build (JS bundle) + shell launcher script. 3.2MB bundle vs 58MB
   binary, and all npm deps resolve correctly at runtime.
2. Filter --server from process.argv in server.ts so bundle ID isn't
   clobbered when CLI spawns itself in server mode.
3. CLI finds the bundled cli.js relative to itself, works from any directory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bug 1: handleCommand() threw immediately if not connected. Now it
auto-reconnects to Appium when the first command arrives, handling
the common case where WDA takes 30-60s to compile on first session.

Bug 2: CLI didn't pass BROWSE_MOBILE_BUNDLE_ID env var when spawning
the server subprocess. Now extracts bundle ID from goto app://... and
forwards it so the Appium session is created with the correct app.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrote mobile-driver.ts to use raw fetch() for all Appium WebDriver
protocol calls instead of webdriverio. This eliminates the transitive
dependency bundling problem permanently.

Results:
- Bundle: 119KB (was 3.2MB with webdriverio)
- Dependencies: 0 npm packages (was webdriverio + 230 transitive deps)
- All Appium commands work via W3C WebDriver REST protocol over HTTP

Also fixed:
- CLI timeout: 180s for goto (Appium connect), 60s for other commands
- Removed webdriverio from package.json

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
/execute returns 404 on Appium — the correct W3C route is /execute/sync.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When /qa detects a mobile project for the first time, it checks if
browse-mobile bash permissions exist in the user's settings.json.
If not, offers to add them — one-time setup that enables fully
automated mobile QA without per-command approval prompts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Expanded permission patterns to cover inline bash (SID=..., curl -X
   POST, JAVA_HOME=...) that the QA skill generates. Previous patterns
   only matched commands starting with $BM.

2. Added speed guidance: batch multiple $BM commands in single bash calls
   using && instead of separate tool calls. Take screenshots at milestones
   only, not after every tap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
browseDir is ~/.claude/skills/gstack/browse/dist — need ../../ to reach
the gstack root, not ../ which only goes up to browse/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…p command

Three fixes:
1. Changed ~"Label" to label:Label syntax — the ~ was being interpreted
   by zsh as home directory expansion, breaking accessibility label clicks.
2. Added tap <x> <y> command for coordinate-based tapping when elements
   can't be found by ref or label.
3. Updated all skill templates and help text to use new label: syntax.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Delete the entire browse-mobile/ directory (~6000 LOC) — the Appium-backed
local mobile QA binary. Replace with Revyl MCP integration: cloud-hosted iOS
and Android devices with AI-grounded element targeting.

Changes:
- generateBrowseMobileSetup() → generateRevylSetup() in gen-skill-docs.ts
- Rewrite mobile section in generateQAMethodology() for Revyl MCP tools
- Update qa/SKILL.md.tmpl and qa-only/SKILL.md.tmpl templates
- Add mobile testing section to root SKILL.md.tmpl
- Remove browse-mobile TODOs, mark section as superseded
- Regenerate all SKILL.md files

Zero local dependencies — no Java, Appium, XCUITest, or Xcode CLI tools.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude's deferred tool system requires ToolSearch to load MCP tool
schemas before they can be called. Without this step, /qa --mobile
fails with "tool not found" errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Separate CLI auth check from MCP tool discovery. If ToolSearch finds
no Revyl tools, the template now tells Claude to stop and guide the
user through `claude mcp add revyl` + restart instead of blocking
with an opaque error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MCP tools are loaded at session startup — not deferred. Check server
connectivity with `claude mcp get revyl` instead of ToolSearch. Call
Revyl tools directly; fall back to ToolSearch only on "tool not found".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Local-scoped MCP servers aren't visible to other projects. Use
`-s user` (global) so Revyl tools are available in any Claude
Code session regardless of which project directory it starts in.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MCP tool discovery was unreliable across sessions. Switch entirely
to `revyl device` CLI (tap, type, swipe, screenshot, etc.) which
works via bash — no MCP server configuration needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@TenzinDhonyoe TenzinDhonyoe changed the title feat: replace browse-mobile with Revyl MCP for mobile QA (v0.11.10.0) feat: replace browse-mobile (Appium) with Revyl CLI for mobile QA Mar 25, 2026
TenzinDhonyoe and others added 4 commits March 25, 2026 11:59
Upstream advanced from v0.11.9.0 to v0.11.18.2 while this branch was
at v0.11.10.0. Conflicts in VERSION, package.json (version field),
and CHANGELOG.md (both sides added new entries at the top).

Resolution: take upstream's entries, add our Revyl entry on top as
v0.11.19.0. Regenerated all SKILL.md files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…bile-check

# Conflicts:
#	CHANGELOG.md
#	VERSION
#	package.json
#	scripts/gen-skill-docs.ts
…paths

- Session keepalive now checks for dead sessions and restarts
- Empty bundle ID grep returns gracefully instead of proceeding silently
- Standardized all screenshot paths to /tmp/mobile-screen.png
- Regenerated SKILL.md files from updated templates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Mobile QA via Revyl cloud devices replaces Appium-based browse-mobile
- Removed unused fast-xml-parser dependency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@TenzinDhonyoe TenzinDhonyoe changed the title feat: replace browse-mobile (Appium) with Revyl CLI for mobile QA feat: replace Appium with Revyl CLI for mobile QA (v0.11.21.0) Mar 26, 2026
TenzinDhonyoe and others added 4 commits March 26, 2026 11:41
…bile-check

Resolve CHANGELOG.md conflict: upstream took 0.11.21.0 for review-log
architecture fixes, so bump our Revyl mobile QA entry to 0.11.22.0.
Regenerated all SKILL.md files with updated version.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Expo development builds need a running dev server — the old static mode
(revyl device start) showed the Expo dev launcher screen. Now /qa
auto-detects Expo via package.json and uses `revyl dev start` which
handles Metro, Cloudflare tunnel, and hot reload automatically.
Non-Expo projects and --static override use the existing static flow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…le QA

Static mode now checks eas.json profiles, prefers local builds over EAS
(avoids 40+ min queue), and auto-detects dev launcher screens (switches
to dev loop automatically). Dev loop mode gains a fallback to static
when revyl dev start fails. New test assertions verify Revyl content
appears in generated SKILL.md files.

Based on field test of /qa on real Expo app (Gluco) that exposed:
- Dev builds installed in static mode show Expo dev launcher (dead end)
- No local build path offered (only EAS with 40+ min queue)
- No eas.json profile awareness (simulator vs real device builds)
- No fallback when dev loop fails

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…bile-check

# Conflicts:
#	CHANGELOG.md
#	VERSION
#	package.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant