Documentation

App Store screenshots

Capture listing screenshots from Simulator at App Store Connect sizes; keep drafts under store/. Companion to testflight.md. Full ship path: app-store.md.

One-minute path

walnut screenshots init .
walnut screenshots slots

walnut simulator --device "iPhone 16 Pro Max"
# Navigate to the screen you want, then:

walnut screenshots capture . --name 01-home --slot iphone-6-9
walnut screenshots check .

Layout

Created by walnut screenshots init:

store/
  README.md
  screenshots/
    raw/<slot>/01-home.png     # simctl capture
    framed/<slot>/             # optional marketing frames
  metadata/
    subtitle.txt
    promotional-text.txt
    description.txt
    keywords.txt
    whats-new.txt

Upload to App Store Connect

walnut store upload .
# → patches description / keywords / promotional text / subtitle
# → replaces screenshots for each slot under store/screenshots/raw/
FlagRole
--locale en-USLocalization (default en-US)
--version 1.0ASC version string (default: marketing_version)
--skip-metadataScreenshots only
--skip-screenshotsCopy only
--dry-runPrint actions; no ASC writes

Requires the same Team ASC API key as TestFlight (walnut device login). Creates the iOS version + locale if missing. First versions often reject whatsNew until a prior release exists — walnut retries without it.

Screenshots for slot iphone-6-9 upload as ASC display type APP_IPHONE_67 (Apple’s API has no APP_IPHONE_69 enum yet; 1320×2868 is accepted there).

Happy path for a new listing:

walnut screenshots init .
walnut simulator . --device "iPhone 16 Pro Max"
walnut screenshots capture . --name 01-home --slot iphone-6-9
# edit store/metadata/*
walnut screenshots check .
walnut testflight .
walnut store upload .

Git

PathIn git?Notes
store/README.mdYesLayout for humans
store/metadata/*.txtYesListing copy (reviewable)
store/screenshots/**/*.png (and jpg/webp/heic)NoRoot .gitignore — regenerate with walnut screenshots capture
store/screenshots/**/.gitkeepYesKeeps empty slot folders

Do not force-add screenshot binaries unless you have a deliberate reason (e.g. LFS golden fixtures). Default is: metadata travels with the app; pixels are local artifacts.

Slots

walnut screenshots slots prints portrait sizes and preferred Simulator names:

Slot idSize (px)Typical sim
iphone-6-91320×2868iPhone 16 Pro Max
iphone-6-71290×2796iPhone 15 Pro Max
iphone-6-51284×2778iPhone 11 Pro Max
ipad-132064×2752iPad Pro 13-inch (M4)

Apple’s required set changes over time — prefer 6.9" for new iPhone apps. check fails the process if PNGs don’t match the slot (portrait or landscape swap).

Commands

CommandRole
walnut screenshots init [dir]Scaffold store/
walnut screenshots capture [dir] --name <slug> [--slot] [--device]Boot sim (if needed) + simctl io booted screenshot
walnut screenshots check [dir]Validate pixel sizes under raw/
walnut screenshots slotsPrint slot table

Flags for capture: --settle <ms> (default 800) after boot before shooting.

Why not Fastlane?

Fastlane snapshot + deliver is a fine Ruby stack for large orgs. Walnut already owns compile → TestFlight; screenshots are a thin simctl + size check + store/ convention so every app gets the same layout without a second toolchain. When ASC API upload lands, it will write into this same tree — not a Fastlane lane file.

  • app-store.md — publish through App Review + release
  • testflight.md — IPA upload
  • device.md — physical install
  • Skill: app-store-screenshots (framing, metadata, quality bar)