Your Access (to) Real Devices.
A device farm for real Android and iOS hardware - live video, touch and keyboard input, app install, clipboard, screenshots, reservations, and adb remote debugging, all from a browser. Plug phones into a machine anywhere, and they show up as something a whole team can book and use over the network.
It takes most of its inspiration from STF, which proved the idea. The iOS device layer comes from stf-ios-provider, an earlier attempt at bolting iOS support onto STF, which is what this project grew out of.
The system is two pieces. The coordinator owns identity, inventory, reservations and policy; the providers own devices and all high-bandwidth traffic.
browser ---- tRPC ----> coordinator <---- WSS ---- provider ---- USB ---> devices
\_________________ WSS + HTTPS _________________/
- A provider is a small Rust daemon on whatever machine the phones are plugged into. It talks to iOS over CoreDevice and to Android over adb, and dials out to the coordinator, so it needs no inbound reachability and works fine behind NAT.
- The coordinator is the thing everyone logs into. It holds users, the device list, reservations and the audit log in Postgres, and signs the short-lived tokens that let a browser open a session.
- Video and input go browser to provider directly, over a WebSocket the provider serves and authorises itself against the coordinator's public keys. The coordinator is never on the data path.
- Uploads take that same direct path and are never stored: an APK or IPA streams to the provider, gets installed, and is deleted. The only trace is an audit-log row.
docs/ARCHITECTURE.md has the detail.
![]() |
![]() |
Android. A live screen with hardware keys, rotate, screenshot and record, APK install, file browsing and clipboard in both directions.
![]() |
![]() |
iOS. The same session, the same controls. Either platform can be popped out into its own window, so a device sits beside whatever it is being used to test.
Everything is logged - reservations and releases, installs, cleanups, setting changes, admin actions.
Verified against real hardware: an iPhone 13 on iOS 27 (beta) and a Galaxy S22 on Android both reserve, stream to a browser, and take touch and keyboard input - through the containerised stack, with the coordinator nowhere near the video.
It also runs with no hardware at all: the Rust provider ships a mock backend
that registers, reserves, streams synthetic video and accepts input and
uploads, and packages/protocol/test/fake-provider.ts does the same one layer
up.
cp .env.example .env # set AUTH_SECRET (openssl rand -base64 32)
bun install
docker compose -f docker-compose.dev.yml up -d
bun run db:migrate
bun run devThen http://localhost:5173. Full instructions, including the first-admin bootstrap, are in docs/DEVELOPMENT.md.
packages/
├── db/ drizzle schema, migrations, client
├── coordinator/ Hono + tRPC + better-auth + provider gateway
├── web/ TanStack Router SPA + shadcn
├── protocol/ zod schemas + Rust codegen + fake provider
└── provider/ cargo workspace: yard-protocol, provider-core,
backend-mock, yard-provider (ios, android)
| ARCHITECTURE.md | The four planes and why they're separate |
| DATA-MODEL.md | Tables and their invariants |
| COORDINATOR.md | Backend package |
| WEB.md | Frontend package |
| PROVIDER.md | Rust provider design |
| PROTOCOL.md | Wire contract |
| CLEANUP.md | Resetting a device between users |
| DEVELOPMENT.md | Setup, commands, conventions |
docs/REFERENCES.local.md covers the STF sources kept on disk outside this
repo, and what to read in them. It's local-only and not committed.
Bun · Hono · tRPC v11 · better-auth · Drizzle + Postgres · TanStack Router + Query · shadcn/ui + Tailwind v4 · Rust (tokio) for providers · Caddy · Docker.





