Skip to content
Development
Skill

/mobile-release

Ship an iOS or Android build to testers and stores without reusing a build number or shipping an OTA bundle that crashes on launch. Covers version and build-number policy, code signing done by the project's own tooling, TestFlight / Play internal / Firebase uploads, Maestro on

From plugin
great-cto
11537 skills73 agents21 commands1 hook

Claude Code

$ npx -y skills add avelikiy/great_cto --skill mobile-release --agent claude-code

SKILL.md

mobile-release.SKILL.md
name: mobile-release
description: Ship an iOS or Android build to testers and stores without reusing a build number or shipping an OTA bundle that crashes on launch. Covers version and build-number policy, code signing done by the project's own tooling, TestFlight / Play internal / Firebase uploads, Maestro on the uploaded build, phased rollout and halt, OTA runtime compatibility, and the store hand-off. Use for any mobile release step ("собери сборку для тестировщиков", "выложи во внутренний трек", "подними номер сборки", "обнови по воздуху", "отправь в стор"). Loaded by release-manager.
when_to_use: |
  Apply when:
  - building a signed iOS or Android binary meant for anyone other than the developer
  - bumping a version, versionCode or CFBundleVersion
  - uploading to TestFlight, Play Console, Firebase App Distribution, or publishing an OTA update
  - preparing a store submission or changing a phased rollout
  Do NOT apply to:
  - a debug build on a simulator or emulator for development
  - store-policy questions (privacy labels, IAP rules) — that is mobile-store-reviewer
effort: medium
allowed-tools: Read, Bash, Grep

mobile-release — the binary testers get is the commit CI checked, signed by tooling, numbered once

A mobile release has three mistakes that cannot be taken back: a build number the store has already seen, a key that left its store, and an update pushed to phones that cannot run it. Everything below exists to make those three impossible, not unlikely.

1. Version and build number

| Field | iOS | Android | Rule | |---|---|---|---| | Marketing version | `CFBundleShortVersionString` / `MARKETING_VERSION` | `versionName` | from the release (semver), the same on both platforms | | Build number | `CFBundleVersion` / `CURRENT_PROJECT_VERSION` | `versionCode` | **strictly increasing, never reused, set by script** |

  • Read the highest build number the store already has before bumping, not the one in the

repo: `fastlane` `latest_testflight_build_number` / `google_play_track_version_codes`, or `eas build:version:get`. The repo can be behind a build someone uploaded by hand.

  • New build number = max(store, repo) + 1. A Play `versionCode` that was uploaded once is

burned even if that build was deleted; Play rejects it forever.

  • Commit the bump with the release (`chore(release): <version> (<build>)`), then build

**that** commit. A build from an uncommitted bump cannot be traced back.

  • Expo with `appVersionSource: remote`: EAS owns the counter; do not also edit native files.

2. Signing — through tooling, never by hand

The agent never opens, prints, copies, moves, base64-encodes or uploads a signing key, keystore, `.p8`, `.p12`, `.jks`, provisioning private key or their passwords. A key that appears in any output is compromised: stop and follow `secrets-rotation`.

| Platform | Where the key lives | What the agent runs | |---|---|---| | iOS | fastlane `match` repo, Xcode automatic signing, EAS credentials | `fastlane match <type> --readonly`, `xcodebuild -allowProvisioningUpdates`, `eas build` | | Android | Play App Signing (upload key), EAS-managed signing, the CI secret store | `./gradlew bundleRelease` with signing config read from env/keystore properties the operator set up |

Allowed metadata checks: `security find-identity -v -p codesigning` (lists identities, not keys), `keytool -list -v -keystore … ` **only if the operator types the password**; `apksigner verify --print-certs` on the built artifact. If signing fails, report the tool's error and stop — do not create, rotate or export credentials; that is the operator's step.

`--readonly` on `match` always: a non-readonly run can revoke and recreate certificates for the whole team.

3. Build

  • Build from a clean tree at the commit CI checked (`git status --porcelain` empty). The

build packs the directory, not HEAD.

  • iOS: `xcodebuild archive` + `-exportArchive` with an `ExportOptions.plist` from the repo,

or the project's fastlane lane, or `eas build --platform ios --profile production`.

  • Android: `./gradlew bundleRelease` (AAB for Play), `assembleRelease` only for Firebase /

direct APK; or `eas build --platform android`.

  • Record: artifact path, size, SHA-256, build number, commit. `bundletool dump manifest`

/ `PlistBuddy` on the artifact proves the number inside equals the number you set.

  • Use the project's pinned tool versions (`Gemfile.lock` → `bundle exec fastlane`,

`npx eas-cli@<pinned>`), not a global install.

4. Distribute to internal testers (no gate)

| Channel | Command shape | Done when | |---|---|---| | TestFlight internal group | `fastlane pilot upload` / `xcrun altool --upload-app` / `eas submit -p ios` | build shows **Processed** in App Store Connect, not just "uploaded" | | Play internal track | `fastlane supply --track internal` / `eas submit -p android` | release on `internal` with this `versionCode`, status completed | | Firebase App Distribution | `firebase appdistribution:distribute <apk/aab> --groups <internal>` | release id returned |

Before each upload `mobile-store-reviewer` re-checks policy (permission strings, privacy manifest, IAP). Its BLOCK stops the upload.

5. E2E on the uploaded build

Maestro runs against the build testers got — installed from the TestFlight / Play internal / Firebase artifact on a simulator or device — **not a fresh local rebuild**. Rebuilding per run costs time and proves a different binary.

  • Flows live in the project (`e2e/flows/`, `.maestro/`); run with `maestro test <dir>`.
  • On failure read the per-step screenshots before re-running.
  • iOS simulator cannot install a TestFlight build; use the exported `.app` from the same

archive (same build number, same commit) and say so in the report.

6. Beyond internal testers — after `gate:release` only

External TestFlight groups, Play closed/open/production tracks, App Store submission and any increase of a staged rollout reach real users and are slow or impossible to rev

Read more
@avelikiy
Ships withgreat-cto

You already have the agent. This is everything around it. great_cto runs Claude Code as a pipeline of 70 specialist agents — an independent model checks each stage before the next builds on it, spending caps refuse rather than warn, and three decisions stay yours: what gets built, how, and whether it ships.

11537 skills73 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
115
Star history of avelikiy/great_cto on GitHub, a chart by star-history.com

Other skills on great-cto.

aesthetic-instrument

aesthetic-instrument

great_cto's own committed aesthetic — the instrument panel. Dark five-step surface ladder, exactly one accent, two faces divided…

@avelikiy@avelikiyInstall Skill
anti-patterns

anti-patterns

Catalogue of known SDLC anti-patterns that great_cto agents must actively reject when reviewing architecture, plans, code, or…

@avelikiy@avelikiyInstall Skill
anydesign

anydesign

Analyze images, websites, and Figma files to extract their design and generate a `design.md` with token system, component…

@avelikiy@avelikiyInstall Skill
archetype-review-base

archetype-review-base

Shared review framework that every domain reviewer (pci, oracle, gov, edtech, healthcare, mlops, etc.) MUST follow. Defines the…

@avelikiy@avelikiyInstall Skill
artifact-retention

artifact-retention

After a build is delivered, delete its intermediate copies and old versions — keep exactly the version that runs and one previous…

@avelikiy@avelikiyInstall Skill
brainstorming

brainstorming

Structured idea generation + multi-LLM debate for the product-owner stage. Diverge (generate genuinely different bets), debate (a…

@avelikiy@avelikiyInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about mobile-release.

Which coding agents can use mobile-release?
mobile-release installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.