android-emulator-mask-…
Specialization of android-emulator-harness for CAMERA / segmentation testing: get a real PERSON in front of the emulator camera so MediaPipe / ML Kit selfie…
Bring up an Android app in a headless emulator on Linux/WSL and drive it for automated integration testing, the Android analog of Playwright for web. Boots an AVD under KVM, installs an APK (standalone or dev-client+Metro), drives the UI with Maestro (resilient
$ npx -y skills add simiancraft/simiancraft-skills --skill android-emulator-harness --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/android-emulator-harnessContext preview
The summary Claude sees to decide when to auto-load this skill.
Bring up an Android app in a headless emulator on Linux/WSL and drive it for automated integration testing, the Android analog of Playwright for web. Boots an AVD under KVM, installs an APK (standalone or dev-client+Metro), drives the UI with Maestro (resilient
name: android-emulator-harness description: >- Bring up an Android app in a headless emulator on Linux/WSL and drive it for automated integration testing, the Android analog of Playwright for web. Boots an AVD under KVM, installs an APK (standalone or dev-client+Metro), drives the UI with Maestro (resilient tap-by-label/wait/assert), and gates on logcat + screenshots that come back for inspection. Use for ANY Android/Expo/React-Native project (not just one app) when the task is "run the app on an emulator", "drive the Android UI", "smoke-test a screen", "reproduce a tap-and-crash", "automate an Android flow", or "set up Android UI testing". Project-agnostic base; layer a domain skill on top for specialized inputs (see android-emulator-mask-testing for camera/segmentation). Validated on Linux/WSL with KVM, Maestro 2.x, and JDK 17.
Specializations (e.g. camera/mask) sit ON TOP of this kernel and override only the parts they must.
> **Runtime/package manager.** Examples use `bun`/`bunx`; substitute your own > runner (`npm`/`npx`, `pnpm`/`pnpm dlx`, or `yarn`) wherever they appear. The > Android tooling itself (`adb`, `emulator`, Maestro, the JDK) is unaffected.
`kvm` group: `sudo gpasswd -a $USER kvm` (needs a real terminal for the password). No relogin if you launch under `sg kvm -c "..."`. Symptom if missing: `x86_64 emulation currently requires hardware acceleration!`.
2.x aborts on Java 8 with `ERROR: Java 17 or higher is required`; it reads the `java` on PATH, so exporting `JAVA_HOME` alone is not enough; prepend it to PATH. Symptom: bare `~/.maestro/bin/maestro --version` fails until you do.
directly, or use the Expo MCP `mcp__expo-mcp__*` tools if your host provides them.
native Linux you may have one. Either way the default software GLES is fine for UI/logic; only GPU-compute workloads (e.g. MediaPipe) need the `swangle` override, which the specialized camera skill covers.
`emulator` or the system `java`. This one block gets you to an operating state:
# ANDROID_HOME varies by OS: Linux (Android Studio default) $HOME/Android/Sdk, macOS $HOME/Library/Android/sdk
export ANDROID_HOME="${ANDROID_HOME:-$HOME/Android/Sdk}"
# JDK 17 home is OS/distro-specific; point this at wherever your JDK 17 lives.
# Debian/Ubuntu: /usr/lib/jvm/java-17-openjdk-amd64 macOS: $(/usr/libexec/java_home -v 17)
export JAVA_HOME="${JAVA_HOME:-/usr/lib/jvm/java-17-openjdk-amd64}"
export PATH="$JAVA_HOME/bin:$PATH" # so Maestro's wrapper sees Java 17
SDK="$ANDROID_HOME"; EMU="$SDK/emulator/emulator"; ADB="$SDK/platform-tools/adb"
# modern SDKs install to cmdline-tools/latest/bin; older/hand-installed to cmdline-tools/tools/bin
CLT="$(ls -d "$SDK"/cmdline-tools/latest/bin 2>/dev/null || ls -d "$SDK"/cmdline-tools/*/bin 2>/dev/null | head -1)"
SDKMGR="$CLT/sdkmanager"; AVDMGR="$CLT/avdmanager"
MAESTRO="$HOME/.maestro/bin/maestro"
# preflight: java -version → 17; $ADB version; $MAESTRO --version → 2.xDefault to **x86_64** (faster under KVM, widest native-lib coverage). Use 32-bit `x86` ONLY when a required native lib lacks an x86_64 variant (see android-emulator-mask-testing).
yes | "$SDKMGR" "system-images;android-34;google_apis;x86_64" "platforms;android-34" # device profile must exist in this SDK's catalog; pixel_3 is safe on older SDKs, pixel_6 on newer echo no | "$AVDMGR" create avd -n harness -k "system-images;android-34;google_apis;x86_64" -d pixel_6 --force
sg kvm -c "nohup $EMU -avd harness \ -no-window -no-audio -no-boot-anim -no-snapshot \ -gpu swiftshader_indirect \ -accel on -port 5554 > /tmp/emulator.log 2>&1 &" $ADB wait-for-device for i in $(seq 1 48); do [ "$($ADB shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')" = "1" ] && break; sleep 5 done $ADB shell settings put global window_animation_scale 0 # determinism: kill animations $ADB shell settings put global transition_animation_scale 0 $ADB shell settings put global animator_duration_scale 0
Snapshot the warmed device once for fast restarts: launch without `-no-snapshot`, let it boot, then future runs reuse the snapshot instead of cold-booting.
APKs come from: a local `./android/gradlew assembleDebug|Release`, or an EAS artifact (`eas build:run -p android --latest` downloads AND installs to the running emulator; `eas build:download --build-id <id>` fetches only; the Expo MCP `mcp__expo-mcp__build_list` works too). Inspect a build's git commit (`eas build:list --json`) BEFORE diagnosing; a stale binary vs fresh JS is a common false bug.
AAPT2="$(ls "$SDK"/build-tools/*/aapt2 2>/dev/null | sort -V | tail -1)" # newest installed build-tools
PKG=$("$AAPT2" dump badging app.apk | sed -n "s/package: name='\([^']*\)'.*/\1/p")
$ADB install -r -g app.apk # -g grants runtime perms (CAMERA, etc.) up front
$ADB shell monkey -p "$PKG" -c android.intent.category.LAUNCHER 1**Launch-type fork (check the landing activity):** `$ADB shell dumpsys activity activities | grep topResumedActivity`
(`bunx expo start` in the app dir), `adb reverse tcp:8081 tcp:8081`, then open the dev-client launch URL. The URL is your app's own custom scheme with the `ex
Claude Code skills for the full arc of a change: farm to table, with receipts. Curated Claude Code skills and agents from simiancraft. Most skill collections are grab bags. This one has a spine: it carries a change through its whole life.
Repo: simiancraft/simiancraft-skills
Specialization of android-emulator-harness for CAMERA / segmentation testing: get a real PERSON in front of the emulator camera so MediaPipe / ML Kit selfie…
Shrink a media asset to the smallest bytes that still serve its purpose, keyed on asset kind (raster, vector, animation, video, audio, model, document, font)…
Read and use the Expo / React Native in-app developer tools: the developer menu (reload, go home, performance monitor, element inspector, Open DevTools, and…
Run and drive an Expo / React Native app on the iOS Simulator. Pick an execution mode (Expo Go, dev client, Storybook-mobile, web-on-mobile), build and install…
Plans self-destruct when shipped (the Inspector Gadget Rule). Use this skill to draft tactical, hand-off-ready planning docs with a 150-word Goal cap, atomic…
Capture proof of a driven iOS-simulator flow: vision-verifiable screenshots, video (mp4), and a manifest tying steps to artifacts, plus an honest list of what…