The official Android app is available on Google Play and, for sideloading, as a signed standalone APK on selected GitHub Releases. Not every release includes the APK and checksum. See Install outside Google Play to find and verify both files. 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 GitHub Release that lists both required assets (see Install outside Google Play), Getting Started for the Gateway, then Pairing. - Gateway: Runbook + Configuration.
- Protocols: Gateway protocol (nodes + control plane).
- Select an agent in the sidebar to view its credential status in Settings → Providers & Models. The page updates when the Gateway publishes model, credential, or config changes. Use Refresh to recheck model availability.
- The sidebar marks sessions waiting for an answer or approval, including inactive sessions and collapsed groups. Tap the attention icon, hover over it, or focus it with a keyboard to read the oldest pending request and the count of additional requests of the same kind. The indicator clears when requests resolve, are canceled, or expire. Question previews never include answer drafts.
- Settings → OpenClaw opens a dedicated Gateway settings assistant when the operator connection has
operator.adminand the Gateway supportsopenclaw.chat. Its setup conversation stays separate from ordinary Chat, redacts secret replies locally, and moves to Chat only after you tap Open Chat.
Simultaneous Gateway sessions
Pair each Gateway once, then open Settings → Gateway. The checkmark marks the focused Gateway and each switch controls whether a non-focused Gateway’s operator session stays connected. Enabled Gateways reconnect independently while the app is in the foreground, so switching focus does not tear down the others. The focused Gateway alone owns the Android node session and device capabilities; this prevents simultaneous Gateways from issuing camera, location, screen, or notification commands to the same phone. Android can suspend the secondary connections after the app leaves the foreground. The sidebar footer opens Add Gateway when none are saved and Gateway settings when one is saved. With multiple saved Gateways, it opens a native quick picker with a checkmark for the focused route, Add Gateway, and Manage Gateways. Add Gateway opens the QR scanner without disconnecting the current Gateway or restarting onboarding. You can also enter a setup code, choose a QR image, or enter a Gateway URL manually. A valid code opens a confirmation; only Connect starts the handoff. Cancel returns to the previous screen without changing the current conversation, drafts, attachments, or saved Gateways. Adding an already saved Gateway uses its existing connection settings; use Manage Gateways to replace its setup. Saved offline entries remain listed; connection status is separate from selection. Unsent text and finished attachments stay with their Gateway, agent, and session when you switch away and back. Finish recording, stop dictation or Talk, and let media imports or pending send admission finish before using the quick picker. The composer stays protected during handoff, but a committed offline Gateway remains usable without waiting for a network connection.Dictation and attachments
Tap the composer microphone to dictate. The composer shows when recognition is starting, listening, or transcribing, with an interim transcript while you speak. Only the final transcript is added to your draft. Tap Stop to finish listening, or Cancel while starting or transcribing to discard that attempt. Recognition errors leave your existing draft intact and explain how to retry. After picking or sharing photos and files, Preparing attachments… stays visible until they are ready. Send remains disabled during preparation. Queuing message… covers local send admission; the message’s outbox status then shows delivery or any failure. Offline messages still use the durable queue.Wear OS companion
The Wear OS companion uses the paired Android phone’s authenticated Gateway connection; the watch never receives or stores Gateway credentials. It can select agents and sessions, read bounded transcripts, send text or dictated replies, abort an active run, start realtime Talk inside the selected session, and connect or disconnect the paired phone’s Gateway. It also offers local reply notifications, dark or light appearance, and optional automatic speech for replies. Agent and Gateway controls are capability-negotiated for staggered phone/watch updates. Realtime Talk streams microphone and playback audio over a temporary Wear OS Data Layer channel and stops when the selected phone, Gateway connection, or audio channel is lost.Install outside Google Play
Selected 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. Android assets may be attached after a release becomes public. Select a release by its listed assets, not by the latest Gateway release tag.
List published releases that contain both required assets:
Building a release artifact (APK or app bundle) from source or a fork requires your own Android signing identity. Debug builds use an automatically generated debug signing key. The official OpenClaw release key is not included in the repository. See Sign your app for how to generate and configure a signing key for release builds.
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); non-loopback setup automatically uses limited operator access
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
Use an authenticated Gateway. If it is not configured yet, runopenclaw onboard first to configure a token or password.
For a trusted same-LAN setup, persist the LAN bind before starting:
auto instead. Set the bind explicitly for this setup.
Use the config command rather than --bind lan alone: a startup-only flag does not change the configuration read by a separate openclaw qr command. Without another configured URL route, setup-code creation still sees loopback and refuses to mint a code.
Run openclaw gateway status. Its Gateway: line should show bind=lan (0.0.0.0) and port=18789.
For remote Android access, choose managed Tailscale Serve as an alternative to LAN binding. Keep its settings in config so setup-code creation can use the same route:
gateway.bind=lan set when switching to them. See Tailscale for Serve and password-authenticated Funnel setup.
This gives Android a secure 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
Create a setup code in the Control UI (Devices → Pair device) or withopenclaw qr.
That mobile setup code (and its QR) is what Android Scan QR or setup code / Enter setup code accept. It is a different artifact from the gateway join URL minted by openclaw devices join-code (https://…/j/<code>), which enrolls a headless node host via openclaw connect. Pasting a join URL or bare join code into Android setup is rejected — generate a fresh mobile QR/setup code with openclaw qr.
An explicit --url or --public-url override wins. Otherwise, setup-code URL selection uses this order:
plugins.entries.device-pair.config.publicUrl, unless remote preference was requested.gateway.remote.urlwhen explicitly preferred.- Managed Tailscale Serve or Funnel.
- The ordinary
gateway.remote.urlsetting. - A usable configured bind, such as the LAN bind from step 1.
openclaw qr --remote selects remote credentials, ignores the configured device-pair publicUrl, and prefers gateway.remote.url before managed Tailscale. See QR.
URL selection does not test network reachability. Resolution errors stop setup-code creation instead of triggering a lower-priority route. A loopback-only Gateway with no configured URL or managed Tailscale route refuses to mint a code.
In the Android app:
- The app keeps its Gateway connection alive via a foreground service (persistent notification).
- During first-run setup, choose Scan QR or setup code or Set up manually.
- After setup, open Settings → Gateway. Add Gateway lets you scan or paste a setup code, or connect to a discovered Gateway.
- If discovery is blocked, use Manual Gateway on that page: enter the host and port, select Connection security, and tap Save & Connect. Private LAN hosts support
ws://; for Tailscale/public hosts, use Secure (TLS) with awss:/// Tailscale Serve endpoint.
wss://. Plaintext non-loopback ws:// setup
automatically uses limited access for bearer-token safety. Settings → Gateway
shows Full or Limited access. For a limited connection, configure
wss:// or Tailscale Serve, generate a new full-access code in Control UI or
with openclaw qr, then scan or paste it on that page and reconnect. Operators
who want the reduced profile can select Limited access in Control UI or run
openclaw qr --limited.
Manage paired Gateways
The app keeps a registry of every Gateway it has paired with, so you can keep operator sessions connected and change focus without pairing again:- Settings → Gateway lists paired Gateways in the Gateways section, with a checkmark beside the focused one. Tap another entry to focus it; the other enabled operator sessions remain connected.
- Each switch controls whether that non-focused Gateway stays connected while the app is in the foreground. The focused Gateway remains enabled and owns the phone’s node connection and device capabilities.
- Credentials, device tokens, TLS trust, chat history, and queued offline messages are stored per Gateway. Changing focus 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. A Gateway that acknowledges node.event with { "ok": true } and no handled field is compatible, but that response 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 draft has its own full-width row above the attachment and voice/send controls, so larger text and narrow screens do not squeeze it between buttons. The empty hint stays on one line; drafts show up to six lines and scroll when space is limited. The composer has narrower side gutters than the transcript, with readable draft text and 48dp action targets. Typography still follows system text scaling. Model and thinking controls sit together, opposite the microphone and primary action. The model name stays on one line and follows system text scaling; long names use a middle ellipsis to keep both ends visible. The full name remains in the model sheet and accessibility text. The thinking dial opens a menu without expanding the composer. Context usage is available in the model sheet and the model control’s accessibility value, leaving more room for the model name in the toolbar. During Talk, the live waveform replaces the microphone and remains tappable to end Talk. If a run is also active, a separate, softly tinted Stop button stays at the trailing edge to abort that run. Open Home from the sidebar’s Pages menu to chat, or select an existing session from the sidebar:- 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) - Long replies: tap View all on a capped assistant reply to load the full formatted text inline. Attachments stay in the conversation, and message actions use the expanded text. Tap Show less or press Back to restore the preview; reopening reuses the loaded reply. Loading, retryable failures, unavailable messages, and required reconnects or Gateway updates appear in the message rather than an alert. Synthetic message-tool and commentary previews retain their existing display and actions but do not offer View all, because their copied transcript ID cannot retrieve that synthesized text. This also recognizes the older capped-preview format from released Gateways such as v2026.7.1-2. Android requests up to 1,000,000 characters per text field, matching the Gateway’s default retrieval limit; oversized or still-capped results show The full message is too large to display. instead of an incomplete reply.
- Large code blocks scroll within a bounded viewport, with Start of code, End of code, and Copy code controls. Start and End also reveal that end of the block in the conversation. Selection stays within the displayed text segment; Copy code copies the entire block. The separate message Select text action opens a plain-text selection reader; long answers use bounded pages, and selection applies to the displayed page.
- Reading: scrolling up or using View all, Start of code, or End of code pauses automatic following. Incoming content and window-size changes preserve your reading position, moving text or images into view when space shrinks. Resizing an idle conversation so that all content fits resumes following. Jump to latest in the chat header resumes following; it appears only while newer content is below the visible history and never covers messages.
- Mermaid code blocks render as diagrams after the closing fence arrives or the reply finishes. Tap a diagram to open a full-screen view with pinch-to-zoom and panning. The small corner controls copy the source or open a menu to switch between diagram and source. Rendering works offline with bundled assets. Failed diagrams keep their readable source, and temporary failures offer retry. Other code block languages remain code.
- Thread activity: search results and sidebar rows use each thread’s own reported activity. An inactive run does not keep a working or queued indicator solely because its last status was running or queued.
- Session selection: while the app is running, each Gateway and agent remembers the last chat you explicitly selected. Returning to an agent checks an older chat directly if it is outside the recent page; temporary lookup failures show an error without forgetting that choice.
- Archiving the open session returns to the app’s main chat only if that same session is still selected. Switching sessions, agents, or Gateways while the archive finishes preserves your newer selection. A successful archive also retires the archived chat’s remembered selection even if its push notification is missed.
- New in the sidebar creates and selects a fresh chat from any page without clearing the previous session. The sidebar and chat header show progress during creation and initial loading, and duplicate New actions are disabled. History refreshes do not cancel creation; selecting another session, agent, or Gateway while it finishes preserves that newer selection.
- Offline history: cached transcripts update in the order live histories are accepted, so a delayed reconnect health check cannot restore an older snapshot. Switching sessions preserves queued cache updates for the session you left.
- Refresh chat in chat actions reloads history and rechecks Gateway health without clearing pending messages. Chat readiness is separate from the Gateway connection: an empty connected thread shows Chat not ready while health is unconfirmed or a check has failed. Use Refresh chat to check again; Gateway offline indicates a disconnected Gateway. History failures do not stop subsequent health checks. Once Android observes a recovered run finish, a delayed history response does not bring back that run’s Stop button or partial reply.
- Send:
chat.send. Outside an active Talk session, you can send text or staged attachments while the agent is working. A new draft brings back Send; clearing it restores Stop. The Gateway applies the existing queue mode, so steering does not require stopping the current run. Sending remains disabled while another submission, attachment staging, or microphone capture owns the draft. - Queued message controls: Delete removes the local queued copy, including when a reconnect refresh is still finishing. It does not undo a message already accepted by the Gateway; use Stop to cancel an active turn.
- Durable sending: every send (text, picked images, and voice notes) is journaled to a per-gateway on-device outbox before any network attempt, so app termination cannot lose submitted input. Sends queued while offline deliver in order on reconnect with stable idempotency keys, and a send is retired only after the turn is visible in canonical
chat.history— an acknowledgement alone is not treated as proof of delivery. Acknowledged reconnect sends show the same streaming progress as online sends; requests that never reach the socket queue remain queued for the next connection. Ambiguous outcomes (lost acknowledgement, app killed mid-send, Gateway restart before the transcript write) surface as visible rows with explicit Retry/Delete instead of auto-resending. If refreshed history changes branches, earlier queued input keeps its text and attachments but requires explicit retry; input admitted after that history is displayed can send normally when reconnecting to the same branch. Slash commands never auto-replay across a reconnect; they park for explicit retry. The queue is bounded (50 messages and 48 MB of attachment bytes per Gateway) and unsent rows expire after 48 hours. Composer drafts that were never submitted are not process-durable. - Completed answers show up to eight compact source cards for cited pages found in that run’s successful web searches and fetches. Tap a card to read its recorded search snippet or page excerpt and open the source. The cards do not fetch page content; favicons come through the Gateway and honor
gateway.controlUi.automaticallyFetchFavicons, with a globe when disabled or unavailable. - Image input works through the picker and Android Sharesheet. Assistant-generated images resolve through the paired Gateway connection, render inline with a full-screen preview, and retain only their small artifact references in the offline transcript cache. Downloads are capped at 12 MiB and decoded to bounded display bitmaps.
- 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. Camera
Camera commands (foreground only; permission-gated):camera.snap (jpg), camera.clip (mp4). See Camera node for parameters and CLI helpers.
8. Voice + expanded Android command surface
- Navigate through the sidebar’s Pages menu. Voice input belongs to the Chat composer; there is no separate Voice tab.
- Tap the composer microphone for on-device speech recognition that inserts a transcript into the draft. While listening, a Stop icon replaces the microphone; tap it to finish listening. While starting or transcribing, a Close icon cancels that attempt. Long-press the microphone to open Voice options, then choose Record voice note to create an attachment. The UI reports unavailable recognition, missing permission, busy/network failures, and no-speech outcomes instead of silently dropping the attempt. If dictation is unavailable and a Gateway is selected, Record voice note offers a new recording while keeping the draft. It does not recover speech from the failed dictation attempt or send anything automatically.
- To start continuous Talk, long-press the microphone and choose Start Talk. Dictation, voice-note recording, and Talk are mutually exclusive microphone paths.
- Your selected agent stays bound to Talk and the main chat when the same Gateway reconnects, including while its agent list refreshes. Removing that agent falls back to the Gateway default. Switching Gateways or restarting the app clears this in-memory choice.
- 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. It inherits the session’s thinking setting. Local system TTS is used only whentalk.speakis unavailable. - Gateway config changes refresh Android’s cached Talk settings on the next use, without reconnecting or interrupting an active capture.
- Android Talk uses realtime Gateway relay only when
talk.realtime.modeisrealtimeandtalk.realtime.transportisgateway-relay. - Enable Settings → Voice → Listen for wake words for foreground on-device
Voice Wake. Android advertises
voiceWakeonly when enabled, on-device recognition and microphone permission are available, and wake words are synchronized with the current Gateway. - 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)
Open Work from the sidebar’s Pages menu to find the Files card. It 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.
If the app cannot prepare a file or open the share sheet, it shows Could not share file and keeps the preview open so you can retry or go back.
Review command approvals
An operator connection withoperator.admin, or a paired
operator.approvals connection explicitly targeted by the Gateway, can review
pending exec requests under Settings -> Approvals. The app loads the
Gateway’s sanitized approval record before enabling its buttons, shows any
security warning and the exact decisions offered by that request, and submits
the approval ID and owner kind back to the Gateway.
Approval state is shared with the Control UI and supported chat surfaces. The
first committed answer wins; Android displays that canonical result even when
another surface answered first. If a resolve response is lost or the Gateway
disconnects, the app keeps the action locked and reads the approval again
before offering another decision.
Gateways that predate the unified approval methods fall back to the shipped
exec-specific methods. Pending review still works, but retained terminal state
and the richer cross-surface result require an updated Gateway.
Answer agent questions
Chat shows pending Gateway questions as native cards for operator connections withoperator.questions (or operator.admin). Cards support single- and
multi-select options, option descriptions, free-text Other answers, and an
expiry countdown. Reconnects reload pending questions from the Gateway. A card
locks when this device answers it, another surface answers it first, or the
question expires or is cancelled.
Secret answer fields mask typed or pasted values and request password input with autocorrection disabled. Android submits secret answers without trimming leading or trailing whitespace.
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.
Notification forwarding requires the Android Notification Listener permission. The app prompts for this during setup.
Related
- iOS app
- Nodes
- Android node troubleshooting
- Stable HTTPS URL — give a loopback-only Gateway a stable, tailnet-only HTTPS URL with Tailscale Serve