$npx -y skills add MADTeacher/mad-agents-skills --skill flutter-driftImplement, fix, review, migrate, test, or debug Drift persistence in Flutter apps using SQLite, drift_flutter, type-safe Dart queries, generated tables, StreamBuilder or Riverpod StreamProvider UI, write operations, transactions, schema migrations, web assets, isolate sharing, an
| 1 | # Flutter Drift |
| 2 | |
| 3 | Use this skill to add or repair Drift-based local persistence in Flutter apps. The skill is an operating workflow: inspect the target app first, choose only the relevant reference files, implement with current Drift APIs, and validate generated code. |
| 4 | |
| 5 | ## Core Workflow |
| 6 | |
| 7 | 1. Inspect the app before editing: |
| 8 | - Check `pubspec.yaml`, existing database files, `build.yaml`, state management package, target platforms, and tests. |
| 9 | - Prefer the app's current architecture and naming over the examples in this skill. |
| 10 | 2. Add or verify dependencies with package commands instead of hardcoding versions: |
| 11 | - `dart pub add drift drift_flutter path_provider dev:drift_dev dev:build_runner` |
| 12 | - Add `provider` or `flutter_riverpod` only when the app already uses it or the user asks for that integration. |
| 13 | 3. Create or update the database entry point: |
| 14 | - Define tables in Dart or `.drift` files. |
| 15 | - Add the tables to `@DriftDatabase`. |
| 16 | - Open Flutter databases with `driftDatabase` from `package:drift_flutter/drift_flutter.dart` unless the project needs a custom executor. |
| 17 | 4. Keep Drift calls scoped to the database object: |
| 18 | - Use `database.select(database.todoItems)`, `database.into(database.todoItems)`, `database.update(database.todoItems)`, and `database.delete(database.todoItems)` from widgets, services, and repositories. |
| 19 | - Use bare `select(todoItems)` only inside `GeneratedDatabase` subclasses or `DatabaseAccessor` classes where the methods and table getters are in scope. |
| 20 | 5. Generate code after changing Drift declarations: |
| 21 | - Run `dart run build_runner build`. |
| 22 | - Treat generator errors as blockers, not optional cleanup. |
| 23 | 6. For schema changes in an existing app, use Drift's guided migration workflow: |
| 24 | - Configure `drift_dev` databases in `build.yaml`. |
| 25 | - Run `dart run drift_dev make-migrations` before and after schema changes as needed. |
| 26 | - Bump `schemaVersion`, write generated step-by-step migrations, and run generated migration tests. |
| 27 | 7. Validate before finishing: |
| 28 | - Run `dart format` on edited Dart files. |
| 29 | - Run `flutter analyze` or `dart analyze` for the package. |
| 30 | - Run targeted tests, including generated migration tests when migrations changed. |
| 31 | |
| 32 | ## Resource Routing |
| 33 | |
| 34 | - Read [references/setup.md](references/setup.md) when adding Drift, opening a database, configuring web support, or sharing a database across isolates. |
| 35 | - Read [references/tables.md](references/tables.md) when defining tables, columns, defaults, keys, indexes, constraints, generated columns, or strict tables. |
| 36 | - Read [references/queries.md](references/queries.md) when implementing selects, filters, sorting, pagination, joins, aggregations, subqueries, custom columns, or unions. |
| 37 | - Read [references/writes.md](references/writes.md) when implementing inserts, updates, deletes, upserts, companions, transactions, or batch operations. |
| 38 | - Read [references/streams.md](references/streams.md) when implementing reactive Drift streams, StreamBuilder, StreamProvider, custom select streams, table update listeners, or manual stream invalidation. |
| 39 | - Read [references/migrations.md](references/migrations.md) when `schemaVersion`, existing user data, `build.yaml`, `make-migrations`, generated schema files, or migration tests are involved. |
| 40 | - Read [references/flutter-ui.md](references/flutter-ui.md) when wiring Drift data into Flutter widgets with Provider, Riverpod, StreamBuilder, search, filtering, pagination, or user-facing loading and error states. |
| 41 | |
| 42 | ## Required API Rules |
| 43 | |
| 44 | - Do not call `select(database.table)` as a top-level function from a widget. Use `database.select(database.table)` outside database classes. |
| 45 | - Do not use `watch(...)`, `todoUpdates(...)`, or `notifyTableUpdates(...)`. Use `customSelect(...).watch()`, `tableUpdates(...)`, and `notifyUpdates(...)`. |
| 46 | - Do not call `delete(table).go(id)`. Add a `where` clause and then call `go()`, or use generated table extension helpers if the project already uses them. |
| 47 | - Do not use `batch.updateAll(...)` or pass raw ids to `batch.delete(...)`. Use `batch.update(..., where: ...)`, `batch.delete(...)` with an insertable row, or `batch.deleteWhere(...)`. |
| 48 | - Do not mix Provider and Riverpod APIs. `Provider.of<AppDatabase>(context)` belongs to `provider`; `Provider<AppDatabase>((ref) { ... })` and `AsyncValue.when(...)` belong to Riverpod. |
| 49 | - Do n |