asc-cli is an open source Go CLI for the Apple App Store Connect API.
It helps iOS, macOS, tvOS, and visionOS developers operate App Store Connect from the terminal with predictable JSON output, stable command names, and a maintainable codebase. It also includes a raw command so LLMs, scripts, and CI jobs can call any App Store Connect API endpoint directly.
This project is based on the App Store Connect OpenAPI spec tracked by EvanBacon/App-Store-Connect-OpenAPI-Spec and currently pins spec 4.3.
Most App Store Connect automation is either:
- too narrow for real operational work
- too broad and generated to maintain comfortably
- awkward for LLMs and automation agents to consume
asc-cli focuses on the operational middle ground:
- common App Store Connect workflows get first-class commands
- everything else is reachable with
asc raw - output stays machine-readable and stable
- App lookup by App Store app ID or bundle ID
- Build inspection and build updates
- App Store version list, create, update, and delete
- Customer review listing
- Review submission list, create, submit, and cancel
- TestFlight beta group and beta tester operations
- App info inspection and category relationship updates
- Raw App Store Connect API access for any uncovered endpoint
- Environment variable and config file based authentication
- Consistent JSON output for LLMs, shell scripts, and CI
go install github.com/techinpark/app-store-connect-cli@latestHomebrew:
brew tap techinpark/tap
brew install app-store-connect-cliBuild from source:
git clone https://github.com/techinpark/app-store-connect-cli.git
cd app-store-connect-cli
go build ./...asc-cli supports App Store Connect API key authentication.
Environment variables:
export ASC_ISSUER_ID="00000000-0000-0000-0000-000000000000"
export ASC_KEY_ID="ABC123DEF4"
export ASC_PRIVATE_KEY_PATH="$HOME/.keys/AuthKey_ABC123DEF4.p8"
export ASC_DEFAULT_APP="com.example.app"Or create a local config file:
asc auth init \
--issuer-id "00000000-0000-0000-0000-000000000000" \
--key-id "ABC123DEF4" \
--private-key-path "$HOME/.keys/AuthKey_ABC123DEF4.p8" \
--default-app "com.example.app"Validate credentials:
asc auth check
asc auth check --jsonConfig file location:
~/.config/asc/config.yaml
asc apps list
asc apps list --query myapp --json
asc apps get com.example.appasc builds list --app com.example.app
asc builds latest --app com.example.app --json
asc builds update build-123 --expired trueasc versions list --app com.example.app
asc versions create --app com.example.app --platform IOS --version 1.3.0
asc versions update ver-123 --version 1.3.1 --downloadable true
asc versions delete ver-123asc reviews --app com.example.app
asc review-submissions list --app com.example.app
asc review-submissions create --app com.example.app --platform IOS
asc review-submissions submit sub-123
asc review-submissions cancel sub-123asc beta groups list --app com.example.app
asc beta groups create --app com.example.app --name "External Testers"
asc beta groups add-build --group-id group-123 --build-id build-123
asc beta testers list --app com.example.app
asc beta testers invite --app com.example.app --email tester@example.com --group-id group-123
asc beta testers add-group tester-123 --group-id group-123
asc beta testers remove-group tester-123 --group-id group-123
asc beta testers delete tester-123asc appinfos list --app com.example.app
asc appinfos get info-123
asc appinfos update-categories info-123 --primary-category-id cat-123asc raw GET /v1/apps --query 'filter[bundleId]=com.example.app'
asc raw POST /v1/reviewSubmissions \
--body '{
"data": {
"type": "reviewSubmissions",
"relationships": {
"app": {
"data": { "id": "123456789", "type": "apps" }
}
}
}
}'If you are using asc-cli from ChatGPT, Codex, Claude, Cursor, CI scripts, or any other automation tool:
- prefer
--jsonfor read operations - prefer explicit IDs over names when you already know them
- use
ASC_DEFAULT_APPonly for local convenience, not for critical automation - use
asc rawfor endpoints not yet wrapped by a first-class command - treat write commands as side-effectful and require explicit user intent
- surface the first App Store Connect error detail to the user when commands fail
See LLM_GUIDE.md for concrete prompting and integration guidance.
- Human-readable tables are the default
--jsonis the preferred machine interface- error responses are normalized for automation use
- command names are intended to stay predictable
- first-class commands are thin wrappers over focused operational workflows
rawis the escape hatch for full App Store Connect API coverage
This repository does not try to expose every App Store Connect resource as its own handcrafted command. Instead it uses this strategy:
- wrap high-value operational workflows with dedicated commands
- keep the codebase hand-written and maintainable
- preserve complete API reachability through
asc raw
That balance is deliberate for an open source CLI that needs to stay easy to evolve.
cmd/: Cobra commandsinternal/config: config loading and precedenceinternal/auth: JWT generation for App Store Connectinternal/httpx: HTTP transport, retries, and normalized errorsinternal/jsonapi: shared JSON:API helpersinternal/appstore: focused domain client methodsinternal/output: table renderinginternal/spec: pinned upstream OpenAPI spec reference
Run the full test suite:
go test ./...
go test ./... -coverThe project includes command tests, HTTP layer tests, JSON:API decoding tests, and domain client tests for operational App Store Connect workflows.
GitHub Actions runs on pushes to main and on pull requests. The workflow:
- verifies
gofmt - runs
go test ./... -cover - runs
go build ./...
- never commit your
.p8App Store Connect private key - prefer environment variables in CI
- use a key with the minimum role and scope you need
- review write commands carefully before using them in automation
- contribution guide: CONTRIBUTING.md
- security policy: SECURITY.md
- changelog: CHANGELOG.md
MIT