eval/skills/android/SKILL.md
MUST be invoked before any work involving: the `kind: android` schema kind, a `target: android` deploy, the `apk:` layer package format (installing Android apps declaratively), AndroidDeployTarget, an in-pod emulator OR a remote/physical adb-endpoint device, or nested `pod → android` deployment. The first-class Android device + app surface that sits above `ov eval adb`/`appium`.
npx skillsauth add overthinkos/overthink-plugins androidInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
apk package formatAndroid is a first-class deploy substrate in ov, modeled on kind: k8s.
Two cooperating concepts:
kind: android — a DEVICE (the substrate). Either an in-pod emulator
(referenced by image:) or a remote/physical adb endpoint (adb: {host: <host:port>}). The analogue of kind: k8s (the cluster).apk package format — Android apps declared in LAYERS (NOT a kind),
parallel to package:/aur:. A target: android deploy applies its layers'
apk: packages onto the device. The app is the deployable workload, the way a
kind: image is the workload for a pod/k8s deploy.This sits ABOVE the device-interaction verbs: ov eval adb (/ov-eval:adb)
and ov eval appium (/ov-eval:appium) drive a running device; kind: android
target: android declaratively describe a device and the apps installed on
it. The install machinery is shared — see "One installer (R3)".kind: android — the device# android.yml (or inline in overthink.yml)
android:
pixel9a-36: # in-pod emulator device
image: android-emulator # the kind:image that BAKES the emulator + system image
device: pixel_9a # informational (documents the baked AVD profile)
api_level: 36 # informational (the API level is a BUILD property of image:)
google_account: # credential-store secret-key refs for apkeep google-play
email_secret: GOOGLE_ACCOUNT_EMAIL
token_secret: GOOGLE_AAS_TOKEN
my-phone: # remote/physical device
adb: { host: 192.168.1.50:5555 } # an adb SERVER addr (a host running `adb connect`)
serial: 192.168.1.50:5555
Device source is exclusive: image: XOR adb:.
image: (in-pod) — apkeep runs INSIDE the emulator pod (engine exec);
the pod's own adb installs onto its emulator. Needs nothing extra on the host.adb: (remote/physical) — apkeep runs ON THE HOST; the APK is pushed to
the endpoint via goadb (or adb -H <host> -P <port> for the apkeep-download
path). The host needs android-tools (adb) + apkeep for the package: path
(PKGBUILD optdepends; apkeep ships as an upstream binary — no Arch package);
the committed-apk: path needs neither (pure goadb push).Build-vs-runtime boundary (load-bearing). The Android system image + API
level are baked into the referenced kind: image at BUILD time (sdkmanager in
the android-sdk layer). kind: android REFERENCES that image — it never drives
a build. device:/api_level: are documentation, not assertions or build
drivers. Two API levels = two images, each with its own kind: android.
apk: — the package format (declared in layers)# layers/<name>/layer.yml
layer:
version: 2026.145.1700
name: my-android-apps
apk:
- package: org.fdroid.fdroid # apkeep download by id
source: apk-pure # apk-pure(default) | google-play | f-droid | huawei-app-gallery
arch: x86_64 # native ABI (apk-pure) — match the emulator
- apk: tests/data/MyApp.apk # committed local APK (project-root- or layer-relative), goadb push
Each entry is package: (apkeep) XOR apk: (committed file). source:
applies only to package:. The format compiles to an ApkInstallStep that
ONLY target: android executes — at image build (OCITarget) and on
local/vm/pod/k8s targets it is recorded-skipped (there is no Android device
there; this is the same "wrong-venue skip" aur: uses off-Arch). A layer
carrying only apk: is valid install content.
Compared to a sideloaded APK: apps with a static-library dependency (e.g. Chrome's Trichrome) can't be sideloaded — install those via the Play Store image (preinstalled) instead.
target: android deploy# deploy.yml / overthink.yml — nested under the emulator pod
deploy:
android-stack:
target: pod
image: android-emulator
nested:
device:
target: android
android: pixel9a-36 # → kind:android device
add_layer:
- my-android-apps # layers whose apk: packages install onto the device
ov deploy add android-stack.device resolves the device, gates on
sys.boot_completed, and installs the add_layer: layers' apk: packages via
AndroidDeployTarget. Apps ride in on add_layer: (the same overlay mechanism
local/vm targets use) — there is no separate apk-list field. ov deploy del
best-effort pm uninstalls each package: id (the device/pod lifecycle is
owned by the pod deploy).
A top-level (non-nested) target: android deploy works too — for an image:
device it resolves the running container by image name; for an adb: device it
talks straight to the endpoint.
pod → android)Mirrors vm → k8s. The emulator runs in a pod; the device deploys onto it; the
apps deploy onto the device. target: android is a passthrough hop in the
deploy chain (the device shares its host pod's adb venue / the endpoint addr —
there is no shell venue to "enter"), so ov eval live pod.android runs the
device's checks against the pod's published adb port. A pod's children can only
deploy AFTER ov start (the container doesn't exist at ov deploy add time),
so ov deploy add --node-only brings the pod up first and the children deploy
afterwards by dotted path; ov eval run <bed> automates this (deploy pod →
config → start → deploy nested children → eval-live).
ov/android_install.go holds the SINGLE install path. AndroidDevice
abstracts where work runs:
InstallByPackage — apkeep download + adb install. In-pod (engine exec,
apkeep baked in the image) for an image device; host (apkeep + adb -H -P)
for an endpoint device. google-play creds come from the container env in-pod,
or the credential store (via google_account:) on the host.InstallFromHostApk — committed APK pushed via goadb, venue-agnostic.Both ov eval adb install-app and ov eval adb install are thin wrappers over
this — so the apk format, the eval verbs, and the deploy target can never drift
on single/split/.xapk handling.
eval-android-emulator-pod nests two devices: device (in-pod, installs
F-Droid via apkeep) and device-net (the same emulator addressed as a remote
adb ENDPOINT, installs the committed ApiDemos via goadb) — proving both device
kinds with no physical hardware. The android-emulator-layer eval ASSERTS the
results (apk-fdroid-present/-launch, apk-net-apidemos-present).
ov/android_spec.go — AndroidSpec / AndroidAdbEndpoint /
AndroidGoogleAccount / ApkPackageSpec.ov/android_install.go — AndroidDevice + the shared installer.ov/android_target.go — AndroidDeployTarget (consumes the IR).ov/unified_targets_apk.go — AndroidUnifiedTarget.Add/.Del (the android
deploy + teardown logic, reached via ResolveTarget).ov/android_deploy_cmd.go — findAndroidSpec + the device-resolution helpers
(resolveAndroidDevice, androidApkPackageIDs).ov/install_plan.go — ApkInstallStep; ov/install_build.go —
compileApkStep.ov/unified.go — loader wiring (mirrors every k8s site).ov/deploy.go DeploymentNode.Android; ov/deploy_add_cmd.go dispatch +
--node-only; ov/deploy_chain.go / ov/deploy_tree.go passthrough./ov-eval:adb — low-level device control (the verbs the installer shares)./ov-eval:appium — UI automation against the device./ov-core:deploy — target: android is one of the deploy targets./ov-image:layer — the apk: field is part of the layer schema./ov-internals:install-plan — the IR ApkInstallStep plugs into./ov-kubernetes:kubernetes — the kind: k8s pattern kind: android mirrors.MUST be invoked for any task involving kind: android, target: android,
the apk: layer package format, AndroidDeployTarget, an adb-endpoint device,
or nested pod → android deployment. Invoke BEFORE reading the android_*.go
source or editing android.yml / a layer's apk: list.
development
Claude Code multi-agent support in Overthink — sub-agents, dynamic workflows, and agent teams, and how each drives the existing `ov eval` disposable beds to test and verify. MUST be invoked before authoring or invoking an ov sub-agent / dynamic workflow / agent team, wiring agent-lifecycle hooks, or asking "which primitive should drive the R10 beds?".
tools
Mounts a virtiofs share tagged `workspace` at /workspace inside a VM guest via a systemd .mount unit. Use when a kind:vm entity shares a host directory into the guest and you need it auto-mounted (and re-mounted at every boot).
tools
Use when committing, branching, pushing, merging, tagging, creating PRs, or approving/merging PRs with gh — the feat/-branch, R10-gated, never-force-push landing workflow across the main repo + the plugins submodule + image/<distro> submodules. Covers sync-to-upstream, branch/worktree pruning, the fork+PR path for contributors without write access, and cross-repo @github landing order.
testing
Use when @github layer/namespace pins drift across repos and the resolver emits "referenced at multiple versions" warnings — `ov image reconcile` aligns every pin of a repo to one version (clearing the warnings). Invoked as `ov image reconcile`.