# TV ADB Remote A slick, installable web remote for Android TV, controlled over ADB. Run a small Node server on any always-on machine on your home network (a Pi, NAS, old laptop, home server); point your phone's browser at it and control the TV from a mobile-optimized PWA. Why a local web app instead of a native Android app: Android TV only exposes control over ADB once you enable network debugging, and the official ADB tooling is a desktop program. Rather than reimplement the ADB protocol inside a phone app, this runs `adb` on a machine that already has it, and serves a touch-friendly remote UI to any phone/tablet browser on the LAN. Add to the home screen and it behaves like an installed app. ## Features - Power, mute, input switch, volume rocker, channel rocker - D-pad navigation, OK, back, home, menu - Media transport (rewind / play-pause / fast-forward) - Text entry (e.g. search boxes) sent as real keystrokes - One-tap launch for common streaming apps (Netflix, YouTube, Prime Video, Disney+, Spotify, Plex) - Manage multiple TVs, each remembered with a friendly name - Built-in pairing flow for Android 11+ ("Wireless debugging") - Installable PWA with offline app shell ## Requirements - Docker and Docker Compose on any always-on machine on your home network (a Pi, NAS, old laptop, home server). - The TV and that machine on the same local network. `adb` does **not** need to run on bare metal — it's a plain TCP client that dials out to the TV's IP once network/wireless debugging is on, so it works fine from inside a container with normal bridge networking. No host networking, USB passthrough, or privileged mode required. The container image bundles `adb` itself, so nothing else needs installing on the host. ## Set up the TV 1. On the Android TV: Settings → System (or Device Preferences) → About → tap "Build" repeatedly to enable Developer options. 2. Settings → Developer options → turn on **Network debugging** (older Android TV) or **Settings → System → Developer options → Wireless debugging** (Android 11+ / Google TV). 3. Note the IP address shown (Settings → Network & Internet). - Android TV ≤ 10: that's it — the debug port (5555) is open. - Android 11+ / Google TV: it shows a separate pairing IP:port and a 6-digit code. Use the app's "Pair a new Android 11+ TV" flow, then add the TV using its regular IP (still port 5555 once paired). ## Run the server ```sh docker compose up -d --build ``` This serves the app at `http://:8787`. Open that URL on your phone, add your TV by IP in Settings (⚙), then optionally "Add to Home Screen" for a full-screen, app-like remote. Saved TVs persist in `./data/devices.json` on the host (bind-mounted into the container), so they survive `docker compose down`/rebuilds. Override the port by changing the `PORT` environment variable and the left side of the `ports` mapping in `docker-compose.yml`. ### Adding this as a service in another docker-compose stack If you're folding this into a larger compose project rather than running it standalone, you have two straightforward options: 1. **Vendor the source** (git submodule or subtree at, say, `services/tv-adb-remote/`) and point that stack's compose file at it: ```yaml services: tv-adb-remote: build: ./services/tv-adb-remote ports: - "8787:8787" volumes: - ./services/tv-adb-remote/data:/app/data restart: unless-stopped ``` 2. **Build and push an image** (e.g. to GHCR or Docker Hub) from this repo's CI, then reference it by tag instead of a build context — no vendored source in the other repo at all: ```yaml services: tv-adb-remote: image: ghcr.io//tv-adb-remote:latest ports: - "8787:8787" volumes: - ./tv-adb-remote-data:/app/data restart: unless-stopped ``` This fits a "docker nearly exclusively" stack best if most of its other services are already referenced as prebuilt images rather than local build contexts — ask if you want a GitHub Actions workflow added here to publish the image on push. Either way, the only two things the other repo's compose file needs to get right are the port mapping and a persistent volume for `/app/data`. ## Development ```sh cd server npm install npm test ``` Runs the server's unit tests (command construction, input validation, device persistence) using Node's built-in test runner — no real TV, and no Docker, required. Useful for iterating on server code before rebuilding the image. ## Project layout ``` Dockerfile Bundles adb + the server into one image docker-compose.yml Standalone run config (port 8787, data/ volume) server/ Express app + ADB bridge (source of truth for control logic) src/adb.js Thin wrapper around the `adb` CLI (connect/pair/keyevent/…) src/keycodes.js Android KeyEvent constants used by the remote buttons src/deviceStore.js Persists saved TVs to data/devices.json src/index.js HTTP API + static file serving test/ Node test runner specs public/ The PWA served to phones (HTML/CSS/vanilla JS, no build step) scripts/ One-off dev scripts (icon generation) ``` ## Security note This server has no authentication and will happily run `adb` commands against whatever IP you give it — it's designed to sit on your trusted home LAN, not the public internet. Don't port-forward it.