Stop Wrestling with Xcode: Automate App Store Connect with asc CLI
Stop Wrestling with Xcode: Automate App Store Connect with asc CLI
Let me ask you something brutal: how many hours did you lose last month clicking through App Store Connect? Uploading IPA files. Waiting for processing. Adding testers one by one. Screenshots. Localizations. That soul-crushing moment when your build gets rejected for a metadata mismatch you could have caught hours ago.
If you're still managing iOS releases through a web browser, you're leaving money on the floor. Worse—you're leaving sanity there too.
Enter asc CLI—the open-source, scriptable command-line interface that transforms App Store Connect from a GUI nightmare into a fully programmable release pipeline. Built in Go for blistering speed. Designed JSON-first for seamless CI/CD integration. Zero interactive prompts to break your automation. This isn't just another wrapper around Apple's API. It's the missing infrastructure layer that serious iOS teams have been desperate for.
Ready to reclaim your afternoons? Let's dissect why top developers are quietly migrating their entire release workflows to rudrankriyam/App-Store-Connect-CLI.
What is asc CLI?
asc (short for App Store Connect) is a fast, lightweight, and ruthlessly scriptable CLI for the App Store Connect API. Created by Rudrank Riyam and actively maintained, this open-source tool is written in Go 1.26+ and distributed through Homebrew for frictionless installation across macOS and Linux environments.
But here's what makes asc genuinely different from the scattered shell scripts and Ruby gems that came before it.
The philosophy is radical simplicity through automation. Every command is built for pipes, scripts, and CI pipelines first. No modal dialogs. No "click here to continue." The tool detects whether it's running in an interactive terminal (TTY) versus a headless environment, automatically switching output formats between human-readable tables and machine-parseable JSON. This TTY-awareness eliminates an entire category of automation bugs that plague other tools.
The project has gained serious traction in the iOS developer community, evidenced by its growing GitHub star history and active sponsorship program. It's unofficial and independent—not affiliated with Apple—which means it moves faster, responds to real developer pain points, and isn't constrained by Apple's release cycles. When the API changes, the community patches it. When a workflow pattern emerges, it gets codified into reusable commands.
Most importantly, asc treats the entire App Store Connect surface as infrastructure as code. TestFlight groups, build uploads, metadata localization, screenshot management, signing certificates, subscription configuration, analytics retrieval—every operation that once demanded manual GUI interaction becomes a version-controlled, reviewable, repeatable command.
Key Features That Separate asc from the Pack
Blazing-Fast Go Implementation
Written in Go 1.26+, asc compiles to native binaries with no runtime dependencies. Compare this to Ruby-based alternatives that drag along gem ecosystems, or Python tools wrestling with virtual environments. Single binary. Sub-second startup. Predictable memory usage. Your CI runners will thank you.
JSON-First, Zero-Prompt Architecture
Every command accepts --output json and returns structured data. No parsing HTML or scraping screenshots. No interactive prompts that hang your GitHub Actions workflow at 2 AM. The --confirm flag pattern makes destructive operations explicit and scriptable. Want to chain commands? Pipe JSON through jq. Need metrics in Datadog? asc outputs exactly what your monitoring stack expects.
Intelligent TTY-Aware Defaults
This is the kind of detail that separates polished tools from hacked-together scripts:
| Environment | Default Output | Why It Matters |
|---|---|---|
| Interactive terminal | table |
Human-readable, colorized columns |
| Pipes, files, CI | json |
Machine-parseable, no formatting noise |
| Explicit override | --output [format] |
Your choice always wins |
Set ASC_DEFAULT_OUTPUT=markdown for documentation pipelines, or force --output json when consistency matters more than convenience.
Lifecycle Stability Labels
asc doesn't surprise you with breaking changes. Commands carry visible labels:
- No label: Stable public contract—safe for production CI
[experimental]: Useful but evolving; expect iterationDEPRECATED:: Migration path provided, with clear timelines
This transparency lets you adopt aggressively while managing risk appropriately.
Comprehensive Workflow Coverage
From asc builds upload to asc publish appstore --submit --confirm, the tool spans the entire release lifecycle. But it goes deeper: Xcode Cloud integration, screenshot automation with device framing, ASO keyword auditing, TestFlight crash log retrieval, subscription and analytics access. This isn't a narrow upload tool—it's a complete operational interface to Apple's ecosystem.
Real-World Use Cases Where asc CLI Dominates
1. CI/CD Native Release Pipelines
Your GitHub Actions workflow triggers on main branch merge. Tests pass. asc takes over: authenticates via stored secrets, uploads the IPA, distributes to internal TestFlight groups, waits for processing completion, then promotes to external beta review. Zero human intervention. The --wait flag blocks until App Store processing completes, eliminating race conditions in downstream steps.
2. Multi-Locale Metadata Synchronization
Managing 40 localizations through a web form is masochism. With asc, version your metadata in Git:
asc metadata init --dir "./metadata" --version "2.4.0" --locale "en-US"
# Edit files, commit, review via PR
asc metadata apply --app "123456789" --version "2.4.0" --dir "./metadata"
The keywords audit command catches ASO anti-patterns—duplicate phrases, blocked terms, byte-budget overruns—before submission.
3. Automated Screenshot Generation and Upload
Pair asc with simulator automation tools (it leverages AXe CLI for UI automation and Koubou for device framing) to generate localized screenshots, then:
asc screenshots plan --app "123456789" --version "2.4.0" --review-output-dir "./screenshots/review"
asc screenshots apply --app "123456789" --version "2.4.0" --review-output-dir "./screenshots/review" --confirm
Your App Store listing stays visually current without manual labor.
4. Incident Response and Monitoring
Production crash reported? Pull TestFlight crash logs programmatically:
asc testflight crashes list --app "123456789" --sort -createdDate --limit 10
asc testflight crashes log --submission-id "SUBMISSION_ID"
Feed this into PagerDuty or Slack for immediate team visibility. No more logging into App Store Connect during outages.
5. Xcode Cloud Orchestration
Trigger workflows from pull requests, rerun builds with clean states, fetch build run details—all without touching Xcode:
asc xcode-cloud run --workflow-id "WORKFLOW_ID" --pull-request-id "PR_ID"
Step-by-Step Installation & Setup Guide
Installation
Homebrew (recommended for macOS/Linux):
# Update Homebrew and install asc
brew update && brew install asc
Install script (macOS/Linux alternative):
# One-line installer from the official distribution endpoint
curl -fsSL https://asccli.sh/install | bash
Windows: Download signed release binaries directly from the GitHub releases page.
Verify installation:
asc version # Display installed version
asc --help # Explore command structure
Authentication Setup
Generate API keys at App Store Connect first. You'll need:
- Key ID (e.g.,
ABC123) - Issuer ID (e.g.,
DEF456) - Private key file (
.p8format downloaded from Apple)
Standard authentication (interactive environments with keychain access):
asc auth login \
--name "MyApp" \
--key-id "ABC123" \
--issuer-id "DEF456" \
--private-key /path/to/AuthKey.p8 \
--network # Verify connectivity immediately
CI/headless authentication (bypasses keychain):
asc auth login \
--bypass-keychain # Critical for CI runners without keychain access \
--name "MyCIKey" \
--key-id "ABC123" \
--issuer-id "DEF456" \
--private-key /path/to/AuthKey.p8
Local project credentials (repo-local, no keychain):
asc auth login \
--local \
--bypass-keychain \
--name "LocalDev" \
--key-id "ABC123" \
--issuer-id "DEF456" \
--private-key /path/to/AuthKey.p8
# Creates ./.asc/config.json in your project directory
Validation
asc auth status --validate # Check active profile validity
asc auth doctor # Run comprehensive auth health check
First Commands
# List apps in table format (default for TTY)
asc apps list --output table
# List apps as pretty-printed JSON
asc apps list --output json --pretty
Environment Configuration
# Set global default output format
export ASC_DEFAULT_OUTPUT=markdown
# Force keychain bypass for entire session
export ASC_BYPASS_KEYCHAIN=1
# Enable API debugging for troubleshooting
export ASC_DEBUG=api
REAL Code Examples from the Repository
The asc CLI README contains battle-tested workflows. Here are the most powerful patterns, extracted and explained.
Example 1: Complete App Store Publish Flow
This is the canonical high-level command that replaces hours of manual work:
# PREVIEW: See exactly what would happen without executing
asc release stage \
--app "123456789" \
--version "1.2.3" \
--build "BUILD_ID" \
--copy-metadata-from "1.2.2" \
--dry-run # Safety first: preview the staging plan
# EXECUTE: Upload, attach build, and submit for review in one command
asc publish appstore \
--app "123456789" \
--ipa "/path/to/MyApp.ipa" \
--version "1.2.3" \
--submit \
--confirm # Explicit confirmation required for destructive action
# MONITOR: Watch submission status in real-time
asc status \
--app "123456789" \
--watch # Blocks and updates until status changes
What's happening here? The release stage with --dry-run is your safety net—it computes the entire staging plan (metadata inheritance, build association, submission requirements) without mutating anything. The publish appstore command compresses what used to be five separate GUI operations into one atomic CLI invocation. The --watch flag on asc status eliminates the manual refresh cycle that burns 15-30 minutes of developer attention per release.
Example 2: TestFlight Crash Investigation Pipeline
When users report crashes, speed matters. This sequence retrieves actionable data:
# List all feedback for an app with automatic pagination
asc testflight feedback list \
--app "123456789" \
--paginate # Auto-fetch all pages, not just first result set
# Get recent crashes sorted by creation date (newest first), limited to 10
asc testflight crashes list \
--app "123456789" \
--sort -createdDate # Negative prefix = descending order \
--limit 10 # Prevent output overload during triage
# Retrieve full crash log for specific submission
asc testflight crashes log \
--submission-id "SUBMISSION_ID" # Use ID from previous list command
The pagination flag is crucial. App Store Connect APIs return paginated results by default. Without --paginate, you miss feedback buried in later pages. The --sort -createdDate pattern appears across many asc commands—learn it once, apply everywhere.
Example 3: Screenshot Upload for Single Locale
Screenshots are notoriously fiddly. This workflow handles the full complexity:
# Step 1: Discover your app ID
asc apps list
# Step 2: Get version ID for target release
asc versions list --app "APP_ID"
# Step 3: Find the VERSION_LOCALIZATION_ID (not locale code!)
asc localizations list \
--version "VERSION_ID" \
--output json \
--locale "en-US" | jsonpp # Pretty-print JSON for human inspection
# Step 4: Upload screenshots for specific device type
asc screenshots upload \
--version-localization "VERSION_LOCALIZATION_ID" \
--path "./screenshots/en-US" \
--device-type "IPHONE_65" \
--replace # Overwrite existing; idempotent for CI
Critical insight: VERSION_LOCALIZATION_ID is the API resource UUID (data[].id), not the human-readable locale code. This distinction trips up every developer initially. The jsonpp pipe (or jq) extracts this opaque identifier. The --replace flag makes this command safe to rerun in CI—your pipeline won't fail if screenshots already exist.
Example 4: Workflow Validation and Execution
asc supports reusable workflow definitions in .asc/workflow.json:
# Validate workflow configuration before execution
asc workflow validate
# Dry-run to preview what would execute
asc workflow run --dry-run testflight_beta VERSION:1.2.3
# Execute actual workflow
asc workflow run testflight_beta VERSION:1.2.3
The VERSION:1.2.3 syntax passes variables into workflow templates. Combined with asc xcode archive, asc xcode export, and asc builds next-build-number, this creates a fully automated local Xcode → TestFlight pipeline documented in docs/WORKFLOWS.md.
Advanced Usage & Best Practices
CI/CD Integration Patterns
For GitHub Actions, GitLab CI, Bitrise, and CircleCI, reference docs/CI_CD.md. The key pattern: store credentials as protected environment variables, authenticate with --bypass-keychain, and always use explicit --output json for downstream parsing.
Debugging Authentication Issues
When auth fails mysteriously:
# Method 1: Environment variable override
ASC_BYPASS_KEYCHAIN=1 asc <command>
# Method 2: Debug API calls
ASC_DEBUG=api asc <command>
# OR
asc --api-debug <command>
Include redacted --api-debug output in GitHub Issues when reporting bugs.
Output Format Discipline
Always specify --output in scripts, even if the default seems correct. Defaults change. Explicit flags don't. For shared repro steps, prefer --output json --pretty—readable for humans, parseable for machines.
Metadata Versioning Strategy
Treat asc metadata init output as source code:
asc metadata init --dir "./metadata" --version "2.0.0" --locale "en-US"
git add metadata/
git commit -m "Initialize v2.0.0 metadata"
Review metadata changes in pull requests just like code changes. Apply with --dry-run first, then commit for real.
Comparison with Alternatives
| Tool | Language | Scriptable | JSON Output | CI/CD Native | Speed | Coverage |
|---|---|---|---|---|---|---|
| asc CLI | Go | ✅ Zero prompts | ✅ First-class | ✅ Designed for | ⚡ Native binary | Full API surface |
| fastlane | Ruby | ⚠️ Prompts possible | ⚠️ Via plugins | ⚠️ Complex setup | 🐢 Gem dependencies | Broad but fragmented |
| App Store Connect web | N/A | ❌ Manual only | ❌ N/A | ❌ N/A | 🐌 Human speed | Complete but GUI-locked |
| Custom curl scripts | Any | ✅ With effort | ✅ Manual parsing | ⚠️ Fragile | ⚡ Fast | Narrow, maintenance burden |
| Xcode Organizer | N/A | ❌ GUI only | ❌ N/A | ❌ N/A | 🐌 Interactive | Upload only |
Why asc wins: It combines fastlane's workflow coverage with native binary performance, eliminates Ruby dependency hell, and provides cleaner JSON output than any custom script without the maintenance burden. The TTY-awareness and stability labels are unique differentiators no competitor matches.
FAQ
Q: Is asc CLI officially supported by Apple? A: No—it's an independent, unofficial tool. This is actually an advantage: faster updates, direct community responsiveness, and no corporate roadmap constraints.
Q: Can I use asc in GitHub Actions without keychain access?
A: Absolutely. Use --bypass-keychain or set ASC_BYPASS_KEYCHAIN=1. This is the recommended pattern for all CI environments.
Q: What Go version is required? A: Go 1.26+ for building from source. Prebuilt binaries have zero dependencies.
Q: How do I update asc?
A: brew update && brew upgrade asc for Homebrew users. The install script auto-detects and updates existing installations.
Q: Can asc handle enterprise/distributed signing certificates?
A: Yes. asc certificates list and asc profiles list expose full signing management. Enterprise workflows are supported.
Q: What's the difference between --dry-run and no flag?
A: --dry-run computes and displays the operation plan without executing mutations. Use it to preview changes before committing them.
Q: Where do I report bugs or request features?
A: GitHub Issues for reproducible bugs and concrete feature requests. GitHub Discussions for workflow advice and "how do I...?" questions. See SUPPORT.md for the full policy.
Conclusion
The App Store Connect web interface was built for occasional human use, not for the relentless cadence of modern continuous delivery. Every minute spent clicking through forms is a minute not spent building features, fixing bugs, or shipping value to users.
asc CLI is the infrastructure upgrade your iOS release pipeline deserves. Fast Go binaries. JSON-first design. Zero prompts. Complete API coverage from TestFlight distribution to App Store submission, screenshot management to crash log analysis. The TTY-aware defaults show polish; the stability labels show maturity; the workflow system shows vision.
I've watched too many teams treat release automation as an afterthought, cobbling together fragile scripts that fail at 3 AM. asc is different—it's designed by someone who felt that pain and built the systematic solution.
Your next step is simple:
brew install asc
asc auth login --name "MyApp" --key-id "YOUR_KEY" --issuer-id "YOUR_ISSUER" --private-key /path/to/AuthKey.p8 --network
asc apps list --output table
Then explore the complete documentation, workflow recipes, and community at github.com/rudrankriyam/App-Store-Connect-CLI. Star the repo. Submit your app to the Wall of Apps. Join the discussions.
The future of iOS release management isn't a browser tab. It's a terminal command. Make the switch.
Comments (0)
No comments yet. Be the first to share your thoughts!