{"id":51079058,"url":"https://github.com/maxgfr/andro","last_synced_at":"2026-06-23T16:33:08.133Z","repository":{"id":364627165,"uuid":"1268528111","full_name":"maxgfr/andro","owner":"maxgfr","description":"Run Android apps (phone \u0026 TV) from the macOS command line on a disposable, self-contained Android emulator (Apple Silicon, HVF)","archived":false,"fork":false,"pushed_at":"2026-06-13T19:01:07.000Z","size":69,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-13T21:05:34.412Z","etag":null,"topics":["adb","andro","android","android-emulator","apple-silicon","avd","cli","devtools","emulator","hvf","macos","rust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maxgfr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-13T16:32:48.000Z","updated_at":"2026-06-13T19:01:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/maxgfr/andro","commit_stats":null,"previous_names":["maxgfr/andro"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/maxgfr/andro","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fandro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fandro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fandro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fandro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxgfr","download_url":"https://codeload.github.com/maxgfr/andro/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fandro/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34698696,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adb","andro","android","android-emulator","apple-silicon","avd","cli","devtools","emulator","hvf","macos","rust"],"created_at":"2026-06-23T16:33:07.508Z","updated_at":"2026-06-23T16:33:08.127Z","avatar_url":"https://github.com/maxgfr.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# andro\n\nRun Android apps on phone **or smart TV** — from your macOS command line, on a\nfast, **disposable** Android emulator. No Android Studio, nothing installed\nsystem-wide — andro downloads a self-contained JDK + Android SDK into `~/.andro`,\nand `andro clean` wipes everything.\n\n```sh\nandro run app.apk          # boot a phone emulator, install, launch\nandro run app.xapk         # split-APK bundles (.xapk/.apks/.apkm) and split dirs too\nandro run app.aab          # Android App Bundles too (built with bundletool on the fly)\nandro --tv run tvapp.apk   # same, on an Android TV (leanback) emulator\nandro clean --yes          # kill the emulator and delete ~/.andro\n```\n\nThe emulator runs **natively on Apple Silicon** via Apple's Hypervisor.framework\n(HVF) with **arm64** system images, so it boots in seconds and runs arm64 apps\nwithout translation.\n\n\u003e Why native and not Docker? The Android emulator needs hardware virtualization.\n\u003e On a Mac that's HVF, which only a native process can use — a container can't\n\u003e (`docker-android` needs Linux + `/dev/kvm`). So `andro` drives the real SDK\n\u003e emulator directly.\n\n## Requirements\n\n- **macOS** (Apple Silicon recommended; Intel works with x86_64 images).\n- That's it — `andro` downloads a self-contained JDK + Android SDK into\n  `~/.andro` on first run (~2 GB).\n\n## Install\n\n```sh\nbrew install maxgfr/tap/andro   # Homebrew (macOS) — recommended\n# or:\ncargo install --path .          # build from source\n# or grab a prebuilt binary from the GitHub Releases\n```\n\n## Usage\n\n```sh\n# run \u0026 install\nandro run \u003ctarget\u003e         # provision (first run) → boot → install → launch\nandro --tv run \u003ctarget\u003e    # Android TV profile (TV image + leanback launcher)\nandro install \u003ctarget\u003e     # install only (no launch)\nandro launch \u003cpkg\u003e         # launch an already-installed package\nandro uninstall \u003cpkg\u003e      # remove a package\nandro clear \u003cpkg\u003e          # wipe an app's data — fast pristine first-run\nandro list                 # list installed (third-party) packages  [--system --json]\nandro test \u003cpkg\u003e           # run instrumentation tests (am instrument)\n\n# inspect \u0026 interact\nandro open \u003curl\u003e           # fire a VIEW intent — deep-link / URL-scheme testing\nandro screenshot [out.png] # capture the screen (defaults to ./screenshot.png)\nandro record [out.mp4]     # record the screen  [--time \u003csecs\u003e, max 180]\nandro shell \u003cargs…\u003e        # passthrough to `adb shell` (e.g. andro shell getprop)\nandro applog \u003cpkg\u003e         # stream just this app's logcat  [--clear --crash]\nandro logcat               # stream the whole device log  [--dump --clear]\nandro push \u003clocal\u003e \u003crem\u003e   # copy a file onto the device\nandro pull \u003crem\u003e [local]   # copy a file off the device (→ ~/.andro/tmp)\nandro reverse \u003cport\u003e       # bridge a Mac host port into the emulator  [--list --remove-all]\n\n# lifecycle \u0026 housekeeping\nandro up                   # provision + boot\nandro wait                 # block until the emulator is ready (scriptable)\nandro status               # running/booted? exits 0/2/3  [--json]\nandro stop                 # stop the emulator, keep ~/.andro\nandro autoclean            # reclaim temp/cache/logs  [--reset --images --deep --dry-run --yes]\nandro clean --yes          # kill the emulator and remove ~/.andro\nandro doctor               # check macOS/Apple Silicon, HVF, paths, adb port\nandro completions \u003cshell\u003e  # print a bash/zsh/fish completion script\n```\n\n`\u003ctarget\u003e` for `run`/`install` is a single `.apk`, a **directory of split APKs**\n(installed with `install-multiple`), a **`.xapk` / `.apks` / `.apkm` bundle**\n(unzipped, then installed), or an **`.aab`** (Android App Bundle — bundletool builds\nthe splits matching the emulator, then they're installed). Apps install with\npermissions pre-granted (`adb -g`).\n\n### Options (global)\n\n| Flag | Default | Meaning |\n|------|---------|---------|\n| `--tv` | off | Use the Android TV profile (leanback). |\n| `--profile \u003cP\u003e` | `phone` | Form factor: `phone` or `tv` (shorthand for `--tv`). |\n| `--playstore` | off | Use a Play Store image (`google_apis_playstore`); phone only. |\n| `--api \u003cN\u003e` | `36` (Android 16) | Android API level. |\n| `--device \u003cP\u003e` | `pixel` / `tv_1080p` | avdmanager device profile. |\n| `--home \u003cDIR\u003e` | `$ANDRO_HOME` or `~/.andro` | Self-contained SDK location. |\n| `--snapshot` / `--fast` | off | Persist a quickboot snapshot for ~2-5s reboots (state survives until `clean`). |\n| `--no-window` | off | Run the emulator headless (e.g. on CI). |\n| `--cores \u003cN\u003e` / `--memory \u003cMB\u003e` | auto | Emulator CPU / RAM overrides. |\n| `--api`/`--device` per run | — | also via `ANDRO_API`, `ANDRO_HOME` env. |\n\n`run`/`install` flags: `--downgrade` (allow an older version, `adb -d`).\n`run` also takes `--no-launch` (install only) and `--clean-after` (tear down afterwards).\n\n### Config file\n\nDrop a `config.toml` in your andro home (`~/.andro/config.toml`, or\n`$ANDRO_HOME/config.toml`) to set defaults. Precedence is **CLI flag \u003e `ANDRO_*`\nenv \u003e config file \u003e built-in**:\n\n```toml\nprofile  = \"tv\"      # phone | tv\napi      = 34\ndevice   = \"tv_4k\"\nplaystore = false\nsnapshot = false     # = --snapshot/--fast\nno_window = false\ncores    = 6\nmemory   = 4096\n```\n\n### Shell completions\n\n```sh\nandro completions zsh  \u003e \"${fpath[1]}/_andro\"        # zsh\nandro completions bash \u003e /usr/local/etc/bash_completion.d/andro\nandro completions fish \u003e ~/.config/fish/completions/andro.fish\n```\n\n## Housekeeping: `autoclean`\n\n`clean` is the nuclear option (removes all of `~/.andro`). `autoclean` reclaims\nspace **without** re-downloading the SDK/JDK/active image:\n\n```sh\nandro autoclean              # SAFE: wipe tmp/, caches, stale locks, rotate the log\nandro autoclean --dry-run    # preview what would be freed, delete nothing\nandro autoclean --reset --yes  # also FACTORY-RESET the device (wipe userdata; no re-download)\nandro autoclean --images --yes # also prune system images no AVD references (re-download on next use)\nandro autoclean --deep --yes   # = --reset + --images\nandro autoclean --legacy --yes # remove pre-containment residue from ~/.android (only if andro-only)\n```\n\nIt refuses while the emulator is running (`andro stop` first), reports bytes\nfreed per category, and **never deletes files it didn't create** (e.g. a\nscreenshot you saved into the home dir is listed and skipped).\n\n## Self-contained — nothing left behind\n\nEverything andro creates lives under `~/.andro` (its own JDK, SDK, AVDs, **and**\nthe tools' `.android` home and all temp files), so `andro clean` truly leaves\nnothing behind. To make that hold even when Android Studio is open, andro runs\nits **own adb server on a dedicated port** (so a foreign `adb` server on the\ndefault 5037 can't capture andro's keys). One consequence: andro's emulator\nwon't show up in a plain `adb devices` on 5037 — use `andro shell` / `andro\nstatus`, and `andro doctor` prints the port. Older installs may have leaked a few\nfiles into `~/.android`; `andro doctor` flags it and `andro autoclean --legacy`\ncleans it (only when that dir holds nothing but andro's own residue).\n\n## How it works\n\nOn first `run`/`up`, `andro` provisions `~/.andro` end to end:\n\n1. downloads a **Temurin JDK 17** (no brew),\n2. downloads the Android **command-line tools**, then installs `platform-tools`,\n   `emulator` and the chosen **system image** (`google_apis` for phone,\n   `android-tv` for `--tv`),\n3. creates an AVD (`andro` or `andro-tv`),\n4. boots the emulator (HVF), waits for `sys.boot_completed`, then waits until\n   PackageManager actually answers (so the first install can't race the boot).\n\n`run` then installs (`adb install -r -g -t`, or `install-multiple` for split\nAPKs/bundles — runtime permissions pre-granted), detects the new package (diffing\n`pm list packages`), resolves its launchable activity for the profile's category\n(`LAUNCHER` / `LEANBACK_LAUNCHER`) and starts it with `am start`.\n\nFor an **`.aab`**, andro first fetches a self-contained **bundletool** jar into\n`~/.andro` (only on the first `.aab`), reads the booted emulator's device spec, and\nbuilds just the splits that device needs (`build-apks` → `extract-apks`), which then\ngo through the same `install-multiple` path. The splits are debug-signed by bundletool\n— fine for a disposable emulator. Override the bundletool download with\n`ANDRO_BUNDLETOOL_URL`.\n\nEverything is contained in `~/.andro`, so cleanup is just removing that folder.\n\n## Known limitations\n\n- **Apps requiring strong Play Integrity / SafetyNet** won't pass attestation on an\n  emulator even with `--playstore`; that flag only helps apps that check for the\n  Play Store's *presence* (real GMS), not hardware-attested integrity.\n\n## Development\n\n```sh\ncargo test                                   # unit + hermetic CLI tests\ncargo clippy --all-targets -- -D warnings\ncargo fmt --check\n# full end-to-end (needs macOS + ~2GB download):\nANDRO_E2E_APK=/path/app.apk cargo test -- --ignored e2e\n```\n\nReleases are cut by **semantic-release** from Conventional Commits; macOS\nbinaries (arm64 + x86_64) are attached to each GitHub release, and the\n[Homebrew tap](https://github.com/maxgfr/homebrew-tap) (`maxgfr/tap/andro`)\nauto-updates its formula from the latest release within a day.\n\n## License\n\nMIT © maxgfr\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxgfr%2Fandro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxgfr%2Fandro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxgfr%2Fandro/lists"}