Publish the hub as pi-mobile-hub with CLI flags and LAN pairing auth, add mobile deep-link pairing and EAS build config, and expand gitignore for Expo/EAS artifacts. Co-authored-by: Cursor <cursoragent@cursor.com>
208 lines
5.3 KiB
Markdown
208 lines
5.3 KiB
Markdown
# Pi Mobile
|
|
|
|
Remote control for [Pi](https://pi.dev/docs/latest) coding agents from your phone.
|
|
|
|
Phone connects to a hub running on your computer over the local network. The hub embeds the Pi SDK in-process and exposes session management plus streaming chat over Socket.IO.
|
|
|
|
## Quick start (developers)
|
|
|
|
### 1. Start the hub on your computer
|
|
|
|
No clone required:
|
|
|
|
```bash
|
|
npx pi-mobile-hub@latest
|
|
```
|
|
|
|
Or from this repo during development:
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev:api
|
|
```
|
|
|
|
The hub listens on `0.0.0.0:8787` by default and prints:
|
|
|
|
- LAN URLs to connect from your phone
|
|
- A **pairing code**
|
|
- A **QR code** encoding a `pimobile://connect` deep link
|
|
|
|
Custom port:
|
|
|
|
```bash
|
|
npx pi-mobile-hub --port 9000
|
|
```
|
|
|
|
Disable pairing auth on trusted networks only:
|
|
|
|
```bash
|
|
npx pi-mobile-hub --no-auth
|
|
```
|
|
|
|
### 2. Install the mobile app
|
|
|
|
**Option A — Prebuilt app (recommended)**
|
|
|
|
Install the Pi Mobile app from TestFlight (iOS) or the APK link (Android). See [Releasing](#releasing) if you are building it yourself.
|
|
|
|
**Option B — Expo Go (development)**
|
|
|
|
```bash
|
|
npm run dev:mobile
|
|
```
|
|
|
|
Scan the QR code with Expo Go.
|
|
|
|
### 3. Pair and connect
|
|
|
|
1. Open Pi Mobile on your phone
|
|
2. Scan the QR code printed by `pi-mobile-hub` in your terminal
|
|
- Or enter your computer's LAN IP, port (`8787`), and pairing code manually
|
|
3. Tap **Connect**
|
|
4. Create a session by choosing a folder under `~/`
|
|
5. Send prompts and watch streamed assistant text + tool activity
|
|
6. Resume persisted Pi sessions from the list
|
|
|
|
Saved computers remember the pairing code for one-tap reconnect.
|
|
|
|
## Prerequisites
|
|
|
|
- Node.js 20+
|
|
- Pi installed and authenticated on the host machine (`pi` CLI with `/login` or provider API keys)
|
|
- Phone and computer on the same LAN
|
|
- For prebuilt mobile installs: iOS or Android device
|
|
|
|
## Project structure
|
|
|
|
```
|
|
apps/api/ Express + Socket.IO hub (`pi-mobile-hub` npm package)
|
|
apps/mobile/ Expo Router mobile app
|
|
```
|
|
|
|
## Development
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev:api # hub on :8787
|
|
npm run dev:mobile # Expo dev server
|
|
npm run build:api # compile hub for publishing
|
|
```
|
|
|
|
## API surface
|
|
|
|
### HTTP
|
|
|
|
- `GET /health` — liveness check (`authRequired` indicates whether pairing is enabled)
|
|
- `GET /fs/list?path=~` — folder-only explorer rooted at home (requires pairing token)
|
|
- `POST /fs/mkdir` — create folder under home (requires pairing token)
|
|
|
|
Authenticated HTTP requests must include header `x-pi-mobile-token: <pairing-code>`.
|
|
|
|
### Socket.IO (client → server)
|
|
|
|
| Event | Payload |
|
|
|-------|---------|
|
|
| `sessions:list` | — |
|
|
| `runtime:create` | `{ cwd, name?, model?, thinkingLevel? }` |
|
|
| `runtime:open` | `{ sessionFile }` |
|
|
| `runtime:attach` | `{ runtimeId }` |
|
|
| `runtime:model:set` | `{ runtimeId, model }` |
|
|
| `runtime:thinking:set` | `{ runtimeId, level }` |
|
|
| `runtime:thinking:cycle` | `{ runtimeId }` |
|
|
| `models:list` | `{ runtimeId?, cwd? }` |
|
|
| `chat:prompt` | `{ runtimeId, message }` |
|
|
| `chat:abort` | `{ runtimeId }` |
|
|
|
|
Socket connections must pass `auth: { token: "<pairing-code>" }` when pairing is enabled.
|
|
|
|
### Socket.IO (server → client)
|
|
|
|
| Event | Payload |
|
|
|-------|---------|
|
|
| `sessions:list:result` | `{ persisted, live }` |
|
|
| `runtime:created` / `runtime:opened` | `{ runtimeId, sessionId, cwd, sessionName?, sessionFile? }` |
|
|
| `chat:event` | `{ runtimeId, event }` |
|
|
| `chat:history` | `{ runtimeId, messages }` |
|
|
| `error` | `{ message }` |
|
|
|
|
## Pairing & security
|
|
|
|
Each hub start generates a fresh pairing token unless `--no-auth` is passed. The token is required for:
|
|
|
|
- Socket.IO connections (`handshake.auth.token`)
|
|
- Folder HTTP endpoints (`x-pi-mobile-token` header)
|
|
|
|
The mobile app stores the token per saved computer. Scanning the terminal QR code auto-fills host, port, and token via `pimobile://connect?host=...&port=...&token=...`.
|
|
|
|
This is LAN pairing, not full remote access over the internet. Do not expose the hub to untrusted networks without additional hardening.
|
|
|
|
## Releasing
|
|
|
|
### Hub (`pi-mobile-hub` on npm)
|
|
|
|
From `apps/api`:
|
|
|
|
```bash
|
|
npm run build
|
|
npm version patch
|
|
npm publish
|
|
```
|
|
|
|
Users can then run `npx pi-mobile-hub@latest`.
|
|
|
|
### Mobile app (EAS)
|
|
|
|
One-time setup:
|
|
|
|
```bash
|
|
cd apps/mobile
|
|
npm install -g eas-cli
|
|
eas login
|
|
eas init
|
|
```
|
|
|
|
Update `app.json` → `extra.eas.projectId` with the ID from `eas init`.
|
|
|
|
Build for internal testing:
|
|
|
|
```bash
|
|
# iOS (TestFlight via internal distribution)
|
|
eas build --platform ios --profile preview
|
|
|
|
# Android (shareable APK)
|
|
eas build --platform android --profile preview
|
|
```
|
|
|
|
Submit to stores:
|
|
|
|
```bash
|
|
eas build --platform ios --profile production
|
|
eas submit --platform ios
|
|
|
|
eas build --platform android --profile production
|
|
eas submit --platform android
|
|
```
|
|
|
|
Optional OTA updates for JS-only changes:
|
|
|
|
```bash
|
|
eas update --branch production --message "Describe the change"
|
|
```
|
|
|
|
## Notes
|
|
|
|
- The folder browser only exposes directories under your home folder.
|
|
- Pi credentials are read from the host environment / Pi auth storage — the mobile app does not handle login.
|
|
- Multiple live runtimes can run concurrently; switch between them from the Sessions screen.
|
|
|
|
## Success checklist
|
|
|
|
- [ ] Start hub via `npx pi-mobile-hub`
|
|
- [ ] Pair via QR code or manual pairing code
|
|
- [ ] Connect from phone via LAN IP
|
|
- [ ] Browse folders starting at `~/`
|
|
- [ ] Create a new Pi session
|
|
- [ ] Send a prompt and see streamed text + tool rows
|
|
- [ ] Resume a persisted session
|
|
- [ ] Open a second live runtime without stopping the first
|