Appstore generate push screenshots
Skill jimmynotjames/simple-recurring-budgets/.claude/skills/appstore-generate-push-screenshots
Wren: An iOS app for fast, easy budgeting on the go
npx -y skills add jimmynotjames/simple-recurring-budgets --skill appstore-generate-push-screenshotsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Capture localized App Store screenshots with fastlane (Simulator) and upload them to App Store Connect via the self-healing retry controller. Runs the full capture → review → upload phase; if capture is already done, asks whether to re-capture (overwrite) or reuse the existing shots. Asks one choice (pause for inspection vs upload immediately) unless pre-authorized by an argument. Precondition: check_content.py exits 0. Use after /appstore:generate-screenshot-seeding. Invoked via /appstore:generate-push-screenshots.
SKILL.md
15.2 KB, as published. Nobody here has run it
Capture and push App Store screenshots
Drives the capture → review → upload phase of the App Store screenshot
workflow. The seed catalog must already be complete
(python3 scripts/screenshot_content/check_content.py exits 0); generate it with
/appstore:generate-screenshot-seeding first if it is not.
This skill does two long-running things back to back:
- Capture —
fastlane screenshotsdrives theAppStoreScreenshotsUI test on the Simulator (50 locales × 2 devices, ~2 h), then renames the captured runtime-code folders to App Store storefront codes (rename_for_deliver.py, run automatically by the lane). - Upload —
upload_with_retry.shpushes the captured shots to App Store Connect, working around ASC's HTTP 500s. Nothing goes live (submit_for_review:false); shots stage into the "Prepare for Submission" version.
Both phases run in the background with 20-minute progress ticks, so the whole skill runs unattended apart from (at most) two choices: whether to re-capture when shots already exist (step 2, only asked if capture is already complete) and the pause-vs-upload choice (step 3). Both are skippable via arguments.
Preflight — orchestrator model (before anything else)
Before any other step, run the orchestrator-model preflight (canonical:
AGENTS.md → "Orchestrator-model preflight"). This skill is tuned to orchestrate on
Sonnet; if the current session model is not Sonnet, stop and confirm
(AskUserQuestion on Claude Code, a markdown block on Cursor) before running
anything. This skill has no subagents — it's pure capture/upload mechanics — so the
only concern is that a model weaker than Sonnet may handle the tick-loop and
success-verification steps unreliably; Opus works but is pricier for no gain.
Arguments — how to run fully unattended
The invocation may carry optional arguments that pre-answer the prompts, so there is zero prompting. Arguments are space-separated and order-independent; they fall on two independent axes.
Capture axis (pre-answers the step-2 re-capture prompt, only relevant when shots already exist):
recapture(also acceptsfresh,overwrite) → clear the existing shots and re-capture from scratch (the ~2 h job), even if capture is already complete.keep(also acceptsreuse,skip-capture) → reuse the existing shots and skip capture.- no capture argument → if capture is already complete, ask the step-2 prompt once (the safe default; recapture is a ~2 h job that overwrites already-inspected shots). If capture is missing or partial, capture runs regardless — no prompt.
Upload axis (pre-answers the step-3 choice):
upload-now(also acceptsb,no-pause,auto) → Option B: capture, then upload immediately; review page opens for post-upload review.pause(also acceptsa,inspect) → Option A: capture, open the review page, and pause for an explicit "proceed" before uploading.- no upload argument → ask the step-3 choice once (the safe default; uploading to ASC is outward-facing, so absent explicit authorization, confirm first).
If the user's surrounding message already authorizes the action (e.g. "re-capture
everything" → recapture; "keep the existing shots" → keep; "push them without
stopping" / "upload as autonomously as possible" → upload-now), treat that as the
matching argument and do not prompt for that axis.
Autonomy
Apart from the step-2 re-capture prompt (only asked when shots already exist, and
skippable via the capture-axis argument above) and the step-3 choice (skippable via
the upload-axis argument), run end to end without pausing: do not ask "shall I
proceed?" between steps, do not ask before re-capturing failed locales, and do not
ask before retrying a failed upload subset — all of that is routine and pre-approved
in .claude/settings.json. The only other time you stop is a hard failure you
cannot self-heal (e.g. the capture lane fails to build) — surface the log tail and
stop.
Progress checklist
Print this checklist unchecked at the start, then re-print it (compact, one line
per step) with - [x] as each step completes:
- Model preflight — confirm session is Sonnet (else confirm before proceeding)
- Precondition — seed catalog complete (
check_content.pyexits 0) - Capture status — is capture already done? (
capture_progress.py); if done, ask re-capture vs reuse (unless pre-answered by argument) - Choice — Option A (pause) or B (upload now), or pre-answered by argument
- Capture —
fastlane screenshots(skipped if step 2 says done) - Review page — open
fastlane/screenshots/screenshots.html - Gate — [A] pause for "proceed"; [B] continue immediately
- Upload —
upload_with_retry.shrunning in background - Done — verify all storefronts confirmed; [B] remind review page is open
Omit steps that provably won't run (e.g. skip step 4 when capture is already complete and you chose to keep the existing shots) and say why.
Recipe
1. Precondition — seed catalog complete
python3 scripts/screenshot_content/check_content.py
- Exit 0: continue.
- Exit non-zero: stop. The seed catalog has gaps — tell the user to run
/appstore:generate-screenshot-seedingfirst. Do not capture against an incomplete catalog.
2. Capture status — is capture already done?
python3 scripts/screenshot_content/capture_progress.py
Reports N/M locales done and exits 0 only when every locale has its full
5-shot story for every device. It accepts both runtime-code folders (mid-capture)
and storefront-code folders (post-rename), so it reads correctly whether capture
just finished or never ran.
-
Exit non-zero: capture is needed (or partial). Step 4 runs it — no re-capture prompt (there is nothing to overwrite).
-
Exit 0: capture is already complete. Do not silently skip — ask whether to re-capture or reuse, unless the capture-axis argument (or the surrounding message) already pre-answered it (see Arguments). Ask once with
AskUserQuestion:Question: "Screenshots are already captured (N/M locales, 2 devices each). Re-capture and overwrite them, or keep the existing ones?"
- Keep existing (recommended): skip capture (step 4) and go straight to the review/upload steps. Recapture is a ~2 h job that would overwrite the already-captured (possibly already-inspected) shots.
- Re-capture (overwrite): clear the old shots and run the full capture.
Cursor / no-AskUserQuestion: present the choice as a markdown block and wait for the reply (unless pre-authorized).
Then branch:
- Keep /
keep: skip step 4. Note this in the checklist. - Re-capture /
recapture: clear the existing shots socapture_progress.pyno longer reports "done", then run step 4:
(This is the only path that wipesrm -rf fastlane/screenshots/*fastlane/screenshots/. It is gated behind the explicit re-capture choice — never clear shots on the "keep" path.)
3. Choice — the one human input (skip if pre-authorized)
If an argument or the surrounding message already pre-answered this (see
Arguments), skip the prompt and record the chosen option. Otherwise ask once,
before the long capture, with AskUserQuestion:
Question: "Capture + upload screenshots. How would you like to proceed?"
- A — Pause for inspection (recommended): after capture, open the review page and pause; you say "proceed" when ready to upload.
- B — Upload without pausing: after capture, start the upload immediately; the review page opens so you can look while it uploads.
Cursor / no-AskUserQuestion: present the choice as a markdown block and wait for the reply (unless pre-authorized).
Record the answer (A or B) — it determines step 6.
4. Capture — fastlane screenshots
Skip entirely if step 2 was already complete and you chose "keep". Run it when
capture was missing/partial, or when you chose "re-capture" in step 2 (the old
shots are already cleared at that point). Run in the background
(run_in_background: true):
fastlane screenshots 2>&1 | tee tmp/screenshots-capture.log
This is the ~2 h capture; the lane renames folders to storefront codes when it finishes. Track it on 20-minute ticks:
- Launch
sleep 1200as a background Bash task (run_in_background: true). - On its completion notification, run
python3 scripts/screenshot_content/capture_progress.py, report the done/pending diff in one line, then re-arm the nextsleep 1200. - Stop re-arming when the
fastlane screenshotsbackground task exits.
Judge capture success by capture_progress.py, not by the task's exit code.
The command is piped through tee, so the reported exit status is tee's, not
fastlane's — it is unreliable. When the capture task exits, run
capture_progress.py and branch on its exit:
- Exit 0 (all locales done): go to step 5.
- Exit non-zero with some locales done (partial capture — a few locales
flaked): self-heal, don't stop. Re-capture only the pending runtime codes it
lists, then re-rename, then re-check:
fastlane snapshot --languages <pending runtime codes, comma-separated> --clear_previous_screenshots false 2>&1 | tee tmp/screenshots-recapture.log python3 scripts/screenshot_content/rename_for_deliver.py python3 scripts/screenshot_content/capture_progress.py--clear_previous_screenshots falseis mandatory here — theSnapfilesetsclear_previous_screenshots(true)for full runs, so without this overridesnapshotwould wipe the entirefastlane/screenshots/tree (every already-good locale) before recapturing just these few. (snapshotreuses the device list fromfastlane/Snapfile; the pending codes are exactly whatcapture_progress.pyprints under "pending".) Loop untilcapture_progress.pyexits 0. Run the recapture in the background with the same 20-minute ticks. - Exit non-zero with zero done (the lane never produced shots — usually a
build/test failure): surface the tail of
tmp/screenshots-capture.logand stop. This is the one hard-failure case; do not upload nothing.
Do not use the Monitor tool for ticks — it prompts on each re-arm. sleep *,
capture_progress.py, and screenshot_status.sh are all allowlisted and never
prompt. See memory feedback_no_prompt_periodic_progress.
5. Open the review page
open fastlane/screenshots/screenshots.html
Opens in the user's default browser, for both A and B.
6. Gate on the step-3 choice
-
Option A — pause: stop and tell the user:
"Review page open at
fastlane/screenshots/screenshots.html. Let me know when you're ready to upload."Wait for an explicit "proceed" (or equivalent) before step 7. Do not auto-continue on a timer.
-
Option B — continue: proceed straight to step 7; the page stays open for post-upload review.
7. Upload — self-healing retry controller
Never use bare fastlane push_screenshots — it hangs indefinitely on ASC HTTP
500s. Use the controller, in the background (run_in_background: true):
bash scripts/screenshot_content/upload_with_retry.sh 2>&1 | tee tmp/screenshots-upload.log
Nothing goes live until App Store Connect review; submit_for_review:false is
baked into the lanes. Track it on 20-minute ticks, same pattern as step 4 but
using the status helper:
- Launch
sleep 1200as a background Bash task. - On its completion notification, run
bash scripts/screenshot_content/screenshot_status.sh, report the status in one line, then re-arm the nextsleep 1200. - Stop re-arming when the upload background task exits.
screenshot_status.sh reports local capture progress, running processes, the
controller's recent log, and per-storefront upload confirmation — prefer it over
ad-hoc ps / find / grep pipelines, which are not allowlisted and will
prompt.
8. Verify completion and self-heal stragglers
When the upload background task exits, do not trust its exit code (piped
through tee). Determine success from authoritative state:
bash scripts/screenshot_content/screenshot_status.sh
- All storefronts confirmed (and
tmp/upload-controller.logshows aSUCCESSline): report success — all shots staged in App Store Connect. If Option B, remind the user the review page is atfastlane/screenshots/screenshots.html. - Some storefronts unconfirmed (controller log shows
EXHAUSTED, orscreenshot_status.shlists "not fully" storefronts): re-push just those, no prompt. Take the unconfirmed storefront names and run, in the background:
A clean controllerSUBSET_ONLY="<storefront codes, space-separated>" bash scripts/screenshot_content/upload_with_retry.sh 2>&1 | tee tmp/screenshots-upload.logSUCCESSline for the subset confirms ASC accepted them. Loop (re-check withscreenshot_status.sh) until every storefront is confirmed.
9. Cleanup — offer to clear tmp working files
After all storefronts are confirmed, offer to clear this run's gitignored tmp
logs/staging (tmp/screenshots-capture.log, tmp/screenshots-recapture.log,
tmp/screenshots-upload.log, tmp/upload-controller.log, tmp/fastlane-push-*.log,
tmp/screenshots-subset/). Ask first; leave fastlane/screenshots/ (the captured
deliverables) in place unless the user asks to remove them.
Commands reference
python3 scripts/screenshot_content/check_content.py # seed catalog gate
python3 scripts/screenshot_content/capture_progress.py # capture done vs pending (authoritative)
rm -rf fastlane/screenshots/* # clear shots before a chosen full re-capture (overwrite path only)
fastlane screenshots # capture (~2 h) + auto-rename
fastlane snapshot --languages ja,de,ar --clear_previous_screenshots false # re-capture a few runtime codes WITHOUT wiping the rest
python3 scripts/screenshot_content/rename_for_deliver.py # rename runtime→storefront after a snapshot recapture
open fastlane/screenshots/screenshots.html # open review page
bash scripts/screenshot_content/upload_with_retry.sh # full upload with retry
SUBSET_ONLY="kn-IN ru" bash scripts/screenshot_content/upload_with_retry.sh # re-push stragglers
bash scripts/screenshot_content/screenshot_status.sh # running jobs + upload confirmation (authoritative)
When NOT to use this skill
- To generate the seed catalog →
/appstore:generate-screenshot-seeding. - To transcreate App Store text metadata →
/appstore:translate-metadata.