Author of flutter_wrapper reveals his dirty secret

4 min readOct 13, 2022

flutter_wrapper is a shell script that downloads and executes a pinned version of the Flutter SDK. Similar to the gradle wrapper that’s used in all Android projects. The project was created 4 years ago by Google Developer Expert Pascal Welsch (@passsy), ancient in the Flutter universe.

Over the years, the project received multiple updates and is widely used in the community. While other solutions exist, like fvm or asdf-flutter, flutterw maintains a fanbase that enjoys the simplicity of the bash script. Unlike others, it doesn't require Dart or the Flutter SDK to be preinstalled. It downloads everything automatically with the correct version and reduces the maintenance cost of Continous Integration. Especially in combination with the popularpasssy/flutterw docker container, building Flutter apps on CI becomes a breeze.

The latest version 1.3.0 was just released. The author hints in the release notes that it won’t break projects anymore. What happened? We got a special interview!

Up and downsides of bash scripts

The install script, as well as the actual flutterw script, are written in Bash. Bash is often used for automation on Unix systems. Shell scripts have become a de facto standard for developers on all major operating systems. On macOS and linux those scripts can be executed directly in the Terminal without the installation of software. Even on Windows, users use the Git Bash or the official Windows Subsystem for Linux to execute shell scripts.

While bash scripts are truly cross-platform in theory, it is a gamble which Builtin commands are available in the shell the users is using to execute the bash script with. While it is likely users use zsh on macOS these days, there are dozens of shells a user might use. Especially in minimal docker containers, the feature set of the shell might be very limited.

This fragmentation makes it especially hard to write shell scripts that work truly cross-platform in production.

Feature creep

When you share a bash script with your team or the community, you will get bug reports. It is way too easy to make mistakes. It’s too hard to know all the quirks of each and every bash beforehand.

Once the issues come in, you start fixing them one by one. Your script grows, it handles more edge cases. And eventually, you introduce new bugs. Ouch!

The flutter_wrapper project is not different. With the number of features and support for more platforms, things break more easily and more often, as the author describes in his own words:

I eventually stopped fixing small annoyances. The script works as it is. I still use it in all my Flutter projects. The risk of fixing a small thing and then introducing a major bug in return is too high.

We can only imagine the stress of maintaining such an important piece of software. What started with giving away a useful piece of code for free, has become the responsibility for many projects that depend on it. Breaking someone else project is not an option.

The only way long-term support actually works

Tests and automation. Period.

When an open-source project doesn’t have tests, it’s very likely that it stops working before it reaches its 3th birthday. The same thing almost happened with the flutter_wrapper. Pascal reveals that the project didn’t have tests for over 3 years!

At some point I had to make a decision: Abandon the project, or finally invest time to write tests. Since the project is too important, I couldn’t give up. I had to find a way to write tests for bash scripts. Something I had no idea how to do it.

In the previous release 1.2.0, tests have been added and the project finally gained traction again.

To our surprise, the latest 1.3.0 release notes that the tests now run on CI. Why wasn’t that implemented earlier? Tests that don’t run, can’t prevent regressions.

At first the tests were very slow. Every unit test downloaded the whole Flutter SDK. I couldn’t bother external contributors to actually debug those tests on their machine in case they break something.

The tests only worked on my machine, really. It was my secret.

In the meantime, I invested time to improve the speed drastically and made sure they also run on CI. I felt so relieved once I saw the green checkmark on GitHub.

Once I had those tests in place I could finally fix small annoyances that existed for years and integrate open PRs.

We agree. The latest 1.3.0 is a huge milestone. While it only fixes small bugs, it is now easier than ever for 3rd party contributors to get their PRs merged in a timely manner.

We thank Pascal Welsch for this time. Don’t forget to check out his GitHub account for more amazing projects. For more updates get subscribed on Twitter

Sorry for the clickbait title and fake interview. It was fun to write and a better post than: “Guess what, I wrote tests for a bash script in dart.”

Forgive me. Pascal 😁

Originally published on on January 14, 2022




Flutter Google Developer Expert, CTO at PHNTM, Co-founder of