agentsclimarketplace

Dart

Skill ndisisnd/cook/standards/dart

When your agent starts coding, you gotta let it cook

Install
npx -y skills add ndisisnd/cook --skill dart

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Dart 3.x language standards and code quality conventions. Use when writing or reviewing any Dart code — null safety, patterns, sealed classes, records, class modifiers, naming, immutability, collections, async, and import organisation.

SKILL.md

9.0 KB, as published. Nobody here has run it

Dart Standards

Priority: P0 — Language Correctness

Null Safety

  • Avoid !. Prefer local promotion, null-check patterns, and private final fields.
  • Use ! only for documented invariants or framework/external boundaries where non-null is guaranteed but not expressible to the analyzer.
  • Prefer ?., ??, and null-aware patterns over forced unwrapping.
  • AVOID late if you need to check whether the variable was initialised — use nullable + null-check instead.
  • DON'T explicitly initialise variables to null; let the type system express optionality.

Immutability

  • Use const > final > var. Use @freezed for data classes.
  • Prefer final for all class members. Use var only for locally-obvious short-lived locals.
  • AVOID public late final fields without initializers.

Pattern Matching (Dart 3.x)

Use switch expressions with exhaustive patterns and destructuring. Supported pattern types:

PatternExample
Constantcase 42:
Variablecase var x:
Wildcardcase _:
Objectcase Circle(radius: var r):
Recordcase (String name, int age):
Listcase [first, ...rest]:
Mapcase {'key': var v}:
Logical-or`case 1
Guardcase var x when x > 0:
String describe(Shape s) => switch (s) {
  Circle(radius: var r) when r > 10 => 'large circle',
  Circle(radius: var r) => 'circle r=$r',
  Rectangle(width: var w, height: var h) => '${w}x$h rect',
};

Records

  • Use records for returning multiple values: (String, int).
  • Use named fields for clarity beyond two elements: ({String name, int age}).

Class Modifiers (Dart 3.x)

Choose the right modifier to express API intent explicitly:

ModifierExtends outside libImplements outside libUse for
sealednonoExhaustive domain state (enables exhaustive switch)
finalnonoClosed hierarchy — no extension or implementation
baseyesnoAllow inheritance, prevent external implementation
interfacenoyesPure contracts — implementation only
  • sealed is implicitly abstract; direct subtypes must be in the same library for exhaustive switching.
  • Subclasses of a sealed class are not implicitly abstract — mark each subtype intentionally.
  • Use final instead of sealed when you want to close external subtyping but still add subtypes later without breaking exhaustive switches.
sealed class AuthState {}
final class Authenticated extends AuthState { final User user; Authenticated(this.user); }
final class Unauthenticated extends AuthState {}

Mixins

  • Use mixin for behaviour shared across unrelated class hierarchies.
  • Use mixin class (Dart 3.0) when the type must also be usable as a standalone class.
  • Prefer mixin over abstract class when no constructor is needed.

Enhanced Enums (Dart 2.17+)

Enums can have fields, constructors, and methods. Prefer over utility classes with static constants.

enum Status {
  active('Active'),
  inactive('Inactive');

  const Status(this.label);
  final String label;
}

Extensions

  • Use extension to add utility methods to third-party or built-in types.
  • Always name extensions (extension StringX on String) — unnamed extensions are harder to import selectively.

Wildcards (Dart 3.7+)

Use _ for unused variables in declarations and patterns.

Async

  • Prefer async/await over raw Future.then.
  • Use unawaited() for intentional fire-and-forget; never silently discard a future.
  • DON'T mark a function async if it contains no await — it adds overhead with no benefit.
  • AVOID using Completer directly; prefer async/await or StreamController.
  • AVOID FutureOr<T> as a return type.
  • AVOID returning nullable Future, Stream, or collection types from public APIs.
  • Cancel StreamSubscriptions and close owned StreamControllers or Sinks.
  • Avoid async void except for framework callbacks that require void.

Error Handling

  • Use on ExceptionType catch (e) — never bare catch without on (swallows everything).
  • DON'T silently discard caught errors.
  • Throw Error subclasses only for programmatic errors (bugs). Use Exception for recoverable runtime conditions.
  • Use rethrow to re-propagate after partial handling; never re-throw the caught object manually.
  • Use assert() for development-time invariants — stripped in production.

Types

  • No dynamic. Use Object, Object?, or generics.
  • Annotate return types and parameter types on all public declarations.
  • DON'T redundantly annotate initialised local variables — let inference work.
  • Use typedef for named type aliases (typedef UserId = String). Prefer inline function type syntax in parameter positions over typedef.

Members & Constructors

  • Use initializing formals: const User({required this.name}).
  • Use ; not {} for empty constructor bodies.
  • Never use new.
  • DON'T use this. except to redirect constructors or avoid shadowing.
  • DON'T perform complex calculations or async work inside constructors.
  • Use a getter for pure computations: int get invoiceTotal => not int calcTotal().

Equality

  • If you override operator ==, override hashCode.
  • Equality must be reflexive, symmetric, transitive, and stable over time.
  • Avoid custom equality on mutable classes; prefer immutable value types.
  • Use identical(this, other) as the fast path before structural comparison.

Priority: P1 — Style & Conventions

Naming

  • Types and extensions: UpperCamelCase
  • Members, variables, parameters: lowerCamelCase
  • Files, packages, directories: lowercase_with_underscores
  • Import prefixes: lowercase_with_underscores
  • Constants: prefer lowerCamelCase (not SCREAMING_CAPS) unless matching generated or existing code style.
  • Capitalise acronyms longer than two letters as words: HttpRequest, parseUrl
  • DON'T use a leading _ on non-private identifiers.
  • Name value-object converters for their target context: get apiFilterType not get filterType.

Scoping

  • No top-level mutable state. Encapsulate in a class or inject via DI.
  • Library-private identifiers use _ prefix.

Strings

  • Prefer single quotes. Use double quotes only when the string itself contains a single quote.
  • Prefer interpolation over concatenation: 'Hello $name' not 'Hello ' + name.
  • Adjacent string literals can be concatenated without +.
  • Omit curly braces in interpolation unless required: '$name' not '${name}'.

Trailing Commas

Always use trailing commas for multi-line argument lists and collection literals.

Expression Bodies

Prefer => for single-expression functions and getters.

Collections

  • Use .isEmpty / .isNotEmpty — never .length == 0.
  • Use collection if, for, and spread ... for composable collections.
  • Type empty collections explicitly: <String>[], <String, User>{}.
  • Prefer .map, .where, .fold, .any over manual loops where clarity wins.
  • Use .firstOrNull, .lastOrNull, .elementAtOrNull(i) for safe indexed access.
  • DON'T use Iterable.forEach() with a function literal — use for loops or tear-offs.
  • DON'T use cast() when a nearby operation will do.

Imports

  • Group order: dart:package: → relative. Sort each section alphabetically.
  • Use relative imports for intra-package files; never package:app/... within the same package.
  • Specify exports in a separate section after all imports.

Tear-offs

Prefer list.forEach(print) over list.forEach((e) => print(e)).


Anti-Patterns

  • ! without a documented invariant, local promotion alternative, or framework boundary
  • Overriding == without hashCode
  • Custom equality on mutable classes
  • var for class members
  • dynamic anywhere
  • async on a function with no await
  • async void outside framework callbacks
  • Leaked StreamSubscription, StreamController, or Sink
  • Bare catch without on
  • Global mutable state
  • new keyword
  • Package imports within the same package
  • FutureOr<T> as a return type
  • Logic or async work inside constructors
  • Zero-argument methods for pure computations — use a getter

References

Load only what the current task requires:

  • tooling — setting up or modifying analysis_options, dart format, DCM, build_runner, pubspec, coverage, CI, or pre-commit hooks
  • testing — writing or reviewing unit tests, mocks (mocktail), stream tests, or fake_async time-dependent tests

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.