mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-07 01:21:37 +00:00
216 lines
12 KiB
Markdown
216 lines
12 KiB
Markdown
# Native apps (iOS / Android)
|
||
|
||
HAPI offers native iOS and Android apps 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](./pwa.md).
|
||
|
||
The native apps are paid downloads. The [Web/PWA](./pwa.md) is free, works in
|
||
any phone browser and includes features the apps do not have yet; see
|
||
[Features available through the web](#features-available-through-the-web).
|
||
|
||
## Install
|
||
|
||
| Platform | Device requirement | Download |
|
||
|---|---|---|
|
||
| iOS / iPadOS | iOS 17 or newer | [App Store](https://apps.apple.com/app/id6805699104) |
|
||
| Android | Android 8.0 (API 26) or newer | [Google Play](https://play.google.com/store/apps/details?id=run.hapi.companion) |
|
||
|
||
Store builds include native push through the encrypted push relay; no Firebase
|
||
or Apple developer setup is needed on your hub. See [Notifications](#notifications).
|
||
|
||
### Build from source (developers)
|
||
|
||
The app source is in the repository. Development builds follow the
|
||
[iOS README](https://github.com/tiann/hapi/blob/main/ios/README.md) (Xcode 27.1
|
||
or newer, shared `Hapi` scheme; device builds require signing) or the
|
||
[Android README](https://github.com/tiann/hapi/blob/main/android/README.md)
|
||
(JDK 17+, Android SDK, Gradle wrapper). Self-built apps need their own push
|
||
configuration; see [Notifications](#notifications).
|
||
|
||
## Pair with your hub
|
||
|
||
1. Start your hub, or use an existing HTTPS hub endpoint:
|
||
|
||
```bash
|
||
hapi hub --relay
|
||
```
|
||
|
||
2. Open 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://bind` opens 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`.
|
||
3. The app checks reachability and protocol compatibility, then authenticates
|
||
and stores credentials for that hub. A namespaced token such as
|
||
`your-token:team` opens 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](./deployment.md).
|
||
|
||
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](./agents.md). The session appears in the app.
|
||
|
||
To create sessions from your phone, start a [Runner](./installation.md#runner-setup)
|
||
on the machine that will execute the agent:
|
||
|
||
```bash
|
||
hapi runner start
|
||
```
|
||
|
||
In 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, `/` command suggestions and steering when supported by the session. iOS also offers `@` session references, plus file references for Codex/Copilot (editable text, not inline chips). |
|
||
| Android incoming shares | Share files, photos, text or links to HAPI, choose a session and confirm sending from its composer. The picker can switch paired hubs and explicitly restore stopped sessions. |
|
||
| Session controls | Both support pin, rename, stopping a turn and sending to resume an inactive session. Active sessions can be archived; inactive sessions can be reopened explicitly or deleted. |
|
||
| 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. |
|
||
|
||
### Share to an Android session
|
||
|
||
In another app, choose **Share → HAPI**, then select a session. Use the hub
|
||
menu to choose another paired hub, or search the session list. A stopped
|
||
session asks for restoration before files can upload. HAPI adds the files and
|
||
any accompanying text to the session composer, preserving its existing draft;
|
||
review the content and tap **Send**.
|
||
|
||
Files use the existing attachment limits and image compression policy. Failed
|
||
files must be retried or removed before continuing. Before import, pending
|
||
content stays in private local storage for up to 24 hours, including while
|
||
pairing or recovering from process recreation. After import, ordinary Android
|
||
attachment behavior applies: leaving the chat discards unsent attachments.
|
||
|
||
### Session-list parity
|
||
|
||
Android and iOS use the shared base session-list order: global-pinned sessions,
|
||
project-pinned sessions, active sessions, pending-request priority among active
|
||
sessions, then `updatedAt` descending. Ties preserve their incoming order. The
|
||
Web sidebar may apply additional directory grouping and client-side search
|
||
ranking; it also exposes text, date-range and unread-only session-list filters.
|
||
Both native apps offer machine filtering and relevance-ranked text search.
|
||
Android adds a date range; iOS adds an unread-only lens and **Mark All as
|
||
Read**. Android and iOS README files describe their platform-specific filter
|
||
presentation and session-row differences.
|
||
|
||
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](../privacy.md)
|
||
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](./voice-assistant.md).
|
||
|
||
### Features available through the web
|
||
|
||
Use the web app for the remote terminal, Work Graph, realtime dictation and
|
||
voice assistant, Markdown export, and the skills picker. These have no native
|
||
UI. On iOS, the chat's … menu forks the current conversation, rewinds or forks
|
||
at a user message with a native history point, and exports the session as
|
||
JSON; Android has no fork, rewind or export UI. Session history actions also
|
||
depend on the agent's capabilities.
|
||
Both apps display existing scheduled messages. On iOS, the composer's clock
|
||
schedules a text-only send up to 7 days ahead (relative presets or a specific
|
||
time); Android has no 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
|
||
|
||
On iOS, Settings lists your hubs: add or switch hubs and sign out there. On
|
||
Android, 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 |
|
||
|---|---|
|
||
| Google Play build | 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. |
|
||
| App Store build | 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](./notifications.md#native-app-notifications)
|
||
and the [push contract](../api/native-companion-contract.md) for configuration.
|
||
|
||
Push registration covers every paired hub. On iOS, a notification tap finds
|
||
the hub that owns the session (active hub first) and switches to it before
|
||
opening the chat. Android opens the session against the active hub; if it
|
||
cannot be found, switch to its owning hub. Background notification actions on
|
||
both platforms 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 from the App Store / Google Play and update the hub; 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](../api/client-contract/index.md). Protocol fixture conformance
|
||
does not imply identical native and web UI features.
|