Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (appstore-cli) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
AppStoreServices CLI
A command-line interface (CLI) to interact with the Apple App Store Connect API. The tool provides commands for managing apps, builds, TestFlight beta testing, and downloading reports.
Installation
Clone the repository:
git clone https://github.com/your-username/appstore-cli.git cd appstore-cli
Install the dependencies:
npm install
Build the project:
npm run buildLink the CLI to make it accessible globally:
npm link
Configuration
To interact with the App Store Connect API, you must provide your API credentials. This tool provides two secure methods for storing your credentials:
Method 1: OS Keychain Storage (Default)
The CLI securely stores your private key in your operating system's keychain:
- macOS: Uses Keychain Access
- Windows: Uses Credential Vault
- Linux: Uses libsecret
Method 2: Environment Variables
You can provide your credentials through environment variables, which is useful for CI/CD pipelines and containerized deployments:
export APPSTORE_KEY_ID="YOUR_KEY_ID"
export APPSTORE_ISSUER_ID="YOUR_ISSUER_ID"
export APPSTORE_PRIVATE_KEY="YOUR_PRIVATE_KEY_CONTENT"Or in a single command:
APPSTORE_KEY_ID="YOUR_KEY_ID" APPSTORE_ISSUER_ID="YOUR_ISSUER_ID" APPSTORE_PRIVATE_KEY="YOUR_PRIVATE_KEY_CONTENT" appstore-cli apps listSetting Up Your Credentials
Before you can use the CLI, you need to set up your App Store Connect API key. You have several options for configuring your credentials:
Method 1: Using the Helper Script (Recommended)
The easiest way to set up your credentials is using the provided helper script. You can provide your private key in two ways:
Option A: Provide a path to your private key file
node setup-config.js --keyId <your-key-id> --issuerId <your-issuer-id> --privateKeyPath <path-to-your-private-key-file>Example:
node setup-config.js --keyId LS76K9LCHB --issuerId 69a6de8b-0aac-47e3-e053-5b8c7c11a4d1 --privateKeyPath ./AuthKey_LS76K9LCHB.p8You can also use the short form:
node setup-config.js -k LS76K9LCHB -i 69a6de8b-0aac-47e3-e053-5b8c7c11a4d1 -p ./AuthKey_LS76K9LCHB.p8Option B: Provide the private key content directly
node setup-config.js --keyId <your-key-id> --issuerId <your-issuer-id> --privateKey <your-private-key-content>Example:
node setup-config.js -k LS76K9LCHB -i 69a6de8b-0aac-47e3-e053-5b8c7c11a4d1 -P "-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK...
-----END PRIVATE KEY-----"Method 2: Using the CLI Directly
You can also configure your credentials using the CLI directly:
Providing Private Key Content Directly:
appstore-cli config set --keyId <your-key-id> --issuerId <your-issuer-id> --privateKey '-----BEGIN PRIVATE KEY-----
[paste your private key content here]
-----END PRIVATE KEY-----'Providing a Path to Your Private Key File:
appstore-cli config set --keyId <your-key-id> --issuerId <your-issuer-id> --privateKeyPath <path-to-your-private-key-file>Example:
appstore-cli config set --keyId LS76K9LCHB --issuerId 69a6de8b-0aac-47e3-e053-5b8c7c11a4d1 --privateKeyPath ./AuthKey_LS76K9LCHB.p8Providing a Fastlane Token:
appstore-cli config set --fastlane-token <your-fastlane-token>Providing a Username:
appstore-cli config set --username <your-apple-id>Authentication Flow Consolidation
As of version 1.0.8, the CLI has consolidated authentication flows. The separate build auth command has been removed in favor of the unified configuration approach. All authentication should now be configured using the appstore-cli config set command:
# For API key authentication:
appstore-cli config set --keyId <key-id> --issuerId <issuer-id> --privateKey <private-key>
# For Fastlane token authentication:
appstore-cli config set --fastlane-token <token>
# For username:
appstore-cli config set --username <username>Precedence Order
The CLI uses credentials in the following precedence order:
- Environment variables (if set)
- Securely stored configuration (keychain/file encryption)
How Authentication Works
The CLI exclusively uses a JSON Web Token (JWT) for all interactions with the App Store Connect API. When you first configure the tool with your API Key, Issuer ID, and Private Key, it securely stores these credentials.
For security, your private key is stored in the OS keychain or encrypted on the file system (depending on your platform). The configuration file (~/.appstore-cli/config.json) only contains non-sensitive information (key ID and issuer ID).
For each command, the CLI automatically generates a short-lived JWT using the ES256 algorithm, which is used to authenticate with the API. The private key is retrieved from secure storage and converted to a proper cryptographic key object using Node.js's crypto.createPrivateKey() to ensure compatibility with the JWT library.
This JWT-based approach provides a secure and consistent authentication flow, as your private key is never sent over the network, and access tokens are valid for a limited time (20 minutes).
Viewing Your Configuration
To view your current configuration (excluding the private key for security reasons), run:
appstore-cli config getNote that your private key is stored securely and is not displayed by this command.
Usage
Apps
List all apps:
appstore-cli apps list
Get app details:
appstore-cli apps get <app-id>
Create a new app:
appstore-cli apps create-app --name <name> --bundle-id <bundle-id> --sku <sku> --primary-locale <locale> --version-string <version>
Builds
List all builds for an app:
appstore-cli builds list --app-id <app-id>
Get build details:
appstore-cli builds get <build-id>
Upload a new build:
appstore-cli builds upload --app-id <app-id> --path <path-to-ipa>
Upload a new build with credentials:
appstore-cli builds upload --app-id <app-id> --path <path-to-ipa> --provisioning-profile <path-to-profile> --certificate-path <path-to-cert> --certificate-password <password>
Upload a new build and submit to App Store:
appstore-cli builds upload --app-id <app-id> --path <path-to-ipa> --submit-to-app-store
Upload a new build with Fastlane token:
appstore-cli builds upload --app-id <app-id> --path <path-to-ipa> --fastlane-token <token>
Submit a build for App Store review:
appstore-cli builds submit-build --build-id <build-id> --app-id <app-id>
Submit a build for App Store review with credentials:
appstore-cli builds submit-build --build-id <build-id> --app-id <app-id> --provisioning-profile <path-to-profile> --certificate-path <path-to-cert> --fastlane-token <token>
Build Phase Commands
Configure build settings:
appstore-cli build configure --scheme <scheme> --workspace <workspace-path> --configuration <config>
or
appstore-cli build configure --scheme <scheme> --project <project-path> --configuration <config>
Configure build settings with custom variables:
appstore-cli build configure --scheme <scheme> --workspace <workspace-path> --configuration <config> --variable KEY1=VALUE1 --variable KEY2=VALUE2
Set authentication for build process:
appstore-cli config set --keyId <key-id> --issuerId <issuer-id>
or
appstore-cli config set --fastlaneToken <token>
Configure export settings:
appstore-cli build export configure --method <method> --team-id <team-id>
Run the build process:
appstore-cli build run
Export IPA after building:
appstore-cli build export run --archive-path <archive-path>
Common Build Workflows
Debug Build for Testing
appstore-cli build configure --scheme "MyApp" --workspace "./MyApp.xcworkspace" --configuration "Debug" --variable API_URL=https://api.dev.example.com --variable DEBUG=true
appstore-cli build runApp Store Release
appstore-cli build configure --scheme "MyApp" --workspace "./MyApp.xcworkspace" --configuration "Release"
appstore-cli config set --keyId "YOUR_KEY_ID" --issuerId "YOUR_ISSUER_ID"
appstore-cli build export configure --method "app-store" --team-id "YOUR_TEAM_ID"
appstore-cli build run
appstore-cli build export run --archive-path "./build/MyApp.xcarchive"Ad Hoc Distribution
appstore-cli build configure --scheme "MyApp" --workspace "./MyApp.xcworkspace" --configuration "Release"
appstore-cli config set --fastlaneToken "YOUR_FASTLANE_TOKEN"
appstore-cli build export configure --method "ad-hoc" --team-id "YOUR_TEAM_ID" --provisioning-profiles "com.example.app:PROFILE_UUID"
appstore-cli build run
appstore-cli build export run --archive-path "./build/MyApp.xcarchive" --output-path "./build/MyApp.ipa"Custom Build Variables
The AppStoreServices CLI supports custom build variables that allow you to pass environment-specific configuration to your builds. This feature is useful for:
- Configuring different API endpoints for development, staging, and production environments
- Enabling or disabling features with feature flags
- Setting build-specific metadata
- Customizing builds for different customers or brands
To use custom variables, add the --variable option to the build configure command:
appstore-cli build configure --scheme "MyApp" --workspace "./MyApp.xcworkspace" --configuration "Debug" --variable API_URL=https://api.example.com --variable DEBUG=trueYou can specify multiple variables by using the --variable option multiple times. Variables should be in KEY=VALUE format. Values containing spaces should be quoted:
appstore-cli build configure --scheme "MyApp" --workspace "./MyApp.xcworkspace" --configuration "Debug" --variable "APP_NAME=My App" --variable API_URL=https://api.example.comThe custom variables will be made available during the build process and can be accessed in your build scripts and application code.
Beta Testers
List all beta testers:
appstore-cli testers list
Add a new beta tester:
appstore-cli testers add --email <email> --firstName <first> --lastName <last>
Remove a beta tester:
appstore-cli testers remove <tester-id>
Beta Groups
List all beta groups:
appstore-cli groups listAdd a tester to a group:
appstore-cli groups add-tester --group-id <group-id> --tester-id <tester-id>
Create a new beta group:
appstore-cli groups create-beta-group --name <name> --app-id <app-id> [--is-internal]
Reports
Download sales and trends reports:
appstore-cli reports download-sales --vendor <vendor> --report-type <type> --frequency <freq> --report-date <date>
Download financial reports:
appstore-cli reports download-financial --vendor <vendor> --region-code <code> --report-date <date>
Credential Management
The AppStoreServices CLI provides comprehensive support for managing iOS app signing credentials, including provisioning profiles, signing certificates, certificate passwords, and Fastlane authentication tokens.
Provisioning Profiles
Provisioning profiles (.mobileprovision files) authorize your app's installation and distribution. They are tied to your app's Bundle ID, your signing certificate, and include entitlements like push notifications.
Using a provisioning profile with build upload:
appstore-cli builds upload --app-id <app-id> --path <path-to-ipa> --provisioning-profile <path-to-profile.mobileprovision>
Using a provisioning profile with build submission:
appstore-cli builds submit-build --build-id <build-id> --app-id <app-id> --provisioning-profile <path-to-profile.mobileprovision>
Signing Certificates
Signing certificates (.p12, .cer files) digitally sign your app so devices and the App Store recognize it as coming from a trusted developer.
Using a signing certificate with build upload:
appstore-cli builds upload --app-id <app-id> --path <path-to-ipa> --certificate-path <path-to-cert.p12> --certificate-password <password>
Using a signing certificate with build submission:
appstore-cli builds submit-build --build-id <build-id> --app-id <app-id> --certificate-path <path-to-cert.p12> --certificate-password <password>
Fastlane Auth Tokens
Fastlane auth tokens (spaceauth sessions) provide temporary Apple account access for Fastlane-based signing and provisioning tasks.
Using a Fastlane token with build upload:
appstore-cli builds upload --app-id <app-id> --path <path-to-ipa> --fastlane-token <your-fastlane-token>
Using a Fastlane token with build submission:
appstore-cli builds submit-build --build-id <build-id> --app-id <app-id> --fastlane-token <your-fastlane-token>
Using environment variables for Fastlane tokens:
export FASTLANE_TOKEN="your-fastlane-token" appstore-cli builds upload --app-id <app-id> --path <path-to-ipa>
Credential Validation
The CLI automatically validates all provided credentials:
- File existence and readability
- Correct file extensions (.mobileprovision, .p12, .cer)
- Provisioning profile content and expiration
- Certificate format
- Fastlane token format
If any credential fails validation, the CLI provides detailed error messages and troubleshooting tips.
Security
All credentials are handled securely:
- Sensitive data is stored in encrypted memory only during processing
- Passwords and tokens are never logged or displayed in output
- Credentials are automatically cleaned up after use
- File permissions are checked to ensure secure access
Security
The AppStoreServices CLI has been enhanced with robust security features:
Private Key Security
- Private keys are securely stored using OS keychain (keytar) when available
- Falls back to AES-256-CBC encryption with machine-specific keys when keytar is not available
- No private keys are logged or exposed in error messages
- Secure functions for storing, retrieving, and deleting private keys
JWT Token Security
- Configuration validation prevents invalid token generation
- Sanitized error messages prevent information disclosure
- Payload validation ensures proper token structure
- Expiration time validation prevents overly long-lived tokens (20 minutes)
- No tokens are logged or exposed in any way
For detailed information about security features and best practices, see SECURITY.md.
Troubleshooting
Common Issues
"secretOrPrivateKey must have a value" Error
This error occurs when the private key is not properly configured. Solutions:
Use the helper script (recommended):
# Option A: Provide a path to your private key file node setup-config.js --keyId <key-id> --issuerId <issuer-id> --privateKeyPath <path-to-p8-file> # Option B: Provide the private key content directly node setup-config.js --keyId <key-id> --issuerId <issuer-id> --privateKey <your-private-key-content>
Use the CLI with a file path:
appstore-cli config set --keyId <key-id> --issuerId <issuer-id> --privateKeyPath <path-to-p8-file>
Check your private key format: Ensure your private key contains a valid ECDSA private key in PEM format starting with
-----BEGIN PRIVATE KEY-----Avoid shell escaping issues: Don't paste multiline private keys directly in double quotes. Use single quotes or the helper script instead.
Provide exactly one private key option: When using the CLI, you must provide exactly one of
--privateKeyor--privateKeyPath, not both.
"Invalid private key format" Error
This indicates the private key cannot be parsed as a valid ECDSA key:
- Verify your .p8 file is a valid App Store Connect API private key
- Check file encoding - ensure the file is UTF-8 encoded
- Re-download the key from App Store Connect if necessary
401 Authentication Error
If you get a 401 error after successful JWT generation:
- Verify your Key ID and Issuer ID are correct
- Check key permissions in App Store Connect - ensure the key has the required scopes
- Confirm the key is active and not expired in App Store Connect
Credential Validation Errors
When using provisioning profiles, certificates, or Fastlane tokens, you may encounter validation errors:
Provisioning Profile Issues:
- Ensure the file has a .mobileprovision extension
- Verify the profile hasn't expired
- Check that the profile matches your app's bundle identifier
- Confirm the profile includes the correct devices (for development profiles)
Certificate Issues:
- Ensure the file has a .p12 or .cer extension
- Verify the certificate hasn't expired
- For .p12 files, ensure you're providing the correct password
- Make sure the certificate matches your provisioning profile
Fastlane Token Issues:
- Generate a new Fastlane session token using 'fastlane spaceauth'
- Ensure the token hasn't expired (tokens typically expire after a few hours)
- Check that you haven't accidentally included extra characters or whitespace
Development Mode
For development, you can run commands directly without building:
# Run in development mode
ts-node src/appstore-cli.ts <command>
# Example
ts-node src/appstore-cli.ts apps listTesting
Run the test suite:
npm testBuilding
Build the TypeScript source:
npm run buildProject Status
The AppStoreServices CLI has successfully achieved all of its core goals and now supports the complete automated workflow for iOS app management in App Store Connect:
- ✅ Create app in App Store Connect - Using
create-appcommand - ✅ Upload IPA file - Using
builds uploadcommand - ✅ Create internal test group - Using
create-beta-groupcommand - ✅ Add user to internal test group - Using
testers addandgroups add-testercommands - ✅ Push build to App Store - Using
submit-buildcommand orbuilds upload --submit-to-app-store - ✅ Credential Management - Comprehensive support for provisioning profiles, signing certificates, and Fastlane tokens
The implementation is robust, secure, and well-tested. For information about ongoing improvements and next steps, see the task tracking files in the .tasks directory.