mirroir-skills
Community marketplace of patterns and skills for mirroir-mcp — AI-driven automation for real iOS devices.
Patterns vs Skills
mirroir uses two complementary concepts:
- Patterns (declarative) — teach mirroir what iOS apps look like and how they behave. Read-only knowledge.
- Skills (imperative) — step-by-step flows the AI executes. Actions.
Patterns come in three scales — same concept, different granularity:
| Scale | What it describes | Location |
|---|---|---|
| Element patterns | Row-level UI components (table rows, tab bars, buttons) | patterns/elements/ |
| Screen patterns | Screen archetypes from element composition (dashboard, feed) | patterns/screens/ |
| App patterns | App-level structure, obstacles, skip lists (APP.md) | patterns/apps/ |
mirroir-skills/
├── patterns/
│ ├── elements/ # 34 iOS UI element definitions
│ ├── screens/ # 7 screen archetype recipes
│ └── apps/ # APP.md app descriptions
├── skills/
│ ├── apps/ # Per-app automation flows
│ ├── workflows/ # Cross-app sequences
│ └── testing/ # Test flows
└── legacy/ # Old YAML skills (deterministic runners)
APP.md — Describe Your App
The most impactful thing you can contribute is an APP.md for your favorite iOS app. Tell mirroir what the app is, where the dangers are, and what obstacles to expect:
---
version: 1
app: Santé
locale: fr_CA
archetype: dashboard
obstacle_mode: auto
---
## Structure
Dashboard with 4 tabs: Résumé, Partage, Parcourir, Profil.
## Résumé Tab
- Summary cards for health metrics that drill down to charts
## Obstacles
- Health Access permission → tap "Autoriser"
- Notification permission → tap "Ne pas autoriser"
## Skip
- Supprimer les données de Santé
- Réinitialiser
The archetype field tells mirroir how the app navigates (dashboard, social-feed, settings-list, content-grid, conversation-list, utility-display, detail-form). Obstacles are auto-dismissed during exploration. Skip elements are never tapped. Structure is injected into generated skills as AI context.
What Are Skills?
Skills describe multi-step iOS automation as intents, not scripts. Steps like "Tap Email" don't hardcode coordinates — the AI finds elements via OCR and adapts to screen layout, localization, and unexpected dialogs.
The primary format is SKILL.md — markdown files with YAML front matter:
---
version: 1
name: Send Slack Message
app: Slack
tags: ["slack", "messaging"]
---
Send a direct message to a contact in Slack.
## Steps
1. Launch **Slack**
2. Wait for "Home" to appear
3. Tap "Direct Messages"
4. Tap "${RECIPIENT}"
5. Tap "Message"
6. Type "${MESSAGE:-Hey, just checking in!}"
7. Press **Return**
8. Screenshot: "message_sent"
Legacy YAML format (used by mirroir test and mirroir compile)
name: Send Slack Message
app: Slack
description: Send a direct message to a contact in Slack
steps:
- launch: "Slack"
- wait_for: "Home"
- tap: "Direct Messages"
- tap: "${RECIPIENT}"
- tap: "Message"
- type: "${MESSAGE:-Hey, just checking in!}"
- press_key: "return"
- screenshot: "message_sent"
YAML files live in the legacy/ directory. They are used by the deterministic mirroir test and mirroir compile CLI tools which require structured step definitions. Use mirroir migrate to convert YAML to SKILL.md format.
Installation
Claude Code
claude plugin marketplace add jfarcand/mirroir-skills
claude plugin install skills@mirroir-skills
GitHub Copilot CLI
copilot plugin marketplace add jfarcand/mirroir-skills
copilot plugin install skills@mirroir-skills
Both install the SKILL.md which teaches the AI how to interpret and execute skill steps.
Manual (all other clients)
Clone into your global skills directory:
git clone https://github.com/jfarcand/mirroir-skills ~/.mirroir-mcp/skills
Or into a project-local directory:
git clone https://github.com/jfarcand/mirroir-skills .mirroir-mcp/skills
Both paths are scanned recursively by list_skills.
Available Skills
App Skills
| Skill | Description |
|---|---|
skills/apps/appstore/install-app | Search for an app in the App Store and install it |
skills/apps/calendar/create-event | Create a new calendar event |
skills/apps/calendar/check-today | Read today's events using remember to extract meeting details |
skills/apps/clock/set-alarm | Create a new alarm |
skills/apps/clock/set-timer | Start a countdown timer and verify it's running |
skills/apps/mail/email-triage | Check inbox for unread email — archive or flag based on content |
skills/apps/mail/batch-archive | Archive all unread emails in a loop until inbox is empty |
skills/apps/maps/save-directions | Search for a destination, get directions, extract travel time with remember |
skills/apps/photos/share-recent | Long-press a recent photo and share it via Messages |
skills/apps/settings/check-about | Extract device model, iOS version, and storage via remember |
skills/apps/settings/check-about-fr | Same as check-about but for French locale (Réglages) |
skills/apps/settings/list-apps | List installed apps with sizes from iPhone Storage |
skills/apps/settings/uninstall-app | Remove an app via Settings > General > iPhone Storage |
skills/apps/slack/send-message | Send a DM to a contact |
skills/apps/slack/check-unread | Read unread notifications with channel names and message previews |
skills/apps/weather/check-forecast | Extract current conditions and 10-day forecast with remember |
skills/apps/weather/add-city | Add a city to Weather |
Testing
| Skill | Description |
|---|---|
skills/testing/expo-go/login-flow | Test login with conditional branching for signup vs existing account |
skills/testing/expo-go/shake-debug-menu | Open React Native debug menu via shake |
skills/testing/expo-go/qa-smoke-pack | Visual regression test — screenshot key screens and use remember to detect UI anomalies |
Workflows
| Skill | Description |
|---|---|
skills/workflows/morning-briefing | Read weather + calendar, compose and send a morning summary via iMessage |
skills/workflows/commute-eta-notify | Get ETA from Waze, send it to your boss via Messages |
skills/workflows/standup-autoposter | Read today's meetings from Calendar, post standup to Slack |
Workflows demonstrate cross-app data extraction — the AI reads dynamic content from one app and composes it into actions in another. This is something only an AI executor can do.
Variable Substitution
Skills use ${VAR} placeholders resolved from environment variables. Use ${VAR:-default} for fallback values.
# Set credentials for testing skills
export TEST_EMAIL=user@example.com
export TEST_PASSWORD=secret
# Or use direnv
echo 'export TEST_EMAIL=user@example.com' >> .envrc
direnv allow
Unresolved variables without defaults are left as-is — the AI will ask for values before proceeding.
Conditions
Skills support branching with condition steps. The AI checks the screen and executes the matching branch:
steps:
- launch: "Mail"
- wait_for: "Inbox"
- condition:
if_visible: "Unread"
then:
- tap: "Unread"
- tap: "Archive"
- assert_visible: "Archived"
else:
- screenshot: "empty_inbox"
A condition step has:
if_visibleorif_not_visible— the label to check on screenthen(required) — steps to run when the condition is trueelse(optional) — steps to run when the condition is false
Steps inside branches are regular steps, including nested conditions. See skills/apps/mail/email-triage.md for a full example.
Repeats
Skills support loops with repeat steps. The AI checks a screen condition before each iteration:
steps:
- launch: "Mail"
- wait_for: "Inbox"
- repeat:
while_visible: "Unread"
max: 10
steps:
- tap: "Unread"
- tap: "Archive"
- tap: "< Back"
- wait_for: "Inbox"
A repeat step has:
- Loop mode (exactly one):
while_visible,until_visible, ortimes max(required) — safety bound to prevent infinite loopssteps(required) — steps to run each iteration
See skills/apps/mail/batch-archive.md for a full example.
Migration from YAML
The mirroir migrate command converts YAML skills to SKILL.md format:
mirroir migrate apps/settings/check-about.yaml # single file
mirroir migrate --dir ../iphone-mirroir-skills/apps # entire directory
mirroir migrate --dry-run apps/mail/email-triage.yaml # preview without writing
Legacy YAML files live in the legacy/ directory and remain accessible for the deterministic mirroir test and mirroir compile CLI tools.
Validation
Run the validation script to check all skills for required fields, valid metadata, and correct variable syntax:
python3 scripts/validate-skills.py
This validates SKILL.md files (in skills/) and legacy YAML files (in legacy/). APP.md files are patterns, not skills, and are skipped. It runs automatically on push and PR via GitHub Actions.
Contributing
Contributions are welcome! By submitting a pull request or patch, you agree to the Contributor License Agreement. Your Git commit metadata (name and email) serves as your electronic signature — no separate form to sign.
The CLA ensures the project can be maintained long-term under a consistent license. You retain full ownership of your contributions — the CLA simply grants the maintainer the right to distribute them as part of the project.
How to contribute
- Fork this repository
- Create your file in the appropriate directory:
patterns/apps/<app-name>/APP.md— describe an app (structure, obstacles, archetype)patterns/elements/— element patterns for new UI componentspatterns/screens/— screen archetype recipesskills/apps/<app-name>/— single-app automationskills/testing/<framework>/— mobile testing and QAskills/workflows/— multi-app sequences that extract data across apps
- Use the SKILL.md format:
--- version: 1 name: Human-readable name app: App Name ios_min: "17.0" locale: "en_US" tags: ["app-name", "category", "action-type"] --- What this skill does. ## Steps 1. Launch **App Name** 2. Wait for "Expected Element" to appear 3. Tap "Element Label" 4. Type "${VAR:-sensible default}" 5. Verify "Success Indicator" is visible 6. Screenshot: "result" - Use
${VAR:-default}for configurable values, never hardcode credentials - Include at least one "Verify" step so the skill is self-verifying
- Submit a pull request