mobile-check
Skill2 starsChanged 34 days agoApache-2.0View on GitHub
Automate mobile apps — native, hybrid, cross-platform, and pages in a mobile browser or installed as a PWA — with the Mobium CLI, on Android emulators and phones and iOS simulators and iPhones. Use to launch and drive an app, fill forms, read the screen, answer system dialogs, reach into WebViews, capture screenshots and recordings, or confirm that a mobile change actually works.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- duncan-buildroom/freeskillstheir own version, first seen Oct 13, 2026
- nobufumi-tego/gcp-agile-templatetheir own version, first seen May 4, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- duncan-buildroom/freeskills★ 65same name
- nobufumi-tego/gcp-agile-template★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repositoryOne other file it gives its agents.
- CLAUDE.mdCLAUDE.md
The file
Show its rules and text
We split this skill into the rules it gives an agent
14 rules. About 0 are common, 6 are distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 27
If you need to test a *website* — tabs, browser sessions, a desktop browser — use vibium instead.
- Distinctive: line 33
Every automation follows the same loop:
- Very specific: line 37
Re-map: after anything that changes the screen, run mobium map again
- Very specific: line 51
Run mobium --help to confirm, then use the resolved path throughout.
- Very specific: line 60
If nothing is listed, an emulator or simulator can be started with mobium boot <avd-or-simulator-name>, which answers once it has booted.
- Very specific: line 98
Use mobium current to check a tap went where you expected:
- Distinctive: line 118
Never sleep. Every action already waits for its target — up to two seconds to be there and enabled, up to five to hold still — so a tap …
- Distinctive: line 255
Every action waits until its target is on screen and enabled (up to two seconds) and holding still (up to five), and refuses — with a …
- Distinctive: line 279
Every step is checked before the first runs, and the batch stops at the first failure with that step's own error and exit status.
- Very specific: line 299
Add ,role=button to narrow an ambiguous locator: text=Continue,role=button.
- Distinctive: line 382
Every one of these can move the screen, so map again before acting.
- Distinctive: line 457
Do not chain when you need to read the output to decide what to do next — run those separately so you can look at the map before choosing a …
- Very specific: line 464
Every failure also carries a code, so you can act on the kind without parsing the sentence: --json prints it ("code": "no_such_element", …
- Very specific: line 503
Ask the user to start one.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Mobium Mobile Automation — CLI Reference
The mobium CLI automates mobile apps on Android emulators and phones, and
iOS simulators and iPhones.
A background daemon keeps the device session alive between commands, so each
command is fast after the first.
mobium launch com.example.shop && mobium map && mobium tap @e5 && mobium mapWhat the app is built with decides how to reach it:
| App type | How |
| Native (Android SDK, Jetpack Compose, UIKit, SwiftUI) | map and act — the default |
| Cross-platform that renders native views (React Native) | the same as native: it renders real native views. Use the @ref from map, not a hand-written label= or testid=: one testID repeats across several views |
| Hybrid (a WebView inside the app) | switch context into the WebView — Hybrid apps |
| A page in Chrome or Safari, or a PWA — including one from the Play Store (a Trusted Web Activity) | the same contexts: the page is WEBVIEW_… — pick it by the URL contexts prints, not by its name. launch of an installed PWA's package says what it is; Chrome draws it, so current names Chrome. On iOS a tap in Safari's or a home-screen web app's page is placed from text the page and the native tree both report, and lands; where it cannot be placed it is refused, and NATIVE_APP reaches the same elements. On Android, a refusal saying Chrome stopped reporting its WebView means no tap can be placed in that page: read it, and say so |
| Cross-platform that paints (Flutter) | the same as native: Flutter publishes a semantics tree, and map reads it. Its text is the label, not the text — use label=; a Semantics(identifier:) is a testid=. A widget with no semantics (a custom painting, an icon with no tooltip) cannot be named: say so rather than retrying |
If you need to test a website — tabs, browser sessions, a desktop browser — use vibium instead. Mobium reaches a page already open on the device; it does not manage the browser.
Core Workflow
Every automation follows the same loop:
- Map:
mobium map— lists what is on screen as@e1,@e2, … - Act:
mobium tap @e5,mobium type @e2 "text",mobium swipe up - Re-map: after anything that changes the screen, run
mobium mapagain
Refs are only valid for the screen they were taken from. A ref is re-resolved against a fresh snapshot before every action, so a stale one fails loudly rather than tapping the wrong thing — but that means you must re-map after navigating.
Binary Resolution
Resolve the mobium binary path once before running commands:
- Try
mobiumdirectly (works if it is on PATH) - Fall back to
./bin/mobium(dev environment, in the project root)
Run mobium --help to confirm, then use the resolved path throughout.
First: check there is a device
mobium devices
# emulator-5554 device (android emulator, model: sdk_gphone64_arm64, Android 15 (API 35), navigation: gestures)If nothing is listed, an emulator or simulator can be started with mobium boot
<avd-or-simulator-name>, which answers once it has booted; a phone has to be
plugged in by the user (Android with USB debugging on; an iPhone trusted and
unlocked). Say so rather than retrying.
Commands
Getting to the screen you want
mobium current— which app is in the foregroundmobium state <package|bundle-id>— any app: not installed, not running, background or foregroundmobium shake— shake an emulator or simulator (shake-to-undo, a debug menu); a real phone refuses. Check the screen after: whether the app reacts is its own detector's businessmobium biometric— whether a face or finger is enrolled;enroll/unenrollset it, andmatch/nomatchpresent one to the prompt that is up and say what the device made of it (accepted, not recognized, failed, locked out). Emulators and simulators only; an emulator gets PIN 1111 to enroll, whichunenrollremoves. With no prompt up it refuses — start the app's sign-in firstmobium hit-test <target>— on an iOS simulator, whether UIKit would give a tap there to the target, and if not, to what; the one way to see an overlay hidden from accessibility. Takes about three seconds: use it when a tap "worked" and the app disagreesmobium background 5— send the app in front away for 5 seconds and bring it back where it was: how a resume path is testedmobium launch <package|bundle-id>— open an appmobium terminate <package|bundle-id>— stop it, to start a flow cleanmobium open <url>— a URL or deep link, the quickest route to a screenmobium install <path>— install a local .apk or .appmobium apps— what is installed;--systemincludes the platform's ownmobium uninstall <package|bundle-id>— remove one, verified by listing afterwards, becauseadb uninstallreports success when it has only removed the updates to a system app
Refs do not survive these. Launching, terminating or opening a link
discards the previous screen's refs; run mobium map afterwards.
Use mobium current to check a tap went where you expected:
mobium tap @e5 && mobium currentWhen something fails for no good reason
mobium doctor checks the environment and needs no device — that is the
point. Several of the toolchain's own errors name the wrong cause, so run it
before believing one of them. It exits non-zero if it found anything.
Discovery
mobium map— actionable elements with@refs(run this before interacting)mobium find <locator>— matching elements, without tappingmobium text— everything readable on screenmobium text @e3— the text of one element
Waiting
Never sleep. Every action already waits for its target — up to two seconds to be there and enabled, up to five to hold still — so a tap straight after a launch or another tap is fine. When something takes longer than that — a login, a network fetch — wait for the thing itself rather than for a duration:
mobium wait "text=Welcome back"— until it is on screenmobium wait 'text="Wi-Fi"'— quoted: the whole text, so a part of it on the screen you are leaving cannot satisfy the waitmobium tap 'label=More within text=Card 8'— the More in Card 8's row; a row without one finds nothing, never its neighbor'smobium tap 'label=Delete,nth=3'— the third Delete shown, in reading order; brittle, so preferwithinmobium wait role=progressbar --for hidden— until a spinner goesmobium wait @e4 --for text --text "Sent"— until its text says somobium wait testid=submit --for enabled— until a control can be used (--for disabledfor the other way)mobium wait testid=terms --for checked— a checkbox, radio or switch (--for uncheckedfor the other way)mobium wait testid=search --for value --text ""— until a field holds exactly that (here: nothing);--for textmatches part of what it saysmobium wait testid=email --for focused— until the field has the cursormobium wait "text=Done" --timeout 30s— default is 10s
A wait that succeeds remaps the screen, so the element it found already has a
ref and can be tapped without a mobium map in between. A wait that fails
says what was on screen instead, which is usually the answer.
Reaching things below the fold
mobium map only sees what is currently on screen. Tap, type and long-press
already scroll to a target that is not, so most of the time nothing extra is
needed — reach for scroll-to to look without acting, or to go back up:
mobium scroll-to "text=Sign out"— bring it into view and get a refmobium scroll-to "text=Network & internet" --direction up
For a horizontal pager, carousel or row of chips, give --direction left
or right. If a scroll reports that the swipe changed the screen instead
of scrolling it, the thing being swiped was not a list.
Permissions
A first-launch permission dialog will stop a flow dead. Grant before you start rather than trying to tap through it:
mobium grant com.example.shop all— everything the app declaresmobium grant com.example.shop camera location— just thesemobium revoke com.example.shop location— test the app without itmobium reset-permissions com.example.shop— that app back to prompting, "don't ask again" included; with no app, every app on the device
Names are the same on both platforms where both have the thing. Where they do
not — camera and notifications have no iOS simulator equivalent,
reminders and siri have no Android one — you get an error saying so rather
than a silent no-op. On Android the grant is verified by reading the state
back, and anything the app never declared is reported as skipped.
Battery and clock
mobium battery— level, charging state, and on Android what powers it; an iOS simulator has no battery and says somobium time— the device's clock in its own zone; a simulator's is the Mac's, and the answer says so
Tests
mobium test runs *.test.json files: each test is a list of the same
steps app_batch takes — {"name": "app_tap", "arguments": {...}} — and its
assertions are app_wait_for steps (not, exact and count included) or
{"expect": {"tool": ..., "field": ..., "equals": ...}} on a tool that only
reads. Projects in mobium.config.json are devices — or, with
MOBIUM_GRID set, a platform each, and every project leases its own
device from the grid for the run. -g, --project,
--retries, --last-failed, --reporter list,junit,html, then
mobium show-report. A failure keeps the step, its error code, a screenshot
and the map. tests/ in the repository is a worked example.
Files
mobium upload invoice.pdf # where a file picker looks
mobium download report.csv # what the app saved there
mobium upload ./seed --device-path /data/local/tmp/seed # Android, any shell path
mobium download --app com.example.shop --device-path databases/shop.db # its private data
mobium download --app com.example.Shop --device-path Library/Caches -o caches # iOS container- Without
--device-patha file goes where the device keeps downloads, and on Android it is indexed so a file picker finds it. With it, a file or a whole folder goes to that exact path. - An Android app's private data needs a debuggable build. A release build is
refused, saying so — Android lets only the app, or
run-ason a debuggable build, read it. Do not retry; use shared storage or a debug build. - A folder downloads to a new folder, never into one that exists. Every file's size is read back at the far end; trust the answer, not the exit code alone.
Network
mobium network— what is in place: online or offline, and any shapingmobium network --offline/--online— airplane mode, waited for until the network is really gone or back; an emulator or a real Android phonemobium network --latency 300 --download 1600 --upload 750— shape the traffic, replacing any shaping before; an emulator only (it needs root)mobium network --reset— no shaping, airplane mode off. The end of the session does this for you, back to how it found the device- iOS refuses all of it: nothing outside it controls its network
Light and dark
Dark mode is a different rendering of every screen and is where contrast and hard-coded colors break, so a flow is worth running in both:
mobium appearance— what is it now?mobium appearance dark/light— switch, confirmed by reading it backmobium appearance auto— Android only; iOS says it has no such thing
Switching discards the refs from the last map, so map again afterwards.
Accessibility settings are the same kind of rendering change, and each lasts only for the session — the device is put back exactly as it was when it ends:
mobium accessibility— every setting the device has, as it is nowmobium accessibility bold_text on— reduce_motion, bold_text, increase_contrast, invert_colors, grayscale and the rest take on or offmobium accessibility text_size accessibility-large(iOS) /text_scale 1.3(Android) — text size is a category on one and a scale on the other, and each says so if given the other's
On a real iPhone, where nothing outside can change them, Mobium goes through the Settings app and comes back to the app that was in front — about ten seconds a change. The six switches work there; invert_colors, grayscale and text size are refused, naming the Settings screen. On Android a text-size change restarts the running app's screen, so map again afterwards.
Acting
Every action waits until its target is on screen and enabled (up to two
seconds) and holding still (up to five), and refuses — with a reason and a
remedy — rather than tapping something a user could not: a target under a system
dialog or under the keyboard, a control that stays disabled, or a button
passed to type.
mobium tap @e5— tap a refmobium tap "text=Sign In"— tap by locator, no map neededmobium tap 540 1200— tap raw device coordinatesmobium type @e2 "hello@example.com"— type into an element, after what it holdsmobium type @e2 ""— clear a fieldmobium fill @e2 "new"— replace the contents (Vibium's fill;typeadds to them)mobium swipe up— scroll down the page (the finger moves up)mobium swipe left— next pager screenmobium swipe 540 1800 540 600— exact dragmobium long-press @e4— open a context menumobium screenshot -o shot.png— capture the screen
Several steps in one call
mobium batch steps.json(or-for stdin) — run a known sequence in one call:[{"name": "app_tap", "arguments": {"target": "text=Sign in"}}, ...], each step a tool and the arguments it takes on its own
Every step is checked before the first runs, and the batch stops at the
first failure with that step's own error and exit status. Use it for steps
whose outcome you do not need to read before choosing the next; after an
app_map step, prefer locators to refs, since the map replaces them.
Locators
Locators work the same on both platforms, so one script targets either:
| Locator | Android | iOS |
text=Sign In | element text | element value |
label=Email | content-desc | accessibility label |
testid=submit | resource-id | accessibility identifier |
role=button | widget class | XCUIElementType |
class=RecyclerView | exact class | exact type |
Roles: button, input, password, checkbox, switch, radio, link,
image, list, tab, text.
Add ,role=button to narrow an ambiguous locator: text=Continue,role=button.
role=password is how you address a password field. Mobium never prints
its contents — map shows the field's resource id and reads come back as
•••••••••••• (12 characters, hidden: …) — so there is no visible text to
match on. password is a narrower input: role=input matches these too.
Hybrid apps (WebViews)
Web content inside an app is a separate context:
mobium contexts # NATIVE_APP, WEBVIEW_com.example
mobium context WEBVIEW_com.example # map and tap now work on the page
mobium context NATIVE_APP # back to the native shellThis works on both platforms. Android WebViews must be debuggable
(setWebContentsDebuggingEnabled(true)) and iOS WKWebViews must be inspectable
(webView.isInspectable = true on iOS 16.4+). If a WebView does not appear in
contexts, that is a property of the app — do not keep retrying.
mobium logs # what has the page logged since the last read?
mobium logs --level error # uncaught errors and rejections
mobium eval "document.title" # ask the page directlylogs drains what it returns, so it reports what happened since the last call —
which is how you assert "nothing was logged during this step". Capture starts
when you enter the context, so a page's initial load is already over.
Two things that look like bugs and are not:
mapmay say "these elements cannot be tapped". The page's position inside its host element is unknowable there — mobile Safari is the usual cause. The refs, labels andmobium textare still correct; only acting on a coordinate is refused. Read the page, act natively, or use a deep link.- "the page never announced a target" means another debugger already holds
that page. Ask the user to close Safari's Web Inspector, or run
mobium daemon stopif a previous session is still switched into it.
Switch back to NATIVE_APP when finished with a page. Leaving a session inside
one keeps it locked away from everything else.
Device state
mobium orientation # which way, and is it pinned?
mobium orientation landscape # turn it and pin it
mobium orientation auto # follow the sensor again
mobium locale org.wikipedia ja-JP # run one app in Japanese
mobium locale org.wikipedia device # back to the device languageBoth invalidate the refs from the last map — a rotation re-lays out every
screen and a language change re-renders it, so map again before acting.
Two honest limits worth knowing, because neither platform will tell you:
- An activity that pins its own orientation cannot be turned from outside. Mobium reports that rather than claiming success.
- Setting a language confirms the device stored the tag, not that the app speaks it. Android accepts a tag the app has no translation for and the app then renders in its default language. Look at the screen.
Relaunch an app after changing its language, or it keeps the old one.
Interruptions and hardware buttons
mobium press back # primary navigation on Android; says where it went
mobium press back --gesture # the swipe in from the edge; the only back on iOS
mobium press home # says the launcher came forward
mobium lock lock # a state, not a toggle
mobium call ring # then accept, or hang
mobium sms "your code is 123456"
mobium timezone Asia/Tokyo
mobium notifications # what is in the shade?
mobium notifications --post "your code is 123456"
mobium notifications --shade open # now the notification can be tappedEvery one of these can move the screen, so map again before acting.
- iOS has no back button.
press backis refused; tap the app's own back chevron, or ask for the swipe withpress back --gesture, which starts in the navigation bar because a list row's swipe actions would take it anywhere else. An app with no navigation stack has no swipe back at all. - On Android
--gestureis refused with three-button navigation — an edge swipe is not back there.mobium devicesnames the mode. - Calls and messages are emulator-only. A real phone cannot be made to ring from outside. Mobium says which it is rather than failing obscurely.
- A notification cannot be tapped until the shade is open. Until then it is
not on screen and
mapcannot see it:notifications --shade open, thenmap, then tap it. Close the shade when finished, or every later locator fails against a panel covering the app. - Back says what it did. "it left com.example.shop" means back closed the app — usually a bug when the app had a screen to go back to; "still in the foreground" means it went somewhere inside it, and on iOS the navigation bar's new title is given. Map again to see which screen.
Dialogs
mobium alert— is a system or app dialog up, what does it say, and what are its buttonsmobium alert accept/dismiss— yes and no, on a dialog of one or two buttons: a two-button permission prompt is granted by accept and denied by dismiss, in any language. A dialog of three or more is refused, naming its buttons — the location prompt has two that grant — and every answer says which button it pressed.mobium alert --button "Allow While Using App"— press one by its caption (any case, straight or curly quotes) or its position from 1, on any dialog.mobium dialogs --when "Save Password" --press "Not Now"— declare an answer for a dialog that turns up on its own schedule. An action that meets it presses that button, confirms the dialog went, carries on, and says so in its result.mobium dialogslists the rules,--clearremoves them.
Choosing a device or backend
--device <serial>— when more than one device is running--driver uiautomator— Android without installing anything (slower, and it cannot type)--driver wda— iOS simulators and iPhones--driver <anything else>— a third-party driver the user installed, as an executable namedmobium-driver-<name>.mobium doctorlists the ones it can find. Such a driver may not support everything: if it refuses something, it never advertised that capability and retrying will not help.
Reading map output
@e1 Search (input)
@e2 Sign In (button)
@e3 Remember me (checkbox)Each line is @ref label (role). Pick by the label, act with the ref.
Prefer the @ref to retyping the label. Many labels are composed from
several elements — a search result's title plus its description, say — so no
single element carries that text and text=<the whole label> will not match
it. A label ending in … has been shortened for readability and will not match
either. The ref always works; it is printed for that reason.
map lists only what is actionable and on screen. Something a locator can
resolve may still be absent from the map — scrolled out of its container, or
reported by the platform as not visible. That is why an element you can see in
a screenshot but not in map is usually a scroll away, not a bug.
Command Chaining
Chain with && when the steps are independent of each other's output:
mobium map && mobium tap @e2 && mobium mapDo not chain when you need to read the output to decide what to do next — run those separately so you can look at the map before choosing a ref.
When things fail
Mobium's errors say what to do; read them rather than retrying blindly.
Every failure also carries a code, so you can act on the kind without
parsing the sentence: --json prints it ("code": "no_such_element", with a
remedy and details), and the exit status groups it:
| Exit | Codes | What to do |
| 2 | invalid_argument | fix the command; retrying it unchanged cannot help |
| 3 | no_device, device_not_ready, toolchain_missing | ask the user: start, unlock or restart a device, install a tool |
| 4 | no_such_element, ambiguous_locator, element_not_reachable, no_such_context, no_such_alert | re-map, narrow the locator, or scroll; with check: receivesEvents, deal with what details names over the target — answer the dialog, hide the keyboard — never restart the device for it |
| 5 | unsupported | this device or backend cannot; do not retry |
| 6 | timeout | the one kind worth retrying as it is |
| 7 | not_confirmed | the command claimed success and the device disagrees — report it, it is a finding |
| 1 | anything else | read the message |
no element matches … — the screen may have changed, run map againThe screen moved. Re-map and pick a fresh ref.… matches N elements — narrow it by appending ",role=button" …Ambiguous locator. Add a role or map and use a ref.the uiautomator backend cannot type into an elementDrop--driver uiautomator; the default backend can type.the <name> backend cannot …That backend never advertised the capability. Switch backends; do not retry.a dialog is over the app — "…" — and nothing on it matches …Answer the dialog first (mobium alert, or tap its button), or declare a rule withmobium dialogs.… failed check <check>: <reason> — <what to do>The target is there and an action refused to touch it. The check is in the error's details too; decide by it, not by the wording:visible— off screen:mobium scroll-toit.enabled— disabled: do what enables it, ormobium wait <target> --for enabled.stable— still moving: wait, or tap by coordinates if it animates on purpose.receivesEvents— something is over it: a dialog (answer it), the keyboard (mobium keyboard --hide, or on an iPhonemobium keyboard --key enter), or the app's own control (dismiss it, wait for it to go, or tap it if it is what you meant).editable— not a text field: usetapfor it;typeis for fields.
no Android device or emulator is runningAsk the user to start one. Mobium cannot.… matches N elements of the page/no element of the page … matchesInside a WebView a locator matches whatmapreads of the page: text and label are an element's accessible name, testid its data-testid or id, role its role. Narrow it with,role=, quotes,,nth=, or a CSS selector:mobium tap 'css=button.save', with a frame's path before it asmapprints one (iframe#f >> button).
Verifying your work
A command reporting success is not evidence the app did anything. After an action that should change the screen, confirm it:
mobium tap @e5 && mobium map # did the screen change as expected?
mobium screenshot -o after.png # look at it when the map is ambiguousDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

