---
name: use-appclaw-cli
description: >
  Use the AppClaw CLI to run YAML flows, start the interactive TUI shell, explore apps,
  record/replay sessions, configure devices, and troubleshoot. Trigger for any request
  involving appclaw commands, device setup, .env configuration, running flows, vision
  setup, or debugging execution failures.
---

# AppClaw CLI Operator

You are an expert mobile automation engineer with deep Appium and real-device experience across Android and iOS. Help users install, configure, run, and troubleshoot AppClaw — the agentic AI layer for mobile automation via appium-mcp.

## Prerequisites

AppClaw requires:

- **Node.js** 18+
- **A connected device** — USB Android, Android emulator, iOS simulator, or real iOS device
- **An LLM API key** (except for Ollama which runs locally)

### Install

```sh
# Global install
npm install -g appclaw

# Or run from a local clone
git clone https://github.com/AppiumTestDistribution/appclaw.git
cd appclaw && npm install
```

### Verify

```sh
appclaw --help
appclaw --version
```

From a local clone, use `npm start` instead of `appclaw`:

```sh
npm start -- --help
npm start "Open Settings"
npm start -- --flow examples/flows/google-search.yaml
```

---

## Source of Truth

- Prefer `appclaw --help` for current flag reference.
- Inspect `.env` for the user's active configuration.
- Read `.appclaw/env/` for variable/secret bindings before giving flow advice.
- Check connected devices via `adb devices` (Android) or `xcrun simctl list devices` (iOS) before troubleshooting device issues.
- Do not invent unsupported flags or commands.

---

## CLI Modes & Commands

### 1. Agent Mode (default) — LLM-driven automation

```sh
# Resident shell — device picker, then a prompt you can run goal after goal in
appclaw

# One goal, then exit — holds the finished screen until a key is pressed
appclaw "Open Settings and turn on WiFi"
appclaw "Send hello on WhatsApp to Mom"

# With platform/device flags
appclaw --platform ios --device-type simulator "Open Safari"
appclaw --platform ios --device "iPhone 17 Pro" "Open Settings"
appclaw --udid 00008120-XXXX "Launch YouTube"

# Unattended (CI, scripts): plain console output, exits on its own
APPCLAW_TUI=off appclaw "Open Settings"
```

Both forms open **Terminal Studio** in goal mode (see below) — a plain line at its
prompt is a goal. The exit code is unchanged: 0 when every sub-goal completed, 1
otherwise. `--record`, `--json`, a non-TTY or `APPCLAW_TUI=off` take the plain
console path instead.

Add `--export [path]` to write the finished run out as a replayable
`@appclaw/runner` spec (`--export-dir` or `EXPORT_DIR` decides where a bare
filename lands; default `tests`). Inside the shell the same thing is `/export`.

**Requires:** `LLM_API_KEY` in `.env` (except Ollama). If it is missing the shell
says so on a setup screen and offers to write it, rather than exiting.

### 2. YAML Flow Mode — declarative, no LLM cost

```sh
appclaw --flow path/to/flow.yaml
appclaw --flow examples/flows/youtube-search-appium3.yaml
appclaw --flow tests/flows/youtube-phased.yaml --env dev
```

**Flags:**

- `--env <name>` — select environment file (`.appclaw/env/<name>.yaml`) for variable/secret resolution

**No LLM key needed** unless the flow has steps that fall back to LLM parsing (unrecognized natural language).

### 3. Terminal Studio (`--tui`, alias `--playground`)

```sh
appclaw --tui
appclaw --tui --platform ios --device-type simulator
appclaw --tui --device "iPhone 17 Pro"
```

One shell, two modes, decided by what a plain (non-slash) line means:

- **record** (`--tui`) — a plain line is one deterministic instruction, run live on the device and appended to a recording. `/list`, `/yaml`, `/edit` and `/export` work on that recording.
- **goal** (bare `appclaw`) — a plain line is a goal, run through the full planner. Nothing is recorded; `/export` writes the run the agent just did.

`/mode goal|record` switches without dropping the device session, and `/goal <text>` works in either. The command palette is listed permanently in record mode; in goal mode it stays hidden until the line starts with `/`.

`--playground` is an alias for `--tui` — the old playground REPL was removed. (`--json --playground` is different: a headless NDJSON bridge used by the VS Code / Cursor extension, not something to run by hand.)

Full-screen Ink shell: platform/device picker, slash-command palette, settings, run history. Device mirroring draws the screen **inside the terminal** — Kitty graphics on Ghostty/kitty/WezTerm, 24-bit ANSI half-blocks everywhere else — via `adb screencap` on Android and `xcrun simctl io … screenshot` on an iOS simulator, inside a drawn device body. Frame rate is device-bound: ~5fps on a fast Android device, ~3fps on a simulator, and as low as ~1fps on a software-rendered emulator. Start it with `^r` or `/stream`, freeze it with `^p`, tear it down with `^x`; `--stream` starts it as soon as the session opens, which is the only way to see it during `appclaw "a goal"`. Requires an interactive terminal; incompatible with `--json`.

### 4. Explorer — PRD to test flows

```sh
appclaw --explore "YouTube app with search and playback" --num-flows 5
appclaw --explore prd.txt --no-crawl --num-flows 3
appclaw --explore "Settings app" --output-dir my-flows --max-screens 15 --max-depth 4
```

| Flag                 | Default           | Purpose                                  |
| -------------------- | ----------------- | ---------------------------------------- |
| `--num-flows <N>`    | 5                 | Number of flows to generate              |
| `--no-crawl`         | false             | Skip device crawling (PRD-only analysis) |
| `--output-dir <dir>` | `generated-flows` | Where to write generated YAML files      |
| `--max-screens <N>`  | 10                | Max screens to crawl                     |
| `--max-depth <N>`    | 3                 | Max navigation depth during crawl        |

### 5. Record & Replay

```sh
# Record a goal execution (actions saved to logs/)
appclaw --record "Open Settings"

# Replay a recording (adaptive — reads screen, not coordinates)
appclaw --replay logs/recording-xyz.json
```

### 6. Report Server

```sh
appclaw --report
appclaw --report --report-port 8080
```

Starts an Express server serving HTML reports from `.appclaw/runs/`. Default port: **4173**.

### 7. Goal Decomposition

```sh
appclaw --plan "Copy the weather and send it on Slack"
```

Breaks complex multi-app goals into sub-goals, then executes each.

---

## Platform & Device Selection

### Priority Order

1. CLI flags (`--platform`, `--device-type`, `--udid`, `--device`)
2. Environment variables (`PLATFORM`, `DEVICE_TYPE`, `DEVICE_UDID`, `DEVICE_NAME`)
3. Interactive prompt (TTY only)

### Android

```sh
# Default — auto-detects connected device
appclaw "Open Settings"

# Specific emulator
appclaw --udid emulator-5554 "Open Settings"
```

Android requires `ANDROID_HOME` or `ANDROID_SDK_ROOT` set (defaults to `$HOME/Library/Android/sdk` on macOS).

### iOS Simulator

```sh
appclaw --platform ios --device-type simulator "Open Settings"
appclaw --platform ios --device-type simulator --device "iPhone 17 Pro" "Open Settings"
```

- If only one simulator is booted, it's auto-selected.
- The CLI boots the simulator, downloads WebDriverAgent (cached in `~/.cache/appium-mcp/wda/`), and installs WDA automatically.

### iOS Real Device

```sh
appclaw --platform ios --device-type real --udid 00008120-XXXX "Open Settings"
```

- **WebDriverAgent must be pre-installed** on the device (Xcode signing required).
- The CLI prompts for confirmation in TTY mode; in CI it assumes WDA is ready.
- See [appium-xcuitest-driver real device setup](https://github.com/appium/appium-xcuitest-driver/blob/master/docs/preparation/real-device-config.md) for WDA signing instructions.

---

## Configuration (`.env`)

All configuration via `.env` in the working directory. Copy `.env.example` to get started:

```sh
cp .env.example .env
```

### LLM Setup (required for agent/explorer/planner modes)

| Variable       | Default     | Options                                           |
| -------------- | ----------- | ------------------------------------------------- |
| `LLM_PROVIDER` | `anthropic` | `anthropic`, `openai`, `gemini`, `groq`, `ollama` |
| `LLM_API_KEY`  | —           | Your provider's API key (not needed for Ollama)   |
| `LLM_MODEL`    | auto        | Override model ID (see defaults below)            |

**Default models per provider:**

| Provider    | Default Model              |
| ----------- | -------------------------- |
| `anthropic` | `claude-sonnet-4-20250514` |
| `openai`    | `gpt-4o`                   |
| `gemini`    | `gemini-2.0-flash`         |
| `groq`      | `llama-3.3-70b-versatile`  |
| `ollama`    | `llama3.2`                 |

### Agent Mode & Vision

Two strategies for finding elements on screen:

| Setup           | `AGENT_MODE` | Best For                                                                                |
| --------------- | ------------ | --------------------------------------------------------------------------------------- |
| **DOM mode**    | `dom`        | Standard apps with good accessibility labels. Uses XML page source. Works with any LLM. |
| **Vision mode** | `vision`     | Custom views, canvas-rendered UI, games. Screenshot-first with AI vision.               |

#### DOM Mode (simplest)

```env
LLM_PROVIDER=gemini
LLM_API_KEY=your-key
AGENT_MODE=dom
```

#### Vision + Stark (recommended for vision)

```env
LLM_PROVIDER=gemini
LLM_API_KEY=your-gemini-key
AGENT_MODE=vision
VISION_LOCATE_PROVIDER=stark
GEMINI_API_KEY=your-gemini-key
```

Stark uses df-vision + Gemini in-process. Same API key works for both LLM and vision.

#### Vision + appium-mcp

```env
LLM_PROVIDER=gemini
LLM_API_KEY=your-key
AGENT_MODE=vision
VISION_LOCATE_PROVIDER=appium_mcp
AI_VISION_ENABLED=true
AI_VISION_API_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai
AI_VISION_API_KEY=your-key
AI_VISION_MODEL=gemini-2.0-flash
AI_VISION_COORD_TYPE=absolute
```

### Vision Fallback (DOM + Vision hybrid)

Even in DOM mode, vision can kick in when DOM matching fails:

```env
AGENT_MODE=dom
VISION_MODE=fallback    # always | fallback | never
```

### Tuning Parameters

| Variable                     | Default | Purpose                                                       |
| ---------------------------- | ------- | ------------------------------------------------------------- |
| `MAX_STEPS`                  | 30      | Max steps per goal before stopping                            |
| `STEP_DELAY`                 | 500     | Milliseconds between steps                                    |
| `MAX_ELEMENTS`               | 40      | Max interactive elements per screen capture                   |
| `MAX_HISTORY_STEPS`          | 10      | Previous steps kept in LLM context                            |
| `LLM_THINKING`               | `on`    | Extended thinking/reasoning (`on` or `off`)                   |
| `LLM_THINKING_BUDGET`        | 128     | Token budget for thinking                                     |
| `LLM_SCREENSHOT_MAX_EDGE_PX` | 0       | Downscale screenshots for LLM (try 384 or 768 to reduce cost) |
| `SHOW_TOKEN_USAGE`           | `false` | Print token usage and cost per step                           |

### MCP Transport

| Variable        | Default     | Purpose                                                                 |
| --------------- | ----------- | ----------------------------------------------------------------------- |
| `MCP_TRANSPORT` | `stdio`     | `stdio` (auto-launches appium-mcp) or `sse` (connect to running server) |
| `MCP_HOST`      | `localhost` | SSE transport: hostname                                                 |
| `MCP_PORT`      | `8080`      | SSE transport: port                                                     |

**stdio** (default) — AppClaw spawns `npx appium-mcp@latest` as a subprocess. No manual server setup.

**SSE** — Connect to an already-running appium-mcp server. Useful for shared environments or debugging.

### Episodic Memory

```env
EPISODIC_MEMORY=on    # off by default
```

Records successful trajectories to `~/.appclaw/trajectories.json` and reuses them for similar goals in future runs.

---

## Safety Policy

**Safe without approval:**

- `appclaw --help`, `appclaw --version`
- `appclaw --flow` (YAML execution — predictable, no LLM)
- `appclaw --report` (read-only report server)
- Reading `.env`, `.appclaw/env/`, flow YAML files

**Ask before executing:**

- `appclaw "goal"` (agent mode — uses LLM credits, takes actions on device)
- `appclaw --explore` (LLM credits + device crawling)
- `appclaw --record` (agent mode + saves recording)
- `appclaw` / `appclaw --tui` (interactive device session; goals typed inside it use LLM credits — `--playground` is an alias for `--tui`)

Why: agent and explorer modes consume LLM API credits and take real actions on the connected device.

---

## Troubleshooting

### Device Issues

| Problem                   | Diagnosis                                   | Fix                                                   |
| ------------------------- | ------------------------------------------- | ----------------------------------------------------- |
| "No devices found"        | `adb devices` / `xcrun simctl list devices` | Connect device, boot emulator/simulator               |
| Android not detected      | Check `ANDROID_HOME`                        | `export ANDROID_HOME=$HOME/Library/Android/sdk`       |
| iOS simulator WDA failure | WDA cache issue                             | Delete `~/.cache/appium-mcp/wda/` and retry           |
| iOS real device WDA       | Signing required                            | Follow appium-xcuitest-driver real device setup guide |
| Wrong device selected     | Multiple devices connected                  | Use `--udid` or `--device` to specify                 |

### MCP Connection Issues

| Problem                    | Fix                                                   |
| -------------------------- | ----------------------------------------------------- |
| "Failed to connect to MCP" | Check that `npx appium-mcp@latest` runs standalone    |
| SSE connection refused     | Verify `MCP_HOST` and `MCP_PORT` match running server |
| Tool call timeout          | Check device USB/network, restart appium-mcp          |

### Vision Issues

| Problem                           | Fix                                                                   |
| --------------------------------- | --------------------------------------------------------------------- |
| Stark vision fails                | Verify `GEMINI_API_KEY` or `STARK_VISION_API_KEY` is set and valid    |
| appium-mcp vision fails           | Check all `AI_VISION_*` vars are set; verify the API URL is reachable |
| Vision returns wrong coordinates  | Try `AI_VISION_COORD_TYPE=absolute` for Gemini                        |
| Element not found (DOM or vision) | Enable vision fallback: `VISION_MODE=fallback`                        |

### Flow Execution Issues

| Problem                              | Fix                                                          |
| ------------------------------------ | ------------------------------------------------------------ |
| "Undefined secret"                   | Export the shell variable: `export VAR_NAME=value`           |
| "Undefined variable"                 | Add the key to `.appclaw/env/<name>.yaml` under `variables:` |
| `launchApp` fails                    | Set `appId` in the YAML header                               |
| Tap misses element                   | Use more specific label text; enable vision fallback         |
| Natural language step not recognized | Use structured syntax instead (e.g., `tap: "Login"`)         |

### LLM Issues

| Problem            | Fix                                                                                                                        |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| "API key required" | Set `LLM_API_KEY` in `.env`                                                                                                |
| Model not found    | Check `LLM_MODEL` matches provider's model ID                                                                              |
| High cost          | Use cheaper models (`gemini-2.0-flash`, `gpt-4o-mini`), reduce `LLM_THINKING_BUDGET`, set `LLM_SCREENSHOT_MAX_EDGE_PX=384` |
| Stuck in loop      | Stuck detection kicks in after 3 repeated screens. Increase `MAX_STEPS` or simplify the goal                               |

---

## Common Workflows

### Run a YAML flow on Android

```sh
appclaw --flow examples/flows/settings-wifi-on.yaml
```

### Run a flow with environment variables

```sh
appclaw --flow tests/flows/youtube-phased.yaml --env dev
```

### Quick test on iOS simulator

```sh
appclaw --platform ios --device-type simulator --tui
# In the TUI: type commands, test them, /export to YAML
```

### Generate test flows from a PRD

```sh
appclaw --explore "E-commerce app with cart and checkout" --num-flows 10 --output-dir flows/
```

### View execution reports

```sh
appclaw --report
# Open http://localhost:4173 in browser
```

### Cost-effective setup (Gemini)

```env
LLM_PROVIDER=gemini
LLM_API_KEY=your-key
LLM_MODEL=gemini-2.0-flash
AGENT_MODE=vision
VISION_LOCATE_PROVIDER=stark
GEMINI_API_KEY=your-key
LLM_SCREENSHOT_MAX_EDGE_PX=512
```

Gemini Flash is the cheapest vision-capable model ($0.10/M input tokens). One key covers both LLM and Stark vision.

### Free local setup (Ollama)

```env
LLM_PROVIDER=ollama
LLM_MODEL=llama3.2
AGENT_MODE=dom
```

No API key needed. Requires [Ollama](https://ollama.ai) running locally. DOM mode recommended since local models lack vision capability.

---

## IDE Integration (VSCode Extension)

AppClaw has a VSCode extension that communicates via JSON mode:

```sh
appclaw --json "Open Settings"
```

The `--json` flag enables structured JSON event output and silences the rich terminal UI. This is used by the VSCode extension bridge — users don't need to use this flag directly.

---

## Coordination

- For **creating or editing YAML flow files**, route to the `generate-appclaw-flow` skill.
- For **reviewing code changes** to the AppClaw codebase itself, route to the `review-changes` skill.
