Rules file: AGENTS.md
Flutter's API has been stable for years but its widget catalogue has churned, and Dart's move to sound null safety split training data into pre and post eras that do not compile together. An agent needs the Flutter and Dart versions, the state management approach the project actually uses, and whether Material 3 is enabled. Layout errors here are constraint errors rather than style errors, so an agent that does not reason about bounded and unbounded constraints will keep producing overflow warnings it cannot explain.
The content is the same across agents, only the filename differs. Copy this, adapt the commands to your repository, and save it as AGENTS.md.
# AGENTS.md
This is a Flutter application for iOS and Android using Riverpod, go_router, and code generation.
## Project
Stack: Flutter stable channel, Dart 3, Riverpod (code generated providers), go_router, freezed, json_serializable, dio.
Layout:
- `lib/main.dart` entry point and provider scope
- `lib/app/router.dart` go_router configuration, the single source of routes
- `lib/app/theme.dart` ThemeData, colors, typography
- `lib/features/<feature>/presentation/` screens and widgets
- `lib/features/<feature>/application/` providers and controllers
- `lib/features/<feature>/domain/` freezed models and value objects
- `lib/features/<feature>/data/` repositories and API clients
- `lib/shared/` widgets and utilities used by more than one feature
- `test/` mirrors `lib/`
Generated files end in `.freezed.dart`, `.g.dart`. They are outputs, not sources.
## Commands
```bash
flutter pub get # install dependencies
flutter run # run on the connected device
flutter run -d ios / -d android # target a platform
dart run build_runner build --delete-conflicting-outputs # codegen, run after model or provider changes
dart run build_runner watch --delete-conflicting-outputs # codegen in watch mode
flutter analyze # static analysis, must be clean
dart format lib test
flutter test # unit and widget tests
flutter test test/features/auth # one directory
flutter build apk --release
flutter build ipa --release
flutter clean # when the build cache is suspect
```
After changing any freezed model, JSON model, or annotated provider, run build_runner before running or testing. A missing codegen step shows up as unresolved symbols.
## Platform notes
- Permissions: declare in `android/app/src/main/AndroidManifest.xml` and `ios/Runner/Info.plist`. Both are required, and iOS needs a human readable usage string.
- Minimum versions: iOS 13, Android minSdk 23. Do not raise them without approval.
- Android system back is handled by go_router. Use `PopScope` for any screen that must confirm before leaving.
- Use `Theme.of(context).platform` for behavioral differences, not `Platform.isIOS`, so widget tests stay controllable.
- Safe areas: wrap scaffold bodies in `SafeArea`. Do not hardcode notch or status bar heights.
- Adding or upgrading a plugin with native code requires `flutter clean` and a full rebuild, hot reload will not pick it up.
- Test on both a physical Android device and an iOS simulator before calling a UI change done.
## Code style
- Widgets are classes, never functions returning a Widget. Extract a `StatelessWidget` instead of a `_buildX` method.
- Use `const` constructors wherever possible. `flutter analyze` must pass with zero warnings.
- State lives in providers. A `StatefulWidget` is only for animation controllers, focus nodes, and text controllers.
- Watch providers with `ref.watch` in build and `ref.read` in callbacks. Never call `ref.read` during build.
- Models are freezed classes with `fromJson`. No hand written `copyWith` or `==`.
- Repositories return domain models, never raw `Map<String, dynamic>`.
- Navigation goes through named routes in `lib/app/router.dart`. No `Navigator.push` with an inline `MaterialPageRoute`.
- Colors, spacing, and text styles come from the theme. No raw `Color(0xFF...)` in a widget.
- Async work in the UI layer goes through `AsyncValue` and renders loading and error states explicitly.
## Boundaries
Do not touch without explicit instruction:
- Any `.freezed.dart` or `.g.dart` file. Change the source and rerun build_runner.
- `ios/` and `android/` build configuration, signing, Gradle files, and `Podfile.lock`.
- `pubspec.lock`. Change `pubspec.yaml` and run `flutter pub get`.
- App identifiers, version, and build number in `pubspec.yaml`.
- `.github/workflows/`, fastlane configuration, and store metadata.
Needs human review: new plugins with native dependencies, permission additions, deep link configuration, and any change to `lib/app/router.dart` route names.
## Testing
- `flutter test` runs unit and widget tests.
- Required unit tests: repositories, controllers and notifiers, and any pure Dart helper.
- Widget tests cover screens with conditional rendering, using `ProviderScope` overrides for fakes.
- Integration tests in `integration_test/` cover sign in and the primary user flow only, they are slow and stay minimal.
- Golden tests are used only for shared design system widgets. Regenerate deliberately, never with a blanket update.
- A bug fix ships with a test that fails before the fix.
## Git workflow
- Branch from `main`: `feat/short-description`, `fix/short-description`.
- Conventional commits: `feat(profile): add avatar upload`.
- Generated files are committed, but regenerate them in a separate commit from behavior changes so the diff stays readable.
- PR description includes screenshots from both platforms for any UI change.
- Never commit to `main`.
These are the failures that repeat across sessions, so each one belongs in AGENTS.md.
A codebase using Riverpod, Bloc, or Provider will still get StatefulWidget plus setState from an agent, because that is the simplest working answer and the surrounding files may not show the pattern. The result is state that no other widget can observe and that bypasses your testing setup. Add to your rules file: 'This project uses [your solution]. New feature state goes through it. setState is acceptable only for purely local widget concerns such as an animation flag or a text field focus state.'
RaisedButton, FlatButton, OutlineButton, the new keyword, and nullable-by-default parameter handling all still appear in agent output, and none of them compile against a current SDK. The failure is at least loud, but it costs a full round trip every time. State it: 'Flutter 3.x with sound null safety and Material 3. Use ElevatedButton, TextButton, and OutlinedButton. Never emit the new keyword or code that assumes implicit nullability.'
Agents write an async handler that awaits a network call and then calls Navigator.of(context) or shows a SnackBar, without checking that the widget is still mounted. If the user navigated away during the await, this throws or targets a disposed element. Add: 'After any await in a widget or State method, check mounted before touching BuildContext. The use_build_context_synchronously lint must stay enabled and its warnings are errors.'
Agents put a ListView inside a Column, or a Column inside a Column, and hit an unbounded height constraint that renders as a yellow overflow stripe or a hard exception. They then add shrinkWrap: true as a blanket fix, which works visually and destroys scroll performance on long lists. Write: 'Resolve unbounded constraints with Expanded or Flexible, or use CustomScrollView with slivers. shrinkWrap is only for genuinely short, non-scrolling lists and its use needs a comment.'
AnimationController, TextEditingController, ScrollController, and StreamSubscription all get created in initState by agents and then never disposed, which leaks and produces setState-after-dispose errors that surface far from the cause. Add: 'Every controller or subscription created in initState is disposed in dispose. If a widget has initState it must have a matching dispose unless there is nothing to release.'
Agents build widget trees with no const anywhere, so subtrees that never change are rebuilt on every parent rebuild. Nothing breaks, the app just does more work per frame than it needs to, and it compounds in long lists. Write: 'flutter_lints is enabled with prefer_const_constructors and prefer_const_literals_to_create_immutables. Mark every widget const where the analyzer allows it, and run dart analyze before finishing.'
Webapp Testing
Tests local web applications using Playwright for verifying frontend functionality, debugging UI behavior, and capturing screenshots.
artifacts-builder
Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui).
great_cto
Claude Code plugin: 7 specialised subagents (tech-lead, senior-dev, qa-engineer, security-officer, devops, l3-support, project-auditor) orchestrating a full SDLC pipeline — architecture, TDD, 12-angle code review, QA, security audit, deploy. 11 project archetypes auto-detected, 13 compliance frameworks (GDPR/PCI-DSS/HIPAA/SOC2/ISO 27001), self-improving knowledge layer that learns from every incident.
iOS Simulator
Enables Claude to interact with iOS Simulator for testing and debugging iOS applications.