One tool ran the code generator without being asked and left all four golden images alone. The other hand-edited a .g.dart file and then updated two goldens to make the failures disappear.
Editorial Note: This article is based on hands-on use of the tools from our own test accounts, combined with product documentation, benchmark data, and publicly available information. All features, pricing, and benchmark figures are verified through official sources. See our Disclaimer.
Twenty-three thousand four hundred lines of Dart, 118 files, 41 screens, and a field-service app two people shipped to both stores. The same four prompts went to Cursor and to GitHub Copilot across four days. Cursor merged all four diffs without an edit from us. Copilot merged two, and both losses came from the same omission: it never ran build_runner.
That is the Flutter-specific part. Half the Dart that compiles does not exist on disk until a generator writes it, and an assistant that edits files and stops has finished half the job with no way to see the other half.
Copilot at $10 is still the right seat for a lot of people. On this app the multi-file work was the work.
| The Flutter job in front of you | Use | What we measured |
|---|---|---|
| Paging and a status filter through an existing Riverpod provider | Cursor | 4 files in 54 seconds, generator run, pull-to-refresh preserved |
| “Vertical viewport was given unbounded height” on a long list | Cursor | CustomScrollView plus SliverList, 44 ms first frame over 1,200 rows |
| Moving a 640-line screen off setState and a ChangeNotifier | Cursor | 14 files, 312 existing tests green, 0 of 4 golden images touched |
| Widget tests you will actually trust next quarter | Neither, quite | 31 tests caught 3 of 5 planted breaks; 12 tests caught 2 |
| One screen, app already running on a device | Copilot | $10, and the debugger sits in the editor you already have open |
| Ten Flutter developers on one repo | Copilot Business | $19 a seat with policy controls; Cursor has no Android Studio story |
Four things in a Flutter repo punish an assistant that reads the file in front of it.
The compiling code is generated. job_list_provider.dart is 41 lines. Its sibling job_list_provider.g.dart is 1,900 lines of generated wiring, rewritten on every build. An agent that edits the generated file has edited something that will be overwritten, and an agent that edits only the source leaves the app referencing a class that no longer matches. There is one correct move, dart run build_runner build --delete-conflicting-outputs, and it changes files the agent never opened.
Layout errors cross file boundaries. “Vertical viewport was given unbounded height” is not a mistake in a file. It is a contradiction between a child that wants infinite height and a parent that offers infinite height. Both files are correct on their own.
The analyzer is a real gate. Most JavaScript repos have no comparable lint wall. Flutter projects do, and two rules catch AI output constantly: use_build_context_synchronously, which fires when you await something and then touch context, and prefer_const_constructors, which fires on nearly every widget you paste. Copilot's Task 1 patch arrived with two new prefer_const_constructors infos. Nothing broke, since infos are advisory here, but they cost six small edits in a patch that was otherwise right.
Hot reload hides the failure. Hot reload keeps state, so a changed initState, a changed global initializer or a changed const does not re-run. Copilot reported two fixes as verified on a hot reload that had not re-executed the code. Both were still broken on hot restart.
The repository already had jobsProvider returning an unbounded list. Cursor changed four files in 54 seconds and, critically, put the page cursor and the status filter into the provider rather than the widget, so pull-to-refresh still reset only the cursor. Copilot's two-file patch was correct as well, just slower at 2 minutes 10 seconds. This is the task that proves Copilot is not the weaker model. It is the weaker workspace.
Cursor replaced the nested list with CustomScrollView and a SliverList, which keeps the 1,200-row invoice list lazy and keeps the parent scroll physics intact. First frame went from 41 ms to 44 ms. Copilot did what most advice on the internet says: shrinkWrap: true plus NeverScrollableScrollPhysics. The exception disappeared and the screen built every one of the 1,200 rows up front. First frame: 380 ms. The prompt had said not to change how it scrolls, and that patch did.
Cursor moved the screen from setState and a ChangeNotifier to a Riverpod Notifier across 14 files, ran build_runner twice, and finished with 312 existing tests green, four golden images byte-identical, and no new analyzer issues. Copilot touched nine files, hand-edited invoice_detail_state.g.dart to make its version compile, and the next generator run reverted it, leaving six analyzer errors. It also ran flutter test --update-goldens when two images failed. That command does not fix a regression. It photographs it.
Both wrote tests. Cursor wrote 31, Copilot wrote 12, and we graded the suites by planting five deliberate breaks after the fact: removing a mounted guard after an await, dropping TextInputType.number, leaving Submit enabled while a request is in flight, letting a negative amount through validation, and switching autovalidateMode to disabled. Cursor's suite caught three. Copilot's caught two. Cursor's own first run also hit a real Flutter trap: five of its tests used pumpAndSettle against a CircularProgressIndicator, which never settles, so the suite hung until it swapped in fixed-duration pump calls.
The debug loop. Copilot runs inside the editor that already has the Flutter plugin, which is the part most guides skim in how to use GitHub Copilot effectively, and in Android Studio that means the widget inspector, the DevTools timeline and hot reload all behave. On Cursor we ran flutter run in the integrated terminal and attached, because DevTools did not launch from the editor twice out of four attempts. If your work is a screen at a time with the emulator open, that matters more than diff size.
Price and administration, too. $10 a month against Cursor's $20, and Copilot Business at $19 a seat with policy controls is the only one of the two a ten-person Flutter team can hand to an IT department. A team can run Copilot for everyone and Cursor seats for the two people doing the refactors. That is what we would do.
October 24 to 27, 2026, on a 2019 Flutter app for field technicians: Riverpod with codegen, freezed models, go_router, dio and sqflite for the offline queue. 118 Dart files, 23,400 lines, 41 screens. Baseline before any prompt: flutter analyze clean with 37 infos, 312 tests green, four golden files. Hardware was a MacBook Pro with an M3 Max, a Pixel 6a on Android 15 and an iPhone 13.
Both tools started each task from the same branch and a fresh session, with no rules file and no custom instructions, so neither got to bring our house style.
Cursor cost $80 for the week: $20 on Pro, then $60 on Pro+ after the agent pool ran dry at 2:40 p.m. on day one, partway through the second task. Copilot cost $10 and never came near a limit, because it did less.
The rest of the bill is your own time. We logged 0.6 hours of cleanup on Cursor's four diffs and 3.2 hours on Copilot's two, and at a $75 loaded rate that is $45 and $240. Divide by merged changes: $31.25 each on Cursor, $125.00 on Copilot. The seat tiers themselves are in Cursor vs Copilot pricing. A cheaper seat that ships half the diffs is the expensive seat, and the arithmetic only looks close until you count the hours.
Cursor is the tool to buy for Flutter in 2026, at $20 a month. It merged four of four, ran the generator on its own, and left the golden images alone. On an app where every real feature crosses a provider, a generated file, a screen and a test, the tool that can hold four files at once wins before model quality enters it.
The boundary is narrow and worth respecting. If you work inside Android Studio with the emulator running, buy Copilot at $10 and keep the inspector, the timeline and hot reload that come with the Flutter plugin. If your team is ten people, put Copilot Business on everyone and buy Cursor for whoever owns the refactors. What does not work is one seat expected to do both, which is how a four-day job becomes a week of reviewing generated files.
Yes, through the Dart Code extension, which installs from the Open VSX registry Cursor uses. Analysis, completion and debugging all worked on our 118-file app. The gap is DevTools: it failed to launch from the editor twice in four attempts, so we ran flutter run in the terminal and attached.
For single-screen work, yes, and at $10 it is the cheapest seat in this test. It merged two of our four diffs. It reads the file or the diff in front of it and never runs build_runner, so any task that adds or changes a provider, a freezed model or a router entry leaves the generated files stale.
Because the part file is out of date. A part directive points at a .g.dart file that build_runner writes, and the analyzer reads both. Fix it with dart run build_runner build --delete-conflicting-outputs, then run flutter analyze again. Never edit the generated file by hand; the next build reverts you.
Partly. Cursor wrote 31 tests and 3 of 5 deliberate breaks failed them; Copilot wrote 12 and caught 2. The trap to watch is pumpAndSettle, which never returns if the widget tree contains an indeterminate progress indicator. Use fixed-duration pump calls around anything that shows a spinner.
October 24 to 27, 2026. One Flutter app for field technicians: 118 Dart files, 23,400 lines, 41 screens, Riverpod with codegen, freezed, go_router, dio and sqflite. Baseline before any prompt was flutter analyze clean with 37 infos, 312 tests green and four golden files. Both tools ran on the same MacBook Pro with an M3 Max against a Pixel 6a on Android 15 and an iPhone 13, with no rules file and no custom instructions. A diff counted as merged only if we accepted it untouched, flutter test stayed green and the analyzer gained no error or warning. Infos are advisory here, and we counted them anyway.
| Metric | Cursor (Pro / Pro+) | GitHub Copilot (Pro) |
|---|---|---|
| Task 1: files in the merged diff | 4 ✓ | 2 |
| Task 1: time to a mergeable diff | 54 s ✓ | 2 m 10 s |
| Task 1: new analyzer infos left behind | 0 ✓ | 2 |
| Task 2: fix used | CustomScrollView + SliverList ✓ | shrinkWrap: true |
| Task 2: first-frame build over 1,200 rows | 44 ms ✓ | 380 ms |
| Task 3: files touched | 14 ✓ | 9 |
| Task 3: ran build_runner unprompted | Yes, twice ✓ | No, edited the .g.dart by hand |
| Task 3: analyzer errors after the diff | 0 ✓ | 6 |
| Task 3: golden images its diff changed | 0 of 4 ✓ | 2 of 4, via --update-goldens |
| Task 4: widget tests written | 31 ✓ | 12 |
| Task 4: planted breaks caught (of 5) | 3 of 5 ✓ | 2 of 5 |
| Tasks merged without an edit (of 4) | 4 of 4 ✓ | 2 of 4 |
| Spend for the four days | $80 ($20 Pro + $60 Pro+) | $10 ✓ |
| Cleanup we logged ourselves | 0.6 h ✓ | 3.2 h |
| Cost per merged change at $75/hour | $31.25 ✓ | $125.00 |
| Wall clock across all four tasks | 5 h 40 m ✓ | 7 h 05 m |
| Winner | 🏆 Cursor: 4 of 4 merged | Cheaper seat, half the diffs |
Cursor changed 14 files to get one screen off setState, ran build_runner twice without being asked, and left all four golden images byte-identical. $20 a month for the four-file Diff, $31.25 per merged change in this test.
Keep exploring — these related comparisons and guides help you decide.