tjdrhs90/flutter-flame-harness/flame-harness-screenshot
Claude Code and agent skill by tjdrhs90/flutter-flame-harness
- community
Checking that the SKILL.md file is still in the repository.
Phase 9 — capture store screenshots in the game's configured locales via integration_test (ads hidden), fill ASO keywords, and upload via fastlane.
Install
npx vskill@latest install tjdrhs90/flutter-flame-harness/flame-harness-screenshotSKILL.md
flame-harness-screenshot
Phase 9 of the flutter-flame-harness pipeline. Captures KO and EN store screenshots by driving the game's integration_test harness on the required device sizes (ads hidden), fills ASO metadata (keywords, localized titles, descriptions), and uploads the screenshots via fastlane.
All file schemas (config.md, state.md, pipeline-log.md) and the phase transition table are defined in docs/harness-protocol.md — that document is the single source of truth (§1 for config.md and credentials_dir; §2 for state.md; §6 for log schemas; §7 for the screenshot → submit transition and the status: running rule). Do not redefine schemas here.
Prerequisites: The game has been built and uploaded (Phase 8 flame-harness-build). The iOS simulator is a 6.7" iPhone model and the Android emulator is a phone-sized device. flutter drive and fastlane must be installed on the developer's macOS machine.
Input — Read Inputs
Before any action, load:
docs/harness/config.md— extractapp_slug,bundle_id,app_name, anddefault_language
(per protocol §1).
docs/harness/state.md— confirmnext_role: screenshot(per protocol §2).
Derive the game root path: <projects-dir>/<app_slug>/.
Phase 1 — Harness Setup
Copy the integration_test template
Copy templates/screenshots_test.dart.template into the game's integration_test/ directory:
Adapt the TODO markers
Open <game>/integration_test/screenshots_test.dart and replace every // TODO(generator): comment block with the game's real screen-driving code:
- Replace
<__APP_SLUG__>in the import with the actual package name (fromconfig.mdapp_slug,
converting hyphens to underscores).
- Seed mock SharedPreferences / Hive / Isar data to skip first-run tutorials and show a
representative UI state (high score, coins, unlocked skins).
- Wire the locale controller to force the locale to the
SCREENSHOT_LOCALEdart-define value so
screenshots are language-deterministic regardless of the simulator's system locale.
- Replace the placeholder screen list with the game's actual key screens (home, gameplay,
game-over/results, optional secondary screen), keeping zero-padded two-digit name prefixes so fastlane and App Store Connect receive them in order.
Test driver
Ensure <game>/test_driver/integration_test.dart exists. `integrationDriver()` has no default screenshot writer — its native path is guarded by onScreenshot != null, so without the callback below every takeScreenshot byte is silently discarded and no file is ever written. Pass one:
Phase 2 — Capture
Device sizes
| Platform | Required device | |
|---|---|---|
| iOS | 6.7" iPhone simulator (e.g. iPhone 15 Pro Max) | |
| Android | Phone emulator (e.g. Pixel 7, 1080 × 2400) |
Run flutter devices to identify the device ID. Use the -d flag to target the correct device.
Ads hidden during capture
Pass --dart-define=screenshots=true to every flutter drive invocation. The game's ad helper must check this flag and suppress all ad units (banner, interstitial, rewarded) during capture so no ad overlays appear in store screenshots. Screenshot mode should also skip the ATT prompt and mute audio (native prompts/sound break automated capture).
No alpha channel (App Store rejection): store screenshots — and the iOS app icon — must be flattened to opaque RGB. Check with sips -g hasAlpha <file> (must report hasAlpha: no).
`sips -s format png` does NOT strip alpha — it re-encodes and keeps the channel, so it silently leaves the rejection in place. Use one of these instead:
See docs/game-gotchas.md → Store rejections.
Locale loop — KO and EN
Run the capture twice, once per locale (ko and en), using --dart-define=SCREENSHOT_LOCALE=:
SCREENSHOT_DIR is read by the onScreenshot callback above — give each locale its own directory so the two runs can't overwrite each other:
Repeat for the Android phone emulator with its device ID, using build/screenshots/android/<ko-KR|en-US>.
Screenshot output directory
The PNGs land in $SCREENSHOT_DIR (default build/screenshots), named after the takeScreenshot argument — e.g. build/screenshots/ios/ko/01_home.png. Nothing is written to the game root. Phase 4 copies these into the fastlane-expected paths.
After each run, confirm the files actually exist before moving on — an empty directory means the onScreenshot callback is missing or the capture failed:
Phase 3 — ASO Metadata
Populate all ASO metadata for both ko and en locales.
iOS keywords.txt
Write <game>/ios/fastlane/metadata/<locale>/keywords.txt for each locale. The field holds at most 100 characters including commas; aim for 95–100 so none of it is wasted.
Example KO keywords (97 characters):
Example EN keywords (99 characters):
Verify the length before writing. Count characters, not bytes — wc -c counts bytes, and one Hangul syllable is 3 bytes in UTF-8, so the KO example above measures 247 with wc -c. Using wc -c makes a valid Korean string look 2.5× over the limit and costs you two thirds of the field:
Both must report 95–100.
iOS localized title and description
Write under <game>/ios/fastlane/metadata/<locale>/:
name.txt— localized app display name (≤ 30 chars).subtitle.txt— localized subtitle (≤ 30 chars).description.txt— full App Store description (≤ 4000 chars, engaging, no keyword stuffing).promotional_text.txt— optional promotional text (≤ 170 chars).release_notes.txt— what's new in this version.
Write both ko and en variants.
Android localized title and description
Write under <game>/android/fastlane/metadata/android/<locale>/:
title.txt— localized app title (≤ 50 chars).short_description.txt— localized short description (≤ 80 chars).full_description.txt— localized full description (≤ 4000 chars).changelogs/<version-code>.txt— what's new.
Write both ko and en variants. Use locale codes ko-KR and en-US for the Android paths.
Phase 4 — Upload
Screenshot file placement
After capture, place PNG files in the fastlane-expected directory layout before running the upload lanes:
iOS — one subdirectory per locale under the fastlane screenshots folder:
Android — locale-scoped phone screenshot directories:
Create the directories, and empty them before copying — deliver and supply upload every PNG they find, so a leftover file from an earlier run or the other locale silently ships:
Every locale must report the same non-zero count. A zero means capture produced nothing (see Phase 2's onScreenshot note).
iOS — fastlane screenshots lane
Run from the iOS fastlane directory to upload the locale screenshot directories to App Store Connect (screenshots only — text metadata goes up in Phase 10):
The lane calls upload_to_app_store with skip_binary_upload: true, then runs a duplicate cleanup and count check and fails if App Store Connect does not end up with exactly the local number of screenshots per locale. A successful run ends with Screenshots verified — no duplicates.
Do not remove that cleanup step. deliver decides "is this screenshot already uploaded?" by comparing App Store Connect's sourceFileChecksum against the local file's MD5. When that comparison does not match, its post-upload verification concludes every local file is missing and retries — and the retry keeps the already-uploaded screenshots while re-uploading the whole set, so each image lands twice. Once a set holds 10 images its own "nothing missing" guard passes, so deliver prints Successfully uploaded all screenshots and exits 0 with a doubled set. overwrite_screenshots: true does not prevent this — it only clears the sets before the first round.
If an app already carries duplicates from an earlier upload, clean it without re-uploading:
Confirm the result against the live API — the per-locale counts must equal the local PNG counts:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/flame-harness-screenshot/SKILL.md
Popularity
- Repository stars
- 60
- Repository forks
- 5
- 7-day trend score
- 21
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/tjdrhs90/flutter-flame-harness/flame-harness-screenshot)