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.
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.18.1 for deterministic output.
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.18.1.
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.
# 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: