The official Android app is available on Google Play and as a signed standalone APK on supported GitHub Releases. It is a companion node and requires a running OpenClaw Gateway. Source: apps/android (build instructions).
Support snapshot
- Role: companion node app (Android does not host the Gateway).
- Gateway required: yes (run it on macOS, Linux, or Windows via WSL2).
- Install: Google Play or
OpenClaw-Android.apkfrom a supported GitHub Release, Getting Started for the Gateway, then Pairing. - Gateway: Runbook + Configuration.
- Protocols: Gateway protocol (nodes + control plane).
Install outside Google Play
Regular final and correction GitHub Releases include a universalOpenClaw-Android.apk and OpenClaw-Android-SHA256SUMS.txt. The APK is built from the release tag, signed with the OpenClaw Android release key, and carries GitHub Actions provenance.
Choose a release that lists both assets, then download and verify that exact tag before sideloading:
Mirror and control Android from a remote Mac
scrcpy mirrors an Android screen in a macOS window and forwards keyboard and pointer input through Android Debug Bridge (ADB). This is an operator-side workflow, separate from the OpenClaw node connection. It is useful when the Android device and the Mac are in different locations but share a private Tailscale network.Before you begin
- Install Tailscale on the Android device and the Mac, and connect both to the same tailnet.
- On Android, enable Developer options and USB debugging. Android 16 places Wireless debugging under Settings > System > Developer options. See Android developer options.
-
Install scrcpy and ADB on the Mac:
- Keep the Android device available for the first connection. Android must approve each Mac’s ADB key before that Mac can control the device.
Enable ADB over TCP
For the initial setup, connect the Android device by USB to a trusted computer and approve its debugging prompt. Then run:adb pair.
Allow only the controller Mac
Tailnets with restrictive grants must explicitly allow the controller Mac to reach TCP port 5555 on the Android device. Add a narrow rule to the tailnet policy, replacing the example addresses with the two devices’ stable Tailscale IPs:Connect and start mirroring
On the remote Mac:adb connect from this Mac shows an authorization dialog on Android. Unlock the device,
confirm the key fingerprint, and select Always allow from this computer only when the Mac is
trusted. A successful adb devices entry ends in device; unauthorized means the on-device prompt
has not been approved.
Once the scrcpy window opens, use it directly or target it with a macOS screen-automation tool such
as Peekaboo. scrcpy carries the display and input; Tailscale provides only the
private network path.
Troubleshooting
Connection timed out: verify the tailnet grant for TCP 5555. A successfultailscale pingproves peer reachability, not that policy permits this TCP port. Test withnc -vz <android-tailnet-ip> 5555from the Mac.unauthorized: unlock Android and approve the remote Mac’s ADB key, or remove the stale workstation under Wireless debugging > Paired devices and pair it again.Connection refused: reconnect locally and runadb tcpip 5555again.- More than one device listed: keep the explicit
--serial <android-tailnet-ip>:5555argument.
Connection runbook
Android node app ⇄ (mDNS/NSD + WebSocket) ⇄ Gateway Android connects directly to the Gateway WebSocket and uses device pairing (role: node).
For Tailscale or public hosts, Android requires a secure endpoint:
- Preferred: Tailscale Serve / Funnel with
https://<magicdns>/wss://<magicdns> - Also supported: any other
wss://Gateway URL with a real TLS endpoint - Cleartext
ws://remains supported on private LAN addresses /.localhosts, pluslocalhost,127.0.0.1, and the Android emulator bridge (10.0.2.2)
Prerequisites
- Gateway running on another machine (or reachable via SSH).
- Android device/emulator can reach the gateway WebSocket:
- Same LAN with mDNS/NSD, or
- Same Tailscale tailnet using Wide-Area Bonjour / unicast DNS-SD (see below), or
- Manual gateway host/port (fallback)
- Tailnet/public mobile pairing does not use raw tailnet IP
ws://endpoints. Use Tailscale Serve or anotherwss://URL instead. - The
openclawCLI available on the gateway machine (or via SSH), to approve pairing requests.
1. Start the Gateway
listening on ws://0.0.0.0:18789
wss:// / https:// endpoint. A plain gateway.bind: "tailnet" setup is not enough for first-time remote Android pairing unless you also terminate TLS separately.
2. Verify discovery (optional)
From the gateway machine:local. plus the configured wide-area domain in one pass, using the resolved service endpoint instead of TXT-only hints.
Cross-network discovery via unicast DNS-SD
Android NSD/mDNS discovery does not cross networks. If the Android node and the gateway are on different networks but connected via Tailscale, use Wide-Area Bonjour / unicast DNS-SD instead. Discovery alone is not sufficient for tailnet/public Android pairing — the discovered route still needs a secure endpoint (wss:// or Tailscale Serve):
- Set up a DNS-SD zone (example
openclaw.internal.) on the gateway host and publish_openclaw-gw._tcprecords. - Configure Tailscale split DNS for your chosen domain pointing at that DNS server.
3. Connect from Android
In the Android app:- The app keeps its gateway connection alive via a foreground service (persistent notification).
- Open the Connect tab.
- Use Setup Code or Manual mode.
- If discovery is blocked, use manual host/port in Advanced controls. For private LAN hosts,
ws://still works. For Tailscale/public hosts, turn on TLS and use awss:/// Tailscale Serve endpoint.
Multiple gateways
The app keeps a registry of every gateway it has paired with, so you can switch between them without pairing again:- Settings -> Gateways lists paired gateways with the active one marked. Tap an entry to switch; the app tears down the current sessions and reconnects to the selected gateway.
- The Connect tab shows a quick switcher when more than one gateway is paired.
- Credentials, device tokens, TLS trust, chat history, and queued offline messages are stored per gateway. Switching never mixes state between gateways, and messages queued while offline are delivered only to the gateway they were written for.
- Forget removes a gateway’s registry entry together with its credentials, device tokens, TLS pin, and cached chats.
Presence alive beacons
After the authenticated node session connects, and when the app moves to the background while the foreground service is still connected, Android callsnode.event with event: "node.presence.alive". The gateway records this as lastSeenAtMs/lastSeenReason on the paired node/device metadata only after the authenticated node device identity is known.
The app counts the beacon as successfully recorded only when the gateway response includes handled: true. Older gateways may acknowledge node.event with { "ok": true }; that response is compatible but does not count as a durable last-seen update.
4. Approve pairing (CLI)
On the gateway machine:role: node pairing with no requested scopes. Operator/browser pairing and any role, scope, metadata, or public-key change still require manual approval.
5. Verify the node is connected
6. Chat + history
The Android Chat tab supports session selection (defaultmain, plus other existing sessions):
- History:
chat.history(display-normalized — inline directive tags, plain-text tool-call XML payloads (<tool_call>,<function_call>,<tool_calls>,<function_calls>, and truncated variants), and leaked ASCII/full-width model control tokens are stripped; silent-token assistant rows such as exactNO_REPLY/no_replyare omitted; oversized rows can be replaced with placeholders) - Send:
chat.send - Push updates (best-effort):
chat.subscribe->event:"chat" - Listen: long-press an assistant message and choose Listen to hear it; audio renders via gateway
tts.speakwith the configured TTS provider chain, and on-device system TTS is used when the gateway cannot render audio. Playback stops on session switch, new chat, app backgrounding, or chat close.
7. Canvas + camera
Gateway Canvas Host (recommended for web content)
To have the node show real HTML/CSS/JS that the agent can edit on disk, point the node at the Gateway canvas host.Nodes load canvas from the Gateway HTTP server (same port as
gateway.port, default 18789).- Create
~/.openclaw/workspace/canvas/index.htmlon the gateway host. - Navigate the node to it (LAN):
.local, e.g. http://<gateway-magicdns>:18789/__openclaw__/canvas/.
This server injects a live-reload client into HTML and reloads on file changes. The Gateway also serves /__openclaw__/a2ui/, but the Android app treats remote A2UI pages as render-only. Action-capable A2UI commands use the bundled app-owned A2UI page.
Canvas commands (foreground only):
canvas.eval,canvas.snapshot,canvas.navigate(use{"url":""}or{"url":"/"}to return to the default scaffold).canvas.snapshotreturns{ format, base64 }(defaultformat="jpeg").- A2UI:
canvas.a2ui.push,canvas.a2ui.reset(canvas.a2ui.pushJSONLlegacy alias). These use the bundled app-owned A2UI page for action-capable rendering.
camera.snap (jpg), camera.clip (mp4). See Camera node for parameters and CLI helpers.
8. Voice + expanded Android command surface
- Voice tab: Android has two explicit capture modes. Mic is a manual Voice-tab session that sends each pause as a chat turn and stops when the app leaves the foreground or the user leaves the Voice tab. Talk is continuous Talk Mode and keeps listening until toggled off or the node disconnects.
- Talk Mode promotes the existing foreground service from
connectedDevicetoconnectedDevice|microphonebefore capture starts, then demotes it when Talk Mode stops. The node service declaresFOREGROUND_SERVICE_CONNECTED_DEVICEwithCHANGE_NETWORK_STATE; Android 14+ also requires theFOREGROUND_SERVICE_MICROPHONEdeclaration, theRECORD_AUDIOruntime grant, and the microphone service type at runtime. - By default, Android Talk uses native speech recognition, Gateway chat, and
talk.speakthrough the configured gateway Talk provider. Local system TTS is used only whentalk.speakis unavailable. - Android Talk uses realtime Gateway relay only when
talk.realtime.modeisrealtimeandtalk.realtime.transportisgateway-relay. - Voice wake is implemented in source (
VoiceWakeMode) but the shipping app runtime always forces it tooffon connect — there is no user-facing toggle today. - Additional Android command families (availability depends on device, permissions, and user settings):
device.status,device.info,device.permissions,device.healthdevice.appsonly when Settings > Phone Capabilities > Installed Apps is enabled; it lists launcher-visible apps by default (passincludeNonLaunchablefor the full list).notifications.list,notifications.actions(see Notification forwarding below)photos.latestcontacts.search,contacts.addcalendar.events,calendar.addcallLog.searchsms.searchmotion.activity,motion.pedometer
9. Workspace files (read-only)
The Home overview includes a Files card that browses the active agent’s workspace through the read-onlyagents.workspace.list / agents.workspace.get gateway RPCs: directory drill-down, text and image previews, and export through the Android share sheet. There are no write operations, and previews are size-capped by the gateway.
Assistant entrypoints
Android supports launching OpenClaw from the system assistant trigger (Google Assistant). Holding the home button (or anotherACTION_ASSIST trigger) opens the app; saying “Hey Google, ask OpenClaw <prompt>” matches the app’s declared App Actions query pattern and hands the prompt into the chat composer without auto-sending it.
This uses Android App Actions (shortcuts.xml capability) declared in the app manifest. No gateway-side configuration is needed — the assistant intent is handled entirely by the Android app.
App Actions availability depends on the device, Google Play Services version, and whether the user has set OpenClaw as the default assistant app.
Notification forwarding
Android can forward device notifications to the gateway asnode.event items. This is configured on the device, in the app’s Settings sheet — not in gateway/openclaw.json config.
| Setting | Description |
|---|---|
| Forward Notification Events | Master toggle. Off by default; requires Notification Listener Access to be granted first. |
| Package Filter | Allowlist (only listed package IDs forwarded) or Blocklist (default: all packages except listed IDs). OpenClaw’s own package is always excluded in Blocklist mode to prevent forwarding loops. |
| Quiet Hours | Local HH:mm start/end window that suppresses forwarding. Disabled by default; defaults to 22:00-07:00 once enabled. |
| Max Events / Minute | Per-device rate limit on forwarded notifications. Default 20. |
| Route Session Key | Optional. Pins forwarded notification events into a specific session instead of the device’s default notification route. |
Notification forwarding requires the Android Notification Listener permission. The app prompts for this during setup.