Android UI Automation
OpenMinis/MinisSkills
Automate Android apps that have no public API or web version by driving the UI layer through the Accessibility Service.
Control an Android phone via Hermes-Relay — navigate apps, tap, type, swipe, and drive Uber, WhatsApp, Spotify, Maps, Settings, and more
$ npx skills add Codename-11/hermes-relay --skill android -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Codename-11/hermes-relay android --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Codename-11/hermes-relay.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/android .claude/skills/android && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "android" agent skill from https://github.com/Codename-11/hermes-relay/tree/main/skills/android into .claude/skills/android/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "android", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Codename-11/hermes-relay/tree/main/skills/androidType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Codename-11/hermes-relay --skill android -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Codename-11/hermes-relay android --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Codename-11/hermes-relay.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/android .agents/skills/android && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "android" agent skill from https://github.com/Codename-11/hermes-relay/tree/main/skills/android into .agents/skills/android/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "android", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Codename-11/hermes-relay --skill android -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Codename-11/hermes-relay android --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Codename-11/hermes-relay.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/android .cursor/skills/android && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "android" agent skill from https://github.com/Codename-11/hermes-relay/tree/main/skills/android into .cursor/skills/android/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "android", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Codename-11/hermes-relay.git --path skills/android--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Codename-11/hermes-relay --skill android -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Codename-11/hermes-relay android --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Codename-11/hermes-relay.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/android .gemini/skills/android && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "android" agent skill from https://github.com/Codename-11/hermes-relay/tree/main/skills/android into .gemini/skills/android/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "android", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Codename-11/hermes-relay androidInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Codename-11/hermes-relay --skill android -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Codename-11/hermes-relay.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/android .github/skills/android && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "android" agent skill from https://github.com/Codename-11/hermes-relay/tree/main/skills/android into .github/skills/android/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "android", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Codename-11/hermes-relay --skill android -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Codename-11/hermes-relay android --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Codename-11/hermes-relay.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/android .opencode/skills/android && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "android" agent skill from https://github.com/Codename-11/hermes-relay/tree/main/skills/android into .opencode/skills/android/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "android", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
androidControl an Android phone via Hermes-Relay — navigate apps, tap, type, swipe, and drive Uber, WhatsApp, Spotify, Maps, Settings, and more
Android is an agent skill from Codename-11/hermes-relay. Control an Android phone via Hermes-Relay — navigate apps, tap, type, swipe, and drive Uber, WhatsApp, Spotify, Maps, Settings, and more
Its SKILL.md is about 4.9k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Mobile. It works with Android, Spotify and WhatsApp. The repository describes itself as: Hermes-Relay — Your Hermes AI agent, in your pocket — chat, voice, and control. The licence is MIT.
11 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 293f00a. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
pythonFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Android loads about 4.9k tokens when it runs. Until then it costs about 36 tokens; SKILL.md has 2,594 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Codename-11/hermes-relay at commit 293f00a, republished under its MIT licence (© Codename-11). 2,594 words, ~4,889 tokens.
.claude/skills/android/SKILL.md (or your agent's skills folder).Drive a paired Android phone from Hermes using the android_* tool family. This skill is the playbook the LLM reads before touching those tools for the first time — architecture, pairing, the tool surface, bounded tool budgets, and per-app step-by-step procedures.
AccessibilityService + MediaProjection dispatcher.:8767) as the bridge channel.android_* tool sends an HTTP request to the relay on loopback, which forwards it as a bridge.command envelope over the WSS socket to the phone. The phone executes the action and replies with bridge.response.sideload builds unlock additional capabilities behind a build-flavor flag (voice-to-bridge intents, direct SMS, direct dial). See section 10.Do not call android_setup. That is a fallback for teaching the host about an existing session token — it does NOT pair a new phone. For first-time setup or re-pairing, use one of the canonical flows:
| Invocation | When to use |
|---|---|
/hermes-relay-pair (slash command) | Any Hermes chat session. Invokes the hermes-relay-pair skill, which generates a pairing QR for the user to scan. |
hermes-pair (shell shim) | Terminal users on the host. Runs python -m plugin.pair. Same QR, no chat round-trip. |
If the user has not paired yet, stop and hand off to /hermes-relay-pair. Do not attempt to drive tools against an unpaired phone — every call will return 503 bridge not connected.
To confirm the phone is reachable before starting a workflow, call android_ping once. A healthy response looks like {"status": "ok", "bridge": {...}}. Anything else means the phone is not connected — stop and tell the user.
All of these live in plugin/tools/android_tool.py (except android_navigate in plugin/tools/android_navigate.py). Every tool returns a JSON string.
| Tool | Purpose |
|---|---|
android_read_screen(include_bounds=False) | Dump the accessibility tree of the current screen. Each node has nodeId, text, contentDescription, className, clickable, focusable, and optionally bounds. This is your primary "what's on screen" input — prefer it over screenshots when you only need to read text or find a tap target. |
android_screenshot() | Capture a JPEG of the phone screen. Returns a MEDIA:hermes-relay://<token> line that the phone fetches over the bearer-auth'd relay. Use this when you need vision (logos, layouts, CAPTCHAs, non-accessibility-reachable content) — not for text that android_read_screen already exposes. |
| Tool | Purpose |
|---|---|
android_tap(x=None, y=None, node_id=None) | Tap by accessibility node_id (preferred — stable across screens) or by (x, y) pixel coordinates (fallback). |
android_tap_text(text, exact=False) | Tap the first element whose visible text matches. Use when you can see the word on screen but don't have a node id from android_read_screen yet. exact=False does substring matching. |
android_type(text, clear_first=False) | Type into the currently focused input field. Set clear_first=True to blank it before typing. You still need a preceding tap to focus the field. |
android_swipe(direction, distance="medium") | Screen-level swipe. direction is one of up, down, left, right. distance is short, medium, or long. |
android_scroll(direction, node_id=None) | Scroll within a scrollable container. Pass node_id from android_read_screen to scroll a specific list; omit it to scroll the root. |
android_press_key(key) | Press a curated system key: back, home, recents, power, volume_up, volume_down, enter, delete, tab, escape, search, notifications. No raw KeyEvent injection. |
android_open_app(package) | Launch an app by package name. See section 7 for common package names. |
android_wait(text=None, class_name=None, timeout_ms=5000) | Poll every 500 ms for an element to appear. Cheaper than burning a retry budget on read_screen loops. |
| Tool | Purpose |
|---|---|
android_current_app() | Return the package and activity of the foreground app. Use to confirm a launch succeeded or that you didn't land on a permission modal. |
android_get_apps() | List all installed apps with package names and labels. Use when the user asks for "an app that does X" and you need to discover what's installed. |
android_ping() | Health check — is the phone connected to the relay? Call once at the start of a workflow, not on every step. |
| Tool | Purpose |
|---|---|
android_navigate(intent, max_iterations=5) | Close-the-loop vision-driven navigation. Takes one screenshot per step, asks a vision model what to tap next, and dispatches to the direct tools above. Hard-capped at max_iterations (default 5, absolute ceiling 20). Returns a full trace of every step. See section 6 for when to reach for this instead of the direct tools. |
There is also an android_setup(bridge_session_token) function in the same module — that is a fallback for reconfiguring the host after a re-install when you already have a session token. It is not how you pair a phone. See section 2.
Hard rule: cap any single user request at 5–7 tool calls total. When you hit that budget, STOP and report the current state to the user. Do not retry. Do not keep tapping. Do not "try one more thing."
Why this exists:
nodeIds across a single app depending on what's loaded above it. A naive retry loop burns minutes chasing stale node ids.android_navigate is the correct escape hatch for "I don't know what to tap next." Its iteration cap is code-enforced. Your job as the outer agent is to bound the total number of invocations, not to write your own retry logic around it.STOP-and-report pattern. When you cannot make progress:
android_read_screen once.Acceptable tool budgets for common workflows:
| Workflow | Budget |
|---|---|
| Launch an app and read what's on screen | 2–3 tools (open_app → wait → read_screen) |
| Send a WhatsApp message to a known contact | 5–6 tools |
| Book an Uber to a known destination | 6–7 tools |
| Find an unknown setting | hand off to android_navigate with max_iterations=5 |
| "Scroll until you see X" | 3 swipes max, then stop and report |
If you realize mid-workflow that you need more than 7 calls, stop, explain the situation to the user, and ask whether to continue.
The canonical shape of every bounded Android workflow:
open_app(package)
→ wait(text="<landmark>", timeout_ms=5000)
→ read_screen()
→ 1–3 targeted actions (tap_text / tap / type / swipe)
→ read_screen() # verify the action landed
→ STOP and reportKey discipline:
tap_text over tap(x, y). Coordinates go stale the instant the layout shifts (keyboard pops, ad loads, notification arrives). nodeId from a fresh read_screen is second-best; raw coordinates are last resort.open_app twice in a row. If the first didn't land, check android_current_app and report.read_screen. UI state drifts faster than you expect.android_navigate vs direct toolsUse the direct tools (tap_text, type, swipe, etc.) when you know the exact step sequence — for example, the app playbooks in section 8. You are in control of the budget, you can inspect intermediate state, and every step is cheap.
Use android_navigate(intent, max_iterations=N) when you need vision in the loop: the user's goal is clear but the path is not, the layout is unfamiliar, or the target element is visible in pixels but not in the accessibility tree (icon-only buttons, canvas-rendered UI, custom views). android_navigate takes one screenshot per step, lets a vision model pick the next action, and dispatches to the same direct tools under the hood. The iteration cap is enforced in code (default 5, max 20).
Rules of thumb:
android_navigate. Let vision decide.android_navigate for the last-mile decision. Don't burn vision budget on open_app → wait that you can script.android_navigate in your own retry loop. If it fails, read the trace, summarize for the user, and stop.| App | Package |
|---|---|
| Uber (rider) | com.ubercab |
com.whatsapp | |
| Spotify | com.spotify.music |
| Google Maps | com.google.android.apps.maps |
| Chrome | com.android.chrome |
| Gmail | com.google.android.gm |
com.instagram.android | |
| X (formerly Twitter) | com.twitter.android |
| Tinder | com.tinder |
| Settings | com.android.settings |
If the user asks about an app not on this list, call android_get_apps and match on the human-readable label.
Each playbook is a minimal bounded sequence. Follow them; do not improvise extra steps.
android_open_app("com.ubercab")android_wait(text="Where to", timeout_ms=8000) — Uber's home search field.android_tap_text("Where to") — opens the destination picker.android_type("<destination>") — type the address into the focused field.android_wait(text="<destination-first-word>", timeout_ms=4000) — wait for autocomplete.android_tap_text("<first matching result>") — select the result.android_read_screen() — verify the ride-type picker appeared. STOP and report the quoted fare + ETA. Do not auto-confirm the ride — requesting a ride is a destructive action that spends money. Let the user confirm manually, or let the Tier 5 destructive-verb gate (section 9) prompt them.Pitfalls:
tap_text("Where to") does nothing, re-read the screen and look for a clickable ancestor node.android_open_app("com.whatsapp")android_wait(text="Chats", timeout_ms=5000) — landing tab.android_tap_text("Search") or tap the magnifying glass icon.android_type("<contact name>") — narrows the chat list.android_tap_text("<contact name>") — opens the chat.android_tap_text("Message") — focus the input field. (Label varies by locale; fall back to read_screen and find the EditText node.)android_type("<message body>")android_tap_text("Send") and letting the phone prompt.Pitfalls:
read_screen shows >1 match, stop and ask which one.android_tap_text("OK") if present before typing.android_open_app("com.spotify.music")android_wait(text="Search", timeout_ms=5000)android_tap_text("Search")android_type("<query>")android_wait(text="<first word of query>", timeout_ms=3000)android_tap_text("<first matching result>") — opens the track or playlist.android_tap_text("Play") — start playback.android_read_screen() — verify the now-playing bar shows the expected track. Report and STOP.Pitfalls:
tap_text("Play") fails, re-read and use the node with className containing PlayButton.android_open_app("com.google.android.apps.maps")android_wait(text="Search here", timeout_ms=5000)android_tap_text("Search here")android_type("<place>")android_wait(text="<place-first-word>", timeout_ms=3000)android_tap_text("<first result>")android_tap_text("Directions")android_read_screen() — report ETA + distance + mode, then STOP. Do not auto-start turn-by-turn. "Start" is on the destructive-verb list because it changes the phone's mode of operation.Pitfalls:
read_screen first and check whether you're on home or already navigating.android_open_app("com.android.settings")android_tap_text("Search settings") — Settings has a global search that saves 80% of navigation effort.android_type("<setting name>") — e.g. "wifi", "notifications", "display".android_wait(text="<setting name>", timeout_ms=3000)android_tap_text("<matching result>")android_read_screen() — you're now on the target settings page. Make the toggle change (tap_text(<label>)) and verify.Pitfalls:
com.android.settings fails, try com.samsung.android.lool or fall back to android_get_apps and filter on "Settings".read_screen to find it, not coordinates.android_open_app("com.tinder")android_wait(text="Discovery", timeout_ms=5000) or landmark of your choice.android_read_screen() — confirm a profile card is visible.android_swipe("right") to like, android_swipe("left") to pass. (Do NOT use coordinate taps — Tinder's card stack is canvas-rendered and coordinates are unstable.)android_read_screen() — verify the deck advanced. Report and STOP.Pitfalls:
Keep Swiping before continuing.The phone enforces user-configurable Tier 5 safety rails on every bridge.command. You will see these as 403 responses. Do not retry on a 403 — report it.
android_ping and android_current_app returns 403 blocked package <name>. Tell the user to either switch out of the blocked app or remove the app from the blocklist in Hermes-Relay → Bridge → Safety.android_tap_text and android_type are intercepted when the payload contains any of the default destructive verbs (send, pay, delete, transfer, confirm, submit, post, publish, buy, purchase, charge, withdraw). The phone pops a confirmation modal with the full payload — the user has a configurable timeout (default 30 s) to allow or deny. A denied or timed-out confirmation returns 403 user denied destructive action.bridge.command will return 403. Tell the user to re-enable the bridge master toggle.Agent discipline: expect 403s, report them, do not retry. The user's safety config is not something you should try to work around.
Hermes-Relay ships in two build flavors: googlePlay (Play Store, conservative accessibility config) and sideload (full agent control). The sideload build unlocks:
android_* tools — they're user-facing voice intents only. You will not see them in your tool list.typeAllMask, gesture dispatch, interactive windows, view IDs — used by the direct tools under the hood. The Play flavor uses a narrower subset.Agent rule: you do not need to know which flavor is running to use the android_* tools. Every tool in section 3 works in both flavors. The flavor only matters if you're building a feature that requires sideload capabilities, in which case check BuildFlavor.current on the phone side, not from the tool layer.
This file is read by the LLM before it touches the android_* tools. Keep it tight and keep it current:
android_* tools land, add them to the section 3 table with a one-line purpose.When adding a new playbook, follow the section 8 template: numbered steps using tool-call syntax, a "Pitfalls" subsection with 2–4 bullets, and an explicit STOP-and-report step before any destructive action.
© Codename-11, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/android of Codename-11/hermes-relay.
Open the folder on GitHubat commit 293f00a
Android next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Android this skillCodename-11/hermes-relay | 310 | — | ~4.9k | Automated safety check: Pass | MIT | |
| Android UI AutomationOpenMinis/MinisSkills | 440 | — | ~1.6k | Automated safety check: Pass | MIT | |
| Android Setupbrim-borium/spotify_sdk | 166 | — | ~331 | Automated safety check: Pass | Apache-2.0 | |
| Platform Syncbrim-borium/spotify_sdk | 166 | — | ~456 | Automated safety check: Pass | Apache-2.0 | |
| Android E2E Testerbrim-borium/spotify_sdk | 166 | — | ~284 | Automated safety check: Notes | Apache-2.0 | |
| Compose Multiplatform Patternsmonta-app/ocpp-emulator | 179 | 5 repos | ~2k | Automated safety check: Pass | Apache-2.0 |
OpenMinis/MinisSkills
Automate Android apps that have no public API or web version by driving the UI layer through the Accessibility Service.
brim-borium/spotify_sdk
Configure or clean Spotify App Remote SDK AAR resolution on Android.
brim-borium/spotify_sdk
Synchronize method channels and event streams across Dart, Android (Kotlin), iOS (Swift), and Web.
brim-borium/spotify_sdk
Run autonomous Android E2E tests on example app via ADB MCP with Logcat verification.
monta-app/ocpp-emulator
Compose Multiplatform and Jetpack Compose patterns for KMP projects — state management, navigation, theming, performance, and platform-specific UI.
ShawnPana/phone-harness
Control the user's phone — an iPhone through the Mac's iPhone Mirroring window, an Android over adb, or a rented cloud Android: open apps, tap, type, swipe, read the screen.
Codename-11/hermes-relay
Generate a signed setup QR for Hermes-Relay Android, preserving Dashboard/Gateway ownership and optional Relay or API routes.
Codename-11/hermes-relay
Setup and run the Hermes-Relay server for Android chat support, terminal, bridge, and related relay features.
Codename-11/hermes-relay
Generate, critique, install, and validate AI-assisted Android string-resource translations for Hermes-Relay.
Categories
Control an Android phone via Hermes-Relay — navigate apps, tap, type, swipe, and drive Uber, WhatsApp, Spotify, Maps, Settings, and more. Android is an agent skill from Codename-11/hermes-relay.
Android fits situations like: mobile work in your project.
Run `npx skills add Codename-11/hermes-relay --skill android -a claude-code`. Or copy the skill folder (skills/android in Codename-11/hermes-relay) into .claude/skills/android in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Codename-11/hermes-relay --skill android -a codex`. Or copy the skill folder (skills/android in Codename-11/hermes-relay) into .agents/skills/android in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Codename-11/hermes-relay --skill android -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/android, .gemini/skills/android, .github/skills/android and .opencode/skills/android in your project.
Going by SKILL.md and its folder, Android needs the command-line tools its instructions call (python). Our summary lists: Python 3.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Android is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.9k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Android: Android UI Automation (OpenMinis/MinisSkills, 440 stars), Android Setup (brim-borium/spotify_sdk, 166 stars), Platform Sync (brim-borium/spotify_sdk, 166 stars) and Android E2E Tester (brim-borium/spotify_sdk, 166 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Codename-11 (a GitHub user) maintains it in Codename-11/hermes-relay, which has 310 GitHub stars. The repository holds 4 skills in this directory. The repository was last updated on October 5, 2026.
Source: Codename-11/hermes-relay on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.