---
name: developing-with-flutter
description: Flutter SDK for cross-platform development targeting iOS, Android, and Web. Use for widget architecture, state management, platform channels, and multi-platform deployment.
---

# Flutter SDK Skill

## Quick Reference

Flutter is Google's UI toolkit for building natively compiled applications for mobile (iOS, Android), web, and desktop from a single Dart codebase.

---

## Table of Contents

1. [Critical: Avoiding Interactive Mode](#critical-avoiding-interactive-mode)
2. [Prerequisites](#prerequisites)
3. [CLI Decision Tree](#cli-decision-tree)
4. [Project Structure](#project-structure)
5. [State Management](#state-management)
6. [Widget Patterns](#widget-patterns)
7. [Navigation (GoRouter)](#navigation-gorouter)
8. [Platform-Specific Code](#platform-specific-code)
9. [Web-Specific Considerations](#web-specific-considerations)
10. [Testing](#testing)
11. [Error Handling](#error-handling)
12. [CI/CD Integration](#cicd-integration)
13. [Auto-Detection Triggers](#auto-detection-triggers)
14. [Agent Integration](#agent-integration)
15. [Sources](#sources)

---

## Critical: Avoiding Interactive Mode

**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)
- Explicit build targets (`apk`, `appbundle`, `ios`, `web`)
- `--no-pub` when pub get is not needed
- `--suppress-analytics` in CI/CD environments

**Never use in Claude Code**:
- Commands that open GUI (Android Studio, Xcode)
- Interactive device selection prompts
- Commands without explicit targets

---

## Prerequisites

```bash
flutter --version          # Expected: Flutter 3.x.x
flutter doctor             # Check all requirements
flutter devices            # List available devices
flutter emulators          # List available emulators
```

---

## CLI Decision Tree

### Project Setup
```
├── 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
```

### Development
```
├── 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>
```

### Building
```
├── 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
```

### Testing
```
├── 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/
```

### Code Quality
```
├── Analyze code ──────────────────────► flutter analyze
├── Format code ───────────────────────► dart format .
└── Fix lint issues ───────────────────► dart fix --apply
```

> **See [REFERENCE.md](REFERENCE.md#complete-cli-reference)** for complete CLI options, flavors, and advanced build configurations.

---

## Project Structure

```
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](REFERENCE.md#project-configuration)** for complete pubspec.yaml and analysis_options.yaml configurations.

---

## State Management

### Riverpod (Recommended)

```dart
// 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');
  }
}
```

### Provider (Simple apps)

```dart
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>();
```

### Bloc (Enterprise apps)

```dart
// 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](REFERENCE.md#state-management-deep-dive)** for complete Riverpod architecture, Bloc patterns, and provider types.

---

## Widget Patterns

### StatelessWidget

```dart
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,
      ),
    );
  }
}
```

### StatefulWidget

```dart
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](REFERENCE.md#widget-architecture)** for compound widgets, builder patterns, and hook widgets.

---

## Navigation (GoRouter)

```dart
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](REFERENCE.md#navigation-patterns)** for deep linking, shell routes, and platform-specific configuration.

---

## Platform-Specific Code

### Platform Checks

```dart
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();
}
```

### Platform Channels (Native Integration)

```dart
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](REFERENCE.md#platform-specific-development)** for iOS/Android native code, conditional imports, and event channels.

---

## Web-Specific Considerations

### Build Renderers

```bash
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

---

## Testing

### Widget Tests

```dart
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);
  });
}
```

### Golden Tests

```dart
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](REFERENCE.md#testing-strategies)** for integration tests, provider testing, and complete test patterns.

---

## Error Handling

| 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` |

### Debug Commands

```bash
flutter run -v                    # Verbose output
flutter doctor -v                 # Check for issues
flutter clean && flutter pub get  # Clean rebuild
```

> **See [REFERENCE.md](REFERENCE.md#troubleshooting)** for complete troubleshooting guide and CI/CD issues.

---

## CI/CD Integration

```yaml
- 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](REFERENCE.md#cicd-integration)** for complete GitHub Actions workflows and multi-platform builds.

---

## Auto-Detection Triggers

This skill auto-loads when Flutter context is detected:

**File-based triggers**:
- `pubspec.yaml` with `flutter` dependency
- `lib/main.dart` present
- `.dart` files in project
- `android/` and `ios/` directories

**Context-based triggers**:
- User mentions "Flutter"
- User runs flutter CLI commands
- Widget development discussions

---

## Agent Integration

| 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**:
- Performance profiling needed
- Crash analysis required
- Memory leak investigation
- Platform-specific bugs

---

## Sources

- [Flutter CLI Reference](https://docs.flutter.dev/reference/flutter-cli)
- [Flutter Documentation](https://docs.flutter.dev)
- [Effective Dart](https://dart.dev/effective-dart)
- [Flutter State Management](https://docs.flutter.dev/data-and-backend/state-mgmt)
