appstore-cli
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.
Quick start
pip install appstore-cli
appstore auth setup # walks you through Key ID, Issuer ID, .p8 path
appstore apps list # verify it works
Requirements
- Python 3.9+
- An App Store Connect API key (
.p8file)
Installation
From PyPI (recommended):
pip install appstore-cli
Or with pipx for an isolated install:
pipx install appstore-cli
With Homebrew:
brew tap ohmguru/tap
brew install appstore-cli
From source:
git clone https://github.com/ohmguru/AppStoreConnectCLI.git
cd AppStoreConnectCLI
pip install .
Authentication
appstore needs three values to authenticate: Key ID, Issuer ID, and the path to your .p8 private key.
Interactive setup (recommended):
appstore auth setup
Prompts 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=...
Multiple profiles
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 profile
Use --profile on any command for a one-off override without switching:
appstore --profile work apps list
Profiles 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
Usage
appstore [--json] [--profile NAME] <resource> <command> [options]
Apps & Builds
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_ID
Certificates, Profiles & Devices
appstore 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.MyApp
TestFlight
appstore 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_ID
App Store Submissions
appstore 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_ID
More resources
There 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 list
Common options
Every 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 5
Use --help on any command to see all available options:
appstore certificates list --help
How it works
openapi.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).
Updating when Apple releases a new API version
- Download the latest OpenAPI spec
- Place
openapi.oas.jsonin the project root - Regenerate:
python3 generate_manifest.py
- Commit the updated
appstore_cli/manifest.json
Customizing commands
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.
Project structure
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
License
MIT
Metadata
Release files for appstore-cli 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| appstore_cli-0.1.1.tar.gz | 28.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| appstore_cli-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.1 kB
Release files / appstore_cli-0.1.1.tar.gz
| Download URL | appstore_cli-0.1.1.tar.gz |
|---|---|
| Size | 28.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
25e04187ae54b44832254874adebbe89f4dc70b1db739268128e94cb619216d4
|
|
BLAKE2b-256 checksum How to use checksums |
8d829281fc5a37ac05a9eabc2a308d255553cdb9510a87e9f1c744ff9a9446e6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / appstore_cli-0.1.1-py3-none-any.whl
| Download URL | appstore_cli-0.1.1-py3-none-any.whl |
|---|---|
| Size | 26.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7965c05dac758a1c1c6f7b688fc82e7c831c921a3d807a9c4cc73428842e03b0
|
|
BLAKE2b-256 checksum How to use checksums |
8e4119f6927a4f43386bb1b1642481397b364121676bd8d723c4abafd35251ce
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|