Asc Shots Pipeline

by rorkai9c7e769f09a1No license1K starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 3 days ago

Orchestrate iOS screenshot automation with xcodebuild/simctl for build-run, AXe for UI actions, JSON settings and plan files, Koubou-based framing (`asc screenshots frame`), and screenshot upload (`asc screenshots upload`). Use when users ask for automated screenshot capture, AXe-driven simulator flows, frame composition, or screenshot-to-upload pipelines.

Instructions onlyDevOps & Cloud
AI-generated overview

Orchestrates an iOS App Store screenshot pipeline: build and run in a simulator, capture UI, frame, and upload.

What it does
This skill documents an agent-driven workflow that builds and launches an iOS app on a simulator with Xcode CLI tools, drives the UI with AXe, and captures screenshots from JSON settings and plan files. It then composes device frames with Koubou via the asc CLI and uploads the resulting images to App Store Connect. It also covers multi-locale capture using per-simulator locale defaults and parallel execution across simulators.
When to use it
Use it when someone asks for automated iOS screenshot capture, AXe-driven simulator flows, frame composition, or a screenshot-to-upload pipeline. It fits App Store screenshot preparation, including multi-locale batches.
Requirements
Requires the asc CLI (App Store Connect CLI), Xcode command line tools (xcodebuild, xcrun simctl), and AXe for UI actions. Framing needs Koubou pinned to 0.20.0 installed via pip, with network access for kou setup-frames. Uploading needs App Store Connect credentials and app/version identifiers. No scripts ship with the skill; it is instructions only.

asc screenshots pipeline (xcodebuild -> AXe -> frame -> asc)

Use this skill for agent-driven screenshot workflows where the app is built and launched with Xcode CLI tools, UI is driven with AXe, and screenshots are uploaded with asc.

Current scope

  • Implemented now: build/run, AXe plan capture, frame composition, and upload.
  • Device discovery is built-in via asc screenshots list-frame-devices.
  • Local screenshot automation commands are experimental in asc cli.
  • Framing is pinned to Koubou 0.20.0 for deterministic output.
  • Feedback/issues: https://github.com/rorkai/App-Store-Connect-CLI/issues/new/choose

Defaults

  • Settings file: .asc/shots.settings.json
  • Capture plan: .asc/screenshots.json
  • Raw screenshots dir: ./screenshots/raw
  • Framed screenshots dir: ./screenshots/framed
  • Default frame device: iphone-air

1) Create settings JSON first

Create or update .asc/shots.settings.json:

json
{  "version": 1,  "app": {    "bundle_id": "com.example.app",    "project": "MyApp.xcodeproj",    "scheme": "MyApp",    "simulator_udid": "booted"  },  "paths": {    "plan": ".asc/screenshots.json",    "raw_dir": "./screenshots/raw",    "framed_dir": "./screenshots/framed"  },  "pipeline": {    "frame_enabled": true,    "upload_enabled": false  },  "upload": {    "version_localization_id": "",    "device_type": "IPHONE_65",    "source_dir": "./screenshots/framed"  }}

If you intentionally skip framing, set:

  • "frame_enabled": false
  • "upload.source_dir": "./screenshots/raw"

2) Build and run app on simulator

Use Xcode CLI for build/install/launch:

bash
xcrun simctl boot "$UDID" || true
xcodebuild \  -project "MyApp.xcodeproj" \  -scheme "MyApp" \  -configuration Debug \  -destination "platform=iOS Simulator,id=$UDID" \  -derivedDataPath ".build/DerivedData" \  build
xcrun simctl install "$UDID" ".build/DerivedData/Build/Products/Debug-iphonesimulator/MyApp.app"xcrun simctl launch "$UDID" "com.example.app"

Use xcodebuild -showBuildSettings if the app bundle path differs from the default location.

3) Capture screenshots with AXe (or asc screenshots run)

Prefer plan-driven capture:

bash
asc screenshots run --plan ".asc/screenshots.json" --udid "$UDID" --output json

Useful AXe primitives during plan authoring:

bash
axe describe-ui --udid "$UDID"axe tap --id "search_field" --udid "$UDID"axe type "wwdc" --udid "$UDID"axe screenshot --output "./screenshots/raw/home.png" --udid "$UDID"

Minimal .asc/screenshots.json example:

json
{  "version": 1,  "app": {    "bundle_id": "com.example.app",    "udid": "booted",    "output_dir": "./screenshots/raw"  },  "steps": [    { "action": "launch" },    { "action": "wait", "duration_ms": 800 },    { "action": "screenshot", "name": "home" }  ]}

4) Frame screenshots with asc screenshots frame

The asc CLI pins framing to Koubou 0.20.0. Install and verify before running framing steps:

bash
pip install koubou==0.20.0kou --version  # expect 0.20.0# After upgrading from 0.18.x, or if Koubou reports missing device frames,# run once with network access:kou setup-frames

List supported frame device values first:

bash
asc screenshots list-frame-devices --output json

Frame one screenshot (defaults to iphone-air):

bash
asc screenshots frame \  --input "./screenshots/raw/home.png" \  --output-dir "./screenshots/framed" \  --device "iphone-air" \  --output json

Supported --device values:

  • iPhone: iphone-air (default), iphone-17-pro, iphone-17-pro-max, iphone-16e, iphone-17
  • iPad: ipad-pro-13, ipad-pro-11, ipad-air-13, ipad-air-11, ipad-mini
  • Other: mac, watch-series-11, watch-ultra-3, apple-tv

5) Upload screenshots with asc

Generate and review artifacts before upload:

bash
asc screenshots review-generate --framed-dir "./screenshots/framed" --output-dir "./screenshots/review"asc screenshots review-open --output-dir "./screenshots/review"asc screenshots review-approve --all-ready --output-dir "./screenshots/review"

For reviewed multi-locale sets, prefer the plan/apply flow so existing remote screenshot counts are included before upload:

bash
asc screenshots plan --app "APP_ID" --version "1.2.3" --review-output-dir "./screenshots/review" --output jsonasc screenshots apply --app "APP_ID" --version "1.2.3" --review-output-dir "./screenshots/review" --confirm --output json

Upload from the configured source directory (default ./screenshots/framed when framing is enabled):

bash
asc screenshots upload \  --version-localization "LOC_ID" \  --path "./screenshots/framed" \  --device-type "IPHONE_65" \  --output json

List or validate before upload when needed:

bash
asc screenshots sizes --output tableasc screenshots list --version-localization "LOC_ID" --output table

Agent behavior

  • Always confirm exact flags with --help before running commands.
  • Re-check command paths with asc screenshots --help because screenshot commands are evolving quickly.
  • Keep outputs deterministic: default to JSON for machine steps.
  • Prefer asc screenshots list-frame-devices --output json before selecting a frame device.
  • Ensure screenshot files exist before upload.
  • Use explicit long flags (--app, --output, --version-localization, etc.).
  • Treat screenshot-local automation as experimental and call it out in user-facing handoff notes.
  • Use asc screenshots plan / asc screenshots apply for reviewed batches when you need append-limit guardrails across existing remote screenshots.
  • If framing fails with a version error, re-install pinned Koubou: pip install koubou==0.20.0.
  • If framing fails because device frames are missing, run kou setup-frames once with network access.

6) Multi-locale capture (optional)

Do not use xcrun simctl launch ... -e AppleLanguages for localization. -e is an environment variable pattern and does not reliably switch app language.

For this pipeline, use simulator-wide locale defaults per UDID. This works with asc screenshots capture, which relaunches the app internally.

bash
# Map each locale to a dedicated simulator UDID.# (Create these simulators once with `xcrun simctl create`.)declare -A LOCALE_UDID=(  ["en-US"]="UDID_EN_US"  ["de-DE"]="UDID_DE_DE"  ["fr-FR"]="UDID_FR_FR"  ["ja-JP"]="UDID_JA_JP")
set_simulator_locale() {  local UDID="$1"  local LOCALE="$2"            # e.g. de-DE  local LANG="${LOCALE%%-*}"   # de  local APPLE_LOCALE="${LOCALE/-/_}" # de_DE
  xcrun simctl boot "$UDID" || true  xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLanguages -array "$LANG"  xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLocale -string "$APPLE_LOCALE"}
for LOCALE in "${!LOCALE_UDID[@]}"; do  UDID="${LOCALE_UDID[$LOCALE]}"  echo "Capturing $LOCALE on $UDID..."  set_simulator_locale "$UDID" "$LOCALE"
  xcrun simctl terminate "$UDID" "com.example.app" || true  asc screenshots capture \    --bundle-id "com.example.app" \    --name "home" \    --udid "$UDID" \    --output-dir "./screenshots/raw/$LOCALE" \    --output jsondone

If you launch manually (outside asc screenshots capture), use app launch arguments:

bash
xcrun simctl launch "$UDID" "com.example.app" -AppleLanguages "(de)" -AppleLocale "de_DE"

7) Parallel execution for speed

Run one locale per simulator UDID in parallel:

bash
#!/bin/bash# parallel-capture.sh
declare -A LOCALE_UDID=(  ["en-US"]="UDID_EN_US"  ["de-DE"]="UDID_DE_DE"  ["fr-FR"]="UDID_FR_FR"  ["ja-JP"]="UDID_JA_JP")
capture_locale() {  local LOCALE="$1"  local UDID="$2"  local LANG="${LOCALE%%-*}"  local APPLE_LOCALE="${LOCALE/-/_}"
  echo "Starting $LOCALE on $UDID"  xcrun simctl boot "$UDID" || true  xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLanguages -array "$LANG"  xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLocale -string "$APPLE_LOCALE"  xcrun simctl terminate "$UDID" "com.example.app" || true
  asc screenshots capture \    --bundle-id "com.example.app" \    --name "home" \    --udid "$UDID" \    --output-dir "./screenshots/raw/$LOCALE" \    --output json
  echo "Completed $LOCALE"}
for LOCALE in "${!LOCALE_UDID[@]}"; do  capture_locale "$LOCALE" "${LOCALE_UDID[$LOCALE]}" &done
waitecho "All captures done. Now framing..."

Or use xargs with locale:udid pairs:

bash
printf "%s\n" \  "en-US:UDID_EN_US" \  "de-DE:UDID_DE_DE" \  "fr-FR:UDID_FR_FR" \  "ja-JP:UDID_JA_JP" | xargs -P 4 -I {} bash -c '    PAIR="{}"    LOCALE="${PAIR%%:*}"    UDID="${PAIR##*:}"    LANG="${LOCALE%%-*}"    APPLE_LOCALE="${LOCALE/-/_}"    xcrun simctl boot "$UDID" || true    xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLanguages -array "$LANG"    xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLocale -string "$APPLE_LOCALE"    xcrun simctl terminate "$UDID" "com.example.app" || true    asc screenshots capture --bundle-id "com.example.app" --name "home" --udid "$UDID" --output-dir "./screenshots/raw/$LOCALE" --output json  '

8) Full multi-locale pipeline example

bash
#!/bin/bash# full-pipeline-multi-locale.sh
declare -A LOCALE_UDID=(  ["en-US"]="UDID_EN_US"  ["de-DE"]="UDID_DE_DE"  ["fr-FR"]="UDID_FR_FR"  ["es-ES"]="UDID_ES_ES"  ["ja-JP"]="UDID_JA_JP")
DEVICE="iphone-air"RAW_DIR="./screenshots/raw"FRAMED_DIR="./screenshots/framed"
# Step 1: Parallel capture with per-simulator locale defaultsfor LOCALE in "${!LOCALE_UDID[@]}"; do  (    UDID="${LOCALE_UDID[$LOCALE]}"    LANG="${LOCALE%%-*}"    APPLE_LOCALE="${LOCALE/-/_}"
    xcrun simctl boot "$UDID" || true    xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLanguages -array "$LANG"    xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLocale -string "$APPLE_LOCALE"    xcrun simctl terminate "$UDID" "com.example.app" || true
    asc screenshots capture \      --bundle-id "com.example.app" \      --name "home" \      --udid "$UDID" \      --output-dir "$RAW_DIR/$LOCALE" \      --output json    echo "Captured $LOCALE"  ) &donewait
# Step 2: Parallel framingfor LOCALE in "${!LOCALE_UDID[@]}"; do  (    asc screenshots frame \      --input "$RAW_DIR/$LOCALE/home.png" \      --output-dir "$FRAMED_DIR/$LOCALE" \      --device "$DEVICE" \      --output json    echo "Framed $LOCALE"  ) &donewait
# Step 3: Generate review (single run, aggregates all locales)asc screenshots review-generate \  --framed-dir "$FRAMED_DIR" \  --output-dir "./screenshots/review"
# Step 4: Upload (run per locale if needed)for LOCALE in "${!LOCALE_UDID[@]}"; do  asc screenshots upload \    --version-localization "LOC_ID_FOR_$LOCALE" \    --path "$FRAMED_DIR/$LOCALE" \    --device-type "IPHONE_65" \    --output jsondone

Source and attribution

Source:rorkai/app-store-connect-cli-skillsinskills/asc-shots-pipelineat commit9c7e769

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal