Native apps (iOS / Android)
HAPI includes native iOS and Android clients for controlling sessions on a hub you run. Agents execute on your CLI/Runner machines; the hub stores the session history. The apps connect directly to that hub and share the same conversations as the Web/PWA.
Build and install
The repository provides these build paths:
| Platform | Device requirement | Build instructions |
|---|---|---|
| iOS | iOS 17 or newer | iOS README: Xcode 16 or newer, shared Hapi scheme; device builds require signing. |
| Android | Android 8.0 (API 26) or newer | Android README: JDK 17+, Android SDK, Gradle wrapper; build/install a debug APK or configure release signing. |
Maintainers can use the Android Official Build workflow to produce signed APK/AAB artifacts with the official Firebase configuration. That workflow does not publish to Google Play. Push setup depends on the build you install; see Notifications.
Pair with your hub
Start your hub, or use an existing HTTPS hub endpoint:
bashhapi hub --relayOpen the native app and choose a pairing method:
- Scan QR: use the in-app scanner with either QR code printed by the hub. Web Settings → Companion pairing also shows the companion QR.
- Open a pairing link:
hapicompanion://bindopens the app's pairing flow. Confirm the hub before pairing. - Enter manually: supply the hub URL and access token printed by the hub. On iOS, enter just the domain/IP and optional port; the separate protocol menu defaults to HTTPS. You can also paste a full address, or paste a pairing link into either field to fill both values before tapping Pair. Use the hub address, not the web frontend address
app.hapi.run.
The app checks reachability and protocol compatibility, then authenticates and stores credentials for that hub. A namespaced token such as
your-token:teamopens that namespace's sessions.
Use an HTTPS hub origin, for example https://hub.example.com. Both apps identify hubs by origin; path prefixes are not retained. Your phone must be able to reach the hub. localhost on a physical phone refers to the phone. The network relay, an HTTPS reverse proxy, or Tailscale Serve can provide an endpoint; see Deployment.
Android rejects HTTP URLs in manual entry, QR codes, deep links and saved hub state, including debug builds. iOS manual entry defaults to HTTPS and accepts HTTP only when explicitly selected or supplied in a full URL/pairing link. It warns about unencrypted HTTP and never automatically downgrades HTTPS. HTTP connection success still depends on system network policy. The iOS project declares no ATS exceptions, so HTTP input acceptance does not guarantee a working connection. Prefer HTTPS on both platforms.
Camera pairing is optional. Use manual entry on an iOS Simulator or any device without a usable scanner.
Sessions and everyday use
Start an agent on your computer with hapi and choose an installed agent, or run a specific agent command. The session appears in the app.
To create sessions from your phone, start a Runner on the machine that will execute the agent:
hapi runner startIn the app, select New Session, choose an online machine, directory and available agent, then create the session. Model and permission controls depend on the agent and session capabilities. Configured workspace roots constrain directory browsing and session creation.
| Capability | Current native behavior |
|---|---|
| Chat and permissions | Streaming messages, history, tool inspection, approvals and question answering on both platforms. |
| Composer | Text, photos/camera/files, drafts, queued-message actions and steering when supported by the session. |
| Session controls | Both support pin/archive, stopping a turn and sending to resume an inactive session. Android also exposes Rename, Delete and explicit Reopen actions; iOS currently has no corresponding UI for those three actions. |
| Files and Git | Open Session files from the chat menu to browse/search files, inspect Git status and read diffs. |
| Scratchlist | On iOS, tap the tray beside the composer attachment button to enter Save draft mode; Android uses the chat menu. Text and attachments sync within the session. |
| Dictation | Record audio, transcribe through a configured hub provider, then edit the inserted text before sending. |
| Usage and storage | Available only to the hub owner (default namespace). |
| Display | English/Simplified Chinese, theme preferences, system text scaling and machine filtering on the session list. |
Selecting an attachment starts its upload after preparation, before you send the message or save the Scratchlist entry. Removing it requests cleanup of unused uploads on a best-effort basis. See the Privacy Policy for storage and provider data flows.
On iOS, Scratchlist opens as a compact drawer above the same input field. Save draft keeps the content without sending it; closing the drawer with × leaves unsaved input intact. The drawer shows one recent draft, or just its header while typing. Take draft keeps the saved entry and restores its text and attachments. If the input is nonempty, choose Append to input or Save input, then take draft. Add to send queue in the draft's menu is an explicit send and removes the draft only after acceptance. A failed removal can be retried without sending again. Tap the drawer header for the full list and pull down to search text or filenames. The same menu offers edit, copy and delete; editing an original draft commits text and attachments together on Save. Cancelling an edit leaves the original unchanged.
Dictation uses the first configured provider that supports standard transcription. The microphone stays hidden until provider discovery succeeds; grant microphone permission when first using it. Configure providers on the hub or through Web Settings → Voice. Native dictation inserts text and does not send it automatically. See Voice input and assistant.
Features available through the web
Use the web app for the remote terminal, Work Graph, realtime dictation and voice assistant, session fork/rewind/export, and the skills picker. These have no native UI. Session history actions also depend on the agent's capabilities. Native apps display existing scheduled messages but do not provide a form to create scheduled sends. Android's full-text file export is a reader action, separate from exporting an entire session.
Multiple hubs and sign-out
The home screen's hub menu lets you add or switch hubs, open Settings, and sign out. You can keep several hubs paired, with one active at a time; session lists and drafts belong to their hub. Signing out removes that hub's stored credentials and attempts to unregister its push token.
Both apps refresh authentication automatically. Temporary network or server failures retain paired credentials. A rejected access token or a freshly issued token that is rejected again requires re-pairing with valid credentials.
Notifications
Allow system notifications after pairing. Native notifications support permission approval/denial and replies; a notification for the foreground chat is suppressed locally because the conversation is already visible.
| App build | Push requirements |
|---|---|
| Official Android Firebase configuration | A current hub uses the encrypted push relay by default when no private FCM credentials are configured. Google Play services and FCM connectivity are required. |
| Official iOS signing | A current hub uses the encrypted push relay by default. No Apple developer credentials are needed on the user's hub. |
| Private Android Firebase project | Bundle that project's client configuration and configure matching Firebase service-account credentials on the hub for direct FCM. |
| Android without Firebase configuration | Session features work; FCM push is unavailable. |
| Self-signed iOS build | Configure direct APNs or a self-hosted push relay with credentials matching the app's developer account, bundle ID and APNs environment. Follow the iOS README's signing instructions. |
The official push relay carries encrypted notification content and routing metadata. It is separate from the network tunnel enabled by hapi hub --relay, so it also works with hubs reached through another HTTPS setup. Private direct FCM delivery uses an unencrypted notification data payload; direct APNs remains encrypted. See Notifications and the push contract for configuration.
Push registration covers every paired hub. Notification taps currently open the session against the active hub; if the session cannot be found, switch to its owning hub. Background notification actions try paired hubs to resolve the session.
Troubleshooting
| Symptom | Check |
|---|---|
| Pairing cannot reach the hub | Use the HTTPS hub origin, verify phone network access and certificate trust, and check the hub's listening address or reverse proxy. |
| Protocol mismatch | Update the app/hub to compatible builds; both apps require the hub protocol version to equal their supported version. |
| Re-pairing requested | Use the current access token, including the intended namespace suffix. |
| No machines for New Session | Start the Runner, verify its connection and namespace, and check agent availability on that machine. |
| Microphone missing | Configure a standard transcription provider and ensure the hub is reachable. |
| Notifications missing | Check OS permission, the build's Firebase/APNs configuration, provider connectivity and hub push settings. |
For development and conformance checks, use the platform READMEs and the client contract. Protocol fixture conformance does not imply identical native and web UI features.