Use Cases (Actualizado: 2/6/2026)

Claude Code para Flutter/Dart: mapa del proyecto, estado, tests y builds

Flujo práctico para Claude Code en Flutter/Dart: pubspec, widgets, estado, tests, builds y verificación.

Claude Code para Flutter/Dart: mapa del proyecto, estado, tests y builds

Claude Code aporta más valor en Flutter/Dart cuando lo tratas como un compañero que entiende el proyecto, no como un generador de widgets sueltos. Un cambio real suele tocar lib/, pubspec.yaml, assets, tests, configuración de Android e iOS, limitaciones web, emuladores y comandos de build. Un widget es una pieza de interfaz, el state es el dato que cambia lo que ve el usuario, y pubspec es el archivo que declara dependencias, recursos y restricciones de SDK.

El ejemplo de esta guía es una pantalla pequeña de carrito. Es lo bastante simple para pegarla en un proyecto creado con flutter create, pero muestra problemas típicos: crear estado dentro de build, añadir paquetes sin necesidad, olvidarse de widget tests o asumir que Android, iOS y Web se comportan igual.

Consulta la documentación oficial al adaptar los ejemplos: Flutter CLI, Flutter testing, Widget testing, Flutter pubspec options, Dart pubspec, Platform channels y Claude Code common workflows. Como lectura relacionada, compara con React Native, estrategias de testing y buenas prácticas de CLAUDE.md.

Empieza con un mapa del proyecto

No empieces con “haz una pantalla de carrito”. Pide primero a Claude Code que inspeccione el repositorio sin editar. Ese harness, o marco de trabajo seguro, define archivos permitidos, restricciones, comandos y criterios de revisión.

Lee primero este proyecto Flutter.
No edites archivos todavía.
Informa:
1. Restricciones de SDK, dependencias y assets en pubspec.yaml
2. Estructura de UI, estado y capa data bajo lib/
3. Estilo de tests existente en test/ e integration_test/
4. Targets activos en android/, ios/, web/, macos/, windows/ y linux/
5. Si flutter analyze, flutter test y los builds están documentados
Termina con archivos seguros para editar y archivos que no deben tocarse.
ÁreaPuede hacer Claude CodeDecide la persona
MapaConvenciones, dependencias, estilo de testsLímites de edición
WidgetComponente, accesibilidad, responsiveCopy de producto y diseño
EstadoAjustarse a setState, ChangeNotifier, Riverpod, Bloc o patrón existenteEstrategia global de estado
pubspecProponer dependencias y assetsAprobar paquetes nuevos
PlataformaDiferencias Android/iOS/Web/DesktopTargets soportados y requisitos de tienda
Tests/buildWidget test, integration test, comandosDecisión de merge y release

Controla pubspec con cuidado

pubspec.yaml parece pequeño, pero controla resolución de dependencias, assets, restricciones de SDK y paquetes de test. Antes de editarlo, Claude Code debe explicar razón, alternativas, impacto y comandos de verificación.

name: cart_ai_demo
description: A small Flutter cart screen used to verify Claude Code prompts.
publish_to: "none"

environment:
  sdk: ">=3.4.0 <4.0.0"

dependencies:
  flutter:
    sdk: flutter

dev_dependencies:
  flutter_test:
    sdk: flutter
  integration_test:
    sdk: flutter
  flutter_lints: ^6.0.0

flutter:
  uses-material-design: true
  assets:
    - assets/images/

Para un sandbox nuevo, usa esta base. En un repositorio existente, pide que adapte los comandos al proyecto actual.

flutter create cart_ai_demo
cd cart_ai_demo
flutter pub get
flutter analyze
flutter test

Los fallos frecuentes son: romper la indentación de assets, actualizar dependencias y pubspec.lock sin mirar el impacto, y añadir una librería de estado para una pantalla que no la necesita. Un prompt seguro:

Revisa pubspec.yaml y decide si el cambio del carrito necesita una dependencia nueva.
Antes de editar, muestra razón, alternativas, archivos afectados y comandos de verificación.
No modifiques pubspec.yaml ni pubspec.lock hasta que apruebe el plan.

Cambia widget y estado en una unidad pequeña

Este código puede reemplazar lib/main.dart en un proyecto creado con flutter create cart_ai_demo. Solo usa APIs del SDK de Flutter. CartController concentra los cambios de estado y el widget renderiza.

import 'package:flutter/material.dart';

void main() => runApp(const CartDemoApp());

class CartDemoApp extends StatelessWidget {
  const CartDemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Cart AI Demo',
      theme: ThemeData(colorSchemeSeed: Colors.teal, useMaterial3: true),
      home: const CartSummaryPage(),
    );
  }
}

class CartLine {
  const CartLine({required this.name, required this.price, required this.quantity});
  final String name;
  final int price;
  final int quantity;

  CartLine copyWith({int? quantity}) =>
      CartLine(name: name, price: price, quantity: quantity ?? this.quantity);
}

class CartController extends ChangeNotifier {
  final List<CartLine> _lines = const [
    CartLine(name: 'Dart notebook', price: 1800, quantity: 1),
    CartLine(name: 'Flutter sticker', price: 500, quantity: 2),
  ].toList();

  List<CartLine> get lines => List.unmodifiable(_lines);
  int get total => _lines.fold(0, (sum, line) => sum + line.price * line.quantity);

  void increment(int index) {
    final line = _lines[index];
    _lines[index] = line.copyWith(quantity: line.quantity + 1);
    notifyListeners();
  }

  void decrement(int index) {
    final line = _lines[index];
    if (line.quantity == 1) return;
    _lines[index] = line.copyWith(quantity: line.quantity - 1);
    notifyListeners();
  }
}

class CartSummaryPage extends StatefulWidget {
  const CartSummaryPage({super.key});

  @override
  State<CartSummaryPage> createState() => _CartSummaryPageState();
}

class _CartSummaryPageState extends State<CartSummaryPage> {
  late final CartController controller;

  @override
  void initState() {
    super.initState();
    controller = CartController();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Cart summary')),
      body: AnimatedBuilder(
        animation: controller,
        builder: (context, _) => ListView(
          padding: const EdgeInsets.all(16),
          children: [
            for (final entry in controller.lines.indexed)
              ListTile(
                title: Text(entry.$2.name),
                subtitle: Text('JPY ${entry.$2.price} x ${entry.$2.quantity}'),
                trailing: Wrap(
                  spacing: 8,
                  children: [
                    IconButton(
                      tooltip: 'Decrease ${entry.$2.name}',
                      onPressed: () => controller.decrement(entry.$1),
                      icon: const Icon(Icons.remove_circle_outline),
                    ),
                    IconButton(
                      tooltip: 'Increase ${entry.$2.name}',
                      onPressed: () => controller.increment(entry.$1),
                      icon: const Icon(Icons.add_circle_outline),
                    ),
                  ],
                ),
              ),
            const Divider(),
            Text('Total: JPY ${controller.total}',
                style: Theme.of(context).textTheme.headlineSmall),
          ],
        ),
      ),
    );
  }
}

El prompt debe fijar límites claros:

Actualiza la UI del carrito, pero mantiene los cambios de estado dentro de CartController.
No crees CartController dentro de build. No añadas paquetes.
Añade un widget test que demuestre el cambio de total al tocar más y menos.

Añade tests y verificación en dispositivo

Con el proyecto llamado cart_ai_demo, coloca esto en test/cart_summary_test.dart.

import 'package:cart_ai_demo/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('updates the cart total when quantity changes', (tester) async {
    await tester.pumpWidget(const CartDemoApp());
    expect(find.text('Total: JPY 2800'), findsOneWidget);

    await tester.tap(find.byIcon(Icons.add_circle_outline).first);
    await tester.pump();
    expect(find.text('Total: JPY 4600'), findsOneWidget);

    await tester.tap(find.byIcon(Icons.remove_circle_outline).first);
    await tester.pump();
    expect(find.text('Total: JPY 2800'), findsOneWidget);
  });
}
flutter analyze
flutter test

Para emulador o dispositivo real, usa un integration test.

import 'package:cart_ai_demo/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('cart can be changed on a real device', (tester) async {
    await tester.pumpWidget(const CartDemoApp());
    await tester.tap(find.byIcon(Icons.add_circle_outline).last);
    await tester.pumpAndSettle();
    expect(find.text('Total: JPY 3300'), findsOneWidget);
  });
}
flutter devices
flutter test integration_test -d <device_id>

Casos de uso y problemas de plataforma

Caso 1: añadir cantidad, filtro u orden a una lista existente. Pide respetar el patrón de estado actual, no añadir dependencias y cubrir el cambio con widget test. Caso 2: limpiar pubspec.yaml y assets; Claude Code debe proponer cambios antes de editar. Caso 3: depurar un problema solo de Android, iOS o Web, como permisos, notificaciones, ubicación o enlaces externos. Caso 4: añadir tests de regresión a una pantalla legacy sin cobertura.

Flutter comparte Dart, pero no todas las reglas de despliegue. Android puede requerir permisos en manifest; iOS necesita textos de Info.plist, CocoaPods y firma; Web puede fallar por CORS o APIs del navegador; Desktop introduce permisos de archivo y comportamiento de plugins nativos.

flutter analyze
flutter test
flutter build apk --debug
flutter build web --release

No pidas verificación de iOS release en una máquina sin macOS y Xcode. El prompt debe distinguir lo que se puede ejecutar de lo que queda pendiente.

Prompts seguros y nota de campo

Investigación: lee lib/, test/, pubspec.yaml y carpetas de plataforma. No edites. Devuelve mapa y riesgos.
Implementación: cambia solo lib/features/cart. Sigue el estado existente. No añadas dependencias.
pubspec: si necesitas una dependencia, pausa y muestra razón, alternativas, impacto y comandos.
Verificación: añade widget test. Ejecuta flutter analyze y flutter test. Reporta fallos con nombres de archivo.
Revisión crítica: revisa dispose, async, efectos dentro de build, plataforma, accesibilidad, paquetes y tests faltantes.

La nota práctica de Masa: Flutter funciona mejor con Claude Code cuando el trabajo se divide en mapa, diff pequeño, tests y build. El prompt débil fue “haz una pantalla Flutter bonita”; produjo UI plausible, pero también estado creado en build, cambios innecesarios de paquetes y sin revisión de plataforma. Para equipos, empieza con la chuleta gratuita y formaliza el proceso con formación y consultoría de Claude Code. Para diseñar límites repetibles, lee harness engineering.

Los snippets están pensados para flutter create cart_ai_demo. Este entorno de escritura no tiene Flutter SDK instalado, así que la verificación final debe hacerse en un entorno real con flutter analyze, flutter test, build de la plataforma objetivo y prueba en emulador o dispositivo.

#Claude Code #Flutter #Dart #desarrollo móvil #multiplataforma
Gratis

PDF gratis: cheatsheet de Claude Code

Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.

Cuidamos tus datos y no enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero enfocado en workflows prácticos con Claude Code.