> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobster.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Test suite tools

> Run the project's saved checks, read their history and settle healed steps.

## `run_tests`

Run the project's saved checks on simulators; returns the summary and JUnit/HTML reports, or a `suite_id` to wait on. With pr, test what this branch changed and answer with the verdict, frames and GIFs.

**Acts on the device.**

**Arguments**

| Name | Type | Default | Description |
| - | - | - | - |
| `path` | string | see description | Absolute path of a check file or a folder of checks; default the project's .mobster/checks. With pr: the project (the folder holding .mobster or the git repository), default the server's. 1 to 4,096 characters. |
| `sims` | array of strings | each check's own | Simulators to run on, each a device type with an optional runtime, such as "iPhone 17 Pro\@iOS 26.4". At most 8 items. Each item: 1 to 128 characters. |
| `parallel` | integer | `1` | Simulators running checks at once. 1 to 4. |
| `retries` | integer | `1` | Attempts after a failure. 0 to 3. |
| `tags` | array of strings | | Run only the checks with any of these tags. At most 10 items. Each item: 1 to 40 characters. |
| `failed` | boolean | | Run only the checks that didn't pass in the project's last run (failed, couldn't run or needs review); path names the project; leave tags out. |
| `locales` | array of strings | | Run every check once in each of these languages, such as \["de", "ja", "ar"] (`mobster test --locale`): the app launches in the language and the screens are read for truncated text, untranslated strings and a right-to-left layout that didn't mirror. At most 12 items. Each item: 2 to 12 characters. |
| `a11y` | string | | Audit the screens each check reads for accessibility (`mobster test --a11y`): warn reports findings and passes, strict fails the check. One of `warn` or `strict`. |
| `fresh` | boolean | `false` | Run every step with Smart and record the path again, instead of replaying the recorded one with no model. |
| `no_heal` | boolean | see description | Fail a check whose screen changed instead of healing the step with Smart (strict CI; default false). |
| `pr` | boolean | `false` | Test what this branch changed; base, device, build, scheme, testflight, drafts and github go with it, and parallel, retries, tags, fresh and `no_heal` don't. |
| `base` | string | `origin/main` | With pr: the branch the PR merges into. 1 to 200 characters. |
| `device` | string | | With pr: run on this iPhone instead of simulators: a name from `list_devices` that `mobster mcp --allow-device` names. 1 to 128 characters. |
| `build` | boolean | `true` | With pr: build the app first. |
| `scheme` | string | the only one | With pr: the Xcode scheme to build. 1 to 200 characters. |
| `testflight` | string | | With pr and device: the bundle ID of the user's TestFlight build to test; only one `mobster mcp --allow-testflight` names. 1 to 200 characters. |
| `drafts` | string | see description | With pr: draft checks for uncovered screens and run them (default), only write them, or neither. One of `run`, `write` or `off`. |
| `github` | string | see description | With pr: put the verdict on the pull request with Mobster Checks, the GitHub App: a check run (default), the check run and one comment, or nothing. One of `check`, `comment` or `off`. |
| `suite_id` | string | | A suite `run_tests` started: wait for it instead of starting one. Matches `^[0-9]{8}-[0-9]{6}-[0-9a-f]{4}$`. |
| `timeout_s` | number | `30` | How long to wait for the suite. 1 to 38. |

**Example**

```json tools/call params theme={"theme":"css-variables"}
{"name": "run_tests", "arguments": {}}
```

**Returns**

While the suite runs past `timeout_s`, a line with its progress, and `structuredContent` has `status` `running`, `suite_id`, `done`, `total` and `message`: call it again with `suite_id` to keep waiting. When it finishes, the counts, each check that didn't pass and why, healed steps, and the report and JUnit paths. `structuredContent` has `status` `finished`, `suite_id`, `exit_code`, `summary`, `failures`, `report`, `junit` and `results`. With `pr`, it has `headline`, `counts`, `rows`, `drafts`, `comment`, `pr_json` and `report` in place of `summary`, `failures`, `junit` and `results`, and up to 2 failed checks' frames come as JPEGs.

> [accordion] Input schema and annotations of run\_tests
>
> Annotations: `title: "Run tests"`, `readOnlyHint: false`, `destructiveHint: false`, `openWorldHint: true`
>
> ```json theme={"theme":"css-variables"}
> {
>   "type": "object",
>   "properties": {
>     "path": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 4096,
>       "description": "absolute path of a check file or a folder of checks; default the project's .mobster/checks. With pr: the project (the folder holding .mobster or the git repository), default the server's"
>     },
>     "sims": {
>       "type": "array",
>       "maxItems": 8,
>       "items": {
>         "type": "string",
>         "minLength": 1,
>         "maxLength": 128
>       },
>       "description": "simulators to run on, each a device type with an optional runtime, such as \"iPhone 17 Pro@iOS 26.4\"; default each check's own"
>     },
>     "parallel": {
>       "type": "integer",
>       "minimum": 1,
>       "maximum": 4,
>       "description": "simulators running checks at once (default 1)"
>     },
>     "retries": {
>       "type": "integer",
>       "minimum": 0,
>       "maximum": 3,
>       "description": "attempts after a failure (default 1)"
>     },
>     "tags": {
>       "type": "array",
>       "maxItems": 10,
>       "items": {
>         "type": "string",
>         "minLength": 1,
>         "maxLength": 40
>       },
>       "description": "run only the checks with any of these tags"
>     },
>     "failed": {
>       "type": "boolean",
>       "description": "run only the checks that didn't pass in the project's last run (failed, couldn't run or needs review); path names the project; leave tags out"
>     },
>     "locales": {
>       "type": "array",
>       "maxItems": 12,
>       "items": {
>         "type": "string",
>         "minLength": 2,
>         "maxLength": 12
>       },
>       "description": "run every check once in each of these languages, such as [\"de\", \"ja\", \"ar\"] (`mobster test --locale`): the app launches in the language and the screens are read for truncated text, untranslated strings and a right-to-left layout that didn't mirror"
>     },
>     "a11y": {
>       "type": "string",
>       "enum": [
>         "warn",
>         "strict"
>       ],
>       "description": "audit the screens each check reads for accessibility (`mobster test --a11y`): warn reports findings and passes, strict fails the check"
>     },
>     "fresh": {
>       "type": "boolean",
>       "description": "run every step with Smart and record the path again, instead of replaying the recorded one with no model (default false)"
>     },
>     "no_heal": {
>       "type": "boolean",
>       "description": "fail a check whose screen changed instead of healing the step with Smart (strict CI; default false)"
>     },
>     "pr": {
>       "type": "boolean",
>       "description": "test what this branch changed (default false); base, device, build, scheme, testflight, drafts and github go with it, and parallel, retries, tags, fresh and no_heal don't"
>     },
>     "base": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 200,
>       "description": "with pr: the branch the PR merges into (default origin/main)"
>     },
>     "device": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 128,
>       "description": "with pr: run on this iPhone instead of simulators: a name from list_devices that `mobster mcp --allow-device` names"
>     },
>     "build": {
>       "type": "boolean",
>       "description": "with pr: build the app first (default true)"
>     },
>     "scheme": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 200,
>       "description": "with pr: the Xcode scheme to build (default the only one)"
>     },
>     "testflight": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 200,
>       "description": "with pr and device: the bundle ID of the user's TestFlight build to test; only one `mobster mcp --allow-testflight` names"
>     },
>     "drafts": {
>       "type": "string",
>       "enum": [
>         "run",
>         "write",
>         "off"
>       ],
>       "description": "with pr: draft checks for uncovered screens and run them (default), only write them, or neither"
>     },
>     "github": {
>       "type": "string",
>       "enum": [
>         "check",
>         "comment",
>         "off"
>       ],
>       "description": "with pr: put the verdict on the pull request with Mobster Checks, the GitHub App: a check run (default), the check run and one comment, or nothing"
>     },
>     "suite_id": {
>       "type": "string",
>       "pattern": "^[0-9]{8}-[0-9]{6}-[0-9a-f]{4}$",
>       "description": "a suite run_tests started: wait for it instead of starting one"
>     },
>     "timeout_s": {
>       "type": "number",
>       "minimum": 1,
>       "maximum": 38.0,
>       "description": "how long to wait for the suite (default 30)"
>     }
>   },
>   "required": [],
>   "additionalProperties": false
> }
> ```

## `test_history`

Read the project's test history: each check's last 20 results per device, pass rate and flake score, flaky first.

**Read-only.**

**Arguments**

| Name | Type | Default | Description |
| - | - | - | - |
| `path` | string | the server's | Absolute path of the project (the folder holding .mobster). 1 to 4,096 characters. |
| `check` | string | | Only checks whose name or file contains this text. 1 to 200 characters. |
| `flaky_only` | boolean | | Only checks the history calls flaky. |
| `limit` | integer | `50` | Most rows to return. 1 to 200. |

**Example**

```json tools/call params theme={"theme":"css-variables"}
{"name": "test_history", "arguments": {}}
```

**Returns**

One line per check and device: its state and how many runs passed. `structuredContent` has `ok` (false when the history file couldn't be read), `total` and `checks`.

> [accordion] Input schema and annotations of test\_history
>
> Annotations: `title: "Test history"`, `readOnlyHint: true`, `destructiveHint: false`, `idempotentHint: true`, `openWorldHint: false`
>
> ```json theme={"theme":"css-variables"}
> {
>   "type": "object",
>   "properties": {
>     "path": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 4096,
>       "description": "absolute path of the project (the folder holding .mobster); default the server's"
>     },
>     "check": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 200,
>       "description": "only checks whose name or file contains this text"
>     },
>     "flaky_only": {
>       "type": "boolean",
>       "description": "only checks the history calls flaky"
>     },
>     "limit": {
>       "type": "integer",
>       "minimum": 1,
>       "maximum": 200,
>       "description": "most rows to return (default 50)"
>     }
>   },
>   "required": [],
>   "additionalProperties": false
> }
> ```

## `test_schedule`

list: the project's nightly run, when it runs and last night's verdict. run: run it now on simulators; a schedule that names an iPhone is refused.

**Local.**

**Arguments**

| Name | Type | Default | Description |
| - | - | - | - |
| `action` | string | see description | List (default) or run. One of `list` or `run`. |
| `path` | string | the server's | Absolute path of the project (the folder holding .mobster). 1 to 4,096 characters. |
| `suite_id` | string | | With run: a suite this tool started, to wait for it again. Matches `^[0-9]{8}-[0-9]{6}-[0-9a-f]{4}$`. |
| `timeout_s` | number | `30` | With run: how long to wait. 1 to 38. |

**Example**

```json tools/call params theme={"theme":"css-variables"}
{"name": "test_schedule", "arguments": {}}
```

**Returns**

With `list`, whether the nightly run is on, its time and flags, and its last run: `structuredContent` has `on`, `at`, `flags` and `last`. With `run`, what `run_tests` returns.

> [accordion] Input schema and annotations of test\_schedule
>
> Annotations: `title: "Test schedule"`, `readOnlyHint: false`, `destructiveHint: false`, `openWorldHint: false`
>
> ```json theme={"theme":"css-variables"}
> {
>   "type": "object",
>   "properties": {
>     "action": {
>       "type": "string",
>       "enum": [
>         "list",
>         "run"
>       ],
>       "description": "list (default) or run"
>     },
>     "path": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 4096,
>       "description": "absolute path of the project (the folder holding .mobster); default the server's"
>     },
>     "suite_id": {
>       "type": "string",
>       "pattern": "^[0-9]{8}-[0-9]{6}-[0-9a-f]{4}$",
>       "description": "with run: a suite this tool started, to wait for it again"
>     },
>     "timeout_s": {
>       "type": "number",
>       "minimum": 1,
>       "maximum": 38.0,
>       "description": "with run: how long to wait (default 30)"
>     }
>   },
>   "required": [],
>   "additionalProperties": false
> }
> ```

## `review_heals`

List the healed steps waiting for review (each with the step before and after, and frames), or settle them: accept keeps them; reject restores the recorded steps. A heal never changes a check's expectations.

**Local.**

**Arguments**

| Name | Type | Default | Description |
| - | - | - | - |
| `path` | string | the project's | Absolute path of the project's .mobster/checks folder or a check file. 1 to 4,096 characters. |
| `action` | string | see description | List (default), accept or reject. One of `list`, `accept` or `reject`. |
| `checks` | array of strings | every check with a heal waiting | Absolute paths of the check files to accept or reject. At most 50 items. Each item: 1 to 4,096 characters. |

**Example**

```json tools/call params theme={"theme":"css-variables"}
{"name": "review_heals", "arguments": {}}
```

**Returns**

With `list`, each healed step waiting for review: its check, step and what it became. `structuredContent` has `heals`, each with `check`, `diff` and `heals`. With `accept` or `reject`, the checks it settled: `structuredContent` has `action` and `settled`, each with `check` and `steps`.

> [accordion] Input schema and annotations of review\_heals
>
> Annotations: `title: "Review heals"`, `readOnlyHint: false`, `destructiveHint: false`, `openWorldHint: false`
>
> ```json theme={"theme":"css-variables"}
> {
>   "type": "object",
>   "properties": {
>     "path": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 4096,
>       "description": "absolute path of the project's .mobster/checks folder or a check file; default the project's"
>     },
>     "action": {
>       "type": "string",
>       "enum": [
>         "list",
>         "accept",
>         "reject"
>       ],
>       "description": "list (default), accept or reject"
>     },
>     "checks": {
>       "type": "array",
>       "maxItems": 50,
>       "items": {
>         "type": "string",
>         "minLength": 1,
>         "maxLength": 4096
>       },
>       "description": "absolute paths of the check files to accept or reject; default every check with a heal waiting"
>     }
>   },
>   "required": [],
>   "additionalProperties": false
> }
> ```

## `import_maestro`

Turn Maestro flows into checks in the project's .mobster/checks. A check that exists is kept unless force; `dry_run` writes nothing; a flow Mobster can't run is refused.

**Local.**

**Arguments**

| Name | Type | Default | Description |
| - | - | - | - |
| `flows` | array of strings | required | Absolute paths of Maestro flow files or folders of them. 1 to 20 items. Each item: 1 to 4,096 characters. |
| `path` | string | the server's | Absolute path of the project (the folder holding .mobster). 1 to 4,096 characters. |
| `bundle` | string | | The app's bundle ID, when the flows don't carry an appId. 3 to 155 characters. |
| `app` | string | | Absolute path of the simulator build (.app) the checks launch. 1 to 4,096 characters. |
| `skip_unsupported` | boolean | | Drop a command Mobster can't run instead of refusing the flow. |
| `dry_run` | boolean | | Write nothing; say what would be written. |
| `force` | boolean | | Replace a check that exists. |

**Example**

```json tools/call params theme={"theme":"css-variables"}
{
  "name": "import_maestro",
  "arguments": {"flows": ["/abs/path/YourApp/.maestro"]}
}
```

**Returns**

What it converted and wrote, flow by flow. `structuredContent` has `flows`, `folder`, `written`, `refused` and `dry_run`.

> [accordion] Input schema and annotations of import\_maestro
>
> Annotations: `title: "Import maestro"`, `readOnlyHint: false`, `destructiveHint: false`, `openWorldHint: false`
>
> ```json theme={"theme":"css-variables"}
> {
>   "type": "object",
>   "properties": {
>     "flows": {
>       "type": "array",
>       "minItems": 1,
>       "maxItems": 20,
>       "items": {
>         "type": "string",
>         "minLength": 1,
>         "maxLength": 4096
>       },
>       "description": "absolute paths of Maestro flow files or folders of them"
>     },
>     "path": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 4096,
>       "description": "absolute path of the project (the folder holding .mobster); default the server's"
>     },
>     "bundle": {
>       "type": "string",
>       "minLength": 3,
>       "maxLength": 155,
>       "description": "the app's bundle ID, when the flows don't carry an appId"
>     },
>     "app": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 4096,
>       "description": "absolute path of the simulator build (.app) the checks launch"
>     },
>     "skip_unsupported": {
>       "type": "boolean",
>       "description": "drop a command Mobster can't run instead of refusing the flow"
>     },
>     "dry_run": {
>       "type": "boolean",
>       "description": "write nothing; say what would be written"
>     },
>     "force": {
>       "type": "boolean",
>       "description": "replace a check that exists"
>     }
>   },
>   "required": [
>     "flows"
>   ],
>   "additionalProperties": false
> }
> ```

## `repro_crash`

Turn a crash (.ips, Sentry event JSON, TestFlight or Xcode crash log, or a brief) into a check that reproduces it on a simulator, recorded. Run it after your fix: it passes once the app stops crashing.

**Local.**

**Arguments**

| Name | Type | Default | Description |
| - | - | - | - |
| `ips_path` | string | | Absolute path of a .ips crash report. 1 to 4,096 characters. |
| `sentry_json` | string | | A Sentry event as JSON text, as its API or MCP returns it. 2 to 1,000,000 characters. |
| `crash_log` | string | | A TestFlight or Xcode Organizer crash log in Apple's text format. 1 to 1,000,000 characters. |
| `brief` | object | | A crash from Crashlytics, Datadog or anywhere else: the app's bundle, exception type, frames (symbol, own), steps in plain words, and a link. |
| `path` | string | the server's | Absolute path of the project (the folder holding .mobster). 1 to 4,096 characters. |
| `bundle` | string | | The app's bundle ID when the crash doesn't name it. 1 to 255 characters. |
| `app` | string | | Absolute path of a .app built for the simulator, to install first. 1 to 4,096 characters. |
| `launch_args` | array of strings | | Launch arguments the crash needs. At most 20 items. Each item: 1 to 200 characters. |
| `link` | string | | A link that opens the app on the crashing screen. 1 to 2,000 characters. |
| `sims` | array of strings | | The simulator to use, such as "iPhone 17 Pro\@iOS 26.4". At most 1 item. Each item: 1 to 128 characters. |
| `suite_id` | string | | Wait for the reproduction a first call started; pass it alone. Matches `^[0-9]{8}-[0-9]{6}-[0-9a-f]{4}$`. |
| `timeout_s` | number | `30` | Seconds to wait for the answer. 1 to 38. |

**Fields of `brief`**

| Name | Type | Description |
| - | - | - |
| `bundle` | string | At most 255 characters. |
| `type` | string | At most 80 characters. |
| `signal` | string | At most 20 characters. |
| `message` | string | At most 300 characters. |
| `version` | string | At most 40 characters. |
| `device` | string | At most 60 characters. |
| `os` | string | At most 60 characters. |
| `link` | string | At most 2,000 characters. |
| `steps` | array of strings | At most 20 items. Each item: at most 200 characters. |
| `frames` | array of objects | At most 12 items. |

**Fields of `brief.frames[]`**

| Name | Type | Description |
| - | - | - |
| `symbol` | string | At most 200 characters. |
| `own` | boolean | |
| `file` | string | At most 120 characters. |
| `line` | integer | |

**Example**

```json tools/call params theme={"theme":"css-variables"}
{"name": "repro_crash", "arguments": {}}
```

**Returns**

While the suite runs past `timeout_s`, a line with its progress, and `structuredContent` has `status` `running`, `suite_id`, `done`, `total` and `message`: call it again with `suite_id` to keep waiting. When it finishes, whether the check reproduced the crash, with the steps it tried. `structuredContent` has `status`, `suite_id`, `reproduction`, `brief`, `check`, `stepsTried`, `crash`, `video`, `report` and `note`.

> [accordion] Input schema and annotations of repro\_crash
>
> Annotations: `title: "Repro crash"`, `readOnlyHint: false`, `destructiveHint: false`, `openWorldHint: false`
>
> ```json theme={"theme":"css-variables"}
> {
>   "type": "object",
>   "properties": {
>     "ips_path": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 4096,
>       "description": "absolute path of a .ips crash report"
>     },
>     "sentry_json": {
>       "type": "string",
>       "minLength": 2,
>       "maxLength": 1000000,
>       "description": "a Sentry event as JSON text, as its API or MCP returns it"
>     },
>     "crash_log": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 1000000,
>       "description": "a TestFlight or Xcode Organizer crash log in Apple's text format"
>     },
>     "brief": {
>       "type": "object",
>       "additionalProperties": false,
>       "properties": {
>         "bundle": {
>           "type": "string",
>           "maxLength": 255
>         },
>         "type": {
>           "type": "string",
>           "maxLength": 80
>         },
>         "signal": {
>           "type": "string",
>           "maxLength": 20
>         },
>         "message": {
>           "type": "string",
>           "maxLength": 300
>         },
>         "version": {
>           "type": "string",
>           "maxLength": 40
>         },
>         "device": {
>           "type": "string",
>           "maxLength": 60
>         },
>         "os": {
>           "type": "string",
>           "maxLength": 60
>         },
>         "link": {
>           "type": "string",
>           "maxLength": 2000
>         },
>         "steps": {
>           "type": "array",
>           "maxItems": 20,
>           "items": {
>             "type": "string",
>             "maxLength": 200
>           }
>         },
>         "frames": {
>           "type": "array",
>           "maxItems": 12,
>           "items": {
>             "type": "object",
>             "additionalProperties": false,
>             "properties": {
>               "symbol": {
>                 "type": "string",
>                 "maxLength": 200
>               },
>               "own": {
>                 "type": "boolean"
>               },
>               "file": {
>                 "type": "string",
>                 "maxLength": 120
>               },
>               "line": {
>                 "type": "integer"
>               }
>             }
>           }
>         }
>       },
>       "description": "a crash from Crashlytics, Datadog or anywhere else: the app's bundle, exception type, frames (symbol, own), steps in plain words, and a link"
>     },
>     "path": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 4096,
>       "description": "absolute path of the project (the folder holding .mobster); default the server's"
>     },
>     "bundle": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 255,
>       "description": "the app's bundle ID when the crash doesn't name it"
>     },
>     "app": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 4096,
>       "description": "absolute path of a .app built for the simulator, to install first"
>     },
>     "launch_args": {
>       "type": "array",
>       "maxItems": 20,
>       "items": {
>         "type": "string",
>         "minLength": 1,
>         "maxLength": 200
>       },
>       "description": "launch arguments the crash needs"
>     },
>     "link": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 2000,
>       "description": "a link that opens the app on the crashing screen"
>     },
>     "sims": {
>       "type": "array",
>       "maxItems": 1,
>       "items": {
>         "type": "string",
>         "minLength": 1,
>         "maxLength": 128
>       },
>       "description": "the simulator to use, such as \"iPhone 17 Pro@iOS 26.4\""
>     },
>     "suite_id": {
>       "type": "string",
>       "pattern": "^[0-9]{8}-[0-9]{6}-[0-9a-f]{4}$",
>       "description": "wait for the reproduction a first call started; pass it alone"
>     },
>     "timeout_s": {
>       "type": "number",
>       "minimum": 1,
>       "maximum": 38.0,
>       "description": "seconds to wait for the answer (default 30)"
>     }
>   },
>   "required": [],
>   "additionalProperties": false
> }
> ```

## `compare_test_suites`

Compare two exact completed local test suites. Returns both verdicts and bounded case transitions; never treats a green run alone as proof of a fix.

**Read-only.**

**Arguments**

| Name | Type | Default | Description |
| - | - | - | - |
| `base_suite_id` | string | required | The saved suite before the proposed change. Matches `^[0-9]{8}-[0-9]{6}-[0-9a-f]{4}$`. |
| `candidate_suite_id` | string | required | The saved suite after the proposed change. Matches `^[0-9]{8}-[0-9]{6}-[0-9a-f]{4}$`. |

**Example**

```json tools/call params theme={"theme":"css-variables"}
{
  "name": "compare_test_suites",
  "arguments": {
    "base_suite_id": "20261101-101500-3fa2",
    "candidate_suite_id": "20261101-104512-9c0d"
  }
}
```

**Returns**

Whether the suites are comparable, whether the candidate verifies a fix, and how many case and target pairs it shows. `structuredContent` has `schema`, `baseSuite`, `candidateSuite`, `baseVerdict`, `candidateVerdict`, `comparable`, `verifiedFix`, `proof`, `reasons`, `cases` (at most 100), `casesTotal` and `casesTruncated`.

> [accordion] Input schema and annotations of compare\_test\_suites
>
> Annotations: `title: "Compare test suites"`, `readOnlyHint: true`, `destructiveHint: false`, `idempotentHint: true`, `openWorldHint: false`
>
> ```json theme={"theme":"css-variables"}
> {
>   "type": "object",
>   "properties": {
>     "base_suite_id": {
>       "type": "string",
>       "pattern": "^[0-9]{8}-[0-9]{6}-[0-9a-f]{4}$",
>       "description": "the saved suite before the proposed change"
>     },
>     "candidate_suite_id": {
>       "type": "string",
>       "pattern": "^[0-9]{8}-[0-9]{6}-[0-9a-f]{4}$",
>       "description": "the saved suite after the proposed change"
>     }
>   },
>   "required": [
>     "base_suite_id",
>     "candidate_suite_id"
>   ],
>   "additionalProperties": false
> }
> ```

## `gate_note`

Remember a file the coding agent wrote, so gate checks it when the agent stops. The Mobster plugin's hook calls it after each Write, Edit and MultiEdit; don't call it yourself.

**Local.**

**Arguments**

| Name | Type | Default | Description |
| - | - | - | - |
| `file_path` | string | required | Absolute path of the file the agent wrote. 1 to 4,096 characters. |
| `session_id` | string | required | The coding agent's session id, as the hook's $\{`session_id`\} gives it. Matches `^[A-Za-z0-9_-]{1,128}$\`. |

**Example**

```json tools/call params theme={"theme":"css-variables"}
{
  "name": "gate_note",
  "arguments": {
    "file_path": "/abs/path/YourApp/YourApp/TaskListView.swift",
    "session_id": "6f1c2d9a-3b7e-4c0a-9d2f-1e8b5a7c4d30"
  }
}
```

**Returns**

An empty answer, so the hook adds nothing to the agent's context.

> [accordion] Input schema and annotations of gate\_note
>
> Annotations: `title: "Note the agent's edit"`, `readOnlyHint: false`, `destructiveHint: false`, `openWorldHint: false`, `idempotentHint: true`
>
> ```json theme={"theme":"css-variables"}
> {
>   "type": "object",
>   "properties": {
>     "file_path": {
>       "type": "string",
>       "minLength": 1,
>       "maxLength": 4096,
>       "description": "absolute path of the file the agent wrote"
>     },
>     "session_id": {
>       "type": "string",
>       "pattern": "^[A-Za-z0-9_-]{1,128}$",
>       "description": "the coding agent's session id, as the hook's ${session_id} gives it"
>     }
>   },
>   "required": [
>     "file_path",
>     "session_id"
>   ],
>   "additionalProperties": false
> }
> ```

## `gate`

Replay on a simulator the saved checks the agent's files reach, and send the agent back with the step and a frame when one fails. The Mobster plugin's Stop hook calls it; don't call it yourself.

**Local.**

**Arguments**

| Name | Type | Default | Description |
| - | - | - | - |
| `session_id` | string | required | The coding agent's session id, as the hook's $\{`session_id`\} gives it. Matches `^[A-Za-z0-9_-]{1,128}$\`. |
| `stop_hook_active` | boolean or string | required | Whether a Stop hook already continued this turn, as the hook's \$\{`stop_hook_active`} gives it. One of `true`, `false`, `true` or `false`. |

**Example**

```json tools/call params theme={"theme":"css-variables"}
{
  "name": "gate",
  "arguments": {
    "session_id": "6f1c2d9a-3b7e-4c0a-9d2f-1e8b5a7c4d30",
    "stop_hook_active": false
  }
}
```

**Returns**

The Stop hook's answer, as JSON text of at most 10,000 characters: `decision` `block` with its `reason` when a saved check failed, `hookSpecificOutput` with `additionalContext` when a changed screen has no check, and `systemMessage` when the checks passed or the turn ends anyway. An empty answer when there's nothing to say, and the reason as an error when the checks couldn't start.

> [accordion] Input schema and annotations of gate
>
> Annotations: `title: "Check the agent's edits"`, `readOnlyHint: false`, `destructiveHint: false`, `openWorldHint: false`
>
> ```json theme={"theme":"css-variables"}
> {
>   "type": "object",
>   "properties": {
>     "session_id": {
>       "type": "string",
>       "pattern": "^[A-Za-z0-9_-]{1,128}$",
>       "description": "the coding agent's session id, as the hook's ${session_id} gives it"
>     },
>     "stop_hook_active": {
>       "type": [
>         "boolean",
>         "string"
>       ],
>       "enum": [
>         true,
>         false,
>         "true",
>         "false"
>       ],
>       "description": "whether a Stop hook already continued this turn, as the hook's ${stop_hook_active} gives it"
>     }
>   },
>   "required": [
>     "session_id",
>     "stop_hook_active"
>   ],
>   "additionalProperties": false
> }
> ```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.