add-exporter
Skill2 starsChanged 19 days agoMITView on GitHub
Add or improve an AppScreenMap exporter that turns a crawl into tests for an E2E tool (Maestro, Appium, Espresso/UI Automator, Playwright-style page objects, Detox, XCUITest, or a user's own template) — and build the pluggable exporter interface itself. Use when asked to support another test tool, make export plug-and-play, add `--format`, or fix a generated test that doesn't run.
- Installs packages
In this repository22 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- a11y-auditSkill
- adaptiveSkill
- add-a11y-ruleSkill
- android-intent-securitySkill
- android-permissions-securitySkill
- crawl-appSkill
- design-systemSkill
- edge-to-edgeSkill
- extend-crawlerSkill
- ios-a11y-rulesSkill
- ios-simulatorSkill
- maintain-crawlerSkill
- play-policy-insightsSkill
- security-auditSkill
- security-rulesSkill
- stack-iosSkill
- stack-rulesSkill
- store-requirementsSkill
- tune-crawlerSkill
- wcag-mobile-rulesSkill
- web-uiSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 5 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 20
Do this before adding a second tool, and move Maestro behind it without changing its output (the existing export tests must still pass …
- Distinctive: line 38
Read the tool's docs for its selector and wait model: Don't generate from memory.
- Very specific: line 43
Use reach_path (steps from launch) and each screen's autofill (type values before the tap that needs them).
- Distinctive: line 46
Start from a clean launch (force-stop, then launch), because that is what the path means.
- Distinctive: line 47
Declare capabilities: If the tool can't express a step (long-press, back, a gesture), the exporter skips that screen and reports it, with …
- Distinctive: line 60
If the tool ships a parser or linter, run generated output through it in a test (skipped when not installed).
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Exporters for E2E tools
Goal: users pick the test tool they already use. The crawl (map.json) stays tool-neutral; an exporter only
translates it. Read .claude/skills/extend-crawler/SKILL.md for the general checklist, and docs/MAP_SCHEMA.md
for the data.
Current state (verify before relying on it)
Export is one hard-coded function: export.maestro_flow(data, screen) plus mermaid(data), both called from
export.export_run(). There is no exporter interface, registry or --format flag yet. Check
packages/exporters/ and apps/engine/src/appscreenmap/engine/cli/verify.py (cmd_export) first; if that changed, follow the code, not this paragraph.
Step 0: build the interface (once, then reuse it)
Do this before adding a second tool, and move Maestro behind it without changing its output (the existing export tests must still pass byte-for-byte).
- Interface: an
Exporterwithname,capabilities, andexport(data: dict, screen: dict) -> dict[str, str](relative path → file text). It receives plainmap.jsondicts, never live objects. - Registry: built-ins registered by name, plus third-party plugins through the
appscreenmap.exportersentry-point group (sopip install appscreenmap-<tool>adds a format). - CLI:
appscreenmap export <run> --format maestro,appium-python(default: maestro, so nothing breaks) and a crawl-time default in config. Keep logic in the module; the CLI (apps/engine/src/appscreenmap/engine/cli/) only parses and prints. - Neutral steps:
--format jsonwrites the resolved path per screen (launch → steps → assertion) so any tool in any language can generate its own tests. Treat this shape as public API: additive changes only. - Templates:
--template filerenders the neutral steps through a user-supplied template, for people who only want different syntax. - Docs: README (formats, how to write a plugin),
docs/MAP_SCHEMA.md(the neutral step format),docs/PLAN.md(§8 roadmap row).
Adding one exporter
- Read the tool's docs for its selector and wait model. Don't generate from memory; wrong syntax is the most common failure, and nothing in the unit tests will catch it unless you test against the tool's own grammar.
- Map the neutral step to the tool's commands:
- Selector preference: resource-id → text / content-desc → point. Say in a comment when you fell back to a point (coordinates are brittle, and the user should know which tests to harden).
- Use
reach_path(steps from launch) and each screen'sautofill(type values before the tap that needs them). scroll_depth > 0means the element is below the fold: use the tool's scroll-until-visible.- Assertion: the screen's title text, else a stable resource-id (see
export._assertion). - Start from a clean launch (force-stop, then launch), because that is what the path means.
- Declare capabilities. If the tool can't express a step (long-press, back, a gesture), the exporter skips that screen and reports it, with the reason. Never emit a test that silently does less than the path.
- Secrets. Typed values come from
config.placeholders(${ENV}placeholders). Never write a literal test password into generated files;packages/crawler/tests/test_secrets.pyshows the expectation. Add the tool's way of reading env vars to the generated file's header comment. - Output layout.
tests/<format>/…or the tool's convention, one file per screen unless the tool prefers a page-object class per screen plus a path helper. Include a generated-file header with the run id.
Tests (no device needed)
- Golden test per exporter in
packages/exporters/tests/test_export.pystyle: a synthetic map → expected file text. - Cases to cover: id / text / desc / point selectors, autofill with a placeholder, scrolled element, a screen the exporter must skip, special characters in labels (quotes, regex metacharacters, unicode).
- If the tool ships a parser or linter, run generated output through it in a test (skipped when not installed). Otherwise validate the format structurally (valid YAML / compiles / imports).
uv run pytest -q && uv run ruff check && uv run ruff format.
Licensing
An exporter writes text in the tool's documented format. Don't import, bundle or copy the tool's code or
templates. Add a short entry to THIRD_PARTY_NOTICES.md (the tool, its license, "format only, not bundled, not
affiliated") and use the tool's name descriptively only ("exports Appium tests"), never as a project name.
Verify for real
Generate for the Playground sample (runs/playground/<run-id>), run the output with the actual tool on the emulator
for at least the launch screen and one three-step path, and say in your report which tool version you used. If you
couldn't run it, say that plainly: "generated, not executed."
Report
List: formats added, capabilities and what's skipped, selector fallbacks (counts of point selectors), tests added, and whether the output was executed against the real tool.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

