Introducing flutpak - automating Flathub submission for Flutter apps
flutpak — major update (0.8.0): Rust/Cargo support, flatpak-flutter-compatible registry, no local SDK required
Since the original post (and the first successful Flathub CI run) a lot has landed. I want to give a proper update, especially on two points raised in the thread.
A note on the proof-of-concept submission
The previous update in this thread reported that PR #8889 passed the Flathub test build on the first try — that part is still true: the build succeeded for both x86_64 and aarch64. However, the PR was subsequently closed for reasons unrelated to the packaging itself:
- Proprietary dependency —
objectbox-cis distributed as a prebuilt binary under the Apache License with no source code available. @hfiguiere flagged this as incompatible with the app’s GPL-3.0 license. - Generative AI policy — Flathub’s requirements restrict AI-generated code in submissions. Claude was used during development of the app, which made the PR ineligible.
Neither of these is a flutpak issue — the tool produced a correct, buildable manifest. The rejection is about the specific app’s dependencies and its codebase, not the packaging toolchain. I mention it for transparency since this thread had the earlier “CI passed” update and it would be misleading to leave it without follow-up.
Registry now compatible with flatpak-flutter
@bbhtt raised the point about flatpak-flutter. Since then the foreign deps registry format has been aligned to be fully schema-compatible withflatpak-flutter’s foreign_deps.json. Every entry from the flatpak-flutter registry can be used in flutpak with no changes. flutpak extends the schema by one optional field (crlf: on patch sources); flatpak-flutter silently ignores it.
The registry currently covers 19 packages:
objectbox_flutter_libs/objectbox_sync_flutter_libssqlite3/sqlite3_flutter_libs/sqlcipher_flutter_libssimple_secure_storage_linuxaudiotags,flutter_webrtc,media_kit_libs_linux,pdfium_flutter,printing,flutter_new_pipe_extractor,fvp,powersyncrhttp,metadata_god,super_native_extensions,flutter_discord_rpc,flutter_vodozemac(cargokit/Rust — see below)
All native archive sources, patches, and version-stamped dest: paths are
resolved and injected automatically by flutpak generate. No manual source
hunting per release.
Version matching is≤: a registry entry for 1.0.0 covers 1.2.3,
1.5.0, etc., reducing churn when upstream bumps patch/minor versions.
Rust / Cargo offline builds (0.8.0)
Flutter plugins using cargokit
(rhttp, metadata_god, super_native_extensions, etc.) now work out of the
box. Add a rust: section to flutpak.yaml:
rust:
version: 1.85.0
rustup-path: /var/lib/rustup
generate will:
- Extract
Cargo.lockfrom pub.dev archives, fetch SHA-256 checksums from the crates.io sparse registry index, emitcargo-sources.json - Generate
rustup-<version>.json: downloads the channel manifest,rustup-initbinaries, and a minimal toolchain (rustc, cargo, rust-std) for bothx86_64andaarch64; setsRUSTUP_DIST_SERVERto the pre-downloaded static directory so nothing touches the network at build time - Insert the
rustupmodule before the app module in the generated manifest - Wire
CARGO_HOME,RUSTUP_HOME, andPATHinto the app module’sbuild-options
Known limitation: git-sourced crates (git+https://...) are skipped with a
warning — they require cloning at generate time, which is out of scope.
Crates.io dependencies are fully supported.
No local Flutter SDK required for generate (0.7.0)
flutpak generate no longer reads from a local Flutter installation. Engine
versions (engine binary, Dart SDK, fonts, Gradle wrapper checksums) are fetched
from the GitHub raw API using flutter.ref:
flutter:
ref: "3.44.1" # tag, branch, or commit SHA
The Flutter SDK sources are emitted as a standalone module
(flutter-sdk-<version>.json) — separate from pubspec-sources.json. Pre-built
module JSONs for recent Flutter releases are cached in the flutpak repo and
fetched on first use, avoiding regeneration across multiple projects on the same
SDK version.
LLVM SDK extension auto-injected (0.5.0)
The correct org.freedesktop.Sdk.Extension.llvmXX is now selected automatically
based on runtime-version (25.08 → llvm20, 24.08 → llvm19, 23.08 → llvm17) with
append-path / prepend-ld-library-path wired up. No manual extension entry
needed.
Breaking changes since the original post
# before
flutter:
sdk: $FLUTTER_ROOT
manifest:
app-id: io.github.YourOrg.YourApp
# after (0.8.0)
flutter:
ref: "3.29.3"
app-id: io.github.YourOrg.YourApp
generated-sources.json→ renamed topubspec-sources.json(update!includereferences)- Flutter SDK sources moved out of
pubspec-sources.jsoninto a separate module - Re-run
flutpak init --forceafter upgrading to 0.8.x to get a clean template
Other notable changes
| Version | Change |
|---|---|
| 0.8.0 | flutpak cache clear — wipes ~/.cache/flutpak/ |
| 0.7.0 | subdir: — Flutter project in a monorepo subdirectory |
| 0.7.0 | flutpak sdk-mod — standalone Flutter SDK module JSON for !include |
| 0.6.0 | patches[].use-git — git apply instead of patch -p1 |
| 0.5.0 | --binary on every type: patch entry — deterministic CRLF handling |
| 0.5.0 | .gitattributes with *.patch -text generated by init |
| 0.4.0 | yaml_edit injection — tag:/commit: written directly into the git source block |
| 0.4.0 | actions/generate + actions/build-flatpak composite CI actions |
| 0.4.0 | Retry on 429/5xx for all network fetches |
Current status
The core workflow is stable. The demo app (examples/demo_app/) builds
sqlite3 + rhttp end-to-end inside the Flatpak sandbox on both architectures —
the CI workflow is a working reference.
The most impactful contribution right now: if you maintain or package a Flutter
app with a native dep not yet in the registry, a PR adding it to
foreign_deps/foreign_deps.json makes it work for everyone. The format is
identical to flatpak-flutter, so existing entries can be copied directly.
Discussion in the ATmosphere