Handsets — Android Automation CLI tool screenshot
Android Automation CLI

Handsets: Best Android Automation CLI for Developers in 2026

7 min read·

Handsets turns Android UI automation into a low-latency shell protocol: one on-device jar, no root, label-based selectors, and millisecond-scale calls instead of ADB round-trips.

Pricing

Open-Source

Tech Stack

Android accessibility APIs, `adb forward`, a Java on-device daemon, Python bindings, and subprocess-friendly JSON output

Target

developers automating Android apps from the terminal

Category

Android Automation CLI

What Is Handsets?

Handsets is one of the best Android Automation CLI tools for developers automating Android apps from the terminal. Built by Elliot Gao (elliotgao2), it drives Android UI state over a tiny on-device daemon and reports single-call latency in the 2–7 ms range in the published benchmark, which is far below the typical adb shell path. It is designed for engineers who want a shell-first workflow, not a heavyweight mobile test stack.

Handsets focuses on tapping, filling, waiting, and inspecting by label instead of brittle screen coordinates. That makes it a strong fit for CLI automation, agent loops, and scripts that need predictable selectors without installing a full mobile test framework.

Quick Overview

AttributeDetails
TypeAndroid Automation CLI
Best ForDevelopers automating Android apps from the terminal
Language/StackAndroid accessibility APIs, adb forward, Java daemon, Python bindings
LicenseMIT
GitHub StarsN/A (not shown on the scraped page)
PricingOpen-Source
Last Releasev0.1.26 — date not shown on the scraped page

Who Should Use Handsets?

  • Android engineers writing terminal-driven flows who want to validate app states with tap, fill, and wait without launching Android Studio or a GUI recorder.
  • Indie hackers building agents or scripts that need fast UI control loops, because Handsets keeps interaction latency low enough for repeated action/observe cycles.
  • Platform or QA teams that already depend on ADB and want a slimmer alternative to heavier harnesses for smoke checks, regression checks, or demo automation.
  • Python or polyglot developers who want a subprocess or SDK workflow instead of being locked into one test runner.

Not ideal for:

  • Teams that need iOS support, rich reporting, or recorder-based test generation.
  • Teams that need pytest plugins, HTML reports, or full device farm orchestration out of the box.
  • UI automation that depends on pixel-perfect coordinates only and has no stable accessibility labels.

Key Features of Handsets

  • Millisecond command latency — The benchmark in the repo shows 2–7 ms single-call latency, which is much lower than the 40–700 ms range shown for adb shell. That matters when a script or agent performs dozens of UI actions per minute.
  • Label-first selectors — Handsets uses CSS-like, Playwright-inspired selectors such as Button:has-text("Continue") and EditText[hint~=Email]. This is a better fit than coordinate tapping when views shift, animate, or reflow.
  • Persistent on-device daemonhs use starts a daemon on the phone and keeps a socket open, so each command does not pay a cold-start penalty. The page describes this as a one-jar setup with no app and no root.
  • Live terminal inspectorhs tui renders the accessibility tree in a ratatui + crossterm interface at roughly 10–20 fps. You can drive the device from the keyboard and watch the screen state update without manual refreshes.
  • Binary wire protocol — The host and device talk over adb forward using length-prefixed binary frames on TCP 9008. That design keeps the protocol small and makes it easy to expose the CLI from any language via subprocess.
  • Native screenshot and export pathsscreenshot defaults to a 768px long-edge JPEG for fast agent loops, while hs see out.jpg can save native-resolution output. The repo also calls out WebP for compact lossy exports and PNG for debug or lossless capture.
  • Structured failures and exit codes — Handsets emits explicit exit codes for NOT_FOUND, TIMEOUT, and AMBIGUOUS, and the JSON mode exposes a structured error.code. That is useful when a calling process needs deterministic branching instead of parsing human text.

Handsets vs Alternatives

ToolBest ForKey DifferentiatorPricing
HandsetsShell-first Android automation with low latencyPersistent daemon, label-based selectors, and ms-level command callsOpen-Source
adb shellDirect device commands and ad hoc debuggingBuilt-in ADB access, but UI automation is slow and coordinate-heavyFree
uiautomator2Python-centric Android automationMature Python API and test ecosystem, but heavier than HandsetsOpen-Source
AppiumCross-platform mobile test suitesWebDriver abstraction, broader ecosystem, but much heavier runtime overheadOpen-Source

For adjacent shell-first workflows, compare browse all CLI Tools with browse all DevOps Automation tools. Handsets beats adb shell when the task is repeated UI driving rather than one-off device commands. uiautomator2 is still the better fit if your whole team lives inside Python and wants the surrounding test tooling.

Pick Appium when you need a broader mobile testing platform, especially if cross-platform coverage and existing WebDriver infrastructure matter more than raw call latency. Pick uiautomator2 when the workflow is Python-only and you want the established Android automation ecosystem with its higher-level helpers.

How Handsets Works

Handsets splits the system into a thin host CLI and a tiny device-side server. The host binary forwards a TCP socket over adb forward to tcp:9008, and the device process runs as a shell-UID Java server via app_process. That server exposes accessibility tree dumps, binder reflection helpers, screenshots, and state mirroring without requiring an installed app package.

The data path is intentionally simple: a host command becomes a length-prefixed binary frame, the device executes the verb, and the response returns either an ok body, an empty end-of-stream marker, or a structured error payload. That is why the CLI can stay fast while still being language-agnostic through subprocesses and JSON output.

hs use
hs ui
hs tap 'Button:has-text("Continue")' --visible --unique
hs wait 'Welcome' --timeout 15s

The first command connects to the device and starts the daemon. The second command dumps tappable nodes as a table, and the last two commands show the selector model: match by text, constrain by visibility, then wait on a success condition. That flow is the core Handsets tutorial pattern and is the shortest path from inspection to automation.

Pros and Cons of Handsets

Pros:

  • Very low per-call overhead compared with adb shell, which is the main reason to choose Handsets for repeated UI actions.
  • Stable selectors based on labels, text, and accessibility properties, which are less brittle than coordinates.
  • No root and no companion app install beyond a tiny jar, which simplifies device setup.
  • CLI-first design that works well with shell scripts, CI jobs, and agent loops.
  • Useful interactive TUI for manual exploration, especially when debugging selectors or screen changes.
  • Python support plus subprocess mode make it easy to integrate into larger automation systems without rewriting everything.

Cons:

  • No iOS support, so teams with cross-platform mobile needs still need another tool.
  • Smaller ecosystem than Appium or uiautomator2, with no recorder, pytest plugin, or built-in HTML report layer.
  • Accessibility-dependent automation can fail on apps with poor labels or intentionally hidden UI metadata.
  • Pre-1.0 surface means the project is stable by its own claim since v0.1.0, but teams should still pin versions for production use.
  • Not a full test farm product; orchestration, retries, and dashboards still need to be supplied by your own tooling.

Getting Started with Handsets

curl -fsSL https://raw.githubusercontent.com/elliotgao2/handsets/main/install.sh | bash
export HANDSETS_VERSION=v0.1.26
hs use
hs ui

After installation, make sure adb is available on your PATH and that your Android device or emulator is already visible to ADB. hs use starts the on-device daemon, and hs ui confirms that the accessibility tree can be read before you begin scripting tap, fill, or wait calls.

If you want a Python integration, install the package with pip install handsets and use the Session API. For other languages, the repo recommends driving hs --json as a subprocess and parsing one JSON line per call, which keeps the integration simple and portable.

Verdict

Handsets is the strongest option for shell-first Android UI automation when you care more about per-call latency than rich test reporting. Its biggest strength is the persistent daemon and label-based selector model; its main caveat is the smaller ecosystem compared with Appium or uiautomator2. Use it when speed and scriptability matter most.

Frequently Asked Questions

Looking for alternatives?

Compare Handsets with other Android Automation CLI tools.

See Alternatives →

You Might Also Like