feat(privacy+dist): telemetry consent gate + app store distribution prep (#4)
* fix(security): fail closed on biometric init error H-03: setting isAuthenticated: true on initialization failure was a security bypass — any crash during biometric setup granted full access. Fail closed instead; user sees auth prompt on next open. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(security): use Crypto.randomUUID for connection IDs H-04: Math.random() is not cryptographically random. Connection IDs are used as SecureStore key suffixes; switch to expo-crypto randomUUID for a secure source. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): pin expo-crypto to ~15.0.9 15.0.10 does not exist on npm; ~15.0.9 is the latest stable in the 15.x series compatible with Expo SDK 54. * feat: add OpenCode Connect coming-soon waitlist card Adds a discoverable 'OpenCode Connect — Coming Soon' card to the add-connection quick-connect screen. Users can enter their email and tap 'Join Waitlist' to send a pre-filled mailto. No backend required. * fix(cua): detect actual screen dimensions and fix JSON parsing - Get real screen size via `wm size` instead of hardcoding 1080x2400; emulator is 1080x1920 so y-coordinates were systematically off - Extract first JSON object via regex when model returns multiple objects - Use AZURE_OPENAI_MODEL env var for deployment name (defaults gpt-5.4) - Add AZURE_DEV_AI_* path for Azure AI Foundry endpoints Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(security): SHA-pin upload-google-play and sanitize notification bodies M-02: Pin r0adkll/upload-google-play to commit SHA e738b9d (v1.1.5) to prevent supply-chain hijack via tag mutation. M-03: Sanitize all push notification bodies — strip control chars, truncate to 200 chars. Prevents server-supplied strings (error messages, file paths from permission patterns, session titles) from leaking unbounded text into the OS notification drawer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(privacy): add telemetry consent gate for Sentry crash reporting Sentry was always-on, violating F-Droid anti-feature policy and user trust norms. Now gated behind explicit opt-in: - First-launch consent modal (TelemetryConsentModal) shows once on fresh install; user can Allow or Decline. - Consent state persisted in expo-secure-store (survives restarts). - Settings > Privacy section: crash reporting toggle + privacy policy link. - initSentry() called only after consent granted — not on app start. Closes #3 (partial) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(config): add real icons and complete iOS/Android app.json config - Add 1024×1024 app icon, 432×432 adaptive icon foreground, 200×200 splash - iOS: push notification entitlement (aps-environment: production), speech/ microphone/camera/photo usage descriptions for future features, disable ITSAppUsesNonExemptEncryption - Android: adaptive icon with dark background (#0F172A), versionCode: 1 - expo-notifications plugin wired in app.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(dist): add iOS CI workflow, README rewrite, CONTRIBUTING, and LICENSE - publish-app-store.yml: EAS Build + TestFlight submission; runs on tag/release/ workflow_dispatch; bumps ios.buildNumber from github.run_number - README: full rewrite — features, install badges, connection guide, contributing - CONTRIBUTING.md: contribution guide for OSS contributors - LICENSE: MIT Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(dist): add store listings, strategy, privacy policy, F-Droid/IzzyOnDroid templates - distribution/strategy.md: monetization strategy (free client + opencode Cloud) - distribution/play-listing.md: Google Play store copy (name, description, tags) - distribution/app-store-listing.md: App Store listing copy - distribution/privacy-policy.{md,html}: GDPR-compliant privacy policy - distribution/PLAY_CONSOLE_SETUP.md: Play Console setup runbook - distribution/ios-enrollment-runbook.md: Apple Developer Program enrollment steps - distribution/SIGNING-KEY-FINGERPRINTS.md: keystore fingerprint for reproducible builds - distribution/fdroid-submission/: F-Droid metadata template - distribution/izzyondroid-submission/: IzzyOnDroid submission template - distribution/whatsnew/: Play Store release notes (en-US) - distribution/whatsnew-ios/: TestFlight release notes - distribution/play-graphics/: Play Store screenshot placeholders - distribution/app-store-graphics/: App Store screenshot placeholders Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(telemetry): handle SecureStore failure + Android back button - add .catch() on loadTelemetryConsent() so SecureStore rejection shows the consent modal instead of blocking startup forever - add onRequestClose={onDecline} to Modal so Android back button records the decline rather than silently dismissing - fix catch block in telemetry.ts to not clobber _resolved when SecureStore read fails mid-session Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): run gradlew clean to prevent stale modules.json duplicate Sentry Gradle plugin writes modules.json to src/main/assets; cached build intermediates contain an old copy → mergeReleaseAssets fails with 'Duplicate resources'. Running clean before assembleRelease clears the intermediate state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): remove android build output cache causing duplicate modules.json Caching android/app/build/intermediates and android/app/.cxx causes two issues: 1. Stale modules.json in intermediates → Duplicate resources error 2. .cxx CMake artifacts reference absolute paths → ninja clean fails Keeping only Gradle distribution cache (~/.gradle) which is safe. Expo prebuild regenerates android sources fresh each run anyway. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
217
README.md
217
README.md
@@ -1,88 +1,183 @@
|
||||
# OpenCode Mobile
|
||||
|
||||
A React Native / Expo app for connecting to OpenCode servers from your phone.
|
||||
**The open-source mobile client for the [opencode](https://github.com/sst/opencode) AI coding agent.**
|
||||
AI-assisted coding from your phone — iOS, Android, and F-Droid.
|
||||
|
||||
[](LICENSE)
|
||||
[](https://play.google.com/store/apps/details?id=ai.opencode.mobile)
|
||||
[](https://apps.apple.com/app/opencode-mobile/id0000000000)
|
||||
[](https://f-droid.org/packages/ai.opencode.mobile)
|
||||
[](https://apt.izzysoft.de/fdroid/index/apk/ai.opencode.mobile)
|
||||
|
||||
---
|
||||
|
||||
OpenCode Mobile is a React Native / Expo app that brings the power of the [opencode](https://github.com/sst/opencode) AI coding agent to your phone. Connect to your own self-hosted opencode server over your local network, a Cloudflare Tunnel, ngrok, Tailscale, or the upcoming opencode Cloud — and write, review, and ship code from anywhere. The mobile client is **free and open-source** under the MIT license. There is no feature gate, no telemetry you did not opt into, and no ad network.
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<img src="distribution/play-graphics/phone-01.png" width="220" alt="Session list screen" />
|
||||
<img src="distribution/play-graphics/phone-02.png" width="220" alt="Chat screen with diff viewer" />
|
||||
<img src="distribution/play-graphics/phone-03.png" width="220" alt="Connection setup wizard" />
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **Multiple Connection Types**: Connect via local network, tunnels (Cloudflare/ngrok), or cloud-hosted instances
|
||||
- **Secure Authentication**: Biometric authentication (Face ID/Touch ID) support
|
||||
- **Session Management**: View, create, and manage coding sessions
|
||||
- **Real-time Chat**: Stream responses from your AI assistant
|
||||
- **File Diff Viewer**: See what changes were made to your code
|
||||
- **Multi-connection** — manage multiple opencode servers (local network, Cloudflare Tunnel, ngrok, Tailscale, or opencode Cloud)
|
||||
- **Biometric unlock** — Face ID, Touch ID, or Android fingerprint protects the app and individual message sends
|
||||
- **Streaming chat** — token-by-token streaming responses directly from your opencode server
|
||||
- **Diff viewer** — inline side-by-side diffs of every file change the agent makes
|
||||
- **Tool call approval** — review and approve (or reject) tool calls before the agent executes them
|
||||
- **Secure credential storage** — server credentials stored in iOS Keychain / Android Keystore via `expo-secure-store`
|
||||
- **Session management** — browse, create, and resume coding sessions
|
||||
|
||||
## Getting Started
|
||||
---
|
||||
|
||||
### Prerequisites
|
||||
## Get OpenCode Mobile
|
||||
|
||||
- Node.js 18+
|
||||
- Bun (recommended) or npm
|
||||
- Expo Go app on your phone (for development)
|
||||
| Platform | Link |
|
||||
|---|---|
|
||||
| Google Play | [play.google.com — ai.opencode.mobile](https://play.google.com/store/apps/details?id=ai.opencode.mobile) |
|
||||
| Apple App Store | [apps.apple.com — OpenCode Mobile](https://apps.apple.com/app/opencode-mobile/id0000000000) |
|
||||
| F-Droid | [f-droid.org/packages/ai.opencode.mobile](https://f-droid.org/packages/ai.opencode.mobile) |
|
||||
| IzzyOnDroid | [apt.izzysoft.de — ai.opencode.mobile](https://apt.izzysoft.de/fdroid/index/apk/ai.opencode.mobile) |
|
||||
|
||||
### Installation
|
||||
> **Note**: App Store and F-Droid listings are pending final review. Play Store internal testing is live.
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
**Step 1 — Start opencode on your machine**
|
||||
|
||||
```bash
|
||||
# From the monorepo root
|
||||
cd packages/mobile
|
||||
bun install
|
||||
# Install opencode (if you haven't already)
|
||||
npm install -g opencode
|
||||
|
||||
# Start the development server
|
||||
bun start
|
||||
# Run opencode in server mode
|
||||
OPENCODE_SERVER_PASSWORD=yourpassword opencode serve --hostname 0.0.0.0 --port 4096
|
||||
```
|
||||
|
||||
### Connecting to OpenCode
|
||||
**Step 2 — Install OpenCode Mobile** from any store above (or build from source — see [CONTRIBUTING.md](CONTRIBUTING.md)).
|
||||
|
||||
1. Start OpenCode in server mode on your machine:
|
||||
**Step 3 — Add a connection in the app**
|
||||
|
||||
```bash
|
||||
OPENCODE_SERVER_PASSWORD=yourpassword opencode serve --hostname 0.0.0.0 --port 4096
|
||||
```
|
||||
Open the app, tap **Add Connection**, and choose your connection type:
|
||||
|
||||
2. Open the app and add a connection:
|
||||
- **Local Network**: Use your machine's local IP (e.g., `http://192.168.1.100:4096`)
|
||||
- **Tunnel**: Set up a Cloudflare Tunnel or ngrok and use the tunnel URL
|
||||
- **Cloud**: Connect to a hosted OpenCode instance
|
||||
- **Local network** — your machine's LAN IP, e.g. `http://192.168.1.100:4096`
|
||||
- **Tunnel** — a Cloudflare Tunnel or ngrok URL, e.g. `https://my-opencode.trycloudflare.com`
|
||||
- **Tailscale** — your machine's Tailscale IP, e.g. `http://100.x.x.x:4096`
|
||||
- **opencode Cloud** *(coming soon)* — one-tap managed hosting, no server to run
|
||||
|
||||
## Building for Production
|
||||
Enter the password you set in Step 1, tap **Connect**, and you're in.
|
||||
|
||||
### iOS
|
||||
---
|
||||
|
||||
```bash
|
||||
bun run ios
|
||||
# or
|
||||
eas build --platform ios
|
||||
```
|
||||
## How It Works
|
||||
|
||||
### Android
|
||||
|
||||
```bash
|
||||
bun run android
|
||||
# or
|
||||
eas build --platform android
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
- Credentials are stored securely using `expo-secure-store` (iOS Keychain / Android Keystore)
|
||||
- Optional biometric authentication for app access
|
||||
- Optional biometric confirmation for sending messages
|
||||
- All traffic should use HTTPS for non-local connections
|
||||
|
||||
## Architecture
|
||||
OpenCode Mobile is a thin client. It speaks the opencode HTTP + SSE API: listing sessions, sending messages, streaming responses, and subscribing to file-change events. All AI model calls are handled by your opencode server — you bring your own API keys (OpenAI, Anthropic, etc.) and the app never touches them. The app never proxies your code or conversation through our servers.
|
||||
|
||||
```
|
||||
packages/mobile/
|
||||
├── app/ # Expo Router screens
|
||||
│ ├── (tabs)/ # Tab navigation
|
||||
│ ├── session/ # Session screens
|
||||
│ └── connection/ # Connection management
|
||||
├── src/
|
||||
│ ├── components/ # Reusable components
|
||||
│ ├── hooks/ # Custom hooks
|
||||
│ ├── lib/ # SDK client & types
|
||||
│ └── stores/ # Zustand state stores
|
||||
└── assets/ # App icons & images
|
||||
┌─────────────────────────────────────┐
|
||||
│ OpenCode Mobile │
|
||||
│ (React Native / Expo, this repo) │
|
||||
└──────────────┬──────────────────────┘
|
||||
│ HTTP + SSE
|
||||
│ (local network / tunnel / cloud)
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ opencode server │
|
||||
│ (github.com/sst/opencode, MIT) │
|
||||
│ Running on your laptop / VPS │
|
||||
└──────────────┬──────────────────────┘
|
||||
│ API calls
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Your AI provider │
|
||||
│ (OpenAI / Anthropic / Gemini / …) │
|
||||
│ Your keys, your bill │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Project Status
|
||||
|
||||
**Current version: v0.2.3**
|
||||
|
||||
| Feature | Status |
|
||||
|---|---|
|
||||
| Multi-connection management | Stable |
|
||||
| Session list + creation | Stable |
|
||||
| Streaming chat | Stable |
|
||||
| Diff viewer | Stable |
|
||||
| Biometric unlock | Stable |
|
||||
| Tool call approval UI | Stable |
|
||||
| Sentry crash reporting (opt-in) | Stable |
|
||||
| Cloudflare / ngrok tunnel wizard | Beta |
|
||||
| opencode Cloud one-tap connect | Planned |
|
||||
| iPad / tablet layout | Planned |
|
||||
| Offline session history | Planned |
|
||||
|
||||
---
|
||||
|
||||
## Supporters and Sponsors
|
||||
|
||||
OpenCode Mobile is built and maintained by [VIBE TECHNOLOGIES, LLC](https://opencode.vibebrowser.app). GitHub Sponsors help cover Sentry, EAS Build, and CI costs (~$60/month). The opencode Cloud hosted backend (planned, $10/mo) is the long-term revenue model.
|
||||
|
||||
If OpenCode Mobile saves you time, consider sponsoring:
|
||||
|
||||
**[github.com/sponsors/VibeTechnologies](https://github.com/sponsors/VibeTechnologies)**
|
||||
|
||||
| Tier | Price | Perk |
|
||||
|---|---|---|
|
||||
| Supporter | $5/mo | Your name in `SUPPORTERS.md` |
|
||||
| Backer | $15/mo | Name + early access to opencode Cloud beta |
|
||||
| Business | $50/mo | Logo on [opencode.vibebrowser.app](https://opencode.vibebrowser.app) + quarterly support call |
|
||||
|
||||
Questions or private support: [support@vibebrowser.app](mailto:support@vibebrowser.app)
|
||||
|
||||
---
|
||||
|
||||
## Roadmap
|
||||
|
||||
Tracked on the [GitHub Projects board](https://github.com/dzianisv/opencode-mobile/projects) and in the [open milestones](https://github.com/dzianisv/opencode-mobile/milestones).
|
||||
|
||||
Near-term priorities:
|
||||
- opencode Cloud one-tap connect + managed hosting
|
||||
- F-Droid mainline acceptance (FCM audit + reproducible build verification)
|
||||
- Tunnel setup wizard (Cloudflare / ngrok / Tailscale)
|
||||
- iPad / tablet layout
|
||||
- Offline session history cache
|
||||
|
||||
---
|
||||
|
||||
## Contributing
|
||||
|
||||
This is part of the OpenCode monorepo. See the root README for contribution guidelines.
|
||||
We welcome bug reports, feature requests, and pull requests. See [CONTRIBUTING.md](CONTRIBUTING.md) for how to set up a dev environment and the contribution process.
|
||||
|
||||
---
|
||||
|
||||
## Privacy
|
||||
|
||||
OpenCode Mobile does not collect personal data. Optional Sentry crash reporting (opt-in, off by default) sends anonymised crash traces to Sentry. No analytics SDKs are bundled. Credentials are stored exclusively on-device in the OS keystore.
|
||||
|
||||
Full privacy policy: [opencode.vibebrowser.app/privacy](https://opencode.vibebrowser.app/privacy)
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT — see [LICENSE](LICENSE).
|
||||
|
||||
Copyright (c) 2026 VIBE TECHNOLOGIES, LLC
|
||||
|
||||
---
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
- [sst/opencode](https://github.com/sst/opencode) — the AI coding agent this app connects to (MIT)
|
||||
- [Expo](https://expo.dev) — the React Native toolchain powering the app
|
||||
- Every contributor who filed a bug, opened a PR, or starred the repo
|
||||
|
||||
Reference in New Issue
Block a user