asc-shots-pipeline

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ASC 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操作,
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.
  • Framing is pinned to Koubou
    0.13.0
    for deterministic output.
  • 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.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"
创建或更新
.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"
  }
}
如果有意跳过加框步骤,请设置:
  • "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
xcodebuild -showBuildSettings
if the app bundle path differs from the default location.
使用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 -showBuildSettings
查看。

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

3) 使用AXe(或
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" }
  ]
}
推荐使用计划驱动的捕获方式:
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.json
最简示例:
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

4) 使用
asc screenshots frame
为截图加框

ASC pins framing to Koubou
0.13.0
. Install and verify before running framing steps:
bash
pip install koubou==0.13.0
kou --version  # expect 0.13.0
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-air
    (default)
  • iphone-17-pro
  • iphone-17-pro-max
  • iphone-16e
  • iphone-17
ASC的截图加框功能固定使用Koubou
0.13.0
版本。 运行加框步骤前请先安装并验证版本:
bash
pip install koubou==0.13.0
kou --version  # 预期输出0.13.0
先查看支持的加框设备值:
bash
asc screenshots list-frame-devices --output json
为单张截图加框(默认使用
iphone-air
设备):
bash
asc screenshots frame \
  --input "./screenshots/raw/home.png" \
  --output-dir "./screenshots/framed" \
  --device "iphone-air" \
  --output json
支持的
--device
值:
  • iphone-air
    (默认)
  • iphone-17-pro
  • iphone-17-pro-max
  • iphone-16e
  • iphone-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
./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
上传前先生成并审核工件:
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/framed
):
bash
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 table

Agent behavior

Agent行为规范

  • 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.
  • 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
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
undefined
请勿使用
xcrun simctl launch ... -e AppleLanguages
进行本地化设置。
-e
是环境变量模式,无法可靠切换应用语言。
在本流水线中,请针对每个UDID设置模拟器全局区域语言默认值。该方式与
asc screenshots capture
兼容,该命令会在内部重新启动应用。
bash
undefined

Map each locale to a dedicated simulator UDID.

将每个语言环境映射到专用的模拟器UDID。

(Create these simulators once with
xcrun simctl create
.)

(可通过
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"
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

如果手动启动应用(在`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/bash

parallel-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
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
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/bash
bash
#!/bin/bash

full-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
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

Step 3: Generate review (single run, aggregates all locales)

步骤3:生成审核文件(单次运行,汇总所有语言环境)

asc screenshots review-generate
--framed-dir "$FRAMED_DIR"
--output-dir "./screenshots/review"
asc screenshots review-generate
--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
undefined
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
undefined