Theming
Code-with-Beto/skills
Scaffold a unified, cross-platform color theme system into an Expo Router app.
Generate a visual navigation map of an Expo / React Native or NativeScript app.
$ npx skills add aleqsio/screenmap --skill screenmap -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install aleqsio/screenmap screenmap --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/aleqsio/screenmap.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/screenmap/skills/screenmap .claude/skills/screenmap && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "screenmap" agent skill from https://github.com/aleqsio/screenmap/tree/main/plugins/screenmap/skills/screenmap into .claude/skills/screenmap/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "screenmap", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/aleqsio/screenmap/tree/main/plugins/screenmap/skills/screenmapType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add aleqsio/screenmap --skill screenmap -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install aleqsio/screenmap screenmap --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/aleqsio/screenmap.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/screenmap/skills/screenmap .agents/skills/screenmap && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "screenmap" agent skill from https://github.com/aleqsio/screenmap/tree/main/plugins/screenmap/skills/screenmap into .agents/skills/screenmap/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "screenmap", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add aleqsio/screenmap --skill screenmap -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install aleqsio/screenmap screenmap --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/aleqsio/screenmap.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/screenmap/skills/screenmap .cursor/skills/screenmap && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "screenmap" agent skill from https://github.com/aleqsio/screenmap/tree/main/plugins/screenmap/skills/screenmap into .cursor/skills/screenmap/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "screenmap", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/aleqsio/screenmap.git --path plugins/screenmap/skills/screenmap--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add aleqsio/screenmap --skill screenmap -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install aleqsio/screenmap screenmap --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/aleqsio/screenmap.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/screenmap/skills/screenmap .gemini/skills/screenmap && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "screenmap" agent skill from https://github.com/aleqsio/screenmap/tree/main/plugins/screenmap/skills/screenmap into .gemini/skills/screenmap/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "screenmap", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install aleqsio/screenmap screenmapInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add aleqsio/screenmap --skill screenmap -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/aleqsio/screenmap.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/screenmap/skills/screenmap .github/skills/screenmap && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "screenmap" agent skill from https://github.com/aleqsio/screenmap/tree/main/plugins/screenmap/skills/screenmap into .github/skills/screenmap/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "screenmap", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add aleqsio/screenmap --skill screenmap -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install aleqsio/screenmap screenmap --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/aleqsio/screenmap.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/screenmap/skills/screenmap .opencode/skills/screenmap && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "screenmap" agent skill from https://github.com/aleqsio/screenmap/tree/main/plugins/screenmap/skills/screenmap into .opencode/skills/screenmap/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "screenmap", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
screenmapGenerate a visual navigation map of an Expo / React Native or NativeScript app.
Screenmap is an agent skill from aleqsio/screenmap. Generate a visual navigation map of an Expo / React Native or NativeScript app. Statically parses routes and links (expo-router, react-navigation, NativeScript Angular Router or Core XML pages, or your own parser) for full coverage, then deep-links through every screen in the iOS simulator or Android emulator capturing screenshots — including runtime states like bottom sheet snap points and modals — and renders a self-contained HTML map. Both platforms can go into one map with a platform switcher. Also diffs two…
Its SKILL.md is about 7.2k tokens, which your agent loads only when the skill is triggered. The skill folder holds 27 other files, including scripts and reference files (for example `references/nativescript.md`).
It sits in Mobile, covering Cross-platform mobile apps and Mobile testing and debugging. It works with Expo, Android, iOS and React Native. The repository describes itself as: Visual navigation maps for Expo/React Native apps: agent-explored screenshots, flows, and an interactive .scrmap visualiser. The licence is MIT.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit febe3f7. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 13 files in scripts/ (JavaScript, from the files we listed), which the agent can run.
Shell commands in SKILL.md call:
adbnodexcrunnpxgitghnpmFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npx, git, gh and npm, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Screenmap loads about 7.2k tokens when it runs, and up to ~8.5k if it reads all its reference files. Until then it costs about 207 tokens; SKILL.md has 3,673 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from aleqsio/screenmap at commit febe3f7, republished under its MIT licence (© aleqsio). 3,673 words, ~7,244 tokens.
.claude/skills/screenmap/SKILL.md (or your agent's skills folder). This skill also uses 21 other files; get the full folder from GitHub.Produce a visual map of an Expo / React Native or NativeScript app's navigation: every route as a card with a screenshot, runtime state variants (bottom sheets at each snap point, modals), and navigation edges between screens.
Arguments: optional path to the app project (default: current working directory). --static = skip the device phases and render a screenshot-less map. --platform ios|android|both (default ios) = which device(s) to capture on. pr <number> or diff <base>..<head> = PR diff mode (see bottom).
Working directory contract: all outputs go to <project>/.screenmap/out/ — graph.json, screens/*.png, flows/*.yaml + flows/*.meta.json, map.html. Suggest adding .screenmap/out/ to the project's .gitignore at the end.
Platform contract: with one platform, screenshots go to screens/<slug>.png as they always have. With --platform both, they go to screens/ios/<slug>.png and screens/android/<slug>.png, capture-status.json is keyed by platform first ({"android": {"<routeId>": …}}), and the bundle carries both so the viewer gets an iOS / Android switcher. Run the device phases once per platform, all the way through, before starting the next — never interleave them.
Everything below that touches a device has a form per platform. <dev> is the iOS UDID or the Android serial (adb devices); with one device attached you can use booted on iOS and omit -s <dev> on Android.
| iOS | Android | |
|---|---|---|
| list devices | xcrun simctl list devices booted | adb devices -l |
| deep link | xcrun simctl openurl <dev> "<url>" | adb -s <dev> shell am start -a android.intent.action.VIEW -d '<url>' |
| screenshot to disk | xcrun simctl io <dev> screenshot <path> | adb -s <dev> exec-out screencap -p > <path> |
| relaunch | xcrun simctl terminate <dev> <bundleId> then launch | adb -s <dev> shell am force-stop <pkg> then monkey -p <pkg> -c android.intent.category.LAUNCHER 1 |
| freeze status bar | xcrun simctl status_bar <dev> override … | SystemUI demo mode (see D3) |
| reach host Metro | works as-is | adb -s <dev> reverse tcp:8081 tcp:8081 first, or nothing loads |
| taps / swipes | argent (--udid <dev>) | argent (--udid <dev> — it takes an Android serial too) |
Quote the Android deep link in single quotes: adb shell runs the string on the device, so an unquoted & in a query string backgrounds the command instead of passing it.
Every interaction sequence you perform is recorded as a replayable flow, written at the moment you perform it — not reconstructed afterwards. Flows use the argent flow format (argent.swmansion.com — Software Mansion's agentic mobile toolkit): a <name>.yaml argent flow plus a <name>.meta.json cartography sidecar, both in <project>/.screenmap/out/flows/. Anyone replays a flow headlessly, no LLM in the loop: npx @swmansion/argent flow run .screenmap/out/flows/<name>.yaml. Full pair schema: docs/scrmap-format.md in the skill repo.
# Open item details and expand the sheet to 50%
steps:
- tool: open-url
args:
url: "myapp://details/42"
- wait: 1500
# Open sheet button
- tap: { x: 0.4975, y: 0.4691 }
- tool: gesture-swipe
args: { fromX: 0.4975, fromY: 0.8009, toX: 0.4975, toY: 0.4828 }{ "formatVersion": 2, "name": "details-sheet-50", "route": "details/[id]",
"title": "Open item details and expand the sheet to 50%", "device": "iPhone 17 Pro",
"steps": { "2": { "target": "Open sheet button" },
"3": { "capture": "details_id--sheet-50.png", "note": "sheet at 50% snap" } } }Rules:
flow-start-recording / flow-add-step): every step executes live, only successful steps are recorded, and taps get durable selectors instead of coordinates. Write the sidecar yourself alongside. Without argent, write the YAML directly using normalized 0–1 coordinates (device points ÷ device point-size).steps is keyed by 0-based YAML step index. Every coordinate tap/swipe needs a target label (visible text or accessibility description). When a tap/swipe NAVIGATES to a different screen, set "screen": "<route id it landed on>" — this is how multi-screen flows stay traceable and observed edges get pinned. Screenshots are sidecar capture entries on the step they follow — never YAML steps."landmarks": ["Explore", "Trending"] — 2–5 words that are visible on the arrival screen and identify it (a title, a section header, a fixed button label; not live content). Headless replays in CI OCR the end screen and check these words to detect flow drift — without landmarks a drifted flow can only be caught heuristically.note.{{secret:NAME}} placeholders if input is unavoidable.node <this skill's dir>/scripts/parse-routes.mjs <project>The parser picks a route provider for the project — expo-router, react-navigation, nativescript (Angular Router, Core XML pages, or the components an Octane / React / Vue / Svelte app mounts, pushes and presents), or a custom command — and prints which one it chose and why. See docs/route-providers.md for the full contract.
For a NativeScript project (mode is nativescript), read references/nativescript.md in this skill's directory now: deep links come from routes.links, there is no Metro, and it has its own state hints and PR-diff steps.
Read the produced <project>/.screenmap/out/graph.json and report the summary to the user: the provider (mode), route count, layouts (with navigator types), edges (flag unresolved ones), routes with state hints, routes needing params, and routes with no deep link (navigationOnlyRoutes).
If the parser exits saying no provider recognised the project, or that two fit equally well, do not guess. Show the user the detection table it printed and ask which to use, then re-run with --provider <id>:
node <this skill's dir>/scripts/parse-routes.mjs <project> --detect # scores only
node <this skill's dir>/scripts/parse-routes.mjs <project> --provider react-navigationA project whose screens are registered somewhere none of the providers read — a generated route table, a home-grown router — is not a dead end: write a small script that emits the graph fragment documented in docs/route-providers.md and point .screenmap/config.json at it with {"routes":{"provider":"custom","command":"…"}}.
If --static was requested, jump to Phase 6.
params, pick a sample value: prefer concrete values found in resolved edges' raw hrefs (e.g. /details/42 → id=42), then seed/fixture data in the repo, else 1. Record the substitution you'll use in deep links.(auth), login, sign-in, or a root layout with a redirect). Expect those to redirect during the sweep; that's fine — capture what actually renders and mark it in your report.Run this phase once per platform.
iOS
xcrun simctl list devices booted — check for a booted simulator.attach action FIRST so the user can watch (harmless error if nothing is booted yet — boot/build, then retry attach).npx expo start via background Bash from the project dir).npx expo run:ios (warn the user this builds and takes minutes), or fall back to web (see bottom).graph.json:xcrun simctl openurl booted "<scheme>://"xcrun simctl openurl booted "exp://127.0.0.1:8081/--/"
Take an MCP screenshot to confirm the app rendered (not a crash/error screen). Use whichever URL form worked for the rest of the run.Android
There is no Android equivalent of the iOS simulator MCP, so the user watches the emulator window itself — say so rather than promising a live panel. The android-debugging skill, if available, covers adb troubleshooting in more depth.
adb devices -l — check for an attached device or a running emulator. If none, list AVDs with emulator -list-avds and start one in the background: emulator -avd <name> -no-snapshot -no-boot-anim &. If adb/emulator are not on PATH, they are under $ANDROID_HOME/platform-tools and $ANDROID_HOME/emulator.adb wait-for-device only waits for adb to see it, so poll until adb shell getprop sys.boot_completed returns 1, then dismiss the lock screen with adb shell input keyevent 82. Installing before that fails in ways that read as a broken APK.adb reverse tcp:8081 tcp:8081. The emulator's localhost is the emulator; without the tunnel the app cannot reach Metro on the host and nothing will load. Redo it after any emulator restart.adb shell monkey -p <pkg> -c android.intent.category.LAUNCHER 1). If no dev build is installed, npx expo run:android (warn the user this builds and takes minutes).adb shell am start -a android.intent.action.VIEW -d '<scheme>://', then screenshot to disk and look at it.Routes with "reach": "navigation-only" have no deep link at all — normal for react-navigation screens that are absent from the linking config. Do not deep-link them and do not visit the app root in their place: that captures the home screen under the wrong route's name, which is exactly the kind of silent bad capture Phase 4b exists to catch. Skip them in this phase, record {"needsNavigation": true} for them in capture-status.json, and reach them by tapping in Phase 5b — their nav flow is their capture.
For each route with a URL (substituting params from Phase 2; for +not-found, deep-link a garbage path like /definitely-not-a-route):
wait, or just sleep). Content screens that fetch over the network need 3–4s — a capture showing a spinner or loading skeleton means the wait was too short, not that the route is broken; the Phase 4b review catches these, and you re-capture with a longer wait.<project>/.screenmap/out/screens/<slug>.png (or screens/<platform>/<slug>.png when capturing both) — use the exact slug from graph.json; the renderer depends on this naming. (The iOS MCP screenshot is for your own eyes only; it doesn't save a file.)screenshot. If a route shows a red error screen, an error boundary, or redirected somewhere else, still keep the capture but note it for the final report.Error boundaries stick: once a bad deep link crashes a screen, subsequent deep links may render into the same error boundary, silently poisoning every capture after it. So before delivering:
Render a draft map (Phase 6 commands) and look at it — it doubles as a contact sheet of all captures.
Classify every capture that isn't clearly the real screen, and write the verdicts to <project>/.screenmap/out/capture-status.json (the renderer badges them on the map):
{ "<routeId>": { "status": "not-found", "needsNavigation": true, "note": "why + what a future agent should do instead" } }Statuses: ok · empty-state · not-found · error-boundary · loading · auth-wall. Decide per capture:
needsNavigation: true, and say in the note how the screen is actually reached (opened from a shared link, requires user-owned data, etc.).empty-state, no needsNavigation. Don't confuse this with not-found.needsNavigation: true. Beware the poisoned tail: error boundaries stick, so captures taken after a crash may show the same stuck error — relaunch the app (xcrun simctl terminate booted <bundleId>, relaunch, wait for the bundle) and re-capture those.Re-render after recovery.
For each route whose stateHints is non-empty, deep-link to it again and:
bottom-sheet — Read the route's source file (file in graph.json) to find what opens the sheet (a button whose onPress calls ref.expand() / present(); some sheets are open by default — check the index prop). Take an MCP screenshot, locate the trigger, tap it. Then for each snap point in the hint (e.g. 25%, 50%, 90%):
swipe from the sheet handle's current position to y ≈ screen_height × (1 − snap). Start the swipe well inside the screen — a start point within 4pt of an edge triggers an OS edge gesture instead.screens/<slug>--sheet-<value>.png (e.g. details_id--sheet-50.png — strip the %).rn-modal — find and tap the trigger, capture screens/<slug>--modal.png, then dismiss (close button, tap outside, or just deep-link away).
router-modal — already captured as its own route in Phase 4; nothing extra needed.
Rules for this phase:
state hints: N routes · captured M · skipped K (list + why) — and carry it into the Phase 6 delivery report. A state pass that quietly processes 3 of 17 hints looks complete on the map and isn't; that silence has bitten before.Deep links are shorthands; the map's primary flow for each screen is the path a human takes. For every reachable route, record flows/nav-<slug>.yaml + sidecar (name nav-<slug>, title "Navigate to <title>") that reaches it from app launch using real taps:
open_url to the app root (scheme://) — that's the app entry, not a shortcut. Everything after is taps/swipes.coordinate (device points), target (durable label), and screen (the route id it landed on). Verify the landing with an MCP screenshot BEFORE writing the step — a wrong screen poisons the graph.<sourceSlug>--<state>.png, e.g. Home--drawer.png) and insert a screenshot step referencing it right after the opening tap in every flow that passes through it. Viewers then render the ripple for the next tap on the drawer capture instead of the closed-drawer base screen.<slug>.png).These flows are what make edges pinnable: a nav flow tapping through a transition tells the map viewer exactly where the trigger sits on the source screen.
# downscale (sips is macOS; on Linux use `mogrify -resize '800x800>' <files>`)
for f in <project>/.screenmap/out/screens/*.png; do sips -Z 800 "$f" >/dev/null; done
node <this skill's dir>/scripts/pack-map.mjs <project> # → .screenmap/out/<app>-<date>.scrmap bundle
node <this skill's dir>/scripts/render-map.mjs <project>/.screenmap/out/graph.json # static HTML fallbackCapturing both platforms: downscale each screens/<platform>/ directory, then pass the platforms to the packer — node .../pack-map.mjs <project> --platforms ios,android. The bundle then carries both and the viewer shows an iOS / Android switcher; report coverage per platform, since a screen can be fine on one and broken on the other.
The .scrmap bundle (zip: manifest.json + map.json + screens/) is the primary deliverable — see docs/scrmap-format.md in the skill repo. Open it in the map viewer (apps/visualiser in the skill repo, npm run dev, drag the bundle in): interactive graph, flow playback, click-to-copy replay commands. Send the bundle with SendUserFile; send map.html too as the no-tooling fallback (display: render). Report: routes captured / total, state variants captured, anything skipped (error screens, auth redirects, un-triggerable sheets), unresolved edges. Offer to publish as an Artifact (if so, load the artifact-design skill first and rebuild the page body-only per Artifact rules — don't publish the full-document HTML as-is). Suggest adding .screenmap/out/ to .gitignore.
/screenmap replay <flow-name>Flows are argent YAML, so the primary replay is headless:
npx @swmansion/argent flow run <project>/.screenmap/out/flows/<flow-name>.yamlRun that first (it needs no LLM and reports pass/fail per step; add --device <id> to pick a device, and argent takes an Android serial wherever it takes an iOS UDID). Fall back to manual replay only when argent isn't installed and can't be (npx unavailable) or when the flow fails and the user wants a diagnosis: execute the YAML steps yourself — open-url/wait via the device command table, taps/swipes via the simulator MCP (iOS) or adb shell input tap <x> <y> in device pixels (Android), using the sidecar's target labels as the source of truth (recorded coordinates are hints that may have drifted).
A flow recorded on one platform is not guaranteed to replay on the other: coordinates are normalized, but layouts, system chrome heights and back-navigation differ. Record per platform when you capture both, and name the platform in the sidecar's device field. Verify each step with an MCP screenshot; if a target can't be found in 3 attempts, stop and report which step failed and what the screen showed instead. Same safety rules as Phase 5: never trigger destructive or submitting controls.
/screenmap pr <number> or /screenmap diff <base>..<head>Preview what a change does to the app's navigation surface: which screens were added,
removed, or changed, which edges appeared or vanished, with before/after screenshots.
The deliverable is a .diff.scrmap bundle (format: docs/diff-scrmap-format.md in the
skill repo) — the map viewer renders it with green/amber/red highlights, a Changes
panel, and base-vs-head comparison per screen.
Working directory: <project>/.screenmap/out/diff/<slug>/ where slug is pr-<number> or
<base>..<head>. Verdicts are static-only (a screen is "changed" iff the change
set touches its file or import closure); screenshots are evidence for the reviewer,
not input to the classification.
gh pr view <n> --json number,title,url,baseRefName,headRefName,mergeCommit,files.
For a merged PR, head = the merge commit, base = its first parent (<merge>^).
For an open PR, gh pr view --json headRefOid,baseRefOid. Write pr.json
({number,title,url,baseSha,headSha,baseRef,headRef}) and changed-files.txt
(gh pr diff <n> --name-only, or git diff --name-only <base> <head>).git rev-parse; same files, no number.git fetch --depth 1 origin <sha> for any SHA the repo doesn't have.ios/, android/, patches/, or change
native deps in package.json, warn the user that the installed dev build may not
match both sides — JS-only diffs are the supported case. Proceed only if they accept.
A change under ios/ only affects the iOS side and one under android/ only the
Android side, so say which platform's captures to distrust rather than both.git stash). Remember the
original ref; restore it at the end, always — even after failures.git -C <project> checkout --detach <baseSha>
node <skill>/scripts/parse-routes.mjs <project> # writes .screenmap/out/graph.json
cp <project>/.screenmap/out/graph.json <diffDir>/base/graph.json
git -C <project> checkout --detach <headSha>
node <skill>/scripts/parse-routes.mjs <project>
cp <project>/.screenmap/out/graph.json <diffDir>/head/graph.json
node <skill>/scripts/diff-map.mjs suspects <diffDir> --project <project>Read suspects.json and report the work-list to the user before capturing: N added,
N removed, N modified (with reasons and via-files), plus any broad files excluded from
expansion. That report alone is already a useful static preview — if the user asked
for --static, skip to D4.
Then read the PR's actual diff for each suspect's via-files and write
<diffDir>/notes.json — { "<nodeId>": "what visibly changes on this screen" }, one
plain sentence per suspect (e.g. "Trending topic pills become full-width ranked rows").
Viewers show this note on the screen's diff card; without it the card only says
"file-touched", which tells a reviewer nothing.
If reading the diff convinces you a statically-flagged suspect has no visible
change (shared import only, pure refactor, code path that doesn't render there),
use { "note": "why it's unaffected", "verdict": "unaffected" } instead — pack drops
it from the changed list into diff.json's dismissed section (omitted from the
viewer's Changes list, kept in the bundle for audit). You can also skip capturing that
screen. Dismiss only on positive evidence from the diff, not on a hunch — when unsure,
keep it and let the captures decide.
Status is tracked per capture state, not just per screen. When a screen's change
lives in one state (below the fold, inside a sheet), say so with per-state notes —
"" is the bare screen, other keys are variant names:
"Settings": { "note": "A 'Beta features' row is added between Languages and Help.",
"states": {
"": { "note": "Top of the list is identical — the row is below the fold.", "verdict": "unaffected" },
"bottom": "New 'Beta features' row appears between Languages and Help." } }The viewer marks each state in the node's dropdown (± bottom etc.), so capture the
state variants that make the change visible (Phase 5 style) — a diff whose change is
below the fold and has no scrolled state variant shows two identical screenshots.
Boot the app (Phase 3), then freeze the status bar so both sides capture identically (clock noise otherwise pollutes every pixel comparison):
# iOS
xcrun simctl status_bar booted override --time "9:41" --dataNetwork wifi --wifiMode active --wifiBars 3 --cellularMode active --cellularBars 4 --batteryState charged --batteryLevel 100
# Android — SystemUI demo mode is the equivalent
adb shell settings put global sysui_demo_allowed 1
adb shell am broadcast -a com.android.systemui.demo -e command enter
adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 0941
adb shell am broadcast -a com.android.systemui.demo -e command battery -e level 100 -e plugged false
adb shell am broadcast -a com.android.systemui.demo -e command network -e wifi show -e level 4
adb shell am broadcast -a com.android.systemui.demo -e command notifications -e visible falseThen for each side in order base → head:
git checkout --detach <sha>, restart Metro (kill the background process, start
again), and relaunch the app; verify a deep link renders the right revision.side: both|base for base,
both|head for head), Phase 4 style, into <diffDir>/<side>/screens/<slug>.png.
Same waits, same 4b review discipline; verdicts go to
<diffDir>/<side>/capture-status.json.stateHints — and any state the diff added (states with
reason hint) — do a scoped Phase 5 pass so state variants land as
<slug>--<state>.png on the right side.Keep both sides comparable: same device, same account, same waits.
for f in <diffDir>/{base,head}/screens/*.png; do sips -Z 800 "$f" >/dev/null; done
node <skill>/scripts/diff-map.mjs pack <diffDir> --device "<device name>"
# both platforms: screens live at <diffDir>/<side>/screens/<platform>/, and
# --device takes one name per platform in the same order
node <skill>/scripts/diff-map.mjs pack <diffDir> --platforms ios,android --device "iPhone 17 Pro,Pixel 7"Restore the original ref. Send the .diff.scrmap with SendUserFile; report the diff
table (added/modified/removed screens, edge changes, state changes, broad-file blind
spots, anything uncapturable). The bundle opens in the same map viewer as .scrmap
files (drag it in). If a full .scrmap of the app exists, tell the user to load both —
the map viewer overlays the diff on the full map, so unchanged screens keep their real
screenshots (dimmed) and changed screens flip base⇄head in place (hover for a red
changed-pixels render).
npx expo start --web, confirm http://localhost:8081/_sitemap lists the same routes as the parse (good cross-check).urlPath with npx playwright screenshot --viewport-size=390,844 "http://localhost:8081<urlPath>" <project>/.screenmap/out/screens/<slug>.png (needs npx playwright install chromium once; ask before installing).npx playwright screenshot --full-page after using its --wait-for-timeout or skip and note the limitation.© aleqsio, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 21 other files (scripts, references) in plugins/screenmap/skills/screenmap of aleqsio/screenmap.
Open the folder on GitHubat commit febe3f7
Screenmap next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Screenmap this skillaleqsio/screenmap | 239 | — | ~7.2k | Automated safety check: Pass | MIT | |
| ThemingCode-with-Beto/skills | 141 | — | ~2.5k | Automated safety check: Pass | None | |
| Expo Development on Limrunsuperset-sh/superset | 15k | — | ~3.6k | Automated safety check: Pass | Custom licence | |
| Fishjam React Native Clientsoftware-mansion-labs/skills | 291 | — | ~1.9k | Automated safety check: Pass | MIT | |
| Expo Tailwind SetupCherryHQ/cherry-studio-app | 4k | 8 repos | ~3k | Automated safety check: Pass | MIT | |
| Expo Brownfield Integrationmweinbach/agent-coworker | 156 | 2 repos | ~900 | Automated safety check: Notes | Custom licence |
Code-with-Beto/skills
Scaffold a unified, cross-platform color theme system into an Expo Router app.
superset-sh/superset
Sets up and runs Expo and React Native apps on Limrun remote iOS simulators and Android emulators, using dev-client builds for fast JS and TS iteration.
software-mansion-labs/skills
React Native / Expo SDK for Fishjam — video/audio streaming on iOS and Android.
CherryHQ/cherry-studio-app
Set up Tailwind CSS v4 in Expo with react-native-css and NativeWind v5 for universal styling
mweinbach/agent-coworker
Helps add Expo and React Native to an existing native iOS or Android app, and choose between a prebuilt AAR or XCFramework and a fully integrated build.
hyochan/react-native-nitro-sound
Build and run repeatable react-native-nitro-sound recorder/player regression tests on an iOS Simulator or Android emulator, with explicit virtual-device selection, microphone permission, Maestro…
Categories
Generate a visual navigation map of an Expo / React Native or NativeScript app. Screenmap is an agent skill from aleqsio/screenmap. Generate a visual navigation map of an Expo / React Native or NativeScript app.
Screenmap fits situations like: the user asks to map an Expo/React Native/NativeScript apps navigation; wants a visual sitemap of their app; wants to preview/review what a PR changes on-screen.
Run `npx skills add aleqsio/screenmap --skill screenmap -a claude-code`. Or copy the skill folder (plugins/screenmap/skills/screenmap in aleqsio/screenmap) into .claude/skills/screenmap in your project. Claude Code loads it when a task matches its description.
Run `npx skills add aleqsio/screenmap --skill screenmap -a codex`. Or copy the skill folder (plugins/screenmap/skills/screenmap in aleqsio/screenmap) into .agents/skills/screenmap in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add aleqsio/screenmap --skill screenmap -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/screenmap, .gemini/skills/screenmap, .github/skills/screenmap and .opencode/skills/screenmap in your project.
Going by SKILL.md and its folder, Screenmap needs JavaScript for the scripts in its folder and the command-line tools its instructions call (adb, node, xcrun, npx, git and gh). Our summary lists: Node.js.
SKILL.md contains no URLs. Its commands use npx, git, gh and npm, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Screenmap is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.2k tokens (SKILL.md is roughly 29k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 1.3k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Screenmap: Theming (Code-with-Beto/skills, 141 stars), Expo Development on Limrun (superset-sh/superset, 15k stars), Fishjam React Native Client (software-mansion-labs/skills, 291 stars) and Expo Tailwind Setup (CherryHQ/cherry-studio-app, 4k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
aleqsio (a GitHub user) maintains it in aleqsio/screenmap, which has 239 GitHub stars. The repository was last updated on October 4, 2026.
Source: aleqsio/screenmap on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.