Skip to main content
skill CX Codex

asc-shots-pipeline — Claude Code skill for iOS screenshots

Automates iOS builds, simulator screenshots, framing, and uploads through asc. Use it when screenshot capture needs a repeatable plan-driven flow.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add rorkai/app-store-connect-cli-skills --skill asc-shots-pipeline -a claude-code
Open on GitHub

What asc-shots-pipeline does

This skill runs an iOS screenshot workflow from build and launch with xcodebuild and simctl through UI actions with AXe. Capture steps live in .asc/screenshots.json, while app details and output paths go in .asc/shots.settings.json.

It can frame captures with asc screenshots frame, prepare review artifacts, and upload screenshots with asc commands. Framing requires Koubou 0.20.0, so checking the installed version before that stage matters.

Local screenshot automation commands in asc are experimental. The skill calls for checking flags with --help, listing frame devices before selection, and confirming screenshot files exist before upload.

What it helps with

  • build and launch an iOS app in a simulator
  • define screenshot capture in a JSON plan
  • drive simulator UI actions with AXe
  • frame captures with Koubou
  • upload reviewed screenshots with asc

Example prompts for the agent

  • Build the app in a simulator and capture screenshots from .asc/screenshots.json.
  • List frame devices, then frame ./screenshots/raw/home.png.
  • Generate review artifacts and create an upload plan for version 1.2.3.

How to install asc-shots-pipeline

1Skills CLI (Vercel)

npx skills add rorkai/app-store-connect-cli-skills --skill asc-shots-pipeline -a claude-code

2Manually: put the files in place

~/.claude/skills/asc-shots-pipeline/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/asc-shots-pipeline/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about asc-shots-pipeline

How do I install asc-shots-pipeline in Claude Code?

Run npx skills add rorkai/app-store-connect-cli-skills --skill asc-shots-pipeline -a claude-code, then run npx skills add rorkai/app-store-connect-cli-skills --skill asc-shots-pipeline -a claude-code again. The skill file is at ~/.claude/skills/asc-shots-pipeline/SKILL.md.

What does asc-shots-pipeline do?

It coordinates iOS builds and simulator launches, AXe-driven UI capture, Koubou framing, review preparation, and screenshot uploads through asc.

What is required for screenshot framing?

Framing uses Koubou 0.20.0. If device frames are missing, it uses kou setup-frames with network access.

Source text

SKILL.md · MIT
---
name: asc-shots-pipeline
description: 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.
---

# 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.0
kou --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 json
asc 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 table
asc 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 json
done
```

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

wait
echo "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 defaults
for 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"
  ) &
done
wait

# Step 2: Parallel framing
for 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"
  ) &
done
wait

# 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 json
done
```

© rorkai · MIT · rorkai/app-store-connect-cli-skills

Similar skills

Everything for Mobile →

From the same set24

asc-testflight-orchestration Automates TestFlight rollout via the asc CLI: manages tester groups, links builds, exports configs, and sets What to Test release notes. CX Codex +1 7,300installs asc-ppp-pricing Sets subscription and in-app purchase prices by territory. Use it for regional pricing plans and checks before changing existing prices. CX Codex +1 7,300installs asc-signing-setup An agent skill that creates bundle IDs, certificates and provisioning profiles through the asc CLI, then shares them with a team over git. CX Codex +1 7,400installs asc-build-lifecycle A skill that hands the agent the asc commands for App Store Connect builds: latest build, processing state, next build number, old build cleanup. CX Codex +1 7,200installs asc-localize-metadata Downloads App Store descriptions, keywords, what's new and subtitles, translates them via LLM, and syncs the results back to App Store Connect. CX Codex +1 7,000installs asc-subscription-localization Bulk-updates display names and descriptions for App Store subscriptions, groups, and in-app purchases using asc. Saves developers from clicking through dozens of languages in the web UI. CX Codex +1 6,800installs asc-workflow Turns App Store Connect chores into a repo-local .asc/workflow.json the agent can validate, dry-run and resume after a failed step. CX Codex +1 6,700installs asc-notarization Prepares a macOS app for distribution outside the App Store by archiving, Developer ID export, and Apple notarization. CX Codex +1 6,600installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor