flutter_distribute_manager 3.0.0 copy "flutter_distribute_manager: ^3.0.0" to clipboard
flutter_distribute_manager: ^3.0.0 copied to clipboard

Ship Flutter apps to QA in one command: build the Android APK and iOS IPA, then upload to Google Drive (via rclone) and Diawi with shareable install links.

πŸš€ flutter_distribute_manager #

pub package license: MIT Dart platforms

Build your Flutter app and hand QA a working link β€” in one command. Android APK + iOS IPA β†’ uploaded to Google Drive and Diawi automatically.

No Google Cloud project. No OAuth client to register. No manual Xcode archiving. No dragging files into shared folders.

$ flutter_distribute_manager
╔══════════════════════════════════════════════╗
  flutter_distribute_manager Β· Build Β· Ship
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
  Project : my_app v1.4.2

? Which platform do you want to build?
  1) Android (APK)   (default)
  2) iOS (IPA)
  3) Android + iOS

βœ” Built    my_app_UAT_2026_06_19_0930_arm64-v8a.apk  (24 MB)
  [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ] 100%  24 MB / 24 MB  8.1 MB/s
βœ” Uploaded to Google Drive

Share links:
  Drive Β· my_app_UAT_2026_06_19_0930_arm64-v8a.apk
  https://drive.google.com/file/d/…

πŸ“– Contents #

What it replaces Β· Why not fastlane? Decide if this is for you
Install Β· Quick start Get running in 3 minutes
Commands Β· Build flags Everyday reference
CI/CD Β· JSON output Β· Exit codes Automate it
How it works Β· Configuration Understand it
Troubleshooting Β· FAQ When something breaks

πŸ€” What it replaces #

Shipping a build to QA by hand is seven boring steps, every single time:

Doing it by hand With flutter_distribute_manager
flutter build apk β†’ wait β†’ hunt for the file in build/… One command builds it for you
Drag the APK into a Google Drive folder Uploaded automatically
Right-click β†’ Get shareable link β†’ copy Link printed in your terminal
Flat Drive folder β€” chaos after 10 builds Organised App/Year/Month/ENV/ folders
"Which build is this β€” DEV or PROD?" Environment stamped into every filename
Android and iOS are two separate chores Both in a single run
Paste the link into Slack yourself Optional auto-notification to Slack/Discord/Teams
cd your_flutter_app
flutter_distribute_manager

That's the whole workflow.


πŸ₯Š Why not fastlane or Codemagic? #

They're excellent β€” and heavier. This tool is deliberately the small one.

flutter_distribute_manager fastlane Codemagic / Bitrise
Setup time ~3 minutes, one command Ruby, Gemfile, Fastfile, lanes Sign-up, connect repo, YAML
Runs on your laptop βœ… Yes, that's the point βœ… Yes ❌ Cloud-only (paid minutes)
Config to write None β€” it asks you A Fastfile per project A codemagic.yaml per project
Cost Free (your Drive quota) Free Free tier, then per-minute
Google Drive delivery βœ… Built in, folder-organised Plugin + service account ❌ Not typically
Needs a Google Cloud project ❌ No β€” rclone signs you in βœ… Service-account JSON βœ… Usually
Play Store / App Store submit ❌ Not its job βœ… Yes βœ… Yes
Code signing management Passes through to Flutter βœ… match/sigh βœ… Managed

Use this when you want QA builds out of your hands and into a tester's, right now, without standing up a pipeline. Use fastlane/Codemagic when you're automating store submissions, managing signing certificates across a team, or need a hosted build farm.

They compose fine, too β€” plenty of people use this for daily QA drops and fastlane for release day.


βœ… What you'll need #

Requirement What it's for How to get it
Flutter & Dart (Dart β‰₯ 3.5) Building the app flutter.dev/get-started
rclone Uploading to Google Drive init offers to install it via your package manager
Xcode (macOS only) Building iOS IPAs Mac App Store β€” full Xcode, not just the CLI tools
Diawi token (optional) iOS one-tap install links diawi.com β†’ Account β†’ API

You do not need a Google Cloud project, an OAuth client ID, or a service-account key. rclone signs you in through your browser.

πŸ’» Platform support #

Android build iOS build Drive upload Diawi
macOS βœ… βœ… βœ… βœ…
Linux βœ… ❌ (needs macOS + Xcode) βœ… βœ…
Windows βœ… ❌ (needs macOS + Xcode) βœ… βœ…

πŸ“₯ Install #

dart pub global activate flutter_distribute_manager

Make sure the global bin directory is on your PATH (add to ~/.zshrc or ~/.bashrc):

export PATH="$PATH":"$HOME/.pub-cache/bin"

Verify:

flutter_distribute_manager --version
flutter_distribute_manager --help

⚑ Quick start (3 steps) #

# 1️⃣  One-time setup β€” installs rclone, connects Google Drive, saves your Diawi token
flutter_distribute_manager init

# 2️⃣  Check everything is wired up correctly
flutter_distribute_manager doctor

# 3️⃣  From inside your Flutter project β€” build & ship
cd path/to/your/flutter_app
flutter_distribute_manager

The tool detects your project, asks for platform + environment, builds, uploads, and prints the share links.

πŸ’‘ Not sure what a command will do? Add --dry-run. It prints the exact plan, checks that Flutter and Google Drive are actually reachable, and exits non-zero if the real run would fail β€” without building anything.


🧭 Commands #

Command What it does
flutter_distribute_manager Build & ship (the default command, interactive).
flutter_distribute_manager init One-time setup: rclone, Google Drive auth, Diawi token, webhook.
flutter_distribute_manager doctor Health check: tools, config, Drive connectivity (+ macOS Gatekeeper). Exits 1 if anything is broken.
flutter_distribute_manager config View or edit saved configuration (interactive or scriptable).
flutter_distribute_manager reset Remove saved configuration and start over.

Every command supports --help.


🚩 Build flags #

Every prompt has a flag, so any build is scriptable.

Flag Alias Default Description
--platform -p ask β†’ android android, ios, or both.
--environment -e ask β†’ DEV DEV, UAT, or PROD.
--app-dir -d current dir Flutter project path (searches parent dirs too).
--app-name -n pubspec name: Label used in artifact file names.
--flavor none Build flavor passed through to flutter build.
--flutter-path auto Explicit Flutter executable (overrides PATH/fvm detection).
--clean off Run flutter clean before building.
--[no-]split-per-abi on Split Android APKs per ABI.
--team-id -t ask / saved Apple Developer Team ID (iOS).
--export-method release-testing development, release-testing, ad-hoc, enterprise, app-store.
--scheme Runner Recorded for reference; Flutter picks the scheme from --flavor.
--upload-drive saved / ask Upload artifacts to Google Drive.
--upload-diawi ask if token set Upload the iOS IPA to Diawi.
--diawi-token saved Diawi API token. Prefer FDM_DIAWI_TOKEN.
--notify-url saved Slack/Discord/Teams webhook. Prefer FDM_NOTIFY_URL.
--retry 3 Upload attempts before giving up.
--skip-build / --upload-only off Reuse the last build instead of rebuilding.
--dry-run off Print the plan and validate readiness; build nothing.
--json off Emit a machine-readable JSON result on stdout.
--yes -y off Assume defaults; never prompt (CI/CD).
--quiet -q off Silence build chatter and detail lines.
--verbose -v off Verbose logging.
--version Print version.

⚠️ --yes changes the defaults. With no terminal (or with -y), the tool never asks: --platform and --environment fall back to whatever is saved in .flutter_distribute_manager.json, and then to android / DEV. Pass both explicitly in CI so a fresh checkout builds what you expect.

πŸ” Secrets via environment #

A token passed as a command-line argument is visible to every user on the machine (ps auxww) and lands in shell history and CI command echoes. Prefer:

Variable Replaces
FDM_DIAWI_TOKEN --diawi-token
FDM_NOTIFY_URL --notify-url

Precedence is flag β†’ environment β†’ saved config.


πŸ”„ Reset flags #

Flag Alias Description
(no flag) Soft reset β€” deletes machine + project config. Drive stays connected.
--all Full reset β€” also deletes the rclone remote (disconnects Google Drive).
--app-dir -d Project whose config to remove (default: current dir).
--yes -y Skip the confirmation prompt (for CI).
flutter_distribute_manager reset        # keep the Google sign-in
flutter_distribute_manager reset --all  # disconnect Drive too

Interactively, reset lists exactly what it will remove and asks you to type reset to confirm β€” nothing is deleted by accident. If --all cannot actually remove the remote, it says so and exits non-zero rather than claiming success.


βš™οΈ Config flags (scriptable) #

config is interactive by default, but every field has a flag so a provisioning script or CI image can configure the tool without a terminal:

flutter_distribute_manager config --show                 # current values
flutter_distribute_manager config --show --json          # machine-readable
flutter_distribute_manager config --set-remote gdrive \
                                  --set-folder "Flutter Builds"
flutter_distribute_manager config --upload-to-drive      # on by default
flutter_distribute_manager config --set-diawi-token -    # clear it

Secrets are never printed back β€” --show reports set / ***set***, never the value.


πŸ€– CI/CD #

One-time: get credentials onto the runner #

--upload-drive needs an rclone remote and this tool's config. On a fresh runner neither exists, and init is interactive β€” so provision them from secrets instead. Run init once locally, then copy ~/.config/rclone/rclone.conf into a CI secret (it contains the Drive OAuth refresh token β€” treat it as a credential).

GitHub Actions #

name: Ship to QA
on:
  workflow_dispatch:
  push:
    tags: ['v*']

jobs:
  ship:
    runs-on: ubuntu-latest          # use macos-latest to also build iOS
    steps:
      - uses: actions/checkout@v4
      - uses: subosito/flutter-action@v2
        with: { channel: stable }

      - name: Install rclone
        run: sudo apt-get update && sudo apt-get install -y rclone

      - name: Restore credentials
        env:
          RCLONE_CONF: ${{ secrets.RCLONE_CONF }}
        run: |
          mkdir -p ~/.config/rclone
          printf '%s' "$RCLONE_CONF" > ~/.config/rclone/rclone.conf
          chmod 600 ~/.config/rclone/rclone.conf

      - name: Install the CLI
        run: |
          dart pub global activate flutter_distribute_manager
          echo "$HOME/.pub-cache/bin" >> "$GITHUB_PATH"

      - name: Configure
        run: |
          flutter_distribute_manager config \
            --set-remote gdrive \
            --set-folder "Flutter Builds"

      - name: Preflight
        run: flutter_distribute_manager -p android --upload-drive --dry-run -y

      - name: Build & ship
        env:
          FDM_NOTIFY_URL: ${{ secrets.SLACK_WEBHOOK }}
        run: |
          flutter_distribute_manager \
            --platform android \
            --environment UAT \
            --app-name MyApp \
            --upload-drive \
            --yes --json > result.json
          cat result.json

      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: build-result
          path: result.json

πŸ’‘ The Preflight step is worth its 5 seconds: --dry-run exits non-zero when Flutter is missing or the Drive token has expired, so you find out before paying for a 15-minute build.

Any other CI #

flutter_distribute_manager \
  --platform both -e UAT --app-name MyApp \
  --upload-drive --yes --json

All human-readable output goes to stderr, so stdout carries only JSON.


πŸ“‹ JSON output schema #

--json writes exactly one JSON document to stdout:

{
  "tool": "flutter_distribute_manager",
  "success": true,          // false when an upload failed (the build still succeeded)
  "dryRun": false,
  "app": "MyApp",
  "version": "1.4.2+7",     // straight from pubspec.yaml
  "environment": "UAT",     // DEV | UAT | PROD
  "platform": "both",       // android | ios | both
  "artifacts": [
    {
      "name": "MyApp_UAT_2026_06_19_0930_arm64-v8a.apk",
      "platform": "android",       // android | ios
      "sizeBytes": 25165824,
      "path": "/abs/path/build/distribute/MyApp_UAT_….apk",
      "abi": "arm64-v8a"           // omitted when not a per-ABI split
    }
  ],
  "links": [
    { "service": "Drive", "artifact": "MyApp_UAT_….apk", "url": "https://…" },
    { "service": "Diawi", "artifact": "MyApp_UAT_….ipa", "url": "https://i.diawi.com/…" }
  ],
  "warnings": [             // non-fatal degradations; see below
    "iOS was skipped: builds require macOS with Xcode (this machine is linux)."
  ],
  "timingsMs": { "androidBuild": 182000, "driveUpload": 9400 }
}

warnings is the field to watch. A run can succeed while quietly doing less than you asked β€” iOS skipped on a Linux runner, Drive upload with no shareable link, Diawi requested with no token. success: true with a non-empty warnings array means "shipped, but not everything you asked for."

# Fail the pipeline on any degradation, not just on a non-zero exit:
jq -e '.warnings | length == 0' result.json

Even when an upload fails, the JSON document is still written (with "success": false) so you never lose the artifact paths and the links that did succeed.


πŸ”’ Exit codes #

Code Meaning Typical cause
0 Success. β€”
1 Generic failure. doctor found problems; an unexpected filesystem error.
64 Bad command-line usage. Unknown command/flag, bad value, no Flutter project, missing --app-dir.
69 Upload failed, or a build is already running for this project. rclone/Diawi failure; the concurrency lock is held.
70 The build itself failed. Gradle/Xcode error; no artifact produced; an unexpected crash.
78 Missing or invalid configuration. Flutter not found, Drive not set up or unreachable, --dry-run blockers.
130 Interrupted (Ctrl-C). Standard 128 + SIGINT.

πŸ—‚ How files land on Google Drive #

Flutter Builds/                  ← your root folder (set during init)
└── MyApp/                       ← --app-name
    └── 2026/
        └── June/
            β”œβ”€β”€ DEV/
            β”œβ”€β”€ UAT/
            β”‚   └── MyApp_UAT_2026_06_19_0930_arm64-v8a.apk
            └── PROD/

Folder matching is case-insensitive, so re-runs reuse the same folders instead of piling up duplicates.


πŸ”¬ How it works #

No magic, and nothing you couldn't do by hand:

  β”Œβ”€ 1. Detect ────────────────────────────────────────────────┐
  β”‚  Walk up from --app-dir for a pubspec.yaml with Flutter.    β”‚
  β”‚  Resolve the toolchain: --flutter-path β†’ fvm β†’ PATH.        β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
  β”Œβ”€ 2. Pre-flight ────────────────────────────────────────────┐
  β”‚  Take a per-project lock (two builds corrupt Gradle caches).β”‚
  β”‚  Prove rclone works AND the Drive remote actually answers   β”‚
  β”‚  β€” before you pay for the build, not after.                 β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
  β”Œβ”€ 3. Build ─────────────────────────────────────────────────┐
  β”‚  flutter build apk --release [--split-per-abi]              β”‚
  β”‚  flutter build ipa --release --export-method …              β”‚
  β”‚  Failures are matched against known signatures and turned   β”‚
  β”‚  into an actionable hint (a corrupt Kotlin cache is even    β”‚
  β”‚  cleaned and retried once, automatically).                  β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
  β”Œβ”€ 4. Stage ─────────────────────────────────────────────────┐
  β”‚  Copy only *this* build's artifacts into build/distribute/  β”‚
  β”‚  as MyApp_UAT_2026_06_19_0930_arm64-v8a.apk.                β”‚
  β”‚  (flutter-apk/ keeps every variant ever built β€” picking the β”‚
  β”‚  wrong one is how a debug APK reaches QA.)                  β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
  β”Œβ”€ 5. Distribute ────────────────────────────────────────────┐
  β”‚  rclone copy β†’ Drive (App/Year/Month/ENV), then rclone link.β”‚
  β”‚  IPA β†’ Diawi, polled until the install link is ready.       β”‚
  β”‚  Retries use backoff; permanent errors are not retried.     β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
  β”Œβ”€ 6. Report ────────────────────────────────────────────────┐
  β”‚  Summary table + share links, --json document, and an       β”‚
  β”‚  optional Slack/Discord/Teams post. Sent on failure too.    β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

βš™οΈ Configuration #

Scope Location Stores
Machine ~/.config/flutter_distribute_manager/config.json
(%APPDATA%\flutter_distribute_manager\config.json on Windows)
rclone remote, Drive folder, Diawi token, notify webhook.
Project .flutter_distribute_manager.json in the project root last platform, app name, Team ID, scheme, export method, environment.

The machine config holds API tokens, so on macOS/Linux it is written user-only (chmod 600) via an atomic temp-file rename β€” there is no window in which it sits world-readable, and an interrupted write cannot truncate a good config. XDG_CONFIG_HOME is honoured.

Add .flutter_distribute_manager.json to .gitignore if you'd rather not commit your per-project choices.


🎯 fvm-pinned projects #

If your app is pinned with fvm, you don't need a global flutter on your PATH. The tool detects fvm (.fvmrc, .fvm/, or .fvm/fvm_config.json) and runs the project's pinned SDK via fvm flutter … automatically β€” so builds use the exact version your project expects.

  • It also finds a vendored SDK (.fvm/flutter_sdk, .fvm/versions/<v>, $FVM_CACHE_PATH, ~/fvm/versions/<v>) when fvm itself isn't on PATH.
  • doctor reports Flutter (fvm 3.x.x) when it resolves via fvm.
  • If the project is pinned but nothing fvm-shaped is found, the run warns and records a warning in the result rather than silently using a different SDK.
  • Override detection anytime with --flutter-path /path/to/flutter.

πŸ›  Troubleshooting #

command not found: flutter_distribute_manager after installing

The global bin directory isn't on your PATH:

export PATH="$PATH":"$HOME/.pub-cache/bin"   # add to ~/.zshrc or ~/.bashrc
source ~/.zshrc
macOS shows a security popup for flutter / dart / rclone (Gatekeeper)

Run flutter_distribute_manager doctor β€” it lists any quarantined binaries and prints the exact command to clear each one:

xattr -d com.apple.quarantine /path/to/binary
rclone remote … not found / Google Drive not reachable

Your sign-in expired or the remote was renamed:

rclone config reconnect <remote>:          # refresh the token
flutter_distribute_manager init            # or redo setup
flutter_distribute_manager doctor          # confirm

Note the remote name is bare β€” gdrive, not gdrive:.

iOS build fails immediately with an export-method error

Pass a value Flutter accepts: development, release-testing (the default β€” exported as Xcode's ad-hoc), ad-hoc, enterprise, or app-store. For signed builds also pass --team-id.

"Xcode command-line tools" are installed but the iOS build still can't archive

The Command Line Tools alone are not enough β€” you need full Xcode, and the toolchain has to point at it:

# Install Xcode from the App Store first, then:
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license accept

(xcode-select --install installs the Command Line Tools, which is the thing that isn't sufficient β€” it will not fix this.)

Noisy FINE: / SLVR: / IO : lines on the very first run

That's pub recompiling its snapshot right after dart pub global activate β€” not this tool. It disappears on the next run. Use --quiet to trim build chatter, or --json for clean machine-readable stdout.

A build "hangs"

Almost always a signing prompt, an SDK licence question, or a CocoaPods/Gradle prompt waiting on input. Run once interactively to answer it; the tool closes child stdin and bounds output draining so daemons can't wedge the run.

"Another build is already running for this project"

A per-project lock stops two concurrent builds corrupting the shared Gradle/Kotlin caches. It's an OS file lock, so it clears automatically when the other process exits β€” including if it crashes. If no other build exists, check the message: a setup problem with the temp directory is reported differently and the build continues unlocked.

The wrong APK got uploaded

build/app/outputs/flutter-apk/ accumulates every variant ever built and Flutter never cleans it. The tool filters by build mode, flavor and timestamp β€” but if you use flavors, pass --flavor with --skip-build too, otherwise "the last build" means whichever variant is newest.


❓ FAQ #

Do I need a Google Cloud project or OAuth credentials? No. rclone handles Google Drive sign-in in your browser during init.

Where is my Diawi token stored, and is it safe? In the machine config file, written user-only (chmod 600) on macOS/Linux via an atomic rename. It is never echoed to the terminal (entry is hidden), never printed by config --show, and is redacted from logs and error messages β€” including the ones Diawi itself echoes back.

Can I upload without rebuilding? Yes β€” --skip-build (alias --upload-only). Add --flavor if you use flavors.

Does it work on Windows / Linux? Yes for Android builds and Drive uploads. iOS builds require macOS + Xcode. On Linux/Windows, --platform ios fails immediately with a clear message (exit 78) β€” and under --dry-run it is reported as a blocker, so the JSON document is still emitted. --platform both builds Android and records a warning about the skipped iOS in warnings.

How do I change a saved setting? flutter_distribute_manager config (interactive), config --set-… (scripted), or override per-run with the matching flag.

Is this safe to run in CI? Yes. Pass every value as a flag plus --yes for zero prompts, and --json for a parseable result. Use --dry-run as a preflight gate. Distinct exit codes (see above) let a pipeline react.

Does it upload my source code anywhere? No. It uploads only the built artifacts, only to the destinations you enable, and it has no telemetry.


🧩 Programmatic use #

The building blocks are also exported as a library:

import 'dart:io';

import 'package:flutter_distribute_manager/flutter_distribute_manager.dart';

Future<void> main() async {
  final project = FlutterProject.find(Directory.current.path);
  if (project == null) {
    stderr.writeln('No Flutter project here.');
    exit(64);
  }

  final artifacts = await AndroidBuilder(const ProcessRunner(), Logger())
      .build(project, environment: ReleaseEnvironment.uat);

  for (final artifact in artifacts) {
    print('${artifact.name}  ${artifact.humanReadableSize}');
  }
}

See example/ for a full walkthrough.


🀝 Contributing #

Issues and PRs welcome at github.com/Ashutoshtripathi980/flutter_distribute_manager.

dart pub get
dart analyze          # must be clean
dart test             # 450 tests

πŸ“„ License #

MIT Β© 2026 Ashutosh Tripathi.

3
likes
160
points
244
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Ship Flutter apps to QA in one command: build the Android APK and iOS IPA, then upload to Google Drive (via rclone) and Diawi with shareable install links.

Repository (GitHub)
View/report issues

Topics

#cli #flutter #release #distribution #automation

License

MIT (license)

Dependencies

args, http, path

More

Packages that depend on flutter_distribute_manager