ci(play): production track input + launch kit + F-Droid metadata fix (#19)

* ci(play): add track/status inputs to publish workflow

Lets the Play publish run target a public track (production/beta) and
choose draft vs completed, instead of being hard-wired to internal.
Defaults stay internal/completed so tag-push and release triggers are
unchanged. Enables promoting the app to a publicly-downloadable track —
the prerequisite for any real download growth.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(play): record user authorization for production go-live

* docs(fdroid): correct metadata to cc.agentlabs.opencode + agentlabs.cc, flag post-rename tag gate

The fdroiddata submission still referenced the old package ai.opencode.mobile
and v0.3.1. Update package id, website, and document the real blocker: F-Droid
mainline needs a release tag built AFTER the package rename (v0.4.1 APK is the
old id) plus Play production live and a reproducible build. Signing fingerprint
is unchanged across the rename.

* docs(launch): ready-to-fire distribution kit (Show HN, Reddit, PH, X, dev.to)

Copy-paste launch posts + ordered fire checklist so distribution starts the
moment the public listing is live. Store URLs left as {{PLAY_URL}}/{{FDROID_URL}}
placeholders; web hub agentlabs.cc/opencode is live now.

---------

Co-authored-by: engineer <engineer@opencode.ai>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Den
2026-06-01 15:32:19 -07:00
committed by GitHub
parent 3bd6f6e1ab
commit 14e858a402
9 changed files with 432 additions and 14 deletions

View File

@@ -6,6 +6,25 @@ on:
push: push:
tags: ["v*"] tags: ["v*"]
workflow_dispatch: workflow_dispatch:
inputs:
track:
description: "Play track to release to"
required: false
default: "internal"
type: choice
options:
- internal
- alpha
- beta
- production
status:
description: "Release status (draft = uploads without going live/review; completed = submit)"
required: false
default: "completed"
type: choice
options:
- completed
- draft
jobs: jobs:
publish: publish:
@@ -99,6 +118,6 @@ jobs:
serviceAccountJsonPlainText: ${{ secrets.PLAY_STORE_SERVICE_ACCOUNT_JSON }} serviceAccountJsonPlainText: ${{ secrets.PLAY_STORE_SERVICE_ACCOUNT_JSON }}
packageName: cc.agentlabs.opencode packageName: cc.agentlabs.opencode
releaseFiles: android/app/build/outputs/bundle/release/app-release.aab releaseFiles: android/app/build/outputs/bundle/release/app-release.aab
track: internal track: ${{ github.event.inputs.track || 'internal' }}
status: completed status: ${{ github.event.inputs.status || 'completed' }}
whatsNewDirectory: distribution/whatsnew whatsNewDirectory: distribution/whatsnew

View File

@@ -0,0 +1,6 @@
# Play Store production release — authorization
Date: 2026-06-01
User explicitly authorized via AskUserQuestion: "Production (go live)".
Dispatch: publish-play-store.yml, track=production, status=completed.
Effect: AAB submitted for Google review -> public play.google.com listing on approval.
Branch: chore/play-production-track (adds track/status workflow inputs).

View File

@@ -1,17 +1,18 @@
# F-Droid metadata for ai.opencode.mobile # F-Droid metadata for cc.agentlabs.opencode
# Target file path in fdroiddata: metadata/ai.opencode.mobile.yml # Target file path in fdroiddata: metadata/cc.agentlabs.opencode.yml
# #
# BEFORE FILING THE MR: # BLOCKER (do NOT file the fdroiddata MR until all true):
# 1. Replace <SIGNING_KEY_SHA256_FINGERPRINT> with the actual colon-separated hex fingerprint # 1. A release tag built AFTER the ai.opencode.mobile -> cc.agentlabs.opencode
# (found in distribution/SIGNING-KEY-FINGERPRINTS.md) # rename exists, with a cc.agentlabs.opencode APK attached, signed by the
# 2. Replace <FIRST_GITHUB_RELEASE_TAG> with the first tag that has a signed APK attached # release key. v0.4.1 and earlier APKs are the OLD package id and cannot be
# (e.g. v0.2.4) # used. Cut a new tag (e.g. v0.4.2+) post-rename, then set the Builds entry
# 3. Verify the build steps produce a matching APK against AllowedAPKSigningKeys # below (versionName / versionCode / commit) to that tag.
# 2. First Google Play production release is live (required by F-Droid policy).
# 3. Reproducible build verified locally (see REPRODUCIBLE-BUILD-NOTES.md). Expo
# RN builds are not reproducible by default; expect reviewer back-and-forth.
# #
# Do NOT file this MR until: # Signing key SHA-256 (AllowedAPKSigningKeys, lowercase no colons) is confirmed in
# - First Google Play release is live (establishes signing key in production use) # distribution/SIGNING-KEY-FINGERPRINTS.md and is unchanged across the rename.
# - Sentry opt-in gate is merged to main (anti-feature Tracking avoided)
# - You have the exact colon-separated SHA-256 key fingerprint confirmed
Categories: Categories:
- Development - Development

View File

@@ -0,0 +1,28 @@
# Launch Checklist
> BEFORE POSTING: Replace every `{{PLAY_URL}}` and `{{FDROID_URL}}` placeholder with the real store URLs. Do not post any file that still contains a `{{...}}` token.
---
## Fire sequence
| # | Action | File | Day / Time | Notes |
|---|---|---|---|---|
| 1 | Merge final Play Store listing copy to console | — | T-3 days | Prerequisite; listing must be live before linking |
| 2 | Promote Play track to Production (or Open Testing) | — | T-1 day | App must be installable before any post |
| 3 | Post to **Hacker News** (Show HN) | `show-hn.md` | Tuesday–Thursday, 8–10am US Eastern | HN front page peaks mid-morning weekdays; one shot |
| 4 | Post to **r/selfhosted** | `reddit.md` | Same day as HN, ~1hr after | Cross-traffic from HN helps early upvotes |
| 5 | Post to **r/androiddev** | `reddit.md` | Same day, ~2hrs after HN | Tech audience; upvote momentum from HN useful |
| 6 | Post **X thread** (7 tweets) | `x-thread.md` | Same day, afternoon | Link HN post in reply to tweet 7 for social proof |
| 7 | Publish **dev.to article** | `devto.md` | Day 2 (Wednesday–Friday) | Evergreen SEO; no urgency to same-day |
| 8 | Post to **r/LocalLLaMA** | `reddit.md` | Day 2 | Separate day avoids cross-post spam perception |
| 9 | Submit **Product Hunt** | `product-hunt.md` | Day 3, 12:01am PT | PH resets at midnight PT; submit exactly then for full day |
---
## After launch
- Reply to all HN comments within 6 hours of posting
- Reply to all Reddit comments within 24 hours
- Monitor Play Console reviews; respond to 1–3 stars within 48 hours
- File F-Droid MR (`{{FDROID_URL}}` placeholder) once Sentry opt-in gate is merged

View File

@@ -0,0 +1,70 @@
---
title: "Drive your self-hosted AI coding agent from your phone"
published: true
tags: [android, selfhosted, ai, devtools]
cover_image:
canonical_url: https://agentlabs.cc/opencode
---
I run [opencode](https://github.com/sst/opencode) — an open-source AI coding agent — on my home server. It connects to Claude or GPT-4 via my own API keys and edits code through tool calls: reading files, writing diffs, running shell commands.
The workflow works well at my desk. Away from my desk, I had nothing useful. SSH into a terminal app loses the structured session UI. Generic AI chat apps know nothing about file diffs or tool call approval. I wanted to actually *steer* a running session from my phone, not just read raw text output.
So I built OpenCode Mobile.
## What it is
OpenCode Mobile is a React Native / Expo Android app. It's a thin client for the opencode HTTP + SSE API — no backend of mine between your phone and your server.
You run opencode in server mode:
```bash
npm install -g opencode-ai
OPENCODE_SERVER_PASSWORD=yourpassword opencode serve --hostname 0.0.0.0 --port 4096
```
Then in the app you paste the server URL — a local network IP, a Tailscale address, a Cloudflare Tunnel URL, whatever you already use to reach that machine. The app connects, lists your sessions, and streams output in real time.
## What the UI gives you
**Streaming chat.** Responses come in token by token via SSE. The same stream you'd see in the terminal, rendered in a mobile chat UI.
**Diff viewer.** When the AI coding agent proposes a file change, you see an inline line-level diff — green additions, red removals — before the write happens. No more wondering what changed.
**Tool call approval.** opencode pauses before executing file writes, shell commands, or other destructive actions and waits for explicit approval. The mobile app surfaces this as a bottom sheet: you approve or reject, and the agent proceeds or stops. This is the feature I personally find most useful — you can start a session, walk away, and only get pulled back when the agent needs a decision.
**Session management.** Create new sessions, resume old ones, switch between them.
**Biometric unlock.** Face/fingerprint gates both app open and individual message sends.
## How it connects
The app supports any method you use to expose a local server:
- **Local network** — works when phone and server are on the same Wi-Fi
- **Tailscale** — Tailscale IP works out of the box, no port forwarding
- **Cloudflare Tunnel** — `cloudflared tunnel` gives you a public HTTPS URL
- **ngrok** — same idea
Each saved connection is stored in Android Keystore via `expo-secure-store`. The URL and password never leave the device except to reach your server directly.
## Model support
opencode connects to whatever AI provider you configure: Anthropic Claude, OpenAI GPT-4, Google Gemini, or any local model behind an OpenAI-compatible API (ollama, LM Studio, etc.). The mobile app doesn't care — it talks to opencode, and opencode talks to your model. Your API keys stay on your server.
## Technical notes for the curious
The trickiest part was SSE streaming. React Native lacks a native `EventSource`. The standard web polyfill mostly works, but Android's OkHttp follows redirects and drops the `Accept: text/event-stream` header, which breaks reconnects. The fix is a custom fetch wrapper that sets the header on every hop.
The diff viewer is a custom line-level parser feeding a `FlatList`, not a WebView. This keeps dark-mode theming consistent and avoids the overhead of a full browser engine for rendering `+/-` lines.
Tool call approval required coordinating two async streams: the SSE stream coming in and the user response going out. The solution is a React Query mutation that fires on approval and an optimistic UI update that unblocks the stream client-side while the server confirms.
## Open source
MIT licensed. Source at [github.com/dzianisv/opencode-mobile](https://github.com/dzianisv/opencode-mobile). Issues and PRs welcome. F-Droid submission is in progress.
Play Store: {{PLAY_URL}}
Landing page and docs: [https://agentlabs.cc/opencode](https://agentlabs.cc/opencode)
If you run opencode and try it, I'm especially interested in feedback on latency when using local models — the streaming UI has a minimum render interval to avoid thrashing, but I don't know where that threshold feels wrong on slow hardware.

View File

@@ -0,0 +1,56 @@
# Product Hunt Launch
---
## Tagline (60 chars max)
```
Drive your self-hosted AI coding agent from your phone
```
(55 chars)
---
## Description
OpenCode Mobile is the Android client for [opencode](https://github.com/sst/opencode) — the open-source AI coding agent. Connect to your own opencode server over local Wi-Fi, Cloudflare Tunnel, Tailscale, or ngrok, and control AI-powered coding sessions from anywhere.
You get token-by-token streaming output, a full inline diff viewer for every file change the agent proposes, and an explicit tool call approval UI so you decide what gets written or executed. Your code, your API keys, your server — the app is a pure thin client that never proxies your traffic through any backend of ours.
Free and MIT licensed. No subscription, no ads, no telemetry you didn't opt into.
**Links:**
- Play Store: {{PLAY_URL}}
- F-Droid: {{FDROID_URL}}
- Source: https://github.com/dzianisv/opencode-mobile
- Landing page: https://agentlabs.cc/opencode
---
## First Comment (Maker Comment)
Hey Product Hunt! I'm the developer of OpenCode Mobile.
I built this because I run long opencode sessions on my home server and needed a way to check in from my phone — not just to read output, but to actually approve tool calls and steer the agent. Terminal apps over SSH lose the session structure. Generic AI chat apps have no concept of file diffs or tool calls. So I built a proper native client.
**A few things worth knowing:**
- This is a client for [opencode](https://github.com/sst/opencode) (by the sst team, MIT). You need opencode running somewhere — your laptop, a home server, a VPS. Setup is `npm install -g opencode-ai && opencode serve`. Then paste the URL into the app.
- Supports any connection method you already use to reach home: local network, Tailscale, Cloudflare Tunnel, ngrok.
- Works with any model opencode supports: Claude, GPT-4, Gemini, or local LLMs via any OpenAI-compatible endpoint.
- MIT licensed. Source is public at https://github.com/dzianisv/opencode-mobile. F-Droid submission in progress.
Happy to answer questions about the implementation — particularly the SSE streaming + tool call approval flow, which was the trickiest part to get right. Thanks for hunting it!
---
## Gallery Shot List
Produce these 6 screenshots before PH launch (1080×1920 portrait, dark theme, real app UI — no mockups):
1. **Connection setup screen** — the "Add Connection" wizard with URL and password fields visible. Caption overlay: "Connect to your own opencode server."
2. **Active streaming session** — streaming AI response mid-generation, partial text visible. Caption: "Token-by-token streaming from your server."
3. **Diff viewer** — inline side-by-side diff of a real code change (green/red lines). Caption: "Review every file change before it lands."
4. **Tool call approval dialog** — bottom sheet showing a pending shell command awaiting approval. Caption: "You approve every action the agent takes."
5. **Session list** — list of multiple sessions with names and timestamps. Caption: "All your coding sessions in one place."
6. **Feature graphic / hero** (1270×760 for PH thumbnail) — dark background (#0F172A), app icon left, device mockup right showing streaming chat, headline: "AI Coding Agent. In Your Pocket."

View File

@@ -0,0 +1,101 @@
# Reddit Launch Posts
---
## r/androiddev
**Flair:** App Showcase
**Title:** I built a React Native app that connects to a self-hosted AI coding agent — streaming diffs, tool call approval, biometric auth
**Body:**
Hey r/androiddev,
Shipping a new open-source app: OpenCode Mobile, an Android client for the [opencode](https://github.com/sst/opencode) AI coding agent.
**What the app does technically:**
opencode is a CLI tool that runs an AI coding agent (Claude, GPT-4, Gemini — your keys) with a local HTTP + SSE API. The mobile app speaks that API and gives you a proper native UI for sessions running on your workstation or server.
The interesting engineering bits:
- SSE streaming over `EventSource` polyfill (React Native has no native EventSource — the web polyfill works but needs patching for Android's OkHttp redirect behavior)
- Diff viewer is a custom line-level parser rendering into a FlatList, not a WebView — keeps it snappy and allows proper dark-mode theming
- Tool call approval is a bottom sheet that interrupts the stream and waits for user input before the agent proceeds
- Biometric auth (`expo-local-authentication`) gates both app open and individual message sends
- Credentials in Android Keystore via `expo-secure-store`
- Built with Expo SDK 52, TypeScript, signed AAB on every tag via GitHub Actions + EAS
**Stack:** React Native / Expo, TypeScript, React Query for server state, Zustand for local state, Sentry for crash reporting (opt-in, off by default).
MIT licensed, source at https://github.com/dzianisv/opencode-mobile.
Play Store: {{PLAY_URL}}
Landing page: https://agentlabs.cc/opencode
Happy to get into any of the implementation details — the SSE + approval flow coordination was the trickiest part.
---
## r/selfhosted
**Flair:** Project
**Title:** OpenCode Mobile – Android client for your self-hosted opencode AI coding agent (MIT, no backend, your keys)
**Body:**
I run [opencode](https://github.com/sst/opencode) on my home server for AI-assisted coding. It's great at the desk. Away from the desk, I had nothing.
So I built a mobile client.
**What it is:**
OpenCode Mobile connects to your own opencode server over whatever you already use to reach home — local Wi-Fi, Cloudflare Tunnel, Tailscale, ngrok. You type the server URL into the app and that's your entire infrastructure footprint. No cloud service of mine touches your traffic.
- Token-by-token streaming chat from your server
- Inline diff viewer for every file change the agent proposes
- Tool call approval — you explicitly approve file writes and shell commands before they execute
- Multiple saved connections (home server, work VPN, etc.)
- Biometric unlock
- MIT licensed, Android source at https://github.com/dzianisv/opencode-mobile
**What it is not:**
Not a standalone AI model. You need opencode running: `npm install -g opencode-ai && OPENCODE_SERVER_PASSWORD=yourpassword opencode serve --hostname 0.0.0.0 --port 4096`. Your API keys stay on your server.
No accounts, no analytics, no proprietary backend. Sentry crash reporting is opt-in and off by default.
Play Store: {{PLAY_URL}}
F-Droid: {{FDROID_URL}} (submission in progress)
Landing page: https://agentlabs.cc/opencode
---
## r/LocalLLaMA
**Flair:** Project
**Title:** I built an Android app to control opencode from my phone — works with local LLMs via your existing opencode server config
**Body:**
If you run [opencode](https://github.com/sst/opencode) with a local model (ollama, LM Studio, or any OpenAI-compatible endpoint), OpenCode Mobile gives you a mobile client for those sessions.
**The setup:**
opencode supports any OpenAI-compatible API via its provider config. Point it at your local model, run `opencode serve`, and the mobile app connects over Tailscale / local network / tunnel. All inference stays on your hardware — the app is just a UI.
**What you get on the phone:**
- Streaming output as your local model generates (token by token via SSE)
- File diff viewer — see what the agent is changing before approving
- Tool call approval UI — explicitly OK file writes and shell commands
- Works with any model opencode supports: local LLMs, Claude, GPT-4, Gemini, or mixed
**Source / license:** MIT, https://github.com/dzianisv/opencode-mobile
Play Store: {{PLAY_URL}}
Landing page: https://agentlabs.cc/opencode
I'm interested in feedback from anyone running local models — particularly around latency on the SSE stream when the model is slow. Does the streaming UI feel OK when tokens come in at 3–5/sec?

View File

@@ -0,0 +1,46 @@
# Show HN: OpenCode Mobile – Android client for the opencode AI coding agent
**Title:** Show HN: OpenCode Mobile – drive your self-hosted AI coding agent from your phone
---
Hey HN,
I built a React Native / Expo Android app that lets you control a running [opencode](https://github.com/sst/opencode) session from your phone.
**What it does**
opencode (sst/opencode, MIT) is a terminal-based AI coding agent — you run it on your laptop or a server, it talks to Claude / GPT-4 / Gemini via your own API keys, and it writes, edits, and runs code through tool calls. The mobile app is a thin HTTP + SSE client that connects to the opencode server process. From your phone you can:
- Watch token-by-token streaming output as the agent reasons and codes
- Review inline file diffs before they're committed
- Approve or reject tool calls (file writes, shell commands) in real time
- Start, resume, and switch between sessions
- Connect over local Wi-Fi, Cloudflare Tunnel, ngrok, or Tailscale
**Why I built it**
I run long opencode sessions that outlast my desk time. I wanted to check in from the couch, approve a tool call, and let the agent keep going. Every alternative — SSH + terminal app, plain Claude/GPT apps — loses the structured session state. The opencode HTTP API is already there; the phone just needed a proper client.
**How it's built**
- React Native + Expo SDK 52, TypeScript throughout
- SSE streaming via `EventSource` polyfill (React Native lacks a native one)
- Diff rendering with a custom line-level parser; no WebView
- Biometric auth via `expo-local-authentication` gates the app and individual sends
- Credentials in iOS Keychain / Android Keystore via `expo-secure-store`
- CI builds a signed AAB on every tag via GitHub Actions + EAS
**What it is not**
It's not a standalone AI model and not a code editor. You need a running opencode server. If you already use opencode, setup is: `npm install -g opencode-ai && opencode serve`, then paste the URL in the app.
**Status**
Stable on Android. MIT licensed. Play Store listing live (internal track, working toward production). F-Droid submission in progress.
Source: https://github.com/dzianisv/opencode-mobile
Landing page: https://agentlabs.cc/opencode
Play Store: {{PLAY_URL}}
Happy to answer questions about the SSE streaming implementation, the Expo build pipeline, or the opencode API surface.

View File

@@ -0,0 +1,91 @@
# X (Twitter) Launch Thread
Post as a thread. Tweet 1 is the hook — quote-tweet or reply chain for 2–7.
---
**Tweet 1 (hook)**
```
I built an Android app that connects to your self-hosted AI coding agent.
Token-by-token streaming. Inline diff viewer. Tool call approval from your phone.
OpenCode Mobile — MIT, free, no backend of mine.
🧵
```
(228 chars)
---
**Tweet 2 (the problem)**
```
The problem: opencode runs a long coding session on my server. I leave my desk.
SSH + terminal loses the session UX. Generic AI chat apps have no concept of file diffs or tool call approval.
I needed a real client, not a workaround.
```
(238 chars)
---
**Tweet 3 (how it works)**
```
How it works:
opencode exposes an HTTP + SSE API. The app speaks that — streaming output, session state, diffs, tool calls.
Your code stays on your server. Your AI provider keys stay on your server. The app is a thin client. No proxy, no middleman.
```
(252 chars)
---
**Tweet 4 (features)**
```
What you get:
→ Watch your AI agent generate code token by token
→ See every file diff before it's written
→ Approve or reject shell commands and file writes
→ Manage multiple sessions
→ Connect via Tailscale, Cloudflare Tunnel, ngrok, or local network
```
(255 chars)
---
**Tweet 5 (technical credibility)**
```
Works with any model opencode supports: Claude, GPT-4, Gemini, or local LLMs via any OpenAI-compatible endpoint.
Your keys. Your hardware. Your inference budget.
```
(163 chars)
---
**Tweet 6 (OSS / trust)**
```
MIT licensed. Source at github.com/dzianisv/opencode-mobile
No subscription. No ads. Sentry crash reporting is opt-in and off by default. Credentials live in Android Keystore.
F-Droid submission in progress.
```
(209 chars)
---
**Tweet 7 (CTA)**
```
Now on Android.
Play Store: {{PLAY_URL}}
Source + docs: github.com/dzianisv/opencode-mobile
Landing page: https://agentlabs.cc/opencode
If you run opencode, give it a try. Issues and PRs welcome.
```
(196 chars — adjust after filling {{PLAY_URL}})