mobilerun-control
Use if controlling or testing a connected Android phone via the mobilerun CLI — tap, type, swipe.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use if controlling or testing a connected Android phone via the mobilerun CLI — tap, type, swipe.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use skill if you are exhaustively testing or release-gating martool CLI commands in a source checkout or deployed Coolify container over SSH, without local Docker or provider spend.
Use if driving agent-browser for Chrome/CDP automation, @ref snapshots, tabs, or verification.
Use if testing or debugging an iOS app via agent-device CLI — simulator flows, evidence, bug triage.
Use if supervising Jean agents through MCP and Computer Use for monitoring, recovery, or closure.
Use if auditing or designing a CLI for agent/LLM use — JSON output, exit codes, non-interactive.
Use if auditing or designing an MCP server for agent-readiness — framework, security, context.
| name | mobilerun-control |
| description | Use if controlling or testing a connected Android phone via the mobilerun CLI — tap, type, swipe. |
| allowed-tools | Bash(mobilerun:*) Bash(adb:*) Read |
mobilerun is your hands and eyes on a real phone. You are the brain. You read the
screen with mobilerun device ui / device screenshot, decide the next move with your own
reasoning, and act with deterministic mobilerun device commands. No cloud, no Gemini, no
mobilerun run, no API key — those are explicitly out of scope here.
Scripts live in scripts/ next to this file; reference docs in references/. Set two
variables once per session, before the loop — the skill is invoked with the project cwd,
not this folder, so a bare scripts/mr-preflight.sh will No such file or directory. And because
each Bash call is a fresh shell (one command per call), no cd persists between calls to rescue a
relative path — so address scripts absolutely:
export MR_DEVICE=<serial> # find it with: mobilerun devices
export SKILL=<absolute path to this skill dir> # the folder holding this SKILL.md
Then call every script as bash "$SKILL/scripts/<name>" — that's how the runnable blocks below
are written, so they work from any cwd. (Prose and tables name a script by its bare filename,
e.g. mr-tap.sh, purely for brevity.)
Six ideas make every other instruction in this skill obvious. Hold them and the right move usually follows on its own.
mobilerun run / Gemini) needs an API key this setup
doesn't have, so the intelligence is you: you read the screen, choose the next move, and issue
one deterministic mobilerun device command at a time. There's nothing else deciding — every tap
is yours.mobilerun
command so you can read its result — Tapped (x,y), Typed:, the tree. Piping (cmd | tail)
hands you tail's exit code instead of mobilerun's, so a real error reads as success; trust the
printed words, or ${PIPESTATUS[0]} if you must pipe.mr-wait.sh and
mr-tap.sh's jitter do this for you.mr-preflight.sh resolves the device, rides out the USB settle, and re-asserts
accessibility in the form the version check expects — the things that otherwise make the first
command of a session fail. Run it once up front and the loop starts on solid ground.The through-line: perception before action. Hold the six ideas above and one truth explains them all — almost every failure on this device is a perception failure, not an action failure. You rarely fail because you tapped the wrong pixel; you fail because you acted on a belief about the screen that a fresh snap would have corrected. That belief takes four shapes, and naming the one you're in hands you the fix:
start
resumes a leftover screen, and a stray back can drop you into another app entirely. Read the
phone-state activityName before you act.Clickable UI elements line before you believe it.So when something doesn't work, your first move is not a different tap — it's a fresh snap, because a
surprising result is data about your perception before it is data about the device. The lone
exception is a tool-contract gap: when the command itself cannot express what you need (clearing a
field to empty), you fix the tool, not your looking — see references/text-input.md.
0. SETUP (once): export MR_DEVICE=<serial> ; export SKILL=<abs path to this skill dir>
PREFLIGHT (once): bash "$SKILL/scripts/mr-preflight.sh" # ready + heals a11y/version/USB
── then repeat ──
1. CAPTURE: bash "$SKILL/scripts/mr-snap.sh" [--boxes] # indexed UI tree (+ screenshot, +numbered boxes)
2. DECIDE (you): read the tree/screenshot; pick the target element by its TEXT/resourceId;
copy its bounds (x1,y1,x2,y2). When unsure of layout, Read the SHOT= PNG.
3. ACT: bash "$SKILL/scripts/mr-tap.sh" --bounds "x1,y1,x2,y2" # jittered box-center tap
bash "$SKILL/scripts/mr-type.sh" "text" [--clear|--human] (focus the field first)
mobilerun device swipe … / press back|home|enter / start <pkg>
bash "$SKILL/scripts/mr-wait.sh" [read|think|MIN MAX] # human pause between steps
4. VERIFY: bash "$SKILL/scripts/mr-snap.sh" ; confirm the expected change appeared.
If nothing changed, retry the tap once; if it's still unchanged, re-plan from
the new snap rather than repeating the same tap.
Give the loop a budget: if the goal state isn't reached in ~15–25 capture→act cycles, stop and report what you saw — a stalled plan is information, so re-plan instead of looping on.
mobilerun device ui prints every on-screen element as:
Current Clickable UI elements:
'index. className: resourceId; checkedState, text - bounds(x1,y1,x2,y2)':
9. TextView: "android:id/title", "Network & internet" - (221,462,566,519)
34. Switch: "…/switchWidget", "Dark theme" ; isChecked=False - (859,1912,996,2038)
(x1,y1,x2,y2) are absolute device pixels: left,top,right,bottom.mr-snap.sh --boxes, or
adb shell content insert --uri content://com.mobilerun.portal/overlay_visible --bind visible:b:true).
The number in each box's top-right corner matches the device ui index — this is your
set-of-marks. Use it when you (or the user) want to see what's clickable.center = ((x1+x2)//2, (y1+y2)//2), then tap (with jitter). mr-tap.sh --bounds "…" does the math + jitter — the same center mobilerun computes internally.Full mechanics, overlap handling, raw JSON: references/box-select-and-clicking.md.
| Need | Use | Why |
|---|---|---|
| Find tappable targets + exact bounds | mobilerun device ui (default) | cheap, text, precise pixels — your primary sense |
| Understand layout / images / a screen with no a11y tree | mobilerun device screenshot → Read the PNG | you are multimodal; Read renders the PNG visually |
| See which elements are clickable, visually | mr-snap.sh --boxes → Read the BOXES png | numbered overlay = set-of-marks |
| Programmatic raw tree | adb … content query --uri …/state_full | JSON with index/bounds/flags |
How to choose between them, and how to handle the temp-path screenshot: references/capture-state.md.
| Action | Command | Notes |
|---|---|---|
| Tap element | mr-tap.sh --bounds "x1,y1,x2,y2" | jittered center; re-snap first |
| Tap raw point | mr-tap.sh --xy X Y | when you have pixels (e.g. from a screenshot) |
| Long-press | mobilerun device long-press X Y | context menus; not on iOS |
| Type / paste | mr-type.sh "text" [--clear] [--human] | focus the field first (tap, ~0.5s settle) |
| Scroll | mobilerun device swipe 540 1700 540 700 --duration 0.4 | up-swipe scrolls down; re-snap after |
| Set a slider | tap its Decrease/Increase buttons, or a point along the track | SeekBar has no isChecked; verify by thumb-bounds shift |
| System buttons | mobilerun device press back|home|enter | back is 2-stage if keyboard is up; only these three |
| Launch app | mobilerun device start <package> | get packages from device apps |
Gestures, scrolling a list to find an item, paging: references/navigation-and-gestures.md.
Text entry, how the keyboard works on this device, atomic paste vs human typing: references/text-input.md.
Default to human cadence: mr-wait.sh between actions, mr-wait.sh read while "reading" a post,
jittered taps, natural scroll distances, and --human typing for anything a person authored
(comments, messages). See references/stealth-and-human-pacing.md. When you compose text a human
will be seen to have written, also read references/writing-like-a-human.md so it doesn't read
like an LLM.
Decompose the goal into the loop above, expressed as concrete CLI steps before you touch the
device. Worked end-to-end plans (Reddit "read N posts then comment", Settings toggles, search-and-
open, multi-app flows) are in references/task-planning-playbook.md. Start there for any non-trivial request.
| File | Read when |
|---|---|
references/task-planning-playbook.md | Planning ANY multi-step task into CLI steps; worked examples. Start here. |
references/box-select-and-clicking.md | Tapping elements: indices, bounds, center math, overlap, numbered boxes, raw JSON. |
references/capture-state.md | Choosing/using ui vs screenshot vs raw state; reading the PNG; temp-path handling. |
references/text-input.md | Typing/pasting; how the keyboard behaves on this device; clearing fields; special characters. |
references/navigation-and-gestures.md | Scrolling, paging a list to find an off-screen item, back/home, switching apps. |
references/stealth-and-human-pacing.md | Pacing, jitter, natural scrolling/typing, anti-bot-pattern hygiene. |
references/writing-like-a-human.md | Composing comments/messages/posts that read human, not LLM. |
references/command-reference.md | Exact CLI flags, Portal content-provider endpoints (query vs insert), bash discipline. |
references/device-health-and-recovery.md | What preflight does and why; re-asserting accessibility, the version pin, USB-blip and empty-tree recovery, GrapheneOS specifics. Read when something degrades mid-session. |