Install
$ agentstack add skill-framara-app-store-screenshots-skill-app-store-screenshots-skill ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
App Store Screenshots — capture → frame → upload
Battle-tested end to end on a shipping game (SAPPER, 2026): 7 shots × 10 languages × iPhone + iPad = 140 frames, replaced across 39 App Store Connect locales and resubmitted for review in one day.
The philosophy: App Store screenshots are marketing frames, not raw UI — a big localized headline over a device mock containing a real, localized, real-data capture. Keep three independent layers so each can change cheaply:
- Raw captures — slow to make, often not regenerable (live data, daily
seeds). Archive them in git.
- Captions + design config — one JSON for all locales and shots.
- Compositor —
scripts/generate.pyre-renders every frame in minutes
after any copy or design tweak. No recapture needed.
Prerequisites
- Xcode + iOS simulators for the target devices (iPhone 17 Pro Max class
for 6.9", iPad Pro 13" class) — captures use xcrun simctl.
- XcodeBuildMCP CLI
(brew install cameroncooke/xcodebuildmcp/xcodebuildmcp) — provides element-ref UI automation (xcodebuildmcp ui-automation snapshot-ui/tap) and bundles the AXe binary the capture scripts depend on, at /opt/homebrew/Cellar/xcodebuildmcp//libexec/bundled/axe. (Alternative: install AXe standalone — brew install cameroncooke/axe/axe.)
- asc CLI, authenticated
against the App Store Connect API — uploads, localizations, builds, review submissions.
- Google Chrome — headless renderer for the frame compositor.
- Python 3 — capture loops, compositor, verification (stdlib only).
- A DEBUG build of the app with a screenshot-mode launch flag (see
Phase 1) installed on the simulators.
References (read the one matching your phase)
references/sizes-and-devices.md— simulators, exact pixel sizes, ASC
display types, device-mock CSS values, type scale tables
references/captions.md— caption anatomy, the narrative arc,
transcreation rules per locale (glossary, line breaks, CJK), captions.json
references/capture-locales.md— per-locale capture loops, iPhone vs iPad
differences, state discriminators, every automation gotcha
references/compositor.md— the HTML/CSS frame generator, auto-fit and
auto-push JS (with the bugs they prevent), render command, review checklist
references/asc-upload.md— locale mapping table, the fan-out abort gotcha- mandatory verification, review-submission rebuild (incl. Game Center)
Bundled scripts (copy into the app's repo and adapt)
scripts/generate.py— the frame compositor (HTML/CSS → headless Chrome)scripts/captions.example.json— the copy/config data shapescripts/loop_locales_skeleton.py— per-locale capture loop with the
battle-tested helpers (frame-targeted taps, state assertions, retries)
scripts/verify_asc_screenshots.py— post-upload per-locale verification
Phase summary
0 — Plan. 5–7 shots, caption-led, arc: hook → core choice → retention → secondary mode → social → monetization → trust. Background colors rotate through the app's own palette, never repeating adjacently. No prices in screenshots (they vary by storefront and drift). Captions transcreated per locale with explicit line breaks.
1 — Prepare the app. Add a DEBUG-only launch flag (e.g. -MarketingScreenshots YES) that: hides store prices behind a neutral localized tag; forces the accessibility overlay on custom-drawn surfaces so automation can read them. Make sure a debug menu can reset/replay any state you need to capture.
2 — Capture iPhone. Use a sim whose native screenshot IS the store size (no resizing, ever). Build each app state once in English, then per locale: background the app (state saves on backgrounding!) → terminate → relaunch with -AppleLanguages "(xx)" -AppleLocale xx_XX → re-shoot with locale-independent navigation. Clean status bar via simctl status_bar.
3 — Capture iPad. Same flow, three traps: axe button home is a silent no-op (use button lock to background); the status bar shows a date in the SYSTEM language (switch .GlobalPreferences + reboot per locale); all layout metrics differ from iPhone — re-probe everything.
4 — Frame. generate.py + captions.json → headless Chrome at exact store resolution. Auto-fit shrinks long headlines; auto-push moves the device below wrapping subs. Validate every PNG's dimensions; eyeball the longest Latin locale and one CJK locale on every shot type.
5 — Upload. Stage a hardlink tree keyed by ASC locale codes (app languages fan out: en serves en-US/GB/AU/CA + all store-only locales). Upload with --replace to the display types the listing ALREADY uses. The fan-out aborts all remaining locales on the first delivery failure while exiting 0 — run verify_asc_screenshots.py and re-run the gaps.
6 — Resubmit (if a review was pending). Save the pending submission's item IDs → cancel → new build + screenshots → attach build → recreate submission → re-add every item (the appStoreVersions item only attaches after screenshot assets finish processing — add it last) → audit the count → submit.
Hard-won rules (apply everywhere)
- Frame-target every tap from
axe describe-uioutput; fixed coordinates
break across locales and states.
- The accessibility tree contains ALL layers at once — find a geometric
discriminator (e.g. a known card's y-position) to assert which screen you're on, and verify after every navigation.
- The first tap after a cold launch or transition is often eaten: retry loops
with state assertions, never fire-and-forget.
- Long-press = separate
touch --down, real sleep,touch --up. The
single-command delay form sometimes registers as a tap.
- After any swipe, wait until two consecutive position reads agree before
computing tap targets (content decelerates).
- Anything that reads localized a11y labels (solvers, content checks) runs in
English only; per-locale passes navigate by geometry.
- Verification is part of every phase: look at the captures with your eyes,
measure the frames, list the uploads. Every silent failure we hit was caught by checking, not by exit codes.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: framara
- Source: framara/app-store-screenshots-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.