asc-shots-pipeline
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseASC screenshots pipeline (xcodebuild -> AXe -> frame -> asc)
ASC截图流水线(xcodebuild -> AXe -> 加框 -> 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当需要由Agent驱动的截图工作流时使用本技能,该工作流通过Xcode CLI工具构建和启动应用,AXe驱动UI操作,工具上传截图。
ascCurrent 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.
- Framing is pinned to Koubou for deterministic output.
0.13.0 - Feedback/issues: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/new/choose
- 已实现功能:构建/运行、AXe计划捕获、截图加框合成、上传。
- 内置设备发现功能,可通过使用。
asc screenshots list-frame-devices - ASC中的本地截图自动化命令仍处于实验阶段。
- 截图加框功能固定使用Koubou 版本以保证输出一致性。
0.13.0 - 反馈/问题提交:https://github.com/rudrankriyam/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
- 配置文件:
.asc/shots.settings.json - 捕获计划:
.asc/screenshots.json - 原始截图目录:
./screenshots/raw - 加框后截图目录:
./screenshots/framed - 默认加框设备:
iphone-air
1) Create settings JSON first
1) 先创建JSON配置文件
Create or update :
.asc/shots.settings.jsonjson
{
"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"
创建或更新:
.asc/shots.settings.jsonjson
{
"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"
}
}如果有意跳过加框步骤,请设置:
"frame_enabled": false"upload.source_dir": "./screenshots/raw"
2) Build and run app on simulator
2) 在模拟器上构建并运行应用
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 if the app bundle path differs from the default location.
xcodebuild -showBuildSettings使用Xcode CLI进行构建/安装/启动:
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"如果应用包路径与默认位置不同,可使用查看。
xcodebuild -showBuildSettings3) Capture screenshots with AXe (or asc screenshots run
)
asc screenshots run3) 使用AXe(或asc screenshots run
)捕获截图
asc screenshots runPrefer plan-driven capture:
bash
asc screenshots run --plan ".asc/screenshots.json" --udid "$UDID" --output jsonUseful 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 example:
.asc/screenshots.jsonjson
{
"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" }
]
}推荐使用计划驱动的捕获方式:
bash
asc screenshots run --plan ".asc/screenshots.json" --udid "$UDID" --output json编写计划时可使用以下实用AXe命令:
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".asc/screenshots.jsonjson
{
"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
asc screenshots frame4) 使用asc screenshots frame
为截图加框
asc screenshots frameASC pins framing to Koubou .
Install and verify before running framing steps:
0.13.0bash
pip install koubou==0.13.0
kou --version # expect 0.13.0List supported frame device values first:
bash
asc screenshots list-frame-devices --output jsonFrame one screenshot (defaults to ):
iphone-airbash
asc screenshots frame \
--input "./screenshots/raw/home.png" \
--output-dir "./screenshots/framed" \
--device "iphone-air" \
--output jsonSupported values:
--device- (default)
iphone-air iphone-17-proiphone-17-pro-maxiphone-16eiphone-17
ASC的截图加框功能固定使用Koubou 版本。
运行加框步骤前请先安装并验证版本:
0.13.0bash
pip install koubou==0.13.0
kou --version # 预期输出0.13.0先查看支持的加框设备值:
bash
asc screenshots list-frame-devices --output json为单张截图加框(默认使用设备):
iphone-airbash
asc screenshots frame \
--input "./screenshots/raw/home.png" \
--output-dir "./screenshots/framed" \
--device "iphone-air" \
--output json支持的值:
--device- (默认)
iphone-air iphone-17-proiphone-17-pro-maxiphone-16eiphone-17
5) Upload screenshots with asc
5) 使用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"Upload from the configured source directory (default when framing is enabled):
./screenshots/framedbash
asc screenshots upload \
--version-localization "LOC_ID" \
--path "./screenshots/framed" \
--device-type "IPHONE_65" \
--output jsonList or validate before upload when needed:
bash
asc screenshots sizes --output table
asc screenshots list --version-localization "LOC_ID" --output table上传前先生成并审核工件:
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"从配置的源目录上传(启用加框时默认路径为):
./screenshots/framedbash
asc screenshots upload \
--version-localization "LOC_ID" \
--path "./screenshots/framed" \
--device-type "IPHONE_65" \
--output json必要时可在上传前列出或验证截图:
bash
asc screenshots sizes --output table
asc screenshots list --version-localization "LOC_ID" --output tableAgent behavior
Agent行为规范
- Always confirm exact flags with before running commands.
--help - Re-check command paths with because screenshot commands are evolving quickly.
asc screenshots --help - Keep outputs deterministic: default to JSON for machine steps.
- Prefer before selecting a frame device.
asc screenshots list-frame-devices --output json - Ensure screenshot files exist before upload.
- Use explicit long flags (,
--app,--output, etc.).--version-localization - Treat screenshot-local automation as experimental and call it out in user-facing handoff notes.
- If framing fails with a version error, re-install pinned Koubou: .
pip install koubou==0.13.0
- 运行命令前务必使用确认准确的参数。
--help - 由于截图命令迭代较快,请通过重新检查命令路径。
asc screenshots --help - 保证输出一致性:机器执行步骤默认使用JSON格式输出。
- 选择加框设备前,优先使用查看支持项。
asc screenshots list-frame-devices --output json - 上传前确保截图文件存在。
- 优先使用显式长参数(如、
--app、--output等)。--version-localization - 本地截图自动化功能仍处于实验阶段,需在面向用户的交付说明中明确标注。
- 如果加框时出现版本错误,请重新安装指定版本的Koubou:。
pip install koubou==0.13.0
6) Multi-locale capture (optional)
6) 多语言环境捕获(可选)
Do not use for localization.
is an environment variable pattern and does not reliably switch app language.
xcrun simctl launch ... -e AppleLanguages-eFor this pipeline, use simulator-wide locale defaults per UDID. This works with
, which relaunches the app internally.
asc screenshots capturebash
undefined请勿使用进行本地化设置。
是环境变量模式,无法可靠切换应用语言。
xcrun simctl launch ... -e AppleLanguages-e在本流水线中,请针对每个UDID设置模拟器全局区域语言默认值。该方式与兼容,该命令会在内部重新启动应用。
asc screenshots capturebash
undefinedMap each locale to a dedicated simulator UDID.
将每个语言环境映射到专用的模拟器UDID。
(Create these simulators once with xcrun simctl create
.)
xcrun simctl create(可通过xcrun simctl create
一次性创建这些模拟器。)
xcrun simctl createdeclare -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
--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"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" # 示例: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 "正在$UDID上捕获$LOCALE语言环境的截图..."
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
--bundle-id "com.example.app"
--name "home"
--udid "$UDID"
--output-dir "./screenshots/raw/$LOCALE"
--output json done
如果手动启动应用(在`asc screenshots capture`外部),请使用应用启动参数:
```bash
xcrun simctl launch "$UDID" "com.example.app" -AppleLanguages "(de)" -AppleLocale "de_DE"7) Parallel execution for speed
7) 并行执行以提升速度
Run one locale per simulator UDID in parallel:
bash
#!/bin/bash在每个模拟器UDID上并行运行一个语言环境的捕获任务:
bash
#!/bin/bashparallel-capture.sh
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
--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
'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 "开始在$UDID上捕获$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
--bundle-id "com.example.app"
--name "home"
--udid "$UDID"
--output-dir "./screenshots/raw/$LOCALE"
--output json
echo "完成$LOCALE语言环境的截图捕获"
}
for LOCALE in "${!LOCALE_UDID[@]}"; do
capture_locale "$LOCALE" "${LOCALE_UDID[$LOCALE]}" &
done
wait
echo "所有截图捕获完成。开始加框..."
也可使用`xargs`搭配`locale:udid`对:
```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
8) 完整多语言环境流水线示例
bash
#!/bin/bashbash
#!/bin/bashfull-pipeline-multi-locale.sh
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"
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
步骤1:基于每个模拟器的区域语言默认值并行捕获截图
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
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 "完成$LOCALE语言环境的截图捕获") &
done
wait
Step 2: Parallel framing
步骤2:并行加框
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
--input "$RAW_DIR/$LOCALE/home.png"
--output-dir "$FRAMED_DIR/$LOCALE"
--device "$DEVICE"
--output json echo "Framed $LOCALE" ) & done wait
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 "完成$LOCALE语言环境的截图加框" ) & done wait
--input "$RAW_DIR/$LOCALE/home.png"
--output-dir "$FRAMED_DIR/$LOCALE"
--device "$DEVICE"
--output json echo "完成$LOCALE语言环境的截图加框" ) & done wait
Step 3: Generate review (single run, aggregates all locales)
步骤3:生成审核文件(单次运行,汇总所有语言环境)
asc screenshots review-generate
--framed-dir "$FRAMED_DIR"
--output-dir "./screenshots/review"
--framed-dir "$FRAMED_DIR"
--output-dir "./screenshots/review"
asc screenshots review-generate
--framed-dir "$FRAMED_DIR"
--output-dir "./screenshots/review"
--framed-dir "$FRAMED_DIR"
--output-dir "./screenshots/review"
Step 4: Upload (run per locale if needed)
步骤4:上传(必要时可按语言环境分别运行)
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
--version-localization "LOC_ID_FOR_$LOCALE"
--path "$FRAMED_DIR/$LOCALE"
--device-type "IPHONE_65"
--output json done
undefinedfor 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
--version-localization "LOC_ID_FOR_$LOCALE"
--path "$FRAMED_DIR/$LOCALE"
--device-type "IPHONE_65"
--output json done
undefined