Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Update the `testing/mobile-visual-testing` skill for `@metamask/client-mcp-core` 0.13.0 and `@metamask/device-mcp` 0.7.0: remove the knowledge store commands, the knowledge-reuse step and the `--goal` / `--flow-tags` launch flags, and document the global `--observe` and `--pretty` flags, one-line JSON output, observations without app state, the partial mobile `get-state`, `run-steps` `observe` (replaces `includeObservations`) and the 30 s `batchTimeoutMs` cap, timed-out calls being cancelled, calling `node_modules/.bin/mm` directly, and the Android `helper-first` snapshot default.
- Update the MetaMask Mobile performance overlay and animation references for React Native 0.86.x, Expo SDK 57, and Reanimated 4.x with `react-native-worklets`. From a worklet, call `scheduleOnRN` (`runOnJS` is a deprecated alias). Static-ESM tree-shaking stays off. ([#203](https://github.com/MetaMask/skills/pull/203))
- Require every revert yes/no to be one line that names the pull request or commit, the files, and exactly one yes/no question, whether or not security or privacy is involved. A shorter message is not that step.
- Keep a new public method or other contract change on the brief and spec path when the objection is that another package should own the edit. Put that objection in the brief.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ Command reference for the prod-only MetaMask Mobile consumer. The generic core C
## Contents

- [Syntax Rules](#syntax-rules)
- [Global Options](#global-options)
- [Lifecycle](#lifecycle)
- [Destructive Launch Flags](#destructive-launch-flags)
- [Installed State](#installed-state)
- [Interaction](#interaction)
- [Discovery](#discovery)
- [Knowledge Store](#knowledge-store)
- [Batching](#batching)
- [Hermes CDP](#hermes-cdp)
- [Simulator Selection](#simulator-selection)
Expand Down Expand Up @@ -61,6 +61,28 @@ Use exactly one targeting method per command: a positional accessibility referen
- **Matching is fuzzy and case-insensitive.** idb matches accessibility label/identifier by substring, so `--testid Confirm` can match `Confirm Transaction`. Use exact, unique test IDs to disambiguate; there is no `--within` scoping fallback on mobile.
- **`--testid` is lowercase.** `--testId` is not recognized as a flag and its value is treated as a positional target.

## Global Options

These flags work with every command and can appear anywhere in the command line.

| Flag | Description |
| --- | --- |
| `--project <path>` | Target a specific project directory. Overrides `MM_PROJECT` and git-based discovery |
| `--observe <none\|diff\|full>` | Observation returned after the call. Default: `diff` for mutating commands and `run-steps`, `none` for reads, discovery and `cdp` |
| `--pretty` | Indent JSON output. Default: one line per result when stdout is not a terminal, indented on a terminal. `MM_PRETTY=1` / `0` sets the default |

| `--observe` level | Response |
| --- | --- |
| `none` | No `observations`. Fastest. Refs are **not** refreshed: run `yarn mm describe-screen` before you use refs again |
| `diff` | Only what changed since the previous observation |
| `full` | The whole compacted screen (`a11y` + `testIds`). Becomes the new diff baseline |

Observations contain `testIds` and `a11y` only, no app state. The mobile a11y tree is flat: layout-only nodes, the status bar, the navigation bar and the React Native dev overlay are filtered out.

Every tool, `launch` and `cleanup` response includes `meta.timing` (`queueMs`, `toolMs`, `observationMs`, `totalMs`).

Agents that run many commands can call `node_modules/.bin/mm <command>` directly. It takes the same arguments as `yarn mm <command>` and skips the Yarn startup (about 0.4–0.5 s per call).

## Lifecycle

| Command | Description |
Expand All @@ -82,10 +104,10 @@ The locally installed core CLI parser exposes these launch flags that are meanin
| `--device-id <UDID>` | Select an iOS Simulator by UDID |
| `--app-bundle <path>` | Install a specific `.app` bundle before launching (for example `ios/build/MetaMask.app`). Required before any destructive flag |
| `--metro-port <port>` | Attach to a running Metro bundler on the given port. Equivalent to `MM_METRO_PORT`; the flag wins when both are set |
| `--goal <text>` | Record the session goal in knowledge metadata |
| `--flow-tags <tags>` | Record comma-separated flow tags |
| `--force` | Replace an existing active session |

The `--goal` and `--flow-tags` launch flags were removed in `@metamask/client-mcp-core` 0.13.0. Session metadata is written to `test-artifacts/<sessionId>/session.json`.

Launch timeout is 120 seconds. The project CLI does not build MetaMask. Install the intended app on the simulator before launching, or pass `--app-bundle <path>` to install a specific build.

The destructive flags `--reinstall`, `--reset-app-data`, and `--allow-fox-code-mismatch` are also parsed but guarded — see [Destructive Launch Flags](#destructive-launch-flags). For command-line Metro attachment, use `--metro-port <port>` or the `MM_METRO_PORT` environment variable as documented below.
Expand Down Expand Up @@ -143,23 +165,18 @@ All interaction commands accept on iOS:

| Command | Description |
| --- | --- |
| `yarn mm describe-screen` | Return app state, visible test IDs, accessibility tree, and prior knowledge |
| `yarn mm describe-screen` | Return the current screen, visible test IDs, and the accessibility tree with refs |
| `yarn mm screenshot [--name <name>]` | Capture the current simulator screen |
| `yarn mm accessibility-snapshot` | Return a trimmed accessibility tree (the shared `--root <selector>` flag is ignored on iOS; the full tree is always returned) |
| `yarn mm list-testids [--limit <n>]` | List visible test IDs |
| `yarn mm get-state` | Return the current app-state snapshot |
| `yarn mm get-state` | Return a partial app-state snapshot: `isLoaded`, `extensionId` (the bundle ID / package) and `source: "stub"`. There is no `currentScreen`, and wallet fields (unlock, account, network, balance) are omitted, not guessed. Identify the screen from `describe-screen` test IDs (for example `login-password-input` = unlock, `wallet-screen` = wallet home) |
| `yarn mm get-context` | Report the static prod environment and available mobile capabilities |

Mutating tools return observations with fresh references. Later actions may return compact differences from the prior observation. Use `describe-screen` whenever a complete tree or refreshed baseline is needed.
Mutating tools (`click`, `type`, ...) and `run-steps` return observations with fresh references, as a compact diff from the prior observation by default. Reads, discovery commands and `cdp` return no observation. Use `describe-screen` whenever a complete tree or refreshed baseline is needed.

## Knowledge Store
Only mutating and batch calls wait for animations before they observe. To get a settled screen after an action, let the action observe (`--observe full`) instead of running a read afterwards.

| Command | Description |
| --- | --- |
| `yarn mm knowledge-search <query>` | Search recorded steps |
| `yarn mm knowledge-last` | Return recent steps from the current session |
| `yarn mm knowledge-sessions` | List recorded sessions and metadata |
| `yarn mm knowledge-summarize [--session <id>]` | Generate a session recipe |
The knowledge store commands (`yarn mm knowledge-search`, `knowledge-last`, `knowledge-sessions`, `knowledge-summarize`) were removed in `@metamask/client-mcp-core` 0.13.0. There is no replacement: discover with `yarn mm describe-screen`.

## Batching

Expand All @@ -178,8 +195,8 @@ yarn mm run-steps '{"steps":[
| --- | --- |
| `steps` | Required array of `{tool, args}` objects |
| `stopOnError` | Stop after the first failure; defaults to `false` (remaining steps still run). Set `true` to abort on the first error |
| `includeObservations` | `'all'`, `'none'`, or `'failures'` |
| `batchTimeoutMs` | Overall deadline; remaining steps are skipped after expiry |
| `observe` | `none`, `diff` (default) or `full`: the observation collected after the batch. Replaces `includeObservations`, which was removed; check `summary.ok` to react to failures |
| `batchTimeoutMs` | Overall deadline, 1000–30000 ms; remaining steps are skipped after expiry. The whole call stops after 30 s, so use a lower value (for example 20000) to get partial results, and split longer flows into several batches |

Each step is independently checked for mobile platform support. Do not put browser-only commands in a mobile batch.

Expand Down Expand Up @@ -222,7 +239,9 @@ yarn mm launch --metro-port 8081
MM_METRO_PORT=8081 yarn mm launch
```

On Node 20, add `NODE_OPTIONS="--experimental-websocket"` when launching. Run `yarn mm describe-screen` after runtime mutation to resynchronize observations.
`yarn mm cdp` and `yarn mm hermes-targets` do not reuse the launch's `--metro-port`: they use the daemon's `HERMES_METRO_PORT` or 8081. When Metro runs on another port, pass `--metro-port <port>` on every `cdp` / `hermes-targets` call, or the call fails with `HERMES_CONNECTION_FAILED`.

On Node 20, add `NODE_OPTIONS="--experimental-websocket"` when launching. `yarn mm cdp` returns no observation by default. After runtime mutation, add `--observe full` or run `yarn mm describe-screen` to resynchronize observations.

## Simulator Selection

Expand Down Expand Up @@ -259,7 +278,6 @@ This consumer always reports the static `prod` environment and provides no local
| Command | Mobile behavior or alternative |
| --- | --- |
| `yarn mm set-context` | Environment switching is unavailable; the mobile consumer is always `prod` |
| `yarn mm get-state` | E2E fixture/state snapshot; use `yarn mm describe-screen` for live UI state |
| `yarn mm seed-contract` | Contract seeding needs the e2e chain, which this consumer does not run |
| `yarn mm seed-contracts` | Contract seeding needs the e2e chain, which this consumer does not run |
| `yarn mm get-contract-address` | Depends on seeded e2e contracts that do not exist here |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,8 @@ For in-app failures:

1. Run `yarn mm describe-screen`.
2. Identify the current screen and visible blockers. If the screen is unknown, capture a screenshot.
3. Query prior successful runs:

```bash
yarn mm knowledge-search "<flow name>"
yarn mm knowledge-sessions
yarn mm knowledge-last
```

4. Capture evidence with `yarn mm screenshot --name "debug"`.
5. Retry only after obtaining fresh accessibility references.
3. Capture evidence with `yarn mm screenshot --name "debug"`.
4. Retry only after obtaining fresh accessibility references.

## Error Codes

Expand All @@ -51,7 +43,7 @@ Launch errors use the core `ErrorCode` set. `@metamask/client-mcp-core` only pre
| `MM_GETTEXT_FAILED` | The target detached or does not expose text. Re-describe and re-target. |
| `MM_GETTEXT_TIMEOUT` | Text retrieval exceeded the deadline. Retry with a fresh target or larger `--timeout`. |
| `MM_PAGE_CLOSED` | The target closed during the action. This can be expected for transitions; inspect current state. |
| `MM_BATCH_TIMEOUT` | `run-steps` exceeded `batchTimeoutMs`. Reduce the batch or increase its deadline. |
| `MM_BATCH_TIMEOUT` | `run-steps` exceeded `batchTimeoutMs`. Split the batch; the deadline is capped at 30000 ms. |

### Session and Launch Errors

Expand Down Expand Up @@ -97,6 +89,9 @@ Launch errors use the core `ErrorCode` set. `@metamask/client-mcp-core` only pre
| `idb` not installed | Missing iOS Debug Bridge dependency (`MM_DEPENDENCIES_MISSING`) | Run `yarn mm:doctor`, then `brew tap facebook/fb && brew install idb-companion && pip3 install fb-idb` |
| Empty or failed screen snapshot | Splash screen, animation, app transition, or crash | Wait briefly, describe again, and capture a screenshot |
| Stale accessibility references | Screen changed after the references were generated | Run `yarn mm describe-screen` and use fresh references |
| Ref taps the wrong element | Ref used after a call with `--observe none` | Run `yarn mm describe-screen`, or target by `--testid` |
| `Tool execution timed out` | Call cancelled after the request limit | Run `yarn mm describe-screen` before retrying; the action can have happened |
| `Error: unknown command 'knowledge-...'` | Knowledge store removed in `@metamask/client-mcp-core` 0.13.0 | No replacement. Discover with `yarn mm describe-screen` |
| Interaction timeout | Animation, overlay, or stale/ambiguous target | Re-`describe-screen`, target by a unique test ID or fresh a11y ref (no `--within` on mobile), and increase `--timeout` only when appropriate |
| `--testId` times out | Incorrect capitalization | Use `--testid` in lowercase |
| Daemon address already in use | Stale daemon state (`MM_PORT_IN_USE`) | Run `yarn mm stop --force`, then `yarn mm launch` |
Expand Down
Loading
Loading