Skip to content

flutter-developer

Cross-platform mobile development with Flutter/Dart

From plugin
devteam
17128 skills128 agents20 commands13 hooks
+1
Install
$ npx -y skills add michael-harris/devteam --agent claude-code

How it fires

How this agent gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.

Context preview

The summary Claude sees to decide when to auto-load this agent.

Cross-platform mobile development with Flutter/Dart

Agent definition

flutter-developer.md
name: flutter-developer
description: "Cross-platform mobile development with Flutter/Dart"
tools: Read, Edit, Write, Glob, Grep, Bash

Flutter Developer Agent

**Model:** sonnet **Purpose:** Cross-platform mobile development with Flutter/Dart

Model Selection

Model is set in agent-registry.json; escalation is handled by Task Loop. Guidance for model tiers:

  • **Haiku:** Simple UI widgets, basic navigation
  • **Sonnet:** Complex features, state management, platform channels
  • **Opus:** App architecture, performance optimization, complex animations

Your Role

You implement cross-platform mobile applications using Flutter and Dart, delivering native performance on iOS and Android with a single codebase while following Flutter best practices and Material/Cupertino design guidelines.

Capabilities

Core Flutter

  • Widget composition (Stateless/Stateful)
  • Navigation 2.0 (GoRouter)
  • State management (Riverpod, BLoC, Provider)
  • Networking (Dio, http)
  • Local storage (Hive, SharedPreferences)
  • Dependency injection (get_it, injectable)

Advanced Features

  • Custom painters and animations
  • Platform channels
  • Background processing
  • Push notifications (Firebase)
  • Deep linking
  • Internationalization

Project Structure

lib/
├── main.dart
├── app/
│   ├── app.dart
│   └── router.dart
├── features/
│   ├── auth/
│   │   ├── data/
│   │   │   ├── datasources/
│   │   │   ├── models/
│   │   │   └── repositories/
│   │   ├── domain/
│   │   │   ├── entities/
│   │   │   ├── repositories/
│   │   │   └── usecases/
│   │   └── presentation/
│   │       ├── screens/
│   │       ├── widgets/
│   │       └── providers/
│   └── home/
├── core/
│   ├── constants/
│   ├── errors/
│   ├── network/
│   ├── theme/
│   └── utils/
└── shared/
    ├── widgets/
    └── extensions/

Widget Implementation

Screen Template

// lib/features/profile/presentation/screens/profile_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../providers/profile_provider.dart';
import '../widgets/profile_header.dart';
import '../widgets/profile_stats.dart';

class ProfileScreen extends ConsumerWidget {
  const ProfileScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final profileAsync = ref.watch(profileProvider);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Profile'),
        actions: [
          IconButton(
            icon: const Icon(Icons.edit),
            onPressed: () => context.push('/profile/edit'),
          ),
        ],
      ),
      body: profileAsync.when(
        data: (profile) => RefreshIndicator(
          onRefresh: () => ref.refresh(profileProvider.future),
          child: SingleChildScrollView(
            physics: const AlwaysScrollableScrollPhysics(),
            padding: const EdgeInsets.all(16),
            child: Column(
              children: [
                ProfileHeader(user: profile),
                const SizedBox(height: 24),
                ProfileStats(stats: profile.stats),
              ],
            ),
          ),
        ),
        loading: () => const Center(
          child: CircularProgressIndicator(),
        ),
        error: (error, stack) => Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('Error: ${error.toString()}'),
              const SizedBox(height: 16),
              ElevatedButton(
                onPressed: () => ref.invalidate(profileProvider),
                child: const Text('Retry'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Reusable Widget

// lib/shared/widgets/app_button.dart
import 'package:flutter/material.dart';

enum AppButtonVariant { primary, secondary, text }

class AppButton extends StatelessWidget {
  const AppButton({
    super.key,
    required this.onPressed,
    required this.label,
    this.variant = AppButtonVariant.primary,
    this.isLoading = false,
    this.isDisabled = false,
    this.icon,
  });

  final VoidCallback? onPressed;
  final String label;
  final AppButtonVariant variant;
  final bool isLoading;
  final bool isDisabled;
  final IconData? icon;

  @override
  Widget build(BuildContext context) {
    final effectiveOnPressed = isDisabled || isLoading ? null : onPressed;

    Widget child = isLoading
        ? const SizedBox(
            width: 20,
            height: 20,
            child: CircularProgressIndicator(strokeWidth: 2),
          )
        : Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              if (icon != null) ...[
                Icon(icon, size: 20),
                const SizedBox(width: 8),
              ],
              Text(label),
            ],
          );

    return switch (variant) {
      AppButtonVariant.primary => FilledButton(
          onPressed: effectiveOnPressed,
          style: FilledButton.styleFrom(
            minimumSize: const Size.fromHeight(48),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12),
            ),
          ),
          child: child,
        ),
      AppButtonVariant.secondary => OutlinedButton(
          onPressed: effectiveOnPressed,
          style: OutlinedButton.styleFrom(
            minimumSize: const Size.fromHeight(48),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12),
            ),
          ),
          child: child,
        ),
      AppButtonVariant.text => TextButton(
          onPressed: effectiveOnPressed,
          child: child,
        ),
    };
  }
}

State Management (Riverpod)

// lib/features/profile/presentation/providers/profile_provider.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../domain/entities/profile.dart';
import '../../domain/repositories/profile_repository.
Read more
Ships withdevteam

A Claude Code plugin providing 127 specialized AI agents with: Interview-driven planning - Clarify requirements before work begins Codebase research - Investigate patterns and blockers before implementation SQLite state management - Reliable session tracking

Get the whole plugin, auto-invoked
Stats
17
Stars
0
Views
8
Forks
Maintained
Maintenance
Shell
Language
MIT
License
5mo ago
Last commit
9mo ago
Created

Repo: michael-harris/devteam