@relictombs/opencode-android
v0.2.0
Published
OpenCode TUI plugin for presenting, controlling, and running Expo apps on one Android Emulator
Downloads
96
Maintainers
Readme
Relictombs Android
Run, present, inspect, and control Expo apps on one Android Emulator from the OpenCode V2 TUI. OpenCode starts without booting Android; an explicit human or agent action creates one owned headless emulator, and the sidebar attaches to that same runtime. Human input, screenshots, accessibility snapshots, agent actions, and Expo all target the same device.
Requirements
- macOS on Apple Silicon for the provided Android setup target.
- Node.js 24 or newer with npm. Bun is only needed when contributing from a source checkout.
- OpenCode V2
0.0.0-next-16650or a newer compatible@nextbuild, launched asopencode2. - A Kitty-graphics terminal such as Ghostty on the machine running OpenCode. Android may run locally or on an Relictombs host reached through WSS, SSH loopback forwarding, or a VPN-side proxy that presents loopback endpoints.
- The Android SDK, Emulator, platform tools, and an existing AVD on whichever machine owns the Emulator. The client does not need them when Android runs on the server.
- Homebrew and Homebrew OpenJDK for the provided macOS setup target.
- For local Expo automation, an app whose project has
expoinstalled locally.expo_startnever falls back tonpxor downloads a CLI; remote mode does not register the Expo tools.
Run the interactive wizard for the complete setup:
npx --yes @relictombs/[email protected]Choose Android or both surfaces, then choose local or remote execution. For remote use, the wizard accepts a direct SSH destination or a Tailscale machine name or address. It checks or prepares the Android host and verifies FFmpeg and connectivity. Local and existing-host flows can print generated JSON instead of writing it; setup-owned SSH sessions apply the global or project configuration because their token and tunnel are temporary.
Advanced manual configuration
Install the package and add the TUI plugin to ~/.config/opencode/cli.json (or
$OPENCODE_CONFIG_DIR/cli.json):
{
"plugins": ["@relictombs/[email protected]"]
}This is the local setup: omitting remoteHost keeps Android stopped until an explicit human or agent action starts the
configured AVD on the same machine as OpenCode. It enables the Android/Expo MCP tools plus /android-start and
/android-stop, and needs no Relictombs host, FFmpeg, or SSH tunnel.
For local development, pack and install the package into OpenCode's package cache, then use a normal package spec in
the config. Do not point OpenCode at dist/tui.js: a raw workspace file can resolve a second copy of OpenTUI/Solid and
fail with No renderer found when the sidebar mounts. The packed artifact keeps OpenCode's renderer packages as
optional peers and bundles the Android implementation around the host's exact @opentui/core singleton.
Do not configure opentui-device-mcp separately. This plugin registers its own combined relictombs-android MCP server
for the configured AVD and current OpenCode project directory.
The package includes skills/relictombs-android/SKILL.md. Copy it to
~/.config/opencode/skills/relictombs-android/SKILL.md when installing manually, or add a workspace-specific skill under
.opencode/skills/ when the project needs an exact demonstration sequence.
Options are passed through the OpenCode plugin configuration:
| Option | Default | Purpose |
| ----------------- | ------------------------ | --------------------------------------------- |
| avdName | OpenTUI_Pixel_8_API_36 | Local Android Virtual Device to launch |
| expoPort | 8081 | Local Metro port owned by this MCP process |
| framePixelRatio | 2 | Terminal capture density |
| maxFps | 30 | Maximum terminal presentation rate |
| nodeCommand | node | Node executable for the local MCP entry |
| remoteHost | unset | Authenticated server control/media connection |
Advanced manual remote configuration
The wizard is the supported start-to-finish remote path. The following JSON shape is only for operators who supervise
the server and authenticated loopback tunnel themselves. mediaEndpoint rewrites the server's advertised media
origin while preserving its source identity and frame-rate query.
{
"plugins": [
{
"package": "@relictombs/[email protected]",
"options": {
"remoteHost": {
"endpoint": "ws://127.0.0.1:43100/control",
"mediaEndpoint": "ws://127.0.0.1:43101",
"token": "<copy the 64-character token printed by the server>"
}
}
}
]
}Plain ws: is rejected for non-loopback names. The stock host CLI serves loopback ws: only, so use SSH forwarding
or a VPN-side port-forward/proxy that presents both endpoints on the client loopback; VPN reachability alone is insufficient.
A directly reachable wss: deployment requires a trusted TLS edge or custom host composition; it must forward
WebSocket upgrades and the Authorization header, and the client must trust its certificate. Raw RGBA and server paths never
cross this connection: the server negotiates ALV2/H.264 with an ALV1/NUT fallback, and the client decodes it into owned memory
before direct Kitty presentation.
Remote mode is intentionally presentation and human-input only in this release. The Relictombs host eagerly owns the
configured Emulator, so /android-start and /android-stop are not registered. The plugin also does not register its
local relictombs-android stdio MCP server: that server owns local ADB, Expo, and a local state file, none of which can
truthfully control the server. Run agent/Expo automation on the server separately until those bounded operations are added to the
authenticated host protocol.
Agent workflow
- Create or edit an Expo app with ordinary OpenCode workspace tools. The plugin deliberately does not expose an arbitrary file-writing or shell MCP tool.
- Show OpenCode's sidebar with its built-in Toggle sidebar command (
<leader>b). Click the Default · Android selector or run/androidto switch between OpenCode's normal sidebar and the full-height device view. - In local mode, call
android_status, thenandroid_startwhen stopped. A human can instead click Start Android, choose Start Android Emulator from the command palette, or run/android-start./android-stopreleases it. - Call
expo_startwith the app directory relative to the OpenCode project, for example{ "project": "apps/demo" }. The tool resolves that app's installedexpo/bin/cli, startsexpo start --android, and pins Expo/ADB to the plugin-owned emulator.expo_startalso starts Android when needed. - Use
snapshotandtap_nodefor semantic interaction,screenshotfor visual verification, and the bounded touch, swipe, text, key, and installed-app tools when needed. - Call
expo_statusfor bounded recent Metro logs orexpo_stopto stop the owned server.
The MCP tools are:
- Lifecycle:
android_status,android_start,android_stop. - Android:
status,snapshot,screenshot,tap,tap_node,swipe,type_text,press,launch_app. - Expo:
expo_status,expo_start,expo_stop.
There is no arbitrary ADB shell escape hatch. Expo projects are canonicalized under the current OpenCode project, and only a project-local Expo CLI is executed. Switching back to the default sidebar releases only its Presentation; the emulator remains ready for MCP and a later remount. Deactivating the plugin removes its sidebar controls, unregisters MCP, and stops the emulator. MCP disconnection stops any Expo process owned by that MCP instance. Terminal touch uses the authenticated Emulator controller; typing and navigation use bounded fixed-argument input commands against the plugin-owned emulator's exact ADB serial.
In remote mode, deactivation closes the authenticated control/media session and leaves the server responsible for the Emulator lifetime.
Exact setup, plugin, and host versions remain a coordinated release set; current peers negotiate ALV2 while older
peers retain the ALV1/NUT compatibility path.
The npx setup and host commands are available in the coordinated 0.2.0 release.
Host composition API
Custom server launchers can import @relictombs/opencode-android/host-mcp and call
acquireAndroidHostMcp(...) after the host has started its one emulator. The adapter attaches automation to the
supplied emulator serial, owns Expo for the supplied absolute server project root and port, and exposes the combined
Android and Expo tools on an authenticated loopback Streamable HTTP endpoint. It never launches a second AVD, and all
resources remain scoped to the caller's Effect scope.
Development
bun run test
bun run typecheck
bun run build
bun run checkThe OpenCode V2 TUI plugin API is beta. Upgrade OpenCode and this plugin together when that API changes.
