Help us improve
Share bugs, ideas, or general feedback.
From ennam-dev-agent-team
Development protocol for mobile-dev agent working with Flutter (primary) and React Native (secondary). Covers project detection, architecture patterns, state management conventions, testing, and platform-specific guidelines. Automatically loaded by the mobile-dev agent.
npx claudepluginhub en-nam/ennam-claude-agent-team --plugin ennam-dev-agent-teamHow this skill is triggered — by the user, by Claude, or both
Slash command
/ennam-dev-agent-team:flutter-dev-protocolThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
On task start, auto-detect the project type:
Guides Flutter development for cross-platform iOS, Android, Web apps. Covers non-interactive CLI, project setup, state management, widgets, GoRouter navigation, platform channels, testing, CI/CD.
Provides Flutter/Dart guidance on architecture (BLoC, Riverpod), state management, widgets, navigation (GoRouter), data (Dio, Hive), performance, and testing for cross-platform mobile apps.
Provides expert Flutter/Dart patterns for cross-platform mobile apps including feature-first project structure, const widget best practices, and Riverpod/Bloc state management.
Share bugs, ideas, or general feedback.
On task start, auto-detect the project type:
pubspec.yaml → Flutter projectpackage.json with react-native dependency → React Native projectBefore starting work on a new Flutter project:
pubspec.yaml dependencies:
flutter_riverpod or riverpod for state managementgo_router for routingflutter_test in dev_dependenciesintegration_test in dev_dependenciesanalysis_options.yaml for strict linting ruleslib/ for existing architecture patterns (feature-first, layer-first)Use Riverpod as the default state management solution:
// lib/features/products/presentation/providers/product_provider.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
final productListProvider = FutureProvider.autoDispose<List<Product>>((ref) async {
final repository = ref.read(productRepositoryProvider);
return repository.getProducts();
});
Rules:
ConsumerWidget or ConsumerStatefulWidget (not StatelessWidget + Consumer)autoDispose for providers that should clean up when no longer listened toref.watch in build methods, ref.read in callbacks// lib/core/router/app_router.dart
final routerProvider = Provider<GoRouter>((ref) {
return GoRouter(
routes: [
GoRoute(path: '/', builder: (_, __) => const HomeScreen()),
GoRoute(path: '/products/:id', builder: (_, state) =>
ProductDetailScreen(id: state.pathParameters['id']!)),
],
);
});
const constructors when possibleKey for list items — ValueKey(item.id) for listsPlatform.isIOS / Platform.isAndroid for platform-specific behaviorLayoutBuilder or MediaQuery for adaptive layouts# Unit tests
flutter test test/unit/ --reporter=expanded
# Widget tests
flutter test test/widget/ --reporter=expanded
# Integration tests (requires device/emulator)
flutter test integration_test/ --reporter=expanded
# All tests
flutter test --reporter=expanded
Test structure:
test/
├── unit/
│ └── features/
│ └── products/
│ └── product_repository_test.dart
├── widget/
│ └── features/
│ └── products/
│ └── product_card_test.dart
└── helpers/
├── test_helper.dart
└── mocks.dart
# Quick analysis
dart analyze
# Format check
dart format --set-exit-if-changed lib/ test/
# Build Android (debug, fast)
flutter build apk --debug
# Build iOS (debug, fast — macOS only)
flutter build ios --debug --no-codesign
When working on a React Native project, adapt these patterns:
npx jest --passWithNoTests
npx react-native run-android
npx react-native run-ios
mobile/<task-id>-<short-description>
Examples:
mobile/task-010-product-listing-screenmobile/task-011-cart-providermobile/task-012-checkout-flowYou may ONLY modify:
lib/, android/, ios/, test/, integration_test/, pubspec.yaml, analysis_options.yamlsrc/, android/, ios/, __tests__/, package.json (dependencies only, with team-lead approval)NEVER modify shared types, backend code, or web frontend code.