Gemini CLI is a terminal coding agent from Google that you start by running gemini in a Flutter project folder. It reads project instructions from GEMINI.md, so a few Flutter-specific rules make it much more reliable. This guide covers setup, the daily working loop, testing, and parallel agent workflows for Flutter teams. For a general introduction, see Gemini CLI and How to use Gemini CLI: a step-by-step guide.
Why Gemini CLI fits Flutter work
Flutter development has many repetitive, well-structured patterns: widget trees, state management setup, model classes, platform channel boilerplate, and widget test scaffolding. Gemini CLI can update Dart files across several layers in one pass, run flutter analyze and flutter test, and use the resulting errors to correct its work. That matters because Flutter has fast static analysis and test feedback compared with native mobile build cycles. The agent is also useful for refactoring a widget tree without changing behavior when you give it exact constraints, and for generating test cases from an existing screen or provider. The key is to treat it as a junior Flutter engineer: explicit instructions, small changes, and a review before merge.
Configuring GEMINI.md for a Flutter project
The most important setup step is a good GEMINI.md at the repo root. The agent reads this file on every turn, so keep it short and current. Include the exact commands you use for dependency installation, formatting, analysis, testing, and builds. Include folder conventions so the agent does not create files in random places. Add Flutter-specific rules that prevent common mistakes: state management choice, const usage, error handling, and test expectations.
Here is a realistic example for a Riverpod-based Flutter app:
# Project instructions
## Commands
- Install dependencies: `flutter pub get`
- Format check: `dart format --output=none --set-exit-if-changed lib test`
- Analyze: `flutter analyze`
- Run unit and widget tests: `flutter test`
- Build debug APK: `flutter build apk --debug`
## Folder conventions
- `lib/features/<feature>/` contains screens, widgets, and providers for one feature.
- `lib/core/` contains shared theme, routing, networking, and utilities.
- `test/` mirrors `lib/` one-to-one.
- Generated files live next to their source files.
## Flutter rules
- Use Riverpod for state management; do not introduce a second state library.
- Mark widgets const where possible.
- Do not add `print` calls; use `debugPrint` or a logger.
- Keep `BuildContext` use inside the widget; pass dependencies into providers or services.
- Always check `mounted` before using `context` after an async gap.
- Prefer `Key` values on interactive widgets so widget tests remain stable.
- Update tests whenever you change public widget or provider behavior.
- Run `flutter pub get` after changing `pubspec.yaml`.
Tell the agent to run a command and to wait for the result; do not assume you can describe command output. If you use code generation, add the build_runner command and the generated file rule. For Bloc, write the same kind of rules with BlocProvider and event/state conventions.
The edit–test–review loop
Use a simple loop: plan, ask for one small change, run the checks, review the diff, then either continue or correct. Start the agent in the repo root with gemini. In each prompt, give the exact file or feature, the expected behavior, and the tests to add or run. Ask for the smallest change that passes the tests. Do not let the agent make unrelated formatting or refactoring changes in the same turn.
Example prompts for typical Flutter work:
- “Add a retry with exponential backoff to the existing
AuthRepository.signInmethod. Keep the public interface unchanged and add unit tests for the retry behavior.” - “Refactor the profile screen from
setStateto Riverpod without changing visible behavior. Run the existing profile widget tests and add one test for the loading state.” - “Add a platform channel method to read the device language from Android and iOS. On unsupported platforms return ‘en’. Add a Dart-side unit test using a mock method channel.”
- “Fix the
RenderFlex overflowerrors on the home screen for small phones. Add a widget test withtester.view.physicalSizeset to 320x568 and verify no exception is thrown.” - “Split the large
CartScreenwidget into smaller private widgets under the same file. Do not change behavior or public APIs, and runflutter analyzeplus the existing cart tests.”
After each prompt, run dart format --output=none --set-exit-if-changed lib test, flutter analyze, and flutter test yourself or ask the agent to run them and show output. Review the diff with git diff. Focus on state management changes, new dependencies, and test changes.
Where the agent excels and where to watch closely
Gemini CLI handles several Flutter tasks well when the scope is clear:
- Adding or updating widget tests for an existing screen.
- Converting a stateful widget to a state management solution like Riverpod or Bloc.
- Generating model classes from JSON with
fromJsonandtoJson. - Adding platform channel methods with Dart-side tests.
- Refactoring a widget tree into smaller widgets while preserving behavior.
- Fixing static analysis issues from
flutter analyze.
Where to watch it closely:
- Over-refactoring. The agent may rename or reorder widgets beyond the requested change. Review the diff and reject cosmetic changes.
- State management mismatches. If your app uses Riverpod and the agent introduces a local
setStateor a newChangeNotifierwhere a provider belongs, tests may still pass but architecture drifts. BuildContextacross async gaps. Dart’suse_build_context_synchronouslylint catches some cases, but the agent may still write code that usesNavigator.of(context)after anawaitwithout checkingmounted.- Generated files. If you use
freezed,json_serializable, orriverpod_generator, the agent may edit generated files directly or forget to runbuild_runner. Set a rule inGEMINI.mdand check the diff for*.g.dartand*.freezed.dartchanges. - Platform channels. The agent may write correct Dart but wrong Android or iOS platform code. Add tests on the Dart side, and manually verify the native side.
- Golden tests. Flutter golden files can differ across font rendering environments. Avoid asking the agent to update goldens unless you have a consistent CI runner.
Verifying changes with Flutter tooling
Make verification a required step, not a suggestion. The agent can run commands, but you should enforce the same gate locally. The commands below are the minimum for a Flutter change:
| Command | Purpose in the loop |
|---|---|
dart format --output=none --set-exit-if-changed lib test | Fails the step if formatting is off |
flutter analyze | Catches type errors, unused imports, and lint issues |
flutter test | Runs unit and widget tests |
flutter test integration_test | Runs device-level integration tests if present |
Run these after every turn, and ask the agent to include test output in its reply. Widget tests are especially important because Flutter UI regressions often appear only at 800x600 default test size; use tester.view.physicalSize and tester.view.devicePixelRatio to test small screens when fixing overflow issues. For state management code, unit test the provider or bloc in isolation with a mocked repository or service.
Review the test changes the agent makes. A bad agent can make a test pass by weakening an assertion or skipping a test. Check that the test still expresses the intended behavior and fails meaningfully if the code is wrong. Use git diff to inspect every changed file, not just the summary.
Parallel agents with AgentVera
On a Flutter codebase, AgentVera helps by running real CLI agents in parallel git worktrees, so one agent can refactor widgets while another adds tests without overwriting files. Automatic code review with file:line findings catches Flutter-specific issues like missing mounted checks or wrong BuildContext use. Checkpoints let you undo a turn that broke a provider graph or a widget test. Token budgets keep a long screen refactor from exhausting the daily limit. This is a practical setup when several Flutter tasks are independent; see AI agent team: a manager, roles and handoffs.
Wrapping up
Gemini CLI works well on Flutter projects when you write a short, explicit GEMINI.md, keep prompts small, run flutter analyze and flutter test after each turn, and review diffs with an eye for state management and generated files. If you run parallel agents, use separate git worktrees and a review gate. The result is a faster edit-test loop without giving up Flutter-specific control.