Den 2b9b571d6e 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>
2026-05-25 17:42:03 -07:00

OpenCode Mobile

The open-source mobile client for the opencode AI coding agent. AI-assisted coding from your phone — iOS, Android, and F-Droid.

License: MIT Play Store App Store F-Droid IzzyOnDroid


OpenCode Mobile is a React Native / Expo app that brings the power of the 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.


Session list screen Chat screen with diff viewer Connection setup wizard


Features

  • 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

Get OpenCode Mobile

Platform Link
Google Play play.google.com — ai.opencode.mobile
Apple App Store apps.apple.com — OpenCode Mobile
F-Droid f-droid.org/packages/ai.opencode.mobile
IzzyOnDroid apt.izzysoft.de — ai.opencode.mobile

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

# Install opencode (if you haven't already)
npm install -g opencode

# Run opencode in server mode
OPENCODE_SERVER_PASSWORD=yourpassword opencode serve --hostname 0.0.0.0 --port 4096

Step 2 — Install OpenCode Mobile from any store above (or build from source — see CONTRIBUTING.md).

Step 3 — Add a connection in the app

Open the app, tap Add Connection, and choose your connection type:

  • 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

Enter the password you set in Step 1, tap Connect, and you're in.


How It Works

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.

┌─────────────────────────────────────┐
│         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. 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

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 + quarterly support call

Questions or private support: support@vibebrowser.app


Roadmap

Tracked on the GitHub Projects board and in the open 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

We welcome bug reports, feature requests, and pull requests. See 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


License

MIT — see LICENSE.

Copyright (c) 2026 VIBE TECHNOLOGIES, LLC


Acknowledgments

  • sst/opencode — the AI coding agent this app connects to (MIT)
  • Expo — the React Native toolchain powering the app
  • Every contributor who filed a bug, opened a PR, or starred the repo
Description
No description provided
Readme 17 MiB
Languages
TypeScript 49%
Python 20.5%
HTML 18.9%
JavaScript 8.8%
Kotlin 1.2%
Other 1.6%