Self-hosted iOS & Android simulator streaming for the whole team
605
stars
1,788
commits
TypeScript
primary language
Sep 10, 2026
updated
Run iOS simulators and Android emulators in any browser — no toolchain setup, no device pool, no cloud uploads.
Your builds, streams, and recordings stay on infrastructure you control.
No WebDriverAgent · 2-line setup · MIT
📖 Docs · 🚀 Quick Start · 🎥 Demo · 🎬 Setup
Streams over H.264 with a zero-buffer decoder (no MSE) — latency measurements ↗
v0.x, actively developed — backward-compatible by default; breaking changes are rare and always noted in the changelog. Roadmap →
Mobile QA usually depends on access to simulators, emulators, or physical devices — and that access is uneven across a team.
For mobile developers it means opening Xcode or Android Studio on a Mac. For everyone else, it often means asking a mobile developer every single time:
Backend developer — "How do I install the sandbox build to check what was deployed?"
Product manager — "I keep installing and removing versions just to compare behavior."
Designer — "I need to check the layout across screen sizes, but I don't have the right devices."
Physical devices add their own overhead — OS-version coverage, availability, charging, storage, handoff. Cloud simulator services solve access, but they require uploading internal builds to a third-party service and paying for remote devices while your own Macs can already run the same simulators.
We hit this exact problem, so we built tapflow.
| Solution | The catch |
|---|---|
| Appetize / BrowserStack | Recurring cost — and app builds are uploaded to a third-party cloud |
| Physical devices | Cost, availability, OS coverage, management overhead |
| Xcode / Android Studio | Each teammate needs a Mac and a full mobile toolchain |
| tapflow | Reuse your own Macs — data stays on infrastructure you control, and the whole team does QA from a browser |
tapflow connects three parts:
Browser (your team) ←─ WebSocket ─→ Relay Server ←─ WebSocket (outbound) ─→ Mac Agent
(Linux / Mac) (iOS · Android)
tapflow doesn't replace native mobile development tools. Mobile developers still use Xcode, Android Studio, and their build tooling. tapflow makes the running simulators and emulators accessible to the rest of the team through a browser, and it is not a device farm. It does have an automated QA axis — a deterministic flow runner and an MCP server for LLM agents — but wiring in external automation frameworks like WebDriverAgent or Appium is out of scope; tapflow ships its own minimal runner instead.
Where this is heading is laid out in VISION.md: growing manual QA into automation, only when you need it.
npm install -g tapflow
# or: yarn global add tapflow | pnpm add -g tapflow
On the Mac that will run an agent, install the simulator/emulator prerequisites in one step:
tapflow setup
Skip this on a relay-only server (Linux). See Environment Setup for details.
tapflow start
# ✓ Relay started on http://localhost:4000
# ✓ iOS Agent connected (3 simulators available)
This starts both the relay and the agent on the same Mac (local mode).
Open http://localhost:4000 in your browser. tapflow redirects you to /setup to create the admin account.
Headless server? Use
tapflow admin initto create the admin account via CLI instead.
Navigate to http://localhost:4000 and sign in with the account you just created.
Having issues? Run
tapflow doctorto re-check prerequisites at any time.
| Component | Requirements |
|---|---|
| Relay server | Node.js ≥ 22, any OS (Linux/macOS), ~512 MB RAM |
| iOS Agent | macOS, Xcode + iOS Simulator runtime (or run tapflow setup ios), Node.js ≥ 22 |
| Android Agent | macOS, Java + Android SDK with an AVD (or run tapflow setup android), Node.js ≥ 22 |
| Browser (QA) | Any modern browser — Chrome, Firefox, Safari, Edge |
Agents run on macOS only (they drive the iOS Simulator and Android emulator on a Mac). The relay runs anywhere.
What's included:
.app.zip / .apk and track builds by status (Backlog / In Progress / Done / Rejected).GET /api/v1/sessions/:sessionId/screenshot for CI and AI agents.@tapflowio/mcp-server lets Claude Code and other LLM agents control simulators as native tools.
1 On a real LAN, decode-to-present measures in the low tens of milliseconds (p50 ~11–17 ms with the WASM software decoder; faster with WebCodecs on HTTPS); end-to-end "glass-to-glass" latency adds your network's round trip on top. See the streaming latency log for the full measurements, conditions, and known limitations.
tapflow is self-hosted by design — build files, device streams, and session recordings stay on infrastructure you control, never sent to a third-party service.
| Data | Where it stays |
|---|---|
App binaries (.app.zip / .apk) | Relay storage |
| Device streams (video · touch) | The relay ↔ browser path you host |
| Session recordings | Relay storage; expire after 72h, then purged |
| Account & team data | The relay's SQLite DB |
| Third-party simulator cloud | Not required |
localhost). Browsers reaching it from elsewhere sign in; agents on another machine present an agent-scope token.builds:write for CI uploads, agent for remote agents), and team roles (Admin / Developer / QA / Viewer) govern dashboard access.Found a vulnerability? See SECURITY.md. For the full model, read Security & Privacy.
A single Mac needs nothing beyond tapflow start (see Quick Start). For a team, run the relay on a separate Linux server or dedicated Mac, and point each Mac agent at it.
Relay server:
# Recommended: PM2 for automatic restarts
npm install -g pm2 tapflow
JWT_SECRET=$(openssl rand -hex 32) pm2 start tapflow --name relay -- relay start
pm2 save && pm2 startup
Each Mac agent:
tapflow agent start --relay wss://your-relay-url --token <agent-token>
A relay on a different machine accepts an agent only with an
agent-scope token — create one in Settings → Tokens (Admin only). Agents on the relay's own machine (tapflow start) need no token. See Remote relay authentication.For nginx / Caddy reverse proxy setup and external access, see Self-Hosting the Relay.
| Command | Description |
|---|---|
tapflow start | Start relay + agent together (local mode) |
tapflow relay start | Start relay only |
tapflow agent start --relay <url> [--token <pat>] | Start agent and connect to a relay (remote relays need an agent-scope token) |
tapflow init | Scaffold tapflow.config.json |
tapflow admin init | Create the first admin account (CLI fallback) |
tapflow doctor [platform] | Diagnose prerequisites (Node, iOS, Android) |
tapflow setup [platform] | Install & configure the local environment |
tapflow devices | List available simulators and emulators |
tapflow boot <name|udid> | Boot a simulator or emulator |
tapflow status | Show connected agents, devices, active sessions |
tapflow reset | Shut down all simulators and emulators |
tapflow logs | Show recent relay log entries |
Full reference → CLI docs
Full docs: www.tapflow.dev
tapflow is actively developed and PRs are welcome — see CONTRIBUTING.md for branch strategy, commit conventions, and an architecture overview. For deep dives, the contributor notes cover the SimulatorKit reverse-engineering and the streaming render pipeline.
Requirements: Node.js ≥ 22, pnpm ≥ 9
git clone https://github.com/jo-duchan/tapflow.git
cd tapflow
pnpm install
pnpm dev
MIT — Copyright © 2026-present tapflow contributors
tapflow bundles scrcpy-server (Apache-2.0) for Android screen streaming. See NOTICE for full attribution.
TypeScript
84.8%
JavaScript
9.3%
Swift
4.0%
Self-hosted iOS & Android simulator streaming for the whole team
605
stars
1,788
commits
TypeScript
primary language
Sep 10, 2026
updated
Run iOS simulators and Android emulators in any browser — no toolchain setup, no device pool, no cloud uploads.
Your builds, streams, and recordings stay on infrastructure you control.
No WebDriverAgent · 2-line setup · MIT
📖 Docs · 🚀 Quick Start · 🎥 Demo · 🎬 Setup
Streams over H.264 with a zero-buffer decoder (no MSE) — latency measurements ↗
v0.x, actively developed — backward-compatible by default; breaking changes are rare and always noted in the changelog. Roadmap →
Mobile QA usually depends on access to simulators, emulators, or physical devices — and that access is uneven across a team.
For mobile developers it means opening Xcode or Android Studio on a Mac. For everyone else, it often means asking a mobile developer every single time:
Backend developer — "How do I install the sandbox build to check what was deployed?"
Product manager — "I keep installing and removing versions just to compare behavior."
Designer — "I need to check the layout across screen sizes, but I don't have the right devices."
Physical devices add their own overhead — OS-version coverage, availability, charging, storage, handoff. Cloud simulator services solve access, but they require uploading internal builds to a third-party service and paying for remote devices while your own Macs can already run the same simulators.
We hit this exact problem, so we built tapflow.
| Solution | The catch |
|---|---|
| Appetize / BrowserStack | Recurring cost — and app builds are uploaded to a third-party cloud |
| Physical devices | Cost, availability, OS coverage, management overhead |
| Xcode / Android Studio | Each teammate needs a Mac and a full mobile toolchain |
| tapflow | Reuse your own Macs — data stays on infrastructure you control, and the whole team does QA from a browser |
tapflow connects three parts:
Browser (your team) ←─ WebSocket ─→ Relay Server ←─ WebSocket (outbound) ─→ Mac Agent
(Linux / Mac) (iOS · Android)
tapflow doesn't replace native mobile development tools. Mobile developers still use Xcode, Android Studio, and their build tooling. tapflow makes the running simulators and emulators accessible to the rest of the team through a browser, and it is not a device farm. It does have an automated QA axis — a deterministic flow runner and an MCP server for LLM agents — but wiring in external automation frameworks like WebDriverAgent or Appium is out of scope; tapflow ships its own minimal runner instead.
Where this is heading is laid out in VISION.md: growing manual QA into automation, only when you need it.
npm install -g tapflow
# or: yarn global add tapflow | pnpm add -g tapflow
On the Mac that will run an agent, install the simulator/emulator prerequisites in one step:
tapflow setup
Skip this on a relay-only server (Linux). See Environment Setup for details.
tapflow start
# ✓ Relay started on http://localhost:4000
# ✓ iOS Agent connected (3 simulators available)
This starts both the relay and the agent on the same Mac (local mode).
Open http://localhost:4000 in your browser. tapflow redirects you to /setup to create the admin account.
Headless server? Use
tapflow admin initto create the admin account via CLI instead.
Navigate to http://localhost:4000 and sign in with the account you just created.
Having issues? Run
tapflow doctorto re-check prerequisites at any time.
| Component | Requirements |
|---|---|
| Relay server | Node.js ≥ 22, any OS (Linux/macOS), ~512 MB RAM |
| iOS Agent | macOS, Xcode + iOS Simulator runtime (or run tapflow setup ios), Node.js ≥ 22 |
| Android Agent | macOS, Java + Android SDK with an AVD (or run tapflow setup android), Node.js ≥ 22 |
| Browser (QA) | Any modern browser — Chrome, Firefox, Safari, Edge |
Agents run on macOS only (they drive the iOS Simulator and Android emulator on a Mac). The relay runs anywhere.
What's included:
.app.zip / .apk and track builds by status (Backlog / In Progress / Done / Rejected).GET /api/v1/sessions/:sessionId/screenshot for CI and AI agents.@tapflowio/mcp-server lets Claude Code and other LLM agents control simulators as native tools.
1 On a real LAN, decode-to-present measures in the low tens of milliseconds (p50 ~11–17 ms with the WASM software decoder; faster with WebCodecs on HTTPS); end-to-end "glass-to-glass" latency adds your network's round trip on top. See the streaming latency log for the full measurements, conditions, and known limitations.
tapflow is self-hosted by design — build files, device streams, and session recordings stay on infrastructure you control, never sent to a third-party service.
| Data | Where it stays |
|---|---|
App binaries (.app.zip / .apk) | Relay storage |
| Device streams (video · touch) | The relay ↔ browser path you host |
| Session recordings | Relay storage; expire after 72h, then purged |
| Account & team data | The relay's SQLite DB |
| Third-party simulator cloud | Not required |
localhost). Browsers reaching it from elsewhere sign in; agents on another machine present an agent-scope token.builds:write for CI uploads, agent for remote agents), and team roles (Admin / Developer / QA / Viewer) govern dashboard access.Found a vulnerability? See SECURITY.md. For the full model, read Security & Privacy.
A single Mac needs nothing beyond tapflow start (see Quick Start). For a team, run the relay on a separate Linux server or dedicated Mac, and point each Mac agent at it.
Relay server:
# Recommended: PM2 for automatic restarts
npm install -g pm2 tapflow
JWT_SECRET=$(openssl rand -hex 32) pm2 start tapflow --name relay -- relay start
pm2 save && pm2 startup
Each Mac agent:
tapflow agent start --relay wss://your-relay-url --token <agent-token>
A relay on a different machine accepts an agent only with an
agent-scope token — create one in Settings → Tokens (Admin only). Agents on the relay's own machine (tapflow start) need no token. See Remote relay authentication.For nginx / Caddy reverse proxy setup and external access, see Self-Hosting the Relay.
| Command | Description |
|---|---|
tapflow start | Start relay + agent together (local mode) |
tapflow relay start | Start relay only |
tapflow agent start --relay <url> [--token <pat>] | Start agent and connect to a relay (remote relays need an agent-scope token) |
tapflow init | Scaffold tapflow.config.json |
tapflow admin init | Create the first admin account (CLI fallback) |
tapflow doctor [platform] | Diagnose prerequisites (Node, iOS, Android) |
tapflow setup [platform] | Install & configure the local environment |
tapflow devices | List available simulators and emulators |
tapflow boot <name|udid> | Boot a simulator or emulator |
tapflow status | Show connected agents, devices, active sessions |
tapflow reset | Shut down all simulators and emulators |
tapflow logs | Show recent relay log entries |
Full reference → CLI docs
Full docs: www.tapflow.dev
tapflow is actively developed and PRs are welcome — see CONTRIBUTING.md for branch strategy, commit conventions, and an architecture overview. For deep dives, the contributor notes cover the SimulatorKit reverse-engineering and the streaming render pipeline.
Requirements: Node.js ≥ 22, pnpm ≥ 9
git clone https://github.com/jo-duchan/tapflow.git
cd tapflow
pnpm install
pnpm dev
MIT — Copyright © 2026-present tapflow contributors
tapflow bundles scrcpy-server (Apache-2.0) for Android screen streaming. See NOTICE for full attribution.
TypeScript
84.8%
JavaScript
9.3%
Swift
4.0%