AI agent that builds, signs, and ships Flutter apps — APK/AAB/IPA — from the terminal
Project description
🚀 FlutterShip
An AI agent that builds, signs, and ships your Flutter app — APK, App Bundle, and IPA — from one terminal. Talk to it in plain English.
fluttership "build apk aab ipa for DEV and LIVE"
One command. Parallel builds. No forgotten version bumps, no wrong keystore passwords, no babysitting.
Table of contents
- What is FlutterShip?
- Quick start (free — uses a Gemini API key)
- How you actually use it
- Command reference
- ⚡ Parallel builds
- 🔐 The secure vault
- 📦 Publishing to the stores (what you need to download)
- 👤 Solo vs 👥 Team mode
- Requirements
- Security model
- License
What is FlutterShip?
FlutterShip is a Python CLI with an AI agent at its core. You point it at your Flutter project and tell it what you want — "build a LIVE apk", "release 2.0.0 to TestFlight" — and it does the rest:
- Reads your project automatically — version, flavors,
dart-definekeys, bundle id, signing config. No config file to write. - Detects your build pattern — flavors,
--dart-define,--dart-define-from-file, or plain. It figures out the rightflutter buildcommand for you. - Builds in parallel — APK + AAB + IPA across multiple flavors at once, each in an isolated sandbox.
- Signs and submits — uploads AAB to Google Play and IPA to TestFlight/App Store, with credentials kept in an encrypted vault the AI never sees.
- Explains failures in plain English — when a build breaks, it reads the log and tells you exactly what to fix.
- Keeps a release history — every build and upload is logged outside your repo.
You can drive it conversationally (the agent decides which tools to run) or with plain
subcommands (fluttership doctor, fluttership status, …).
Quick start
FlutterShip needs an LLM API key to power the agent. The easiest free option is Google Gemini — the free tier is plenty for normal use.
1. Get a free Gemini API key
- Go to aistudio.google.com and sign in.
- Click Get API key → Create API key.
- Copy the key (looks like
[YOUR_GEMINI_API_KEY]).
Prefer Claude or GPT? FlutterShip also supports
anthropic(console.anthropic.com) andopenai(platform.openai.com). Pick your provider during setup.
2. Install FlutterShip
pip install fluttership
That's it — the fluttership command is now on your PATH.
Install from source (for development)
git clone https://github.com/AscEmon/fluttership.git
cd fluttership
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
3. First run — the setup wizard
From inside any Flutter project, run:
cd /path/to/your/flutter/app
fluttership
On first run a ~30-second wizard walks you through:
- Mode — solo (just you) or team (a lead shares credentials).
- AI provider + model — pick
geminiand the default model. - Your API key — paste it and FlutterShip saves it to
~/.fluttership/.env(permissions600), or set it yourself (see below).
After that, you're talking to the agent. That's it.
Setting the API key manually (optional)
Instead of pasting it into the wizard, you can put it in a .env file in your project
root, or in ~/.fluttership/.env:
# Pick one, matching your chosen provider
GEMINI_API_KEY=[YOUR_GEMINI_API_KEY]
# ANTHROPIC_API_KEY=[YOUR_ANTHROPIC_API_KEY]
# OPENAI_API_KEY=[YOUR_OPENAI_API_KEY]
# Optional — override provider/model without re-running the wizard
# LLM_PROVIDER=gemini
# GEMINI_MODEL=gemini-2.5-flash
Project
.envwins;~/.fluttership/.envfills the gaps. Both are git-ignored.
Verify everything is wired up:
fluttership doctor
How you actually use it
There are two ways to drive FlutterShip — mix them however you like.
A) Talk to the agent (natural language)
Just run fluttership and type what you want. Or pass it inline:
fluttership "build LIVE apk"
fluttership "build apk aab ipa for DEV and LIVE" # parallel matrix
fluttership "release version 2.0.0 to production"
fluttership "what was the last release?"
The agent reads your project, shows a short build plan, asks for confirmation, builds, and offers the right next step (e.g. "Submit to TestFlight?" only after an IPA is built).
Inside an interactive session, type / to open the command palette
(/status, /doctor, /vault, /mode, /new, /exit, …). Press Esc to
interrupt the agent mid-thought and redirect it.
B) Plain subcommands (no LLM involved)
fluttership status # version, bundle id, detected build pattern
fluttership doctor # health checks — tools, signing, vault, API key
fluttership history # build & release history for this project
fluttership clean # delete build artifacts (fluttership-dist/)
Command reference
| Command | What it does |
|---|---|
fluttership |
Start the interactive AI agent |
fluttership "<request>" |
Run a one-off request, e.g. "build LIVE apk" |
fluttership setup |
Re-run the setup wizard (mode / provider / model) |
fluttership mode |
Show or switch solo/team mode |
fluttership mode solo |
Switch to solo mode |
fluttership mode team lead|member |
Switch to team mode with a role |
fluttership config |
Show current configuration |
fluttership doctor |
Environment + project health checks |
fluttership status |
Project info — version, bundle id, build pattern |
fluttership history |
Build & release history |
fluttership clean |
Delete build artifacts (fluttership-dist/) |
fluttership vault setup |
Create the encrypted credentials vault (team: lead only) |
fluttership vault verify |
Test the vault password + show what's configured |
fluttership vault status |
Vault info (no password needed) |
fluttership vault log |
Credential-access audit log |
fluttership vault export [dest] |
Share the encrypted vault with your team (lead only) |
fluttership vault import <file> |
Install a vault shared by your team lead |
fluttership help |
Full usage |
Slash commands (inside an interactive session): /status, /history, /doctor,
/clean, /mode, /config, /vault, /setup, /new, /exit.
⚡ Parallel builds
FlutterShip's headline feature. Ask for several targets and/or flavors at once and it builds them concurrently, each job in its own isolated git worktree sandbox:
fluttership "build apk aab ipa for DEV and LIVE"
A live dashboard shows every job's status as it runs:
⚡ Building 6 jobs · v2.0.0+9
┌──────────────┬──────────────┬────────┬──────────────────────────────┐
│ Job │ Status │ Time │ Detail │
├──────────────┼──────────────┼────────┼──────────────────────────────┤
│ apk·DEV │ ✅ done │ 1m42s │ myapp_DEV_2.0.0(9).apk │
│ apk·LIVE │ ✅ done │ 1m48s │ myapp_LIVE_2.0.0(9).apk │
│ aab·LIVE │ 🔨 building │ 0m55s │ logs/aab-LIVE.log │
│ ipa·LIVE │ 🍎 archiving │ 2m10s │ logs/ipa-LIVE.log │
└──────────────┴──────────────┴────────┴──────────────────────────────┘
Why it's worth it:
- Faster releases — wall-clock time is your slowest build, not the sum of all of them.
- No collisions — each job runs in a fresh, isolated worktree, so Gradle's project lock and the shared
build/directory never clash. iOS archives are automatically serialized (Xcode's global state can't take twoRunnerarchives at once), while Android builds stay fully parallel. - One shared version — every artifact in a run carries the same version+build number, so a matrix release is consistent.
- Artifacts collected safely — finished builds land in
fluttership-dist/(outsidebuild/), soflutter cleancan't wipe what you just built. Per-job logs go tobuild/fluttership-logs/. - Different flavors per platform — "LIVE and DEV apk, plus LIVE ipa only" builds exactly those pairs, no wasted builds.
Run fluttership clean to reclaim space from fluttership-dist/ when you're done
(your release history, kept in ~/.fluttership, is never touched).
🔐 The secure vault
Store credentials (App Store .p8 key, Play Store service-account JSON, IDs) are
sensitive. FlutterShip keeps them in an encrypted vault — never in your repo, never
in plain text, and never shown to the AI model.
How it's protected:
- AES-256-GCM encryption with PBKDF2 key derivation (200,000 iterations).
- Lives in
~/.fluttership/vault.enc(chmod 600) — outside your project. - Files are base64-encoded before encryption — not human-readable.
- Decrypted in memory only; temp files written to
/tmp(chmod 600) are deleted immediately after each upload. - The LLM only ever sees success/fail status — never a key, password, or token.
- Every access is written to an audit log (
fluttership vault log).
Set it up once:
fluttership vault setup
It asks for your Play Store service-account JSON, App Store .p8 key, and the matching
IDs (see the next section for how to get those), then asks you to set a vault password.
fluttership vault verify # test your password + see what's configured
fluttership vault status # info only — no password needed
Choose a strong vault password and store it in a password manager. If you share the vault with a team, never send the password over chat or email — use a shared password-manager item.
📦 Publishing to the stores
To upload builds, FlutterShip needs store credentials in the vault. Here's exactly what
to download and where to get each piece. Run fluttership vault setup and have these
ready.
🍎 App Store / TestFlight (iOS — IPA)
You need an App Store Connect API key. Three pieces:
| What | Where to get it |
|---|---|
.p8 key file |
App Store Connect → Users & Access → Integrations / Keys → (+) generate a key with App Manager access. Download the .p8 — it can only be downloaded once. |
| Key ID | Shown next to the key you created (e.g. [YOUR_KEY_ID]). |
| Issuer ID | At the top of the Keys page (e.g. [YOUR_ISSUER_ID]). |
| Bundle ID | Your app's bundle identifier, must match your Xcode project. |
The app must already exist in App Store Connect (My Apps → (+) New App) with a matching bundle ID before the first upload. Uploads go to TestFlight via
xcrun altool, so iOS publishing requires macOS + Xcode.
🤖 Google Play (Android — AAB)
You need a service-account JSON with Play Developer API access:
| What | Where to get it |
|---|---|
| Service account JSON | Google Play Console → Setup → API access → create/link a service account in Google Cloud Console, grant it release permissions, then download its JSON key. |
| Package name | Your app's applicationId (e.g. com.example.myapp). |
Play uploads default to the
internaltrack (safest). Change it withfluttership configor by telling the agent "release to production". The Play Store rejects duplicate version codes, so FlutterShip prompts you to confirm the version + build number for every store-bound build.
Then just ask
fluttership "release 2.0.0 to TestFlight and Play Store"
FlutterShip unlocks the vault (you enter the vault password), uploads, and records it as a release in your history. A build that was only compiled — never uploaded — stays a "build", not a "release".
Solo vs Team mode
Solo — everything lives on your machine. You own the vault and the releases.
Team — a shared-vault workflow:
- The lead runs
vault setuponce, thenvault exportto produce the encryptedfluttership-vault.encfile and hands it to members. - Members run
vault import <file>and can build + submit, but never manage or re-export credentials. - The vault file is safe to share (it's AES-256-GCM encrypted and useless without the password). Share the password only through a team password manager.
fluttership mode team lead # you manage credentials
fluttership mode team member # you import the lead's vault
Requirements
- Python 3.9+
- Flutter SDK (on your
PATH) - git and rsync (rsync powers the isolated parallel-build sandboxes)
- For iOS builds/uploads: macOS + Xcode + CocoaPods
- An LLM API key (Gemini free tier works great)
Run fluttership doctor any time to check all of the above.
Security model
- Credentials are never committed — the vault lives in
~/.fluttership/, outside your repo, and.p8/.jks/.json/.envfiles are git-ignored by default. - The AI never sees secrets — it receives only success/fail status and file paths, never key material.
- Encryption at rest — AES-256-GCM + PBKDF2; decrypted only in memory; temp files wiped after use.
- Audit trail — vault unlocks, exports, imports, and uploads are logged.
- Built artifacts can embed compiled code and
dart-definevalues, sofluttership-dist/is git-ignored automatically — never commit your builds.
If you fork or publish this repo, scrub any API keys from your git history before making it public — a key committed even once stays in the history until rewritten.
License
MIT
Built by a Flutter dev who got tired of spending 3 hours on a 10-minute release.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fluttership-1.0.0.tar.gz.
File metadata
- Download URL: fluttership-1.0.0.tar.gz
- Upload date:
- Size: 90.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b67d9110fd9c76f30f33af045e4f983dad1c733c73e11906c0c6f03e32ded25
|
|
| MD5 |
277a50976d44841471188f0b6134ddcb
|
|
| BLAKE2b-256 |
db67c076fce6fcc5cb766c5436bce2627d5414be3a31c225924df195dc2e2dd7
|
File details
Details for the file fluttership-1.0.0-py3-none-any.whl.
File metadata
- Download URL: fluttership-1.0.0-py3-none-any.whl
- Upload date:
- Size: 94.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
255ed4cef15cb7d6b84f1c4606dda2ccba28ce6c541f558d8cc644b97006533a
|
|
| MD5 |
2f3399e8f8ada4e240952080190aad17
|
|
| BLAKE2b-256 |
3b5ebe8c72cdb8edd4dfa37316fe2a6db44b51e2750a50bcaa2a57240d9c52c2
|