Skip to main content

torchinlane 0.4.0 copy "torchinlane: ^0.4.0" to clipboard
torchinlane: ^0.4.0 copied to clipboard

Flutter release CLI and local GUI for builds, localized store texts/images, release notes, credentials, signing, and GitHub Actions automation.

torchinlane #

A global Dart CLI and local browser GUI for Flutter releases. Build and upload apps, manage localized App Store/Google Play texts and images, translate release notes, import credentials, configure signing, and generate GitHub Actions CI.

Torchinlane runs outside your Flutter application. No widget, runtime SDK, Node.js installation, or hosted service is needed for Studio.

Install and upgrade #

Requirements: Dart ^3.5.0, a Flutter project with pubspec.yaml, ios/ and android/, Ruby/Fastlane, and macOS/Xcode for iOS builds. Use a current Fastlane release; newer Apple locales and Google OAuth credential support depend on it. CocoaPods is required for iOS plugins. doctor --fix installs/repairs the gems.

dart pub global activate torchinlane
# Add ~/.pub-cache/bin to your PATH if needed.

For development or a local checkout:

dart pub global activate --source path /path/to/torchinlane

Upgrade the CLI and update each previously initialized Flutter project. Upgrading the package alone does not regenerate existing Fastfiles.

dart pub global activate torchinlane
cd /path/to/flutter_app
torchinlane update --dry-run
torchinlane update -y

update backs up changed generated files as .bak and preserves your config, store content, release notes and ExportOptions. New generated helpers are fastlane/StoreHelper.rb and fastlane/locales.json; do not edit the registry in generated Ruby. See migration.

Start with the GUI #

Run inside your Flutter project:

torchinlane studio

Studio opens an authenticated, loopback-only local panel. Keep the terminal open; Ctrl+C stops it. --no-open prints the URL, and --port 8787 selects a port. Copy the complete URL, including its session fragment, when opening a second browser tab.

Studio opens a readiness overview in Turkish or English. Use the header Arayüz dili / Interface language selector to switch instantly. The choice is remembered across restarts; first-time selection follows your browser language. Switching the interface does not translate your store text, change source/target locales, or discard unsaved edits. Native tool logs keep their original language. Select App Store, Google Play, or both. It detects existing files and tells you which steps are complete, which checks have not run, and what can be skipped. No setup is repeated merely because you opened the panel.

  1. Setup / Kurulum: existing values are loaded. Save only changed/missing settings. Valid credential files are recognized; import controls collapse when a file is present. Live access is a separate check, remembered for this server session and invalidated when credentials/app identity change.
  2. Texts / Metinler: open the configured source language and write app texts and release notes. Common fields can be copied from the other store into empty fields. Existing texts can be left alone. Advanced fields are collapsed.
  3. Translation / Çeviri: add target languages, click Çeviri görevini hazırla, then Görevi kopyala. Paste into Claude Code/Codex working in the Flutter project. When finished, click Sonuçları yükle ve kontrol et. Counts show missing fields; completed translations can be skipped. No translation API key is required. Paid API and overwrite options remain under advanced details.
  4. Images / Görseller: add files per language/device, only if replacing or adding images. Existing remote images do not need to be re-imported.
  5. Upload / Gönder: the default is app metadata only. Check the upload plan, then send content. Google version/track fields appear when notes are selected. Building/uploading a new app binary is a separate collapsed section.

Read the English quick start or Turkish step-by-step quick start. You can prepare content without store credentials, Ruby/Fastlane, or native signing. Before upload, check account access and tools in Setup. Imzalama (signing) matters for new app builds, not metadata-only upload. Tool checks do not install anything; repair is an explicit action. Existing signing files are only evidence of setup, not proof that a release build will succeed. Optional API translation requires ANTHROPIC_API_KEY; it is not part of the default translation workflow.

Studio never sends credentials to a hosted Torchinlane backend. Credentials remain on the local machine. Agent tasks are generated locally; you choose which coding agent receives the metadata. Optional API translation sends text to Anthropic; store operations connect to Apple/Google. The local panel blocks foreign origins and concurrent edits while a job runs.

Torchinlane Studio guided readiness overview

Initialize from terminal or CI #

torchinlane init                     # interactive setup + tool checks
torchinlane init --skip-tools        # scaffold without installing gems
torchinlane init --config /path/to/prepared.yaml --skip-tools

init reads the bundle ID and Team ID from the Xcode project and the package name from Gradle, so Enter accepts them. It asks which languages you write release notes in, then offers to run credentials setup (below), which creates the store keys for you. The --config form avoids stdin prompts and keeps all supplied configuration. --force allows replacing an existing initialization. Store content and existing ExportOptions are preserved. You can use Studio before init to complete setup.

Localized texts and images #

torchinlane store locales --platform ios,android
torchinlane store init --locales en,tr,de,pt-PT,zh-Hant
torchinlane store init --locales all   # explicitly opt into all store locales

Files use native store locale codes, with separate platform content:

store/
  ios/
    en-US.json
    tr.json
    images/tr/iphone/01-home.png
    images/tr/ipad/01-home.png
  android/
    en-US.json
    tr-TR.json
    images/tr-TR/phoneScreenshots/01-home.png
    images/tr-TR/featureGraphic/banner.png
    images/tr-TR/icon/icon.png

Example Google text file:

{
  "title": "My App",
  "short_description": "Plan your day with ease.",
  "full_description": "A longer description of the app's actual features.",
  "release_notes": "Improved reminders and fixed calendar issues."
}

Apple fields: name, subtitle, description, keywords, promotional_text, support_url, marketing_url, privacy_url, release_notes. Google fields: title, short_description, full_description, video, release_notes.

Blank fields are omitted from uploads, preserving existing remote text. Long text is rejected instead of truncated. Images are checked for format, dimensions, transparency and count. These checks do not replace store review or all device-specific promotional eligibility rules.

Instead of editing dozens of locale files, write one file per language and let torchinlane fill every Apple and Google locale of it (en → en-US, en-GB, en-AU, … on both stores; es → es-ES, es-MX, es-419, es-US; zh-Hant → zh-Hant, zh-TW, zh-HK):

store/
  listing/
    en.json        # name, subtitle, short_description, description, keywords,
    de.json        # promotional_text, tagline, screenshots[], URLs (en only)
  screenshots/     # rendered images, gitignored
    de/iphone/01.jpg   ipad/  play/  feature/
torchinlane store languages   # the 72 language codes and the locales each fills
torchinlane store generate    # listing/*.json → ios/*.json + android/*.json

name → Apple name + Google title; description → Apple description + Google full_description; subtitle, keywords, promotional_text → Apple; short_description → Google. support_url, marketing_url, privacy_url, video come from the source language unless a language sets its own. tagline and screenshots (headlines) are for screenshot generators and are never uploaded. Release notes: when the source language has notes for the pubspec version (see Release notes), each locale gets its language's notes (a language without them loses old notes); otherwise release notes stay untouched. Changelog folders use these language codes (pt-BR, not pt): deploy and store validate stop when two folders feed one store locale. Nothing is written when any value breaks a store limit.

Rendered screenshots in store/screenshots/<language>/<kind>/ are used for every locale of that language that has no own images/<locale>/<group>/ folder: iphone → Apple iphone, ipad → Apple ipad + Google 7″/10″ tablet, play → Google phone (Google rejects images longer than 2:1, so the 6.9″ iPhone size cannot be reused), feature → Google feature graphic.

# Print a task to paste into Claude Code/Codex (no API request):
torchinlane store translate --from en --locales tr,de,pt-PT
# Same task; without --locales, use locales already added under store/:
torchinlane store prompt --from en
# Optional direct API translation, potentially separately billed:
torchinlane store translate --api --from en --locales tr,de,pt-PT
torchinlane store validate
torchinlane store export --output build/store-export
torchinlane store push --scope metadata --dry-run
torchinlane store push --scope metadata
torchinlane store push --scope images --platform ios,android
torchinlane store push --scope notes --track production --version-code 42 --app-version 1.2.0
torchinlane store push --version-code 42 --app-version 1.2.0

--scope is all (default), metadata, images or notes. Google note-only updates require an existing --version-code on the chosen --track; supplied notes are merged with existing locales and release status is preserved. Apple changes target an editable version; --app-version selects its version string. Store uploads do not upload binaries, submit Apple review or change Google rollout status.

Google synchronizes each supplied screenshot group; omitted groups are preserved. Apple adds screenshots by default. --replace-images clears all existing screenshot device sets for supplied Apple locales, then uploads the local set. Include every device set you want to retain for those locales.

torchinlane store pull                         # save snapshot and report differing fields
torchinlane store pull --platform ios --app-version 1.2.0
torchinlane store pull --apply                 # import remote text with .bak backups

Pull downloads text metadata, not screenshot files. Apple notes are included; Google pull downloads listing text, not track-specific release notes. Snapshots are stored in gitignored store/.snapshots/. See store content reference for image groups, locale policy, field limits and first-release prerequisites.

Store access in one command #

torchinlane credentials setup                    # both stores
torchinlane credentials setup --platform android
torchinlane credentials setup --apple-id you@example.com --developer-id 1234567890123456789

App Store Connect. Give the Apple ID of an Account Holder or Admin. Fastlane asks for its password and the two-factor code (the password is not stored). Torchinlane then creates a team API key (role App Manager; --apple-role admin if signing sync --write should create certificates), downloads the .p8, saves it with mode 0600 and writes the Key ID and Issuer ID into torchinlane.yaml. This uses the same App Store Connect web requests as the "Generate API Key" button, which Apple does not document; if it fails, setup switches to a guided download: it opens the keys page, picks up AuthKey_<KEYID>.p8 from ~/Downloads as soon as you download it, reads the Key ID from the file name and asks only for the Issuer ID. --key-file imports a key you already have. The Account Holder must enable API access once ("Request Access") before any key can be created.

Google Play. Needs the Google Cloud CLI (brew install --cask gcloud-cli). One browser sign-in with the Google account that owns the Play Console developer account, then torchinlane:

  1. creates a Google Cloud project (or uses --project-id / the saved one),
  2. enables the Google Play Android Developer API,
  3. creates the torchinlane service account and its JSON key and imports it,
  4. invites the service account to Play Console with release and store-listing permissions for this app only,
  5. saves gcp_project_id and play_developer_id, revokes the sign-in and checks app access.

The Play API cannot list developer accounts, so the first run asks you to paste any Play Console address (it contains /developers/<ID>/); --developer-id skips the question. The sign-in uses a temporary gcloud configuration; your own gcloud login and Application Default Credentials are not changed. An existing service account key is reused. The app must already exist in Play Console. If the invite is refused (for example you are not an admin of the developer account), setup prints the one Play Console step to do by hand. New permissions can take a few minutes before credentials verify passes. Organizations that block service account keys need keyless CI (bootstrap-google --repository, below).

Credentials and signing #

torchinlane credentials import --platform ios --file /path/AuthKey_KEYID.p8
torchinlane credentials import --platform android --file /path/google.json
torchinlane credentials verify --platform ios,android
torchinlane doctor --platform android --verify-credentials

Use --profile company on import to store a reusable credential outside the project, at ~/.torchinlane/credentials/company/. The config records its absolute path; use a different profile name to rotate a key. Existing different keys are not silently overwritten. Do not commit a machine-specific config path if other machines should use the default; CI can override credential paths.

Environment overrides: ASC_KEY_PATH, ASC_KEY_ID, ASC_ISSUER_ID and GOOGLE_APPLICATION_CREDENTIALS. Google service account and external-account (WIF) JSON are supported. OAuth authorized_user JSON needs a current Fastlane version with that credential type; Torchinlane does not create an OAuth client or consent screen for you.

Google Cloud bootstrap uses your existing gcloud login and permissions:

gcloud auth login
torchinlane credentials bootstrap-google --project-id my-cloud-project --dry-run
torchinlane credentials bootstrap-google --project-id my-cloud-project --create-key
# Keyless GitHub CI:
torchinlane credentials bootstrap-google --project-id my-cloud-project --repository OWNER/REPO

It enables APIs, creates/reuses a service account and optionally imports a JSON key or creates repository-restricted WIF. The Cloud project must already exist. Run credentials setup --platform android afterwards to invite the service account to Play Console.

An Apple .p8 is not a signing certificate. Automate certificate/profile setup with an encrypted private match repository:

export MATCH_PASSWORD='your repository encryption password'
torchinlane signing sync --git-url git@github.com:company/ios-certificates.git --write
# Later machines/CI install existing identities without changing the repository:
torchinlane signing sync --git-url git@github.com:company/ios-certificates.git

This installs profiles, configures Release/Profile signing in Runner.xcodeproj and updates ExportOptions to manual signing with the installed profile. Local project/export files receive .bak backups. Requires macOS, private repository access, appropriate Apple API permissions and a valid developer membership. Custom targets/flavors need their own signing configuration.

For Android, reuse the app's existing upload keystore:

export KEYSTORE_PASSWORD='...'
export KEY_PASSWORD='...'
torchinlane signing android --keystore /path/upload-keystore.jks --alias upload

This copies the keystore to gitignored .torchinlane/, writes protected android/key.properties, and replaces the stock Flutter debug-signing placeholder in Groovy/Kotlin Gradle with release signing. Existing custom signing blocks are preserved; unsupported layouts produce an actionable error. The command imports an existing key; it does not create/replace a published app's signing identity. Passwords are read from environment variables, not CLI arguments. More: automation and signing.

Build and deploy #

torchinlane deploy --platform ios,android --target internal
torchinlane deploy --platform ios,android --target production --with-store
torchinlane deploy --platform android --upload-only --with-store
torchinlane deploy --dry-run --with-store

Live app access is checked before building (skip with --skip-credential-check when CI already verified it). Android/iOS run independently; failures are reported per platform. --with-store validates local store content before building and uploads it after binary uploads. The Flutter pubspec.yaml version selects the Apple version and Google version code. Store JSON notes, when supplied, override legacy changelog notes for the same release. --skip-release-notes skips both sources of release notes.

Flag Behavior
--platform ios, android, or ios,android
--target internal (default) or production
--upload-only Reuse existing AAB/IPA
--skip-clean Skip Flutter clean/pub get
--skip-credential-check Skip the automatic pre-build live app-access check
--deep-clean Remove native build caches before building
--skip-release-notes Upload without release notes
--with-store Upload saved store content after binaries
--release-status Google draft (default), completed, or inProgress
--rollout Fraction between 0 and 1, required with inProgress
--dry-run Print/validate commands without uploading/building

Draft Google builds are not served to testers or users. For an automated internal release or production rollout, explicitly select the serving status:

torchinlane deploy --platform android --target internal --release-status completed
torchinlane deploy --platform android --target production --release-status inProgress --rollout 0.1

Google reviews/account restrictions can still apply. Apple production uploads remain unsubmitted (submit_for_review: false, automatic_release: false); submit the final version through App Store Connect. TestFlight uploads attach localized What to Test text and wait for processing when notes are supplied (up to 30 minutes); tester assignment and external beta review remain Apple requirements.

Release notes #

torchinlane changelog languages en,tr,de   # choose the languages (once)
torchinlane changelog new                  # changelogs/<language>/<version>.txt for this version
torchinlane changelog translate --from en  # optional, needs ANTHROPIC_API_KEY

Only the languages in changelogs.locales get folders, and only for the pubspec version you are shipping. For version: 1.2.0+42 the notes file is changelogs/<language>/1.2.0.txt; a 1.2.0+42.txt wins when both exist, so a build-only bump keeps its notes. Notes of other versions are never uploaded. Write the whole file as the notes (- bullets work well); empty files ship no notes. Emoji are removed from App Store and TestFlight notes automatically (App Store Connect rejects them) and kept for Google Play. scripts/build.sh runs changelog new and waits until you type ok.

Project layout torchinlane expects #

torchinlane.yaml
changelogs/<language>/<version>.txt           # this version's notes; <language> = a store/listing code
store/listing/<language>.json                 # one store text per language
store/screenshots/<language>/<iphone|ipad|play|feature>/
store/ios/*.json, store/android/*.json        # written by `store generate`; do not hand-edit
fastlane/, ios/fastlane/, android/fastlane/   # managed; refresh with `torchinlane update -y`

Use the torchinlane store languages codes for changelog folders too (pt-BR, zh-Hans, fil; not pt, zh, tl).

Checks that run before anything is uploaded #

Each one stops a problem that the stores would otherwise reject after the upload (Apple then counts the build number as used):

  • Two changelogs/ folders that feed one store locale, or notes over the limit (deploy, deploy --dry-run, store validate).
  • Emoji in Apple release notes: they are removed for App Store/TestFlight (also from store/ios/*.json on store push) and kept for Google Play.
  • Missing Info.plist purpose strings (ITMS-90683): after flutter build ipa, the app and every framework are scanned for Photos, camera, location, contacts, calendar, Bluetooth, motion, health, speech and media-library APIs. A dependency's unused picker is enough to trigger it: add the purpose string or switch that code off (e.g. Pod::PICKER_MEDIA = false for file_picker).
  • fastlane older than 2.234.0 when store/ios holds Apple's newer locales (bn-BD, gu-IN, kn-IN, ml-IN, mr-IN, or-IN, pa-IN, sl-SI, ta-IN, te-IN, ur-PK).
  • An App Store version named anything but X.Y.Z (e.g. 2.0.0 + 13) gets a clear message instead of a crash.

Google store uploads commit in small edits (texts, 8 locales of images at a time, notes), so a long upload cannot expire and a rerun skips committed images. store push --replace-images on Apple uploads only new or changed screenshots when every App Store localization with screenshots also has local images; otherwise it replaces them all.

The generated sh scripts/build.sh remains available for terminal-guided build/version/release-note prompts. Release notes are retained after successful upload for audit and retry; changelog clear empties this version's notes.

Generate GitHub Actions #

torchinlane ci init --platform android
torchinlane ci init --platform ios,android \
  --wif-provider projects/123/locations/global/workloadIdentityPools/torchinlane-github/providers/github-ID \
  --service-account torchinlane@my-cloud-project.iam.gserviceaccount.com \
  --signing-git-url git@github.com:company/ios-certificates.git

Generates .github/workflows/torchinlane.yml with manual dispatch, independent platform jobs, tool setup, credential restoration, signing, app-access checks and optional store upload. The package version is pinned to the installed CLI version for reproducible activation. Local development versions must be published first or use a private/local source installation. Use --flutter-version to pin Flutter; stable is the default. Existing workflows need --force and receive backups. Set up secrets as described in automation. The generated iOS job deliberately requires a signing repository or your own signing step.

Existing commands #

torchinlane bump patch               # major/minor/patch/build
torchinlane changelog push --platform android --track production --version-code 42
torchinlane changelog push --platform ios --app-version 1.2.0
torchinlane changelog clear
torchinlane screenshots capture --platform ios --locale tr
torchinlane screenshots prompts
torchinlane doctor --fix
torchinlane uninstall --yes

A notes folder whose language a store does not support is reported and skipped. Duplicate folders mapping to the same store locale fail explicitly. Google/Apple notes have separate 500/4000 character validation.

Screenshot capture is interactive and captures the current app screen; --locale labels the output, it does not switch the app's language. Android capture now reads binary PNG output correctly. Prompts produce Markdown, not finished artwork. Fully automatic navigation/capture requires app-specific integration/UI tests and is not generated by this package.

Only optional store translate --api, legacy changelog translate and AI screenshot prompts use ANTHROPIC_API_KEY and the configurable TORCHINLANE_AI_MODEL (default claude-sonnet-4-6). Translation outputs are checked for complete fields and character limits. Failed translations do not write invalid content. Translation is optional; manually authored content requires no AI key. Agent task generation also requires no AI key or network. Agent usage follows the chosen tool’s own subscription and limits.

uninstall removes the generated Fastlane/config/build wrapper/ExportOptions; changelogs/, store/, signing files and generated CI workflows remain yours.

Configuration #

app_name: "My App"
ios:
  bundle_id: "com.example.app"
  team_id: "ABCDE12345"
  itc_team_id: "" # optional App Store Connect provider ID
  apple_id: "dev@example.com"
  asc_key_id: "KEYID"
  asc_issuer_id: "issuer-uuid" # empty for individual API keys
  asc_key_path: "ios/fastlane/api_key.p8"
  firebase_crashlytics: false
  firebase_app_id: ""
android:
  package_name: "com.example.app"
  service_account_json: "android/fastlane/fastlane-service-account.json"
  firebase_app_id: ""
  gcp_project_id: "torchinlane-a1b2c3"     # written by credentials setup
  play_developer_id: "1234567890123456789" # written by credentials setup
changelogs:
  dir: "changelogs"
  source_locale: "en"
  locales: [en, tr, de]   # release note languages; unknown codes are rejected
build:
  obfuscate: true
  split_debug_info: "build/debug-info"

Config contains IDs and paths, not key contents. Strings are quoted on render to preserve names containing colons and numeric-looking IDs. Credential paths are honored by all generated lanes; CI environment overrides take precedence. screenshots settings in older configs are reserved; current capture uses the screenshots/ directory and connected/booted devices.

Verification #

dart analyze
dart test

Tests cover locales, partial-content preservation, Unicode limits, image validation, translation failures, credentials, signing/CI generation, GUI HTTP flows, and generated Ruby/shell behavior. They do not perform authenticated live store uploads; the Apple and Google setup calls are tested against recorded API shapes, not live accounts.

MIT license.

1
likes
160
points
997
downloads
screenshot

Documentation

API reference

Publisher

verified publishertorchingale.com

Weekly Downloads

Flutter release CLI and local GUI for builds, localized store texts/images, release notes, credentials, signing, and GitHub Actions automation.

Repository (GitHub)
View/report issues

Topics

#flutter #fastlane #cli #deployment #app-store

License

MIT (license)

Dependencies

args, http, image, path, yaml, yaml_edit

More

Packages that depend on torchinlane