An AI agent that runs directly on your Android phone. BunnyRunner gives you an OpenAI-compatible API endpoint and a web portal to control your device via natural language — no cloud required, everything stays local.
| Capability | Description |
|---|---|
| Local API server (port 8765) | OpenAI-compatible /v1/chat/completions endpoint |
| Web portal (port 8080 / 8443) | Chat with the agent from any browser on your network |
| Device control | Tap, swipe, type, read screen text, launch apps, press keys |
| ReAct agent loop | The AI reasons and acts in a loop until your task is complete |
| Accessibility integration | Uses Android AccessibilityService for UI interaction |
| Dynamic device awareness | Auto-detects your phone model, screen size, Android version, and manufacturer-specific navigation tips |
| Screen wake lock | Keeps the display on during agent missions so automation isn't interrupted |
| HTTPS support | Optional self-signed certificate generation for secure LAN access |
- "Open WhatsApp and check my messages from John"
- "Open Chrome and search for weather in Paris tomorrow"
- "Pull down my notifications and tell me what I missed"
- "Check my calendar for today"
- "Open Outlook and show unread emails"
| Limitation | Why |
|---|---|
| Unlock your phone | Android security model prevents AccessibilityService from bypassing the lock screen. You must unlock the device first. |
| Bypass app security | Apps with biometric or PIN locks (banking apps, password managers, etc.) will block the agent. |
| Access background app data | The agent can only interact with apps that are currently visible on screen. It cannot read data from apps running in the background. |
| Work without Accessibility | Device control (tap, swipe, type, read screen) requires the Accessibility Service to be enabled in system settings. |
| Run without an AI provider API key | You must supply your own API key for Minimax or Grok. The app does not bundle AI access. |
| Guarantee 100% accuracy | The agent relies on AI reasoning and screen parsing. Complex or ambiguous UIs may cause mis-taps. |
| Take true screenshots | The screenshot action is currently a placeholder. Screen reading is done via AccessibilityService node tree (instant and text-accurate). |
| Run on Android below API 26 | Minimum supported Android version is 8.0 (Oreo). |
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Browser / CLI │────▶│ LanProxy 8080 │────▶│ BunnyServer │
│ │ │ TlsProxy 8443 │ │ (port 8765) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ ReAct Loop │
│ → AI provider │
│ → Device tools │
└─────────────────┘
│
▼
┌─────────────────┐
│ Accessibility │
│ Service │
└─────────────────┘
- Android 8.0+ (API 26)
- Wi-Fi network
- Minimax API key or Grok (xAI) API key
./gradlew assembleDebug./gradlew installDebug./gradlew test- Launch the app — Open BunnyRunner on your Android device.
- Configure AI provider — Enter your API key for Minimax or Grok.
- Enable Accessibility — Grant Accessibility permission so BunnyRunner can interact with your screen.
- Battery exemption — Prevent Android from killing the background service.
- Generate HTTPS certificate — Optional; enables
https://your-phone:8443
After setup, open http://your-phone-ip:8080 in any browser on the same Wi-Fi network.
BunnyRunner exposes an OpenAI-compatible chat API:
curl http://your-phone-ip:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "grok-3-latest",
"messages": [{"role":"user","content":"Open WhatsApp and check my messages"}]
}'The agent will launch WhatsApp, read the screen, and report back.
- The app builds a system prompt with your phone's real specs (model, screen size, Android version, manufacturer tips).
- The AI reasons and outputs an action in text format, e.g.
ACTION: tap(500, 800). - The app parses the action, executes it via AccessibilityService, and reads the screen.
- The screen result is fed back as an OBSERVATION: in the next prompt.
- The AI repeats until it outputs
DONE: summaryor hits the 90-action safety limit.
The parser automatically strips <think> tags and other reasoning artifacts that some models emit.
| Permission | Why |
|---|---|
INTERNET |
Run local HTTP server and proxy |
ACCESS_NETWORK_STATE |
Display LAN IP address |
ACCESS_WIFI_STATE |
Display LAN IP address |
FOREGROUND_SERVICE |
Keep the server alive in background |
WAKE_LOCK |
Prevent CPU sleep during agent missions |
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS |
Stay alive when screen is off |
BIND_ACCESSIBILITY_SERVICE |
Tap, swipe, type, and read screen content |
- The agent cannot unlock your phone. If the screen is locked, it will ask you to unlock it first.
- The agent cannot bypass app security. Apps with biometric or PIN locks will block the agent.
- Everything stays on your device. Screen content and commands never leave your phone. Only the AI chat requests go to your chosen provider.
- You are always in control. The agent executes one action at a time and reports what it does. You can stop a mission at any time.
- Kotlin + Android SDK 26–35
- NanoHTTPD (embedded web server)
- OkHttp (AI provider client)
- Material Design 3
LocalClaw/
├── app/src/main/java/com/localclaw/app/
│ ├── ai/ # AI chat client & ReAct tool parser
│ ├── cert/ # Self-signed HTTPS certificate manager
│ ├── device/ # Accessibility service & command handler
│ ├── proxy/ # LAN & TLS proxy servers
│ ├── server/ # BunnyServer (NanoHTTPD + ReAct loop)
│ ├── service/ # Foreground service (keeps everything alive)
│ ├── setup/ # Onboarding wizard logic
│ └── util/ # Network helpers
├── app/src/main/assets/portal/
│ └── index.html # Web chat UI
├── docs/ # HTML documentation
└── README.md # This file
MIT — see LICENSE