A command-line interface for the App Store Connect API. Manage apps, builds, TestFlight, certificates, provisioning profiles, App Store submissions, and 190+ other resources — all from your terminal.
Commands are auto-generated from Apple's OpenAPI spec via a compact manifest, so when Apple ships new API endpoints, a single python3 generate_manifest.py brings them into the CLI.
pip install appstore-cli
appstore auth setup # walks you through Key ID, Issuer ID, .p8 path
appstore apps list # verify it works- Python 3.9+
- An App Store Connect API key (
.p8file)
From PyPI (recommended):
pip install appstore-cliOr with pipx for an isolated install:
pipx install appstore-cliWith Homebrew:
brew tap ohmguru/tap
brew install appstore-cliFrom source:
git clone https://github.com/ohmguru/AppStoreConnectCLI.git
cd AppStoreConnectCLI
pip install .appstore needs three values to authenticate: Key ID, Issuer ID, and the path to your .p8 private key.
Interactive setup (recommended):
appstore auth setupPrompts for each value and saves them to ~/.config/appstore/default.env (chmod 600).
Environment variables (override any profile):
export ASC_KEY_ID=...
export ASC_ISSUER_ID=...
export ASC_KEY_PATH=...If you work across multiple teams or accounts, create named profiles:
appstore auth setup # default profile
appstore auth setup --profile work # additional profile
appstore auth setup --profile client # another one
appstore auth list # show all profiles
appstore auth use work # switch active profile
appstore auth status # show active profile details
appstore auth reset --profile client # remove a profileUse --profile on any command for a one-off override without switching:
appstore --profile work apps listProfiles are stored as individual files in ~/.config/appstore/:
~/.config/appstore/
active # contains name of active profile
default.env # default profile credentials
work.env # work profile credentials
appstore [--json] [--profile NAME] <resource> <command> [options]
appstore apps list
appstore apps list --filter-bundle-id com.example.MyApp
appstore apps get APP_ID
appstore builds list --include app --sort -uploadedDate
appstore builds list --filter-app APP_ID --include app
appstore builds get BUILD_IDappstore certificates list --filter-certificate-type IOS_DISTRIBUTION --sort displayName
appstore certificates create --csr-content "$(cat req.csr)" --certificate-type IOS_DISTRIBUTION
appstore certificates delete CERT_ID
appstore profiles list --filter-profile-type IOS_APP_STORE
appstore devices list --filter-platform IOS
appstore devices create --name "iPhone" --platform IOS --udid UDID_HERE
appstore bundle-ids list --filter-platform IOS
appstore bundle-ids create --name "MyApp" --platform IOS --identifier com.example.MyAppappstore beta-groups list --include app
appstore beta-groups create --name "Testers" --app-id APP_ID
appstore beta-groups add-build GROUP_ID BUILD_ID
appstore beta-groups remove-build GROUP_ID BUILD_ID
appstore beta-testers list --filter-email user@example.com
appstore beta-testers create --email user@example.com --first-name Jane --last-name Doe \
--beta-groups-id GROUP_ID
appstore beta-app-review-submissions create --build-id BUILD_IDappstore app-store-versions create --version-string 1.2.0 --platform IOS --app-id APP_ID
appstore app-store-versions set-build VERSION_ID BUILD_ID
appstore review-submissions create --platform IOS --app-id APP_ID
appstore review-submissions get SUBMISSION_IDThere are 198 resource groups in total. Run appstore --help to see them all, or appstore <resource> --help for available subcommands.
appstore users list
appstore in-app-purchases list
appstore subscriptions get SUB_ID
appstore customer-reviews listEvery list command supports:
| Option | Description |
|---|---|
--limit N |
Max results per page (default 200) |
--all |
Auto-paginate through all results |
--sort FIELD |
Sort by field (prefix with - for descending) |
--filter-FIELD VALUE |
Filter results (available filters vary by resource) |
--include TYPE |
Sideload related resources into the response |
Add --json before any subcommand for raw JSON:API output:
appstore --json builds list --limit 5Use --help on any command to see all available options:
appstore certificates list --helpopenapi.oas.json ──▶ generate_manifest.py ──▶ manifest.json ──▶ appstore (generic engine)
(Apple spec) (one-time gen) (198 resources) (CLI commands)
generate_manifest.pyparses Apple's OpenAPI spec and extracts a compact manifest of every resource: paths, operations, filters, sort fields, create/update schemas, and display attributes.manifest.jsonis the generated output — bundled inside theappstore_clipackage so the CLI works without the 6 MB OpenAPI spec at runtime.appstoreloads the manifest at startup and dynamically registers Click command groups for each resource. The only hand-written command isauth(credential management).
- Download the latest OpenAPI spec
- Place
openapi.oas.jsonin the project root - Regenerate:
python3 generate_manifest.py- Commit the updated
appstore_cli/manifest.json
To override any generic command with a hand-written one, add a Click group with the same name in cli.py before register_generic_commands() is called. The engine skips any name that's already registered.
appstore_cli/
__init__.py Package init
cli.py CLI entry point
manifest.json Generated resource definitions (198 resources)
generate_manifest.py OpenAPI → manifest generator
pyproject.toml Package metadata and dependencies
MIT