Files
asc-client/README.md
Kerem Erkan 1dfcc1c27b Add builds await-processing, workflow build tracking, and processing-aware attach
- Add builds await-processing command to poll until a build finishes processing
- Track uploaded build version across workflow steps via lastUploadedBuildVersion
- attach-latest-build now waits for a just-uploaded build to appear and process
- attach-latest-build prompts to wait when the latest build is still processing
- Shared awaitBuildProcessing helper eliminates duplicated polling logic
- Dot-based progress indicator for builds not yet available in the API
- Note on builds list about recently uploaded builds taking time to appear
- Bump version to 0.2.1
2026-02-13 18:46:17 +01:00

12 KiB

asc-client

A command-line tool for building, archiving, and publishing apps to the App Store — from Xcode archive to App Review submission. Built with Swift on the App Store Connect API.

Note: Covers the core app release workflow: archiving, uploading builds, managing versions and localizations, screenshots, and review submission. More API coverage is planned.

Requirements

  • macOS 13+
  • Swift 6.0+ (only for building from source)

Installation

Homebrew

brew tap keremerkan/tap
brew install asc-client

The tap provides a pre-built binary for Apple Silicon Macs, so installation is instant.

Download the binary

Download the latest release from GitHub Releases:

curl -L https://github.com/keremerkan/asc-client/releases/latest/download/asc-client-macos-arm64.tar.gz -o asc-client.tar.gz
tar xzf asc-client.tar.gz
mv asc-client /usr/local/bin/

Since the binary is not signed or notarized, macOS will quarantine it on first download. Remove the quarantine attribute:

xattr -d com.apple.quarantine /usr/local/bin/asc-client

Note: Pre-built binaries are provided for Apple Silicon (arm64) only. Intel Mac users should build from source.

Build from source

git clone https://github.com/keremerkan/asc-client.git
cd asc-client
swift build -c release
strip .build/release/asc-client
cp .build/release/asc-client /usr/local/bin/

Note: The release build takes a few minutes because the asc-swift dependency includes ~2500 generated source files covering the entire App Store Connect API surface. strip removes debug symbols, reducing the binary from ~175 MB to ~59 MB.

Shell completions

Set up tab completion for subcommands, options, and flags (supports zsh and bash):

asc-client install-completions

This detects your shell and configures everything automatically. Restart your shell or open a new tab to activate.

Setup

1. Create an API Key

Go to App Store Connect > Users and Access > Integrations > App Store Connect API and generate a new key. Download the .p8 private key file.

2. Configure

asc-client configure

This will prompt for your Key ID, Issuer ID, and the path to your .p8 file. The private key is copied into ~/.asc-client/ with strict file permissions (owner-only access).

Usage

Apps

# List all apps
asc-client apps list

# Show app details
asc-client apps info <bundle-id>

# List App Store versions
asc-client apps versions <bundle-id>

# Create a new version
asc-client apps create-version <bundle-id> <version-string>
asc-client apps create-version <bundle-id> 2.1.0 --platform ios --release-type manual

# Check review submission status
asc-client apps review-status <bundle-id>

# Submit for review
asc-client apps submit-for-review <bundle-id>
asc-client apps submit-for-review <bundle-id> --version 2.1.0

Build Management

# Interactively select and attach a build to a version
asc-client apps attach-build <bundle-id>
asc-client apps attach-build <bundle-id> --version 2.1.0

# Attach the most recent build automatically
asc-client apps attach-latest-build <bundle-id>

# Remove the attached build from a version
asc-client apps detach-build <bundle-id>

Localizations

# View localizations (latest version by default)
asc-client apps localizations <bundle-id>
asc-client apps localizations <bundle-id> --version 2.1.0 --locale en-US

# Export localizations to JSON
asc-client apps export-localizations <bundle-id>
asc-client apps export-localizations <bundle-id> --version 2.1.0 --output my-localizations.json

# Update a single locale
asc-client apps update-localization <bundle-id> --whats-new "Bug fixes" --locale en-US

# Bulk update from JSON file
asc-client apps update-localizations <bundle-id> --file localizations.json

The JSON format for export and bulk update:

{
  "en-US": {
    "description": "My app description.\n\nSecond paragraph.",
    "whatsNew": "- Bug fixes\n- New dark mode",
    "keywords": "productivity,tools,utility",
    "promotionalText": "Try our new features!",
    "marketingURL": "https://example.com",
    "supportURL": "https://example.com/support"
  },
  "de-DE": {
    "whatsNew": "- Fehlerbehebungen\n- Neuer Dunkelmodus"
  }
}

Only fields present in the JSON are updated -- omitted fields are left unchanged.

Screenshots & App Previews

# Download all screenshots and preview videos
asc-client apps download-media <bundle-id>
asc-client apps download-media <bundle-id> --folder my-media/ --version 2.1.0

# Upload screenshots and preview videos from a folder
asc-client apps upload-media <bundle-id> --folder media/

# Upload to a specific version
asc-client apps upload-media <bundle-id> --folder media/ --version 2.1.0

# Replace existing media in matching sets before uploading
asc-client apps upload-media <bundle-id> --folder media/ --replace

Organize your media folder with locale and display type subfolders:

media/
├── en-US/
│   ├── APP_IPHONE_67/
│   │   ├── 01_home.png
│   │   ├── 02_settings.png
│   │   └── preview.mp4
│   └── APP_IPAD_PRO_3GEN_129/
│       └── 01_home.png
└── de-DE/
    └── APP_IPHONE_67/
        ├── 01_home.png
        └── 02_settings.png
  • Level 1: Locale (e.g. en-US, de-DE, ja)
  • Level 2: Display type folder name (see table below)
  • Level 3: Media files -- images (.png, .jpg, .jpeg) become screenshots, videos (.mp4, .mov) become app previews
  • Files are uploaded in alphabetical order by filename
  • Unsupported files are skipped with a warning

Display types

Folder name Device Screenshots Previews
APP_IPHONE_67 iPhone 6.7" (iPhone 16 Pro Max, 15 Pro Max, 14 Pro Max) Yes Yes
APP_IPHONE_61 iPhone 6.1" (iPhone 16 Pro, 15 Pro, 14 Pro) Yes Yes
APP_IPHONE_65 iPhone 6.5" (iPhone 11 Pro Max, XS Max) Yes Yes
APP_IPHONE_58 iPhone 5.8" (iPhone 11 Pro, X, XS) Yes Yes
APP_IPHONE_55 iPhone 5.5" (iPhone 8 Plus, 7 Plus, 6s Plus) Yes Yes
APP_IPHONE_47 iPhone 4.7" (iPhone SE 3rd gen, 8, 7, 6s) Yes Yes
APP_IPHONE_40 iPhone 4" (iPhone SE 1st gen, 5s, 5c) Yes Yes
APP_IPHONE_35 iPhone 3.5" (iPhone 4s and earlier) Yes Yes
APP_IPAD_PRO_3GEN_129 iPad Pro 12.9" (3rd gen+) Yes Yes
APP_IPAD_PRO_3GEN_11 iPad Pro 11" Yes Yes
APP_IPAD_PRO_129 iPad Pro 12.9" (1st/2nd gen) Yes Yes
APP_IPAD_105 iPad 10.5" (iPad Air 3rd gen, iPad Pro 10.5") Yes Yes
APP_IPAD_97 iPad 9.7" (iPad 6th gen and earlier) Yes Yes
APP_DESKTOP Mac Yes Yes
APP_APPLE_TV Apple TV Yes Yes
APP_APPLE_VISION_PRO Apple Vision Pro Yes Yes
APP_WATCH_ULTRA Apple Watch Ultra Yes No
APP_WATCH_SERIES_10 Apple Watch Series 10 Yes No
APP_WATCH_SERIES_7 Apple Watch Series 7 Yes No
APP_WATCH_SERIES_4 Apple Watch Series 4 Yes No
APP_WATCH_SERIES_3 Apple Watch Series 3 Yes No
IMESSAGE_APP_IPHONE_67 iMessage iPhone 6.7" Yes No
IMESSAGE_APP_IPHONE_61 iMessage iPhone 6.1" Yes No
IMESSAGE_APP_IPHONE_65 iMessage iPhone 6.5" Yes No
IMESSAGE_APP_IPHONE_58 iMessage iPhone 5.8" Yes No
IMESSAGE_APP_IPHONE_55 iMessage iPhone 5.5" Yes No
IMESSAGE_APP_IPHONE_47 iMessage iPhone 4.7" Yes No
IMESSAGE_APP_IPHONE_40 iMessage iPhone 4" Yes No
IMESSAGE_APP_IPAD_PRO_3GEN_129 iMessage iPad Pro 12.9" (3rd gen+) Yes No
IMESSAGE_APP_IPAD_PRO_3GEN_11 iMessage iPad Pro 11" Yes No
IMESSAGE_APP_IPAD_PRO_129 iMessage iPad Pro 12.9" (1st/2nd gen) Yes No
IMESSAGE_APP_IPAD_105 iMessage iPad 10.5" Yes No
IMESSAGE_APP_IPAD_97 iMessage iPad 9.7" Yes No

Note: Watch and iMessage display types support screenshots only -- video files in those folders are skipped with a warning. The --replace flag deletes all existing assets in each matching set before uploading new ones.

download-media saves files in this same folder structure (defaults to <bundle-id>-media/), so you can download, edit, and re-upload.

Verify and retry stuck media

Sometimes screenshots or previews get stuck in "processing" after upload. Use verify-media to check the status of all media at once and optionally retry stuck items:

# Check status of all screenshots and previews
asc-client apps verify-media <bundle-id>

# Check a specific version
asc-client apps verify-media <bundle-id> --version 2.1.0

# Retry stuck items using local files from the media folder
asc-client apps verify-media <bundle-id> --folder media/

Without --folder, the command shows a read-only status report. Sets where all items are complete show a compact one-liner; sets with stuck items expand to show each file and its state. With --folder, it prompts to retry stuck items by deleting them and re-uploading from the matching local files, preserving the original position order.

Builds

# List all builds
asc-client builds list
asc-client builds list --bundle-id <bundle-id>

# Archive an Xcode project
asc-client builds archive
asc-client builds archive --scheme MyApp --output ./archives

# Validate a build before uploading
asc-client builds validate MyApp.ipa

# Upload a build to App Store Connect
asc-client builds upload MyApp.ipa

# Wait for a build to finish processing
asc-client builds await-processing <bundle-id>
asc-client builds await-processing <bundle-id> --build-version 903

The archive command auto-detects the .xcworkspace or .xcodeproj in the current directory and resolves the scheme if only one exists. It accepts .ipa, .pkg, or .xcarchive files for upload and validate. When given an .xcarchive, it automatically exports to .ipa before uploading.

Workflows

Chain multiple commands into a single automated run with a workflow file:

asc-client run-workflow release.txt
asc-client run-workflow release.txt --yes   # skip all prompts (CI/CD)

A workflow file is a plain text file with one command per line (without the asc-client prefix). Lines starting with # are comments, blank lines are ignored.

Example -- release.txt for submitting version 2.1.0 of a sample app:

# Release workflow for MyApp v2.1.0

# Create the new version on App Store Connect
apps create-version com.example.MyApp 2.1.0

# Build, validate, and upload
builds archive --scheme MyApp
builds validate --latest --bundle-id com.example.MyApp
builds upload --latest --bundle-id com.example.MyApp

# Wait for the build to finish processing
builds await-processing com.example.MyApp

# Update localizations and attach the build
apps update-localizations com.example.MyApp --file localizations.json
apps attach-latest-build com.example.MyApp

# Submit for review
apps submit-for-review com.example.MyApp

Without --yes, the workflow asks for confirmation before starting, and individual commands still prompt where they normally would (e.g., before submitting for review). With --yes, all prompts are skipped for fully unattended execution.

Automation

Most commands that prompt for confirmation support --yes / -y to skip prompts, making them suitable for CI/CD pipelines and scripts:

asc-client apps attach-latest-build <bundle-id> --yes
asc-client apps submit-for-review <bundle-id> --yes

Acknowledgments

Built on top of asc-swift by Aaron Sky.

Developed with Claude Code.

License

MIT