feat: replace Appium with Revyl CLI for mobile QA (v0.11.21.0)#488
Open
TenzinDhonyoe wants to merge 27 commits intogarrytan:mainfrom
Open
feat: replace Appium with Revyl CLI for mobile QA (v0.11.21.0)#488TenzinDhonyoe wants to merge 27 commits intogarrytan:mainfrom
TenzinDhonyoe wants to merge 27 commits intogarrytan:mainfrom
Conversation
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>
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>
…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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
revyl auth statuscheck at skill startup. Mobile QA auto-activates when Revyl is authenticated ANDapp.json/app.config.*is present. Web QA works regardless.generateRevylSetupand extendedgenerateQAMethodologyplaced inscripts/resolvers/utility.ts+ registered inscripts/resolvers/index.ts, aligned with upstream's modular resolver refactoring.fast-xml-parserdependency removed./tmp/mobile-screen.pngacross all templates.Changes
scripts/resolvers/utility.tsgenerateRevylSetup(), extendedgenerateQAMethodology()with mobile step 3bscripts/resolvers/index.tsREVYL_SETUPin RESOLVERS mapscripts/gen-skill-docs.tsqa/SKILL.md.tmpl{{REVYL_SETUP}}, mobile command mapping,--mobile/--webplatform paramqa-only/SKILL.md.tmplSKILL.md.tmpl(root)package.jsonfast-xml-parser, bumped to 0.11.21.0TODOS.mdPre-Landing Review
Pre-landing review completed. Adversarial review found 5 issues:
revyl auth statusexit code assumption)Test plan
bun testpasses (1 pre-existing failure inreview.tsCodex path — not related to this branch)bun run gen:skill-docsregenerates all SKILL.md files without error{{REVYL_SETUP}}unresolved placeholders in generated output🤖 Generated with Claude Code