| name | mirroir-skills |
| description | Community skills for mirroir-mcp. Provides ready-made skills (SKILL.md and YAML) for automating iOS apps via AI-driven screen interaction. |
Mirroir Skills
This skill provides community-contributed skills for mirroir-mcp, the MCP server that gives AI agents control of a real iPhone screen.
Skills come in two formats:
- SKILL.md (
.md) — natural-language markdown with YAML front matter, the primary format for AI execution
- YAML (
.yaml) — structured step definitions in legacy/, used by the deterministic mirroir test and mirroir compile CLI tools
How Skills Work
Skills describe multi-step iOS automation flows as intents, not scripts. Steps like "Tap Email" don't specify coordinates — you (the AI) find the element using describe_screen and adapt to the actual screen layout.
Executing a Skill
- Use
list_skills to discover available skills
- Use
get_skill with the skill name to load it (e.g. get_skill("apps/slack/send-message"))
- Read the steps and execute each one using the appropriate MCP tools
Step Type Reference
| Step | How to Execute |
|---|
launch: "App" | Call launch_app |
tap: "Label" | Call describe_screen to find the element, then tap at its coordinates |
long_press: "Label" | Call describe_screen to find the element, then long_press at its coordinates |
type: "text" | Call type_text |
swipe: "up" | Call swipe with appropriate coordinates based on screen size |
wait_for: "Label" | Poll describe_screen until the element appears (retry with short delays) |
assert_visible: "Label" | Call describe_screen and verify the label is present. Report failure if not found. |
assert_not_visible: "Label" | Call describe_screen and verify the label is absent. Report failure if found. |
screenshot: "label" | Call screenshot and label it in your response |
press_key: "return" | Call press_key |
press_home: true | Call press_home to return to the home screen |
open_url: "https://..." | Call open_url |
shake: true | Call shake |
remember: "instruction" | Read dynamic data from the screen and hold it in memory. Use {NAME} (single braces) in later steps to insert the remembered value. |
condition: | Branch based on screen state. See Conditions below. |
repeat: | Loop over steps until a screen condition is met. See Repeats below. |
Conditions
Skills can branch using condition steps. Call describe_screen to evaluate the condition, then execute the matching branch.
- condition:
if_visible: "Label"
then:
- tap: "Label"
- screenshot: "found"
else:
- screenshot: "not_found"
How to execute:
- Call
describe_screen and check whether the label from if_visible (or if_not_visible) is present
- If the condition is true, execute the
then steps sequentially
- If the condition is false and
else is provided, execute the else steps
- If the condition is false and there is no
else, skip and continue to the next step
Steps inside then and else are regular steps — including nested condition steps if needed. Avoid nesting deeper than 2-3 levels to keep skills readable.
Repeats
Skills can loop using repeat steps. The AI checks a screen condition before each iteration and stops when the condition fails or max iterations are reached.
- repeat:
while_visible: "Unread"
max: 10
steps:
- tap: "Unread"
- tap: "Archive"
- tap: "< Back"
Loop modes (use exactly one):
while_visible: "Label" — continue while the label is on screen
until_visible: "Label" — continue until the label appears
times: N — repeat exactly N times (no screen check)
How to execute:
- Before each iteration, call
describe_screen and evaluate the loop condition (while_visible or until_visible). For times, just count.
- If the condition allows another iteration and
max is not reached, execute the steps sequentially
- After the steps complete, go back to step 1
- When the condition fails or
max is reached, stop and continue to the next step after the repeat
Steps inside repeat are regular steps — including condition and nested repeat if needed.
Skill Metadata
Skills include metadata in the YAML front matter (for .md files) or as top-level keys (for .yaml files):
| Field | Purpose |
|---|
version | Format version (currently 1). Required in .md files. |
name | Human-readable skill name. |
app | Target iOS app name. |
ios_min | Minimum iOS version (e.g. "17.0"). Skip the skill if the device is below this version. |
locale | Expected locale (e.g. "en_US", "fr_CA"). Adapt UI labels if the phone's locale differs. |
tags | List of strings for discovery (e.g. ["calendar", "create"]). Used for filtering, not execution. |
Variable Substitution
${VAR} placeholders are resolved from environment variables by get_skill. ${VAR:-default} provides a fallback. If you see unresolved ${VAR} in the loaded skill, ask the user for the value before proceeding.
Auto-Compilation
When you execute a skill, get_skill appends a compilation status line at the end of the response. Use it to decide whether to compile:
[Not compiled] — No compiled version exists. Follow the compilation steps below.
[Compiled: stale — ...] — Source changed since last compile. Recompile using the steps below.
[Compiled: fresh] — Up to date. Skip compilation (no record_step calls needed).
How to compile during execution
- After each step, call
record_step with the step index, type, label, and any data you observed:
- For tap steps: include
tap_x, tap_y, confidence from describe_screen
- For wait_for / assert steps: include
elapsed_ms (approximate time waited)
- For scroll_to steps: include
scroll_count and scroll_direction
- For launch, type, press_key, swipe, home, open_url, shake, reset_app, set_network, screenshot, switch_target: just index, type, and label
- For remember, condition, repeat (AI-only steps): just index, type, and label (hints will be null)
- After all steps complete successfully, call
save_compiled with the skill name
The compiled file (.compiled.json) enables mirroir test to replay the skill deterministically without OCR. Your first execution IS the compilation — no separate learning run needed.
Adapting to Reality
Real iOS screens differ from what skills expect. You should:
- Dismiss unexpected dialogs (permission prompts, update banners, cookie consent)
- Scroll to find off-screen elements when
describe_screen doesn't show the target
- Handle localized UI (the phone may be in French, Spanish, etc.)
- Retry failed taps — OCR coordinates may be slightly off, try nearby positions
- Report assertion failures clearly with what was expected vs. what was actually on screen