Flutter SDK for cross-platform development targeting iOS, Android, and Web. Use for widget architecture, state management, platform channels, and multi-platform deployment.
Provides Flutter SDK expertise for cross-platform mobile, web, and desktop development. Use when creating Flutter projects, writing widget/state management code, or running CLI commands for building, testing, and deploying apps.
/plugin marketplace add FortiumPartners/ensemble/plugin install ensemble-development@ensembleThis skill inherits all available tools. When active, it can use any tool Claude has access to.
README.mdREFERENCE.mdexamples/ci-cd.example.yamlFlutter is Google's UI toolkit for building natively compiled applications for mobile (iOS, Android), web, and desktop from a single Dart codebase.
Flutter CLI can enter interactive mode which will hang Claude Code. Always use flags to bypass prompts:
| Command | WRONG (Interactive) | CORRECT (Non-Interactive) |
|---|---|---|
| Create project | flutter create (prompts) | flutter create my_app --org com.example |
| Run app | flutter run (prompts for device) | flutter run -d <device_id> |
| Build | flutter build (may prompt) | flutter build apk --release |
| Emulators | flutter emulators --launch | flutter emulators --launch <emulator_id> |
Always include:
-d <device_id> for device selection (use flutter devices to list)apk, appbundle, ios, web)--no-pub when pub get is not needed--suppress-analytics in CI/CD environmentsNever use in Claude Code:
flutter --version # Expected: Flutter 3.x.x
flutter doctor # Check all requirements
flutter devices # List available devices
flutter emulators # List available emulators
├── Create new project ────────────────► flutter create <name> --org <org>
├── Get dependencies ──────────────────► flutter pub get
├── Upgrade dependencies ──────────────► flutter pub upgrade
├── Clean build artifacts ─────────────► flutter clean
└── Check project health ──────────────► flutter doctor
├── Run on device ─────────────────────► flutter run -d <device_id>
├── Run in release mode ───────────────► flutter run --release -d <device_id>
├── Attach to running app ─────────────► flutter attach -d <device_id>
└── View logs ─────────────────────────► flutter logs -d <device_id>
├── Build Android APK ─────────────────► flutter build apk --release
├── Build Android App Bundle ──────────► flutter build appbundle --release
├── Build iOS ─────────────────────────► flutter build ios --release
├── Build iOS (no codesign) ───────────► flutter build ios --release --no-codesign
└── Build Web ─────────────────────────► flutter build web --release
├── Run all tests ─────────────────────► flutter test
├── Run specific test file ────────────► flutter test test/widget_test.dart
├── Run with coverage ─────────────────► flutter test --coverage
└── Run integration tests ─────────────► flutter test integration_test/
├── Analyze code ──────────────────────► flutter analyze
├── Format code ───────────────────────► dart format .
└── Fix lint issues ───────────────────► dart fix --apply
See REFERENCE.md for complete CLI options, flavors, and advanced build configurations.
my_app/
├── lib/
│ ├── main.dart # Entry point
│ ├── app.dart # App widget
│ ├── features/ # Feature modules
│ │ └── auth/
│ │ ├── data/ # Repositories, data sources
│ │ ├── domain/ # Entities, use cases
│ │ └── presentation/ # Widgets, providers
│ ├── core/ # Shared utilities
│ └── l10n/ # Localization
├── test/ # Unit and widget tests
├── integration_test/ # Integration tests
├── android/ # Android platform code
├── ios/ # iOS platform code
├── web/ # Web platform code
├── pubspec.yaml # Dependencies
└── analysis_options.yaml # Lint rules
See REFERENCE.md for complete pubspec.yaml and analysis_options.yaml configurations.
// Provider definition
@riverpod
class Counter extends _$Counter {
@override
int build() => 0;
void increment() => state++;
void decrement() => state--;
}
// Usage in widget
class CounterWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Text('Count: $count');
}
}
class CartNotifier extends ChangeNotifier {
final List<Item> _items = [];
List<Item> get items => List.unmodifiable(_items);
void addItem(Item item) {
_items.add(item);
notifyListeners();
}
}
// Usage
final cart = context.watch<CartNotifier>();
// Events and States
sealed class AuthEvent {}
class LoginRequested extends AuthEvent {
final String email, password;
LoginRequested(this.email, this.password);
}
sealed class AuthState {}
class AuthLoading extends AuthState {}
class AuthSuccess extends AuthState { final User user; AuthSuccess(this.user); }
// Bloc
class AuthBloc extends Bloc<AuthEvent, AuthState> {
AuthBloc() : super(AuthInitial()) {
on<LoginRequested>(_onLoginRequested);
}
}
See REFERENCE.md for complete Riverpod architecture, Bloc patterns, and provider types.
class UserCard extends StatelessWidget {
final User user;
final VoidCallback? onTap;
const UserCard({required this.user, this.onTap, super.key});
@override
Widget build(BuildContext context) {
return Card(
child: ListTile(
leading: CircleAvatar(backgroundImage: NetworkImage(user.avatarUrl)),
title: Text(user.name),
subtitle: Text(user.email),
onTap: onTap,
),
);
}
}
class SearchField extends StatefulWidget {
final ValueChanged<String> onChanged;
const SearchField({required this.onChanged, super.key});
@override
State<SearchField> createState() => _SearchFieldState();
}
class _SearchFieldState extends State<SearchField> {
final _controller = TextEditingController();
Timer? _debounce;
@override
void dispose() {
_debounce?.cancel();
_controller.dispose();
super.dispose();
}
void _onSearchChanged(String value) {
_debounce?.cancel();
_debounce = Timer(const Duration(milliseconds: 300), () {
widget.onChanged(value);
});
}
@override
Widget build(BuildContext context) {
return TextField(controller: _controller, onChanged: _onSearchChanged);
}
}
See REFERENCE.md for compound widgets, builder patterns, and hook widgets.
final router = GoRouter(
initialLocation: '/',
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
routes: [
GoRoute(
path: 'user/:id',
builder: (context, state) {
final id = state.pathParameters['id']!;
return UserScreen(userId: id);
},
),
],
),
],
errorBuilder: (context, state) => ErrorScreen(error: state.error),
);
// Usage
context.go('/user/123');
context.push('/user/123');
context.pop();
See REFERENCE.md for deep linking, shell routes, and platform-specific configuration.
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart' show kIsWeb;
Widget build(BuildContext context) {
if (kIsWeb) return WebSpecificWidget();
if (Platform.isIOS) return CupertinoWidget();
if (Platform.isAndroid) return MaterialWidget();
return DefaultWidget();
}
class BatteryLevel {
static const platform = MethodChannel('com.example.app/battery');
Future<int> getBatteryLevel() async {
try {
return await platform.invokeMethod('getBatteryLevel');
} on PlatformException catch (e) {
throw Exception('Failed: ${e.message}');
}
}
}
See REFERENCE.md for iOS/Android native code, conditional imports, and event channels.
flutter build web --web-renderer canvaskit # Better fidelity, larger
flutter build web --web-renderer html # Smaller size
flutter build web --web-renderer auto # Auto-detect
Best for: Internal tools, dashboards, PWAs, authenticated apps Note: Flutter web renders to canvas - limited SEO by default
void main() {
testWidgets('Counter increments', (tester) async {
await tester.pumpWidget(const MyApp());
expect(find.text('0'), findsOneWidget);
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
expect(find.text('1'), findsOneWidget);
});
}
testWidgets('Button matches golden', (tester) async {
await tester.pumpWidget(MaterialApp(home: MyButton(label: 'Submit')));
await expectLater(find.byType(MyButton), matchesGoldenFile('goldens/my_button.png'));
});
// Update: flutter test --update-goldens
See REFERENCE.md for integration tests, provider testing, and complete test patterns.
| Error | Solution |
|---|---|
No connected devices | Run flutter devices, start emulator |
Gradle build failed | Run flutter doctor, check Android Studio |
CocoaPods not installed | sudo gem install cocoapods |
pub get failed | Check pubspec.yaml, run flutter clean |
flutter run -v # Verbose output
flutter doctor -v # Check for issues
flutter clean && flutter pub get # Clean rebuild
See REFERENCE.md for complete troubleshooting guide and CI/CD issues.
- uses: subosito/flutter-action@v2
with:
flutter-version: "3.24.0"
channel: stable
cache: true
- run: flutter pub get
- run: flutter analyze
- run: flutter test --coverage
- run: flutter build apk --release
See REFERENCE.md for complete GitHub Actions workflows and multi-platform builds.
This skill auto-loads when Flutter context is detected:
File-based triggers:
pubspec.yaml with flutter dependencylib/main.dart present.dart files in projectandroid/ and ios/ directoriesContext-based triggers:
| Agent | Use Case |
|---|---|
mobile-developer | Primary agent for Flutter development |
deep-debugger | Performance profiling, crash analysis |
code-reviewer | Dart code review, accessibility audit |
deployment-orchestrator | App store submissions |
Handoff to Deep-Debugger:
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.