Skip to content
Deployment
Skill

/flame-harness-build

Phase 8 — bootstrap signing credentials, generate fastlane config from templates, and build + upload signed IPA (TestFlight) and AAB (internal track).

From plugin
flutter-flame-harness
6014 skills1 hook
Install
$ npx -y skills add tjdrhs90/flutter-flame-harness --skill flame-harness-build --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/flame-harness-build

Context preview

The summary Claude sees to decide when to auto-load this skill.

Phase 8 — bootstrap signing credentials, generate fastlane config from templates, and build + upload signed IPA (TestFlight) and AAB (internal track).

SKILL.md

flame-harness-build.SKILL.md
name: flame-harness-build
description: Phase 8 — bootstrap signing credentials, generate fastlane config from templates, and build + upload signed IPA (TestFlight) and AAB (internal track).
argument-hint: ""
allowed-tools: [Read, Write, Edit, Bash, Glob]

flame-harness-build

Phase 8 of the flutter-flame-harness pipeline. Bootstraps signing credentials into the generated game, generates fastlane config from the Task 3 templates, then builds and uploads a signed IPA to TestFlight and a signed AAB to the Play Store internal track.

All file schemas (`config.md`, `state.md`, `pipeline-log.md`) and the phase transition table are defined in `docs/harness-protocol.md` — that document is the single source of truth (§1 for `config.md` including `credentials_dir`, `ios`, and `android` blocks; §2 for `state.md`; §6 for log schemas; §7 for the `build → screenshot` transition and the `status: running` rule). Do not redefine schemas here.

**Prerequisites:** An App Store Connect app record and a Google Play Console app must already exist (created once manually). The upload lanes will fail without them. Fastlane and Ruby must be installed on the developer's macOS machine (Xcode and the flutter CLI are assumed present).

---

Input — Read Inputs

Before any action, load:

1. `docs/harness/config.md` — extract `app_slug`, `bundle_id`, `app_name`, and `credentials_dir` (per protocol §1). Also read `ios.asc_key_id` and `android.key_alias`. 2. `docs/harness/state.md` — confirm `next_role: build` (per protocol §2).

Derive the game root path: `<projects-dir>/<app_slug>/`.

---

Phase 1 — Credential Bootstrap

Copy signing credentials from the shared `credentials_dir` (per protocol §1 — skills must not hard-code credential paths; always read `credentials_dir` from `config.md`) into the game's platform directories.

iOS credentials

mkdir -p <game>/ios/fastlane/certs
cp <credentials_dir>/AuthKey_<asc-key-id>.p8 <game>/ios/fastlane/

The `.p8` filename encodes the ASC key ID from `config.md` `ios.asc_key_id`. The `certs/` directory holds the downloaded distribution certificate and provisioning profile (written by `fastlane certs`).

Android credentials

mkdir -p <game>/android/fastlane
cp <credentials_dir>/play-store-key.json <game>/android/fastlane/

Android keystore

Check whether `<credentials_dir>/upload-keystore.jks` exists.

  • **If it exists:** copy it.
  cp <credentials_dir>/upload-keystore.jks <game>/android/upload-keystore.jks
  • **If it is missing:** generate a new keystore with `keytool`. Use the alias and password

defined in `config.md` `android.key_alias` (default: `upload`). Store and key passwords are both `<keystore-password>`.

  keytool -genkey -v \
    -keystore <game>/android/upload-keystore.jks \
    -alias upload \
    -keyalg RSA -keysize 2048 -validity 10000 \
    -storepass <keystore-password> -keypass <keystore-password> \
    -dname "CN=<company>, OU=Dev, O=<company>, L=Seoul, S=Seoul, C=KR"

android/key.properties

Write `<game>/android/key.properties` by substituting the `templates/key.properties.template` values (placeholders are already concrete — the template uses literal values matching the keystore generated above):

storePassword=<keystore-password>
keyPassword=<keystore-password>
keyAlias=upload
storeFile=upload-keystore.jks

The `storeFile` path is relative to the `android/` directory, which is where Gradle reads it.

---

Phase 2 — Fastlane Config Generation

Generate fastlane `Appfile` and `Fastfile` for both platforms by substituting the following placeholders in the templates located at `templates/fastlane/`:

| Placeholder | Value | |---|---| | `__APP_ID__` | `bundle_id` from `config.md` | | `__PACKAGE__` | `bundle_id` from `config.md` | | `__IPA_NAME__` | `<app_name>.ipa` (spaces allowed; use the value of `app_name` verbatim) | | `__PROFILE_NAME__` | `<bundle_id> AppStore` (e.g. `com.<company>.mygame AppStore`) |

Note: `__PROFILE_NAME__` is used both as the Xcode code-signing profile name and as the `.mobileprovision` filename (with `.mobileprovision` appended by fastlane). Spaces are acceptable.

iOS fastlane

mkdir -p <game>/ios/fastlane/certs
# Write Appfile
sed -e 's/__APP_ID__/<bundle_id>/g' \
    templates/fastlane/ios-Appfile.template \
    > <game>/ios/fastlane/Appfile
# Write Fastfile
sed -e 's/__APP_ID__/<bundle_id>/g' \
    -e 's/__IPA_NAME__/<app_name>.ipa/g' \
    -e 's/__PROFILE_NAME__/<bundle_id> AppStore/g' \
    templates/fastlane/ios-Fastfile.template \
    > <game>/ios/fastlane/Fastfile

Android fastlane

mkdir -p <game>/android/fastlane
# Write Appfile
sed -e 's/__PACKAGE__/<bundle_id>/g' \
    templates/fastlane/android-Appfile.template \
    > <game>/android/fastlane/Appfile
# Write Fastfile
sed -e 's/__PACKAGE__/<bundle_id>/g' \
    templates/fastlane/android-Fastfile.template \
    > <game>/android/fastlane/Fastfile

After substitution, verify with `grep '__' <game>/ios/fastlane/Appfile <game>/ios/fastlane/Fastfile <game>/android/fastlane/Appfile <game>/android/fastlane/Fastfile` — output must be empty (no unresolved placeholders).

---

Phase 3 — Build and Upload

Run all build commands from the game root (`<projects-dir>/<app_slug>/`).

Pre-build platform requirements

Before building, ensure the platform items in `docs/game-gotchas.md` (Build/platform + Store rejections) are in place — these are submit-blockers if missing: iOS `PrivacyInfo.xcprivacy` registered (iOS 17+), Android `minSdk = 23` + core-library desugaring, iOS `Podfile` platform bumped, `Info.plist` ATT + `SKAdNetworkItems`, and `ITSAppUsesNonExemptEncryption = false` (skip the export-compliance prompt). **Bump the build number on every upload** — App Store Connect rejects a duplicate build number, so increment it (don't reuse `1`).

**Re-run / resume safety (store uploads are NOT idempotent):** if this phase is re-entered after a pa

Read more
Ships withflutter-flame-harness

A Claude Code plugin that takes a Flutter/Flame game from raw idea all the way to the app stores.

Get the whole plugin
Stats
60
Stars
5
Forks
Active
Maintenance
Shell
Language
MIT
License
14d ago
Last commit
2mo ago
Created

Repo: tjdrhs90/flutter-flame-harness

Other skills on flutter-flame-harness.