| name | appium-cli |
| description | Drive Android and iOS automation through the appium-cli terminal tool against a running Appium server. Covers session lifecycle (connect, attach, disconnect), semantic UI actions (tap, type, swipe, scroll, long-press, double-tap, pinch, drag), waits and locators (wait, find, active-element, inspect-locators, dump-ui, inspect, scroll-to), app and device control (launch, terminate, install, uninstall, is-installed, background, app, device, permissions, geo, record, settings, clipboard, orientation, lock, unlock, hide-keyboard, keyboard, alert, context, send-keys, press-key, keyevent, logs), screenshots, capabilities, and host-side device discovery (devices, ios). Always emits stable JSON via --json or --ai with documented exit codes, so it is the preferred tool when the user mentions appium-cli, Appium from a shell or CI, semantic UI commands, mobile automation scripting, or driving an emulator, simulator, or real device from the terminal. Deploy this skill with `appium-cli skill install <agent>` where `<agent>` is cursor, claude, codex, or cwd. |
appium-cli (agent skill)
appium-cli is a Node.js CLI that talks to a running Appium HTTP server. It is the right tool whenever the user wants to automate a mobile device or emulator from the shell, especially when stable JSON output and exit codes matter (CI pipelines, agentic loops, reproducible scripts).
This skill is the contract for an agent that drives appium-cli. Read this file first; pull in the reference files only when you need them.
| When you need… | Read |
|---|
| Full command catalogue with flags | commands.md |
| Worked recipes (login, scroll-until, capture evidence, parallel sessions) | recipes.md |
| Exit codes, error payloads, recovery rules | troubleshooting.md |
1. Preconditions before any command
Verify these once per session, in order:
- Node.js 18 or newer is on
PATH (node --version).
- An Appium server is running and reachable (default
http://127.0.0.1:4723). If unsure, run curl <url>/status or ask the user.
- The right driver is installed on that server (UiAutomator2 for Android, XCUITest for iOS, etc.). The CLI does not install drivers.
- A device, emulator, or simulator is online and matches the capabilities you intend to send.
- The CLI is invokable. Pick one:
- In-repo:
node ./bin/appium-cli.js <args>
- Linked:
npm link once, then appium-cli <args>
- Published:
npm i -g appium-cli, then appium-cli <args>
Do not invent flags. When unsure, run appium-cli --help or appium-cli <group> --help and parse the output instead of guessing.
2. Required mental model
-
The CLI is stateful across processes via a session file at ~/.appium-cli/session.json. Each invocation is a fresh Node process that reads that file.
-
A session is named (default default). Use --session <name> to keep multiple flows isolated (e.g. smoke, login, regression).
-
Session state stores the remote serverUrl, sessionId, normalized platform, and capabilities. attach sets attachOnly: true so disconnect knows it did not create the session.
-
Commands fall into three buckets:
| Bucket | Examples | Needs active session? |
|---|
| HTTP to Appium | tap, type, swipe, screenshot, find, dump-ui, app …, device … | Yes (connect or attach first) |
| Local session admin | session status, session list, session use, disconnect --detach | No |
| Host-side discovery | devices list, devices caps-snippet, ios simulator prepare, ios wda prepare-real | No |
3. Global flags (always place BEFORE the subcommand)
appium-cli [GLOBAL FLAGS] <command> [command flags] [args]
| Flag | What it does | When to use it |
|---|
--json | Print a structured JSON object on stdout. | Default this on for any agent / script step. |
--ai | Like --json plus extra hints (e.g. suggestions). | When you want the CLI to volunteer next-step ideas. |
--session <name> | Pick which named session to operate on. | Parallel flows; restoring a specific run. |
--timeout <ms> | HTTP timeout. Default 10000. | Slow networks, real devices, large dumps. |
--quiet | Suppress non-error stdout (text mode only). | Pipelines that only care about exit code. |
--verbose | Extra diagnostics. | Debugging. |
Wrong: appium-cli tap "OK" --json (Commander treats --json as a tap-level flag and may not parse).
Right: appium-cli --json tap "OK".
4. Standard agent workflow
Use this checklist for every automation task. Fill in command lines as you go.
- [ ] 1. Confirm preconditions (see section 1)
- [ ] 2. Pick or create a session (connect | attach | session use)
- [ ] 3. Snapshot the screen (dump-ui or inspect with --json)
- [ ] 4. Plan the smallest sequence of semantic actions
- [ ] 5. Execute each step with --json; check ok and exit code
- [ ] 6. Capture evidence on failure (screenshot, dump-ui)
- [ ] 7. Disconnect or detach when done
4.1 Session lifecycle
appium-cli --json connect \
--server http://127.0.0.1:4723 \
--caps ./caps.json \
--session smoke
appium-cli --json attach \
--server http://127.0.0.1:4723 \
--session-id <existing-session-id> \
--name smoke
appium-cli --json session status
appium-cli --json session list
appium-cli --json disconnect --session smoke
appium-cli --json disconnect --session smoke --detach
4.2 See what is on screen before acting
appium-cli --json dump-ui --simplified
appium-cli --json inspect "Continue"
appium-cli --json inspect-locators
appium-cli --json active-element
4.3 Act semantically
appium-cli --json tap "Sign in"
appium-cli --json tap "Sign in" --role button --index 0
appium-cli --json type "Email" "user@example.com" --clear
appium-cli --json type "Password" "hunter2" --submit
appium-cli --json swipe up --distance 0.5 --duration 300
appium-cli --json scroll-to "Privacy Policy"
appium-cli --json wait "Welcome"
appium-cli --json wait "Loading..." --gone
4.4 Act at the locator / coordinate level
appium-cli --json find --using "accessibility id" --selector "submit_btn"
appium-cli --json long-press "Item"
appium-cli --json double-tap --x 200 --y 400
appium-cli --json pinch "Map" --scale 1.5
appium-cli --json drag --from-query "Card A" --to-query "Trash"
appium-cli --json actions --file ./gestures.json
4.5 Capture evidence
appium-cli --json screenshot --out ./out/step.png
appium-cli --json screenshot --element "Profile avatar" --out ./out/avatar.png
appium-cli --json dump-ui --out ./out/tree.json
5. Output contract (parse this, do not parse text)
When --json or --ai is set, every command writes a single JSON object to stdout. Errors go to stderr as JSON too.
Success shape (fields beyond ok and action vary per command):
{
"schemaVersion": 1,
"ok": true,
"action": "tap",
"okText": "tapped",
"query": "Sign in",
"matched": {
"score": 0.93,
"strategy": "accessibility id",
"resourceId": "...",
"text": "Sign in",
"bounds": [120, 480, 600, 560]
}
}
Error shape:
{
"schemaVersion": 1,
"ok": false,
"error": {
"message": "No element matched query \"Continue\"",
"code": "ELEMENT_NOT_FOUND",
"details": { "query": "Continue" }
}
}
Rules for agents:
- Always check
ok === true before treating the run as success.
- Use the process exit code as the primary signal in shell pipelines (see troubleshooting.md).
- Do not regex the human-readable lines (
✓ tapped …); they are for users, not for parsing.
schemaVersion may rise; keep parsing tolerant of new fields.
6. Decision rules (when to do what)
| Situation | Do this | Avoid |
|---|
| Need to click a button by visible label | tap "<label>" (semantic) | Hand-writing XPath unless find is required |
| Element identified by accessibility id only | find --using "accessibility id" --selector "<id>" | Trying many semantic queries |
| Same screen, multiple matches | Add --role or --index | Random retries |
| Element off-screen | scroll-to "<query>" then act | Long manual swipes |
| App not responding to touch | screenshot + dump-ui first | Re-tapping blindly |
| Need to test deep link | app deep-link "<url>" | Manual launcher navigation |
| Need to install / replace an APK or IPA | install <path> (use uninstall <appId> first if needed) | Driver-specific shell tricks |
| Multiple parallel devices | One --session <name> per device | Sharing the default session |
| Long-running waits | Raise --timeout, prefer wait over sleep | Sleeping in the shell |
| You do not know what is on screen | dump-ui --simplified or inspect | Guessing |
7. What this CLI does NOT do
State these limits upfront when relevant; do not pretend otherwise.
- It does not run an Appium server or install drivers; the user manages those.
- It does not run an embedded driver; a reachable HTTP server URL is required for HTTP commands.
- It does not bundle docs search or test generation; rely on
--help, dump-ui, and the project README.
- The
ios simulator prepare and ios wda prepare-real commands require macOS with Xcode and are skipped on other operating systems.
- Behavior of
mobile:* extensions, screen recording, permissions on real iOS, alert handling, and pinch parameters depends on the driver and version running on the server. Surface the server's error message verbatim when these vary.
8. Failure handling protocol
When a command fails (ok: false or non-zero exit code):
- Capture context immediately before the screen changes:
appium-cli --json screenshot --out ./out/fail-<step>.png
appium-cli --json dump-ui --out ./out/fail-<step>.json
- Map the exit code using troubleshooting.md and act on the cause, not the symptom:
2 element not found → re-snapshot, refine query or use find.
3 ambiguous → add --role / --index.
5 no active session → run connect or attach.
6 timeout → raise --timeout, or wait for the precondition first.
7 attach / server unreachable → check the Appium server and URL.
- Do not loop blindly. Two failed attempts on the same query without new evidence means stop and report.
- Report back with: command run, full JSON payload, exit code, and the next step you propose.
9. Installing this skill in different agents
This is a portable skill bundle. The folder name appium-cli and the file name SKILL.md are what each tool looks for.
Required: skill install <agent>
From the published CLI (npm i -g appium-cli), you must pass an agent name. There is no bare skill install.
appium-cli skill install --help
appium-cli skill install cursor
appium-cli skill install claude
appium-cli skill install codex
appium-cli skill install cwd
- For
cursor or cwd, cd to the project directory first — both use process.cwd().
- For
claude and codex, the destination is under your home directory; cwd only matters if you care where you run the command from for logging.
If you run skill install cursor from inside the appium-cli package repo where the bundled skill already lives at the same path, the CLI reports already in place and does nothing. Use another project, or use claude / codex / cwd.
| Tool | How to get the skill |
|---|
| Cursor (this repo) | Files already under <repo>/.cursor/skills/appium-cli/ (and Skill/appium-cli/). |
| Cursor (other projects) | appium-cli skill install cursor from that project’s root. User-wide: manually copy the folder to ~/.cursor/skills/appium-cli/ — never ~/.cursor/skills-cursor/ (reserved by Cursor). |
| Claude Code | appium-cli skill install claude |
| OpenAI Codex CLI | appium-cli skill install codex |
| Other tools | Copy the appium-cli folder (or the four .md files) per that tool’s documentation. |
The bundle is four files: SKILL.md, commands.md, recipes.md, troubleshooting.md.
10. Authoritative discovery commands
When you are unsure about a flag or subcommand, prefer running the help over guessing:
appium-cli --help
appium-cli skill install --help
appium-cli <command> --help
appium-cli <group> <sub> --help
appium-cli --version
Also useful for state inspection without touching the device:
appium-cli --json session list
appium-cli --json session status
appium-cli --json caps