u2-agent DWG U2-001 · REV 0.2.0 Star the repo

LLM-native
Android
automation

u2-agent turns the Android view hierarchy into a ~250-token semantic tree of @handles, then resolves each action from a hot daemon in under 15 ms.

Zero dependencies. Bun + TypeScript native APIs. Built for agent loops that cannot afford to burn context.

Fig. 1 Agent control loop idle
screen read · 15,000 → 250 tokens
A1 Agent issues ui snapshot
D1 Daemon keeps the session hot
U1 Device executes the action
round trip · ~850 ms → < 15 ms
@1 standing by
loop halted — press run to energize the circuit.

The loop, on a real phone

A recorded session of an agent driving a physical Android device — read a ~250-token snapshot, act on a handle, verify the receipt. No mockups, no simulated taps.

Fig. 2 Recorded run · youtu.be/UUP5fDA2C5w ready

The YouTube player is requested only after you press play.

Why raw hierarchies choke an agent

A single Android XML dump is 5,000–20,000 tokens of container noise. By step fifteen the context window is spent and the reasoning degrades — so the agent stalls exactly when the task gets long.

Detail A — raw hierarchy ~15,000 tokens
+------------------------------------------------------------------+
| <hierarchy rotation="0">                                          |
|   <node index="0" class="android.widget.FrameLayout" ...>         |
|     <node index="0" class="android.widget.LinearLayout" ...>      |
|       <node index="0" class="android.view.ViewGroup" ...>         |
|         <node class="androidx.recyclerview.widget.RecyclerView"> |
|           <node class="android.widget.FrameLayout" ...>           |
|             <node text="Search YouTube"                            |
|                   class="android.widget.EditText" ...>           |
|           ... 240 more nodes ...                                   |
+------------------------------------------------------------------+

Representative dump. Containers, indices and bounds the agent never needs.

15,000 tokens → 250
Detail B — u2 semantic tree ~250 tokens
[App: com.google.android.youtube]
[@1] Input  "Search YouTube"
[@2] Button "Explore"
[@3] Item   "Live lo-fi hip hop radio"
[@4] Button "Subscribe"
[@5] Tab    "Home"
[@6] Tab    "Shorts"

Actionable handles only. This output is the real shape the CLI prints.

The dump is measured, not argued: snapshot drops structural containers, collapses nodes with ≥85% bounding-box overlap, and normalizes roles to Input, Button, Tab, Toggle and Item.

The three-command loop

One wire, three stations. The agent reads the screen, acts on a handle, and gets a clean receipt — no re-dump, no disconnects, no reasoning poisoned by diagnostics.

  1. Read the screen

    Dump the hierarchy and index every interactive element with an ephemeral handle.

    u2-agent ui snapshot
    [@1] Input  "Search YouTube"
    [@2] Tab    "Home"
    [@3] Tab    "Shorts"
  2. Act on a handle

    The daemon resolves coordinates for the handle from RAM — no cold re-dump on the wire.

    u2-agent ui tap --ref @1
    ok
  3. Read the receipt

    stdout carries only machine text. Diagnostics and recovery hints stay on stderr.

    u2-agent ui type --ref @1 --text "synthwave"
    ok

Schedule of components

Everything the drawing above depends on, itemized. No browser stack, no Java wrapper, no WebDriver.

Ref Component Specification
C1 Core runtime Bun and TypeScript native APIs only — no external browser or device SDKs.
D2 Background daemon Keep-alive ADB socket and an in-RAM @handle store; actions resolve in under 15 ms.
U3 Snapshot engine Structural-noise filtering, ≥85% bounding-box deduplication, role normalization.
T4 Tool schema export tools schema --format openai drops into Anthropic, OpenAI or Gemini tool catalogs.
E5 Error contract Deterministic codes — SELECTOR_NOT_FOUND, DEVICE_OFFLINE, USAGE, TIMEOUT — with defined exit codes.
K6 Agent compatibility Claude Code, OpenCode, Cursor, Antigravity, LangChain, AutoGen and custom orchestrators.

Installation procedure

Prerequisites: Bun ≥ 1.1, adb on your PATH, and an Android device with USB debugging enabled.

  1. Clone and install

    git clone https://github.com/themikehage/u2-agent.git && cd u2-agent && bun install
  2. Provision the device

    Install the lightweight UIAutomator2 RPC server on the target device.

    bun run src/index.ts setup install
  3. Take the first snapshot

    bun run src/index.ts ui snapshot
  4. Compile a standalone binary optional

    bun run build

System block diagram

How a handle action crosses four boundaries in under 15 milliseconds.

A1 AI agent Claude · GPT · OpenCode
issues --ref @N
P1 u2-agent CLI Bun / TypeScript
parses and validates
D1 Background daemon keep-alive ADB socket
in-RAM handle store
U1 Android device UIAutomator2 JSON-RPC
clicks and types

Exit-code legend

Exit Codes Meaning
1 USAGE invalid arguments
2 DEVICE_OFFLINE · DEVICE_NOT_FOUND · DEVICE_UNAUTHORIZED device layer failure
3 SELECTOR_NOT_FOUND · APP_NOT_FOUND element or app not found
4 PROVISION_BLOCKED provisioning failure
5 TIMEOUT · POSTCONDITION_FAILED timeout or postcondition failure
10 internal internal error