Skip to documentation
Open dashboard
Docs/Connect stores

CherrySub CLI

Install the CLI, automate store setup, migrate catalogs and purchases, and manage profiles.

Download this chapter
On this page

CherrySub CLI signs you in, chooses your project and app, and provisions store credentials locally. It uses the same account permissions as the dashboard. The preview defaults to staging (https://api-staging.cherrysub.com).

Install

macOS / Linux (arm64 or amd64), without Go or Node.js:

sh
curl -fsSL https://api-staging.cherrysub.com/cli/install.sh -o /tmp/cherrysub-install.sh
sh /tmp/cherrysub-install.sh
export PATH="$HOME/.local/bin:$PATH"
cherrysub --version

The installer verifies the archive's SHA-256 checksum before installing. It requires no sudo. CHERRYSUB_INSTALL_DIR changes the destination. Add that directory to your shell's PATH for future terminal sessions.

Windows: download amd64 or arm64, verify against checksums.txt, and extract cherrysub.exe to a directory on PATH.

Repository contributors can run go install ./cmd/cherrysub from the checkout. python3 scripts/build-cli.py produces all six platform archives and checksums.

First connection

sh
cherrysub auth login
cherrysub setup apple
# or:
cherrysub setup google --oauth-client ./google-desktop-client.json

The CLI prompts for missing project/app selections and remembers your choice. If you have several projects, --project UUID selects one explicitly. Pass the app UUID after apple or google to connect a particular app. The dashboard's Integrations page provides the command with both identifiers filled in.

An existing app credential is kept unless you pass --rotate. Shared deployment credentials can be replaced with an app credential. Old store keys are never automatically revoked, including during rotation.

sh
cherrysub projects list
cherrysub projects use PROJECT_UUID
cherrysub apps list
cherrysub apps use APP_UUID
cherrysub setup apple APP_UUID --dry-run --json
cherrysub stores status APP_UUID --json

--dry-run checks CherrySub access and prints a plan. It does not sign in to a store or create/upload keys. It can update the CLI session's selected project.

Apple automation

setup apple performs local Apple Account sign-in, trusted-device or SMS 2FA, team selection, a bundle-ID lookup, and In-App Purchase key access checks. After you confirm the app and team, it creates and downloads an In-App Purchase key and sends it directly to CherrySub. Passwords and Apple session cookies are not stored. The key exists only in process memory before upload.

Use an Apple role allowed to create In-App Purchase keys. The app must already exist in App Store Connect with the bundle ID configured in CherrySub. Account agreements or Apple's key limits may need attention in App Store Connect. This uses Apple's web-session endpoints, which can change independently of the public API. File import is available if interactive sign-in is unavailable.

sh
cherrysub setup apple APP_UUID --sms
cherrysub setup apple APP_UUID --team-id 123456 --rotate
cherrysub setup apple APP_UUID --key-file ./SubscriptionKey_ABC123DEFG.p8 --issuer-id ISSUER_UUID

Key ID is detected from SubscriptionKey_ID.p8 (also AuthKey_ID.p8) or supplied with --key-id. Use an In-App Purchase key, not an App Store Connect API key. The key format alone cannot distinguish them.

Google automation

Google browser authorization needs a Desktop app OAuth client belonging to your organization. A CherrySub-owned verified OAuth client is not bundled in this preview. Create one at Google Cloud credentials, configure its audience/test users as required by Google, download the client JSON, and supply --oauth-client. This is an OAuth client file, distinct from the service-account key the setup command will create.

sh
cherrysub setup google APP_UUID \
  --oauth-client ./google-desktop-client.json \
  --cloud-project my-google-project \
  --developer-account https://play.google.com/console/u/0/developers/1234567890123456789/app-list

Sign in as someone who can enable services, create service accounts/keys in that Cloud project, and manage Play users. The command:

  1. Uses browser OAuth with PKCE and a loopback callback.
  2. Enables IAM and Android Publisher APIs on the selected existing Cloud project.
  3. Creates or reuses an app-specific cherrysub-* service account.
  4. Grants the package's app information, financial data, and order/subscription permissions.
  5. Creates a JSON key in memory and uploads it to CherrySub.

The temporary Play account-level bootstrap permission is removed even when package access fails; a cleanup failure is reported. Existing users' permissions are preserved. Organization policies blocking key creation are surfaced; the CLI does not change those policies. Google OAuth tokens never go to CherrySub.

Existing service-account key:

sh
cherrysub setup google APP_UUID --service-account ./service-account.json

Scripting and profiles

Use --json --no-input --yes with explicit identifiers for unattended setup. Errors go to stderr and return a nonzero exit status. Store credentials are never included in JSON output. auth login --password-stdin --email EMAIL accepts a password via stdin without a password command-line argument.

Supported secret environment variables:

  • CHERRYSUB_PASSWORD: CherrySub sign-in only.
  • CHERRYSUB_APPLE_PASSWORD, CHERRYSUB_APPLE_2FA_CODE: local Apple sign-in.
  • CHERRYSUB_GOOGLE_ACCESS_TOKEN: existing user OAuth access token with cloud-platform and androidpublisher scopes; alternative to browser sign-in.
  • CHERRYSUB_GOOGLE_CLIENT_ID, CHERRYSUB_GOOGLE_CLIENT_SECRET: alternative to the Desktop OAuth client JSON file.

CHERRYSUB_EMAIL and CHERRYSUB_APPLE_ID supply account emails. Avoid shell tracing and putting secret values directly into shell history.

Sessions are private files (0600 on macOS/Linux) in the OS user config directory under cherrysub/. The containing directory is 0700. On Windows use your private user profile directory with its normal account ACLs. CHERRYSUB_CONFIG_DIR overrides the directory. Passwords/store credentials are never saved there.

sh
cherrysub --profile self-hosted --api-url https://api.example.com auth login
cherrysub --profile self-hosted setup apple APP_UUID
cherrysub auth status
cherrysub auth logout

A signed-in profile cannot be retargeted to another API. Use another profile. The CLI rejects credential-bearing redirects and non-HTTPS origins (except literal loopback IPs for development). Profile locks serialize session-scoped project selection; concurrent jobs should sign in to separate profiles. After a hard crash, remove the reported .lock file only when no command is running.

Create new resources:

sh
cherrysub projects create --name "My project"
cherrysub apps create --name "My app" --bundle-id com.example.app --keys-out ./sdk-keys.json

App creation saves the one-time SDK keys to a new private file. It never overwrites an existing file or prints the secret key.

After setup / recovery

credential_saved means CherrySub accepted and encrypted the credential. It does not mean a live purchase or all store permissions have been verified. Notifications (Apple server notifications / Google RTDN) remain a separate step. Use the dashboard setup guide and make a sandbox purchase to verify the complete flow. New Google permissions may need time to propagate.

If upload fails after key creation, the CLI reports the new key's ID, retains old keys, and exits nonzero. Check stores status before retrying because a network timeout can occur after the server commits. Revoke an unused new key in the store console if needed. Newly created Apple keys cannot be downloaded again. CLI tests use local Apple/Google/API fixtures; live account provisioning is performed only when an operator runs setup with their own account.

Each CLI archive includes THIRD_PARTY_NOTICES.md for the MIT-licensed RevenueCat CLI components adapted for local store provisioning.

Catalog and purchase migration

The CLI reads RevenueCat configuration locally, imports portable CSV/JSON files, and lists connected App Store or Google Play products. Every catalog command previews by default; use --apply to apply a reviewed plan. A verified owner/admin session and the selected CherrySub project scope catalog operations.

sh
cherrysub migrate revenuecat APP_ID --source-project RC_PROJECT_ID
cherrysub migrate revenuecat APP_ID --source-project RC_PROJECT_ID --apply
cherrysub migrate store google APP_ID --product premium,credits --apply
cherrysub migrate file ./catalog.json APP_ID --apply
cherrysub migrate history APP_ID

RevenueCat needs a V2 secret key with project-configuration read permissions. Enter it at the masked prompt or use CHERRYSUB_REVENUECAT_API_KEY in automation. --source-app resolves ambiguous source-app matches. --output saves a new private JSON catalog that can be reviewed in the dashboard. --activate-current explicitly selects the source's current offering; leaving it out preserves the destination selection.

The distinct purchase command uses a CherrySub app secret and normal verified receipt ingestion. CHERRYSUB_APP_SECRET selects the app regardless of the dashboard project/app selection. It does not use the hosted session cookie. Preview checks the file locally; applying verifies each purchase server-side and may emit normal webhooks.

sh
cherrysub migrate purchases --template > purchases.csv
cherrysub migrate purchases ./purchases.csv
cherrysub migrate purchases ./purchases.csv --apply --checkpoint ./progress.jsonl
cherrysub migrate purchases ./purchases.csv --apply --resume --checkpoint ./progress.jsonl

Use real StoreKit 2 JWS transactions or Google purchase tokens and retain exact App User IDs. Checkpoints bind the file, API origin, and app secret and contain no plaintext receipt/token or user identity. Completed records are skipped on resume. Do not modify the input file to fix a rejected row while reusing its checkpoint; use a separate corrected file and checkpoint. The complete migration guide covers source formats, Google base-plan policy, limits, failure recovery, and cutover validation.