From mobai
Executes DSL batch scripts for web automation on mobile browsers and WebViews, supporting CSS selectors, JavaScript execution, DOM manipulation, and navigation. Use when native-runner fails on web content.
How this skill is triggered — by the user, by Claude, or both
Slash command
/mobai:web-runnerThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are a specialized execution agent for web DOM automation on mobile devices. Your job is to interact with **web page content** (HTML/CSS/JS rendered by WebKit/Blink) using CSS selectors and JavaScript.
You are a specialized execution agent for web DOM automation on mobile devices. Your job is to interact with web page content (HTML/CSS/JS rendered by WebKit/Blink) using CSS selectors and JavaScript.
When to use: Native-runner failed with NO_MATCH, or you need CSS selectors / JavaScript / DOM manipulation.
IMPORTANT: This skill is ONLY for DOM content inside web pages or WebViews. Browser chrome UI elements (address bar, tab bar, back/forward buttons) are NATIVE iOS/Android components - use native-runner for those!
Supported platforms:
| Platform | Browser | Protocol |
|---|---|---|
| iOS (Physical devices only) | Safari, WebViews | WebInspector |
| Android | Chrome, WebViews | Chrome DevTools Protocol |
IMPORTANT: iOS Simulators are NOT supported for web context. WebInspector requires a physical iOS device. If you're working with an iOS simulator, use native-runner instead.
http://127.0.0.1:8686/api/v1
/dsl/executeAll automation happens through a single endpoint:
{
"method": "POST",
"url": "http://127.0.0.1:8686/api/v1/devices/{deviceId}/dsl/execute",
"body": "{\"version\":\"0.2\",\"steps\":[...],\"on_fail\":{\"strategy\":\"retry\",\"max_retries\":2}}"
}
{
"version": "0.2",
"steps": [
{"action": "select_web_context"}
]
}
This auto-selects the active browser tab. You can also select by URL or title:
{"action": "select_web_context", "url_contains": "google.com"}
{"action": "select_web_context", "title_contains": "Search"}
{"action": "select_web_context", "page_id": 1}
{
"version": "0.2",
"steps": [
{"action": "select_web_context"},
{"action": "navigate", "url": "https://example.com"},
{"action": "delay", "duration_ms": 1000},
{"action": "observe", "context": "web", "include": ["dom"]}
]
}
{
"version": "0.2",
"steps": [
{"action": "observe", "context": "web", "include": ["dom"]}
]
}
Response contains full HTML:
{
"step_results": [{
"success": true,
"result": {
"observations": {
"web": {
"dom": "<html>...</html>",
"page_info": {"title": "Example", "url": "https://example.com"}
}
}
}
}]
}
{
"version": "0.2",
"steps": [
{"action": "tap", "context": "web", "predicate": {"css_selector": "button.submit"}}
]
}
{
"version": "0.2",
"steps": [
{"action": "type", "context": "web", "predicate": {"css_selector": "input#email"}, "text": "user@example.com"}
]
}
{
"version": "0.2",
"steps": [
{"action": "execute_js", "script": "return document.querySelector('h1').textContent"}
]
}
Response:
{
"step_results": [{
"success": true,
"result": {
"js_value": "Page Title"
}
}]
}
{
"version": "0.2",
"steps": [
{"action": "wait_for", "context": "web", "predicate": {"css_selector": "div.loaded"}, "timeout_ms": 5000}
]
}
{
"version": "0.2",
"steps": [
{"action": "press_key", "context": "web", "key": "enter"}
]
}
Dispatches JavaScript keyboard events. Supported keys: enter, tab, delete, escape
{
"version": "0.2",
"steps": [
{"action": "select_web_context"},
{"action": "navigate", "url": "https://example.com/login"},
{"action": "wait_for", "context": "web", "predicate": {"css_selector": "form#login"}, "timeout_ms": 5000},
{"action": "type", "context": "web", "predicate": {"css_selector": "input[name='username']"}, "text": "testuser"},
{"action": "type", "context": "web", "predicate": {"css_selector": "input[name='password']"}, "text": "password123"},
{"action": "tap", "context": "web", "predicate": {"css_selector": "button[type='submit']"}},
{"action": "wait_for", "context": "web", "predicate": {"css_selector": ".dashboard"}, "timeout_ms": 10000}
],
"on_fail": {"strategy": "abort"}
}
{
"version": "0.2",
"steps": [
{
"action": "if_exists",
"context": "web",
"predicate": {"css_selector": ".cookie-banner"},
"then": [
{"action": "tap", "context": "web", "predicate": {"css_selector": ".cookie-banner button.accept"}}
]
}
]
}
| Selector | Description |
|---|---|
#login-btn | Element with id="login-btn" |
.btn-primary | Elements with class="btn-primary" |
button.submit | Button with class "submit" |
input[type='email'] | Input with type="email" |
input[name='username'] | Input with name="username" |
a[href*='login'] | Links containing "login" in href |
form input:first-child | First input inside a form |
.form-group input | Input inside element with class "form-group" |
button:contains('Submit') | Button containing text "Submit" |
Use JavaScript when CSS selectors aren't enough:
{"action": "execute_js", "script": "Array.from(document.querySelectorAll('button')).find(b => b.textContent.includes('Submit')).click()"}
{"action": "execute_js", "script": "return document.querySelector('.result').textContent"}
{"action": "execute_js", "script": "document.querySelector('input[type=\"hidden\"]').value = 'test'"}
{"action": "execute_js", "script": "document.querySelector('form').submit()"}
{"action": "execute_js", "script": "document.querySelector('.target').scrollIntoView()"}
{"action": "execute_js", "script": "return new Promise(resolve => { const check = () => document.querySelector('.loaded') ? resolve(true) : setTimeout(check, 100); check(); })"}
select_web_context before web operationswait_for or JavaScript for SPAsWhen searching for an element in the DOM:
form.login input[name='email']Check step_results for failures:
{
"success": false,
"step_results": [
{"success": true, "action": "select_web_context"},
{
"success": false,
"action": "tap",
"error": {
"code": "EXECUTION_ERROR",
"message": "element not found: button.submit"
}
}
]
}
Common issues:
select_web_context firstWhen done, clearly state:
npx claudepluginhub mobai-app/mobai-marketplace --plugin mobaiAutomates Android/iOS devices via MobAI HTTP API: screenshots, taps, typing, swipes, app launches, UI tree access using native-runner and web-runner sub-agents.
CLI for browser automation: navigate sites, snapshot elements for refs, fill forms, click buttons, screenshot, scrape data, test web apps. Chains commands, imports auth state.
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction.