AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Flutter Agent Kit

skill-zero-labsco-flutter-agent-kit-flutter-agent-kit · by zero-labsco

This skill provides general Flutter/Dart development guidance - implementing features, fixing bugs, managing pubspec dependencies and version constraints, following effective_dart, structuring lib/ (feature-first architecture, state management selection), writing platform channels for plugins across Android/iOS/Linux/macOS/Windows/Web/OpenHarmony, running flutter analyze/flutter test, and publish…

No reviews yet
0 installs
33 views
0.0% view→install

Install

$ agentstack add skill-zero-labsco-flutter-agent-kit-flutter-agent-kit

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-zero-labsco-flutter-agent-kit-flutter-agent-kit)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Flutter Agent Kit? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Flutter Agent Kit

> Self-contained bundle (v1.0.0). This SKILL.md is an auto-generated, complete copy > of the guidance from AGENTS.md and the docs > in references/ (the canonical sources in this kit's repository root). It is > bundled so the skill works on its own even when a marketplace (e.g. skills.sh) > downloads only SKILL.md. The helper scripts (scripts/) are NOT included in > this download — clone the repo at https://github.com/zero-labsco/flutter-agent-kit to run them. > > Tool-agnostic. This skill loads via SKILL.md in any agent that supports > the format — Claude Code, Cursor, Codex, GitHub Copilot, CodeBuddy, OpenCode, > Aider, and any other tool skills.sh or a compatible marketplace targets. > Follow the guidance below for any Flutter / Dart task regardless of which tool > you use.

Overview

This skill activates for any Flutter / Dart project work. The guidance below is the tool-agnostic, bundled core: architecture, coding conventions, dependency and version rules, plugin platform-channel patterns, verification commands, and the deep-dive reference appendices.

General guidance (bundled from AGENTS.md)

Scope

Applies to any Flutter / Dart project, covering two scenarios:

  • Application projects — UI apps with lib/, state management, networking, persistence.
  • Plugin projects — packages exposing a platform channel for Android/iOS (and beyond).

In scope (this kit owns these): general Flutter / Dart conventions, lib/ structure, architecture pattern selection, dependency and version rules, platform-channel patterns, verification commands, and the anti-AI-smell / anti-hallucination discipline. These are tool-agnostic and apply to every project.

Out of scope (this kit does NOT own these): project-specific decisions and facts — exact package names and versions, business/domain logic, directory depth and folder naming beyond the recommended layouts, CI/CD configs, secrets, and any rule that is unique to one repo. Those belong in the project's own AGENTS.md (or its team docs), which should override this kit when they conflict. When a project already has an established convention, follow it (see Match the existing codebase, not a template) and do not impose this kit's defaults.

Uncertainty handling (say so instead of guessing)

When you are not certain about a fact — an API's existence or signature, a package's export, the project's intended behavior, a version's compatibility — do not fabricate a plausible-looking answer. Instead:

  • State the uncertainty explicitly. Say "I can't verify X from the available

context" rather than emitting a confident-but-unchecked symbol or snippet.

  • Point to where to verify. Name the source to check: dart doc, the package

source in pubspec.lock, pub.dev, the project's own code/docs, or flutter analyze to surface errors. See API truthfulness.

  • Prefer a safe, minimal stub over a wrong implementation. If you must

proceed, write the smallest correct shape you can defend and flag what needs confirmation, instead of guessing parameters or methods.

  • Ask when the cost of being wrong is high (data loss, breaking changes,

auth/security). A short clarifying question beats a silent wrong assumption.

Coding conventions

  • Follow effective_dart. Enforce with flutter analyze and flutter_lints.
  • Use null safety; avoid ! unless proven safe. Prefer final and immutable models.
  • Name files snake_case.dart, classes PascalCase, constants lowerCamelCase or kConstant.
  • Keep lib/ free of business logic leakage into UI; separate data / domain / presentation.
  • Do not write hardcoded secrets; use --dart-define or a .env excluded from VCS.
  • Do not hardcode theme values. Do not create a color-constants file

(e.g. app_colors.dart with static const brand = Color(0xFF2E5BFF)) — that only relocates hardcoded colors and still can't adapt to light/dark or brand swaps. Instead:

  • Define the palette once in the app's ThemeData, derived from a single

seed color via ColorScheme.fromSeed(seedColor: ...). Let Flutter generate the shades (primary, surface, error, …) for you.

  • In widgets, read everything from the theme at runtime — `Theme.of(context)

.colorScheme.primary, .textTheme.titleLarge, .colorScheme.error — never literal Color(0xFF...), Colors.x`, or magic pixel numbers inline.

  • The only acceptable exception is a project that already ships its own

design-token system wired into the theme (light/dark aware); then import those tokens, don't invent new hardcoded ones. This keeps the look consistent and themeable. See the UI guidance.

Dependencies and versioning

  • Prefer the caret (^) constraint on pub dependencies; do not pin exact versions without reason.
  • Keep sdk constraints realistic (e.g. >=3.0.0 /{data,domain,presentation}/.
  • Or a layer-first layout for small apps: lib/data/, lib/domain/, lib/presentation/.
  • Choose state management deliberately: Provider/Riverpod for scoped DI, Bloc/Cubit for event-driven flows, GetIt for service locators. Document the choice in the project README.
  • Default when unchosen: if the project has no established state-management

approach, recommend Riverpod (or Provider for very small apps) as the default — low boilerplate, scoped DI, and strong testability. Only pick Bloc/Cubit when the flow is genuinely event-driven and benefits from explicit states. Pick ONE primary approach and document it.

  • Never import lib/src/ of a dependency directly; use its public API only.
  • Read existing code before generating. Imitate the project's established

patterns (file layout, naming, error handling, state shape) rather than emitting a generic template. Code that looks identical across every project is the tell-tale sign of an LLM — match the repo's voice.

  • Verify APIs before using them (see API truthfulness). Never assume a

method/constructor/parameter or package export exists — confirm it in the pinned SDK/package version.

Componentization & reuse (reduce duplication)

Prefer composable, reusable components over copy-pasted UI and logic. Aim to remove duplication wherever the same markup or behavior appears more than once:

  • Extract before repeating. The first time you write a block of UI, leave it

inline. The second time the same structure appears, extract it into a named widget / helper / function. Three or more repetitions of near-identical code is a strong signal to refactor into a shared component.

  • Build a small shared component set. Colocate genuinely reusable widgets

(buttons, cards, inputs, headers, empty/error states, list rows) in lib//presentation/widgets/ or a cross-feature lib/shared/ (or lib/common/, lib/components/) following the project's existing convention. Give them clear, single-purpose names — not MyWidget.

  • Parameterize, don't fork. When two usages differ only by data, color, or

callback, pass them as parameters instead of duplicating the widget with hardcoded variants. Prefer const constructors and a small set of named arguments over long positional lists.

  • Prefer composition over inheritance. Compose small widgets (a Card +

ListTile + Icon) rather than subclassing to reuse a look. Flutter widgets are cheap to nest; levers like Builder, LayoutBuilder, and InheritedWidget / provider reads share behavior without copying code.

  • Reuse logic, not just markup. Lift repeated business rules, formatting,

validation, and parsing into services / extensions / free functions in domain or core/utils; don't re-implement the same if chain in three screens. Share state via the chosen state-management container instead of duplicating fetches.

  • Match the project's existing components first. Before adding a new shared

widget, check whether one already exists (search lib/shared, lib/common, existing *_widget.dart). Reuse the repo's own building blocks so the UI stays consistent — do not introduce a second, parallel component library.

  • Keep components self-contained and dependency-light. A shared widget should

not reach into a specific feature's state or data layer; pass what it needs via the constructor. That keeps it reusable and avoids accidental coupling.

  • Don't over-abstract. Extract a component only when it earns its place (two+

real call sites, or a genuinely shared cross-feature need). A one-off widget pulled into shared/ prematurely adds indirection with no payoff.

Navigation & routing (avoid inline routes)

  • Don't inline Navigator.push(MaterialPageRoute(...)) blocks inside widgets.

That scatters destinations and the page-construction logic across the codebase.

  • Use a centralized router when the project has one — go_router,

auto_route, or the project's own RouteGenerator. If the project has no convention, recommend go_router (declarative, typed routes, deep-linking) as the default for new apps.

  • Keep routes in one module, not scattered. Define the router in a dedicated

location rather than inside main.dart or individual pages:

  • Small apps: a single lib/router.dart (or lib/app_router.dart) holding the

GoRouter/RouterConfig instance.

  • Larger / multi-feature apps: a lib/router/ (or lib/routing/) folder with

the router, route table, and guards split out (e.g. app_router.dart, routes.dart, guards.dart).

  • Define path strings as constants. Don't write magic route strings like

context.go('/users/123') across widgets — centralize them (e.g. route_paths.dart with static const users = '/users'; and a typed usersDetail(String id) helper) so destinations have one source of truth.

  • Pass typed arguments, not raw Maps/strings. Route params should be typed

(e.g. GoRouterState.pathParameters['id'] parsed to the real type), not a loosely-typed Map passed through constructors.

  • Match the project's existing navigation before introducing a new approach.

If screens currently use named routes or a specific package, stay consistent.

Architecture (plugin)

  • Define the abstract API once in lib/_platform_interface.dart (Platform).
  • Provide a concrete impl per target platform: MethodChannel for Android / iOS / macOS / Linux / Windows / OpenHarmony (鸿蒙), and pure-Dart dart:js_interop for Web (no MethodChannel).
  • Register the right impl conditionally (use kIsWeb + dart:io Platform.isX) in the public barrel; re-export public symbols only. Consumers call the abstract API and never change when a platform is added.
  • Keep native changes minimal and matching the method-channel contract. Android lives under android/src/main/kotlin/..., iOS/macOS under ios/Classes / macos/Classes, Linux/Windows under linux/ / windows/ (C++), OHOS under ohos/ (ArkTS).
  • See the Plugin Platform Channel Reference appendix below for a full multi-platform template.

Testing discipline

Generated code should be accompanied by tests, not shipped alone:

  • Write a test for every non-trivial change. A new use case, repository

method, formatter, or validation rule gets a unit test. A new screen or flow gets at least one widget/integration test covering the critical path.

  • Test by layer (see Testing layering in the Architecture Reference):

domain as pure unit tests; data with mocked sources (verify mapping and error handling); presentation with widget tests for key flows and integration tests for end-to-end.

  • Make it runnable and green. After generating, the project must pass

flutter analyze and flutter test (or dart analyze / dart test for non-Flutter packages). Do not leave failing or commented-out tests behind.

  • Prefer meaningful assertions over "does not throw". Assert behavior and

state, not just that the code executed.

  • Match the project's existing test style (test framework, mocking library,

file location test/ vs */test/) before introducing a new pattern.

Dependency discipline

Adding a package is a decision, not a reflex:

  • Confirm the need first. Before adding a dependency, check whether the SDK

or an existing package already covers the use case (e.g. dart:convert, dart:async, flutter/material.dart). Prefer the standard library over a third-party package.

  • Audit the package before adding. On pub.dev, check the **popularity +

health + maintenance** scores, last published date, open issues, and null-safety / SDK compatibility. Avoid unmaintained or single-maintainer packages for critical functionality.

  • Avoid overlapping packages. Don't add two packages that do the same thing

(e.g. multiple HTTP clients, multiple state libraries). One chosen approach per concern.

  • Scope correctly. Runtime needs go in dependencies; test/build tooling

goes in dev_dependencies. Never commit a permanent dependency_overrides.

  • Pin with care (see Dependencies and versioning): prefer caret (^)

constraints; don't pin exact versions without reason.

Error handling (fail loudly, recover gracefully)

Generated code should treat failures as first-class, not an afterthought:

  • Don't swallow exceptions. Avoid bare catch (e) {} or try { … } catch (_)

that discards the error. At minimum log it; rethrow or surface it when the caller can act on it.

  • Represent failure explicitly. For operations that can fail, prefer throwing

a typed exception or returning a Result/sealed type over returning null to mean "it broke". A null success/failure ambiguity is a common source of downstream crashes.

  • Use async/await + try/catch for async work rather than nested

.then().catchError() chains, which are harder to read and easy to leave unhandled.

  • Show the user a recoverable message, not a stack trace. Map errors to a

human-readable, localized string (see Internationalization) and offer a retry where it makes sense — using the project's existing error/empty-state pattern, not a generic dialog.

  • Catch at the right boundary. Let lower layers (data/domain) throw and

let the presentation layer decide how to present the failure, rather than catching and hiding it deep inside a repository.

Internationalization (i18n)

  • Don't hardcode user-facing strings. Extract them to arb files

(lib/l10n/app_en.arb, app_zh.arb, …) via flutter_localizations + intl (or slang/easy_localization if the project already uses one).

  • Generate the delegate (flutter gen-l10n) and wire localizationsDelegates
  • supportedLocales in MaterialApp/CupertinoApp. Follow the project's

chosen i18n tool, not a new one.

  • Keep plurals/formatting in the arb, not in Dart string concatenation, so

translators and locale rules are respected.

  • Never convey meaning by UI text alone for accessibility — pair labels with

icons/semantics as noted in the UI guidance.

Verification commands (run locally before pushing)

  • dart format --line-length 80 . (or flutter format) — must report no

unformatted files. Run formatting before analyze; never hand-format around the formatter.

  • flutter analyze — must pass with no errors.
  • flutter test — all unit tests green.
  • flutter pub publish --dry-run — confirm pana score and no excluded files.

Helper scripts

Located in scripts/dart/ (Dart, cross-platform, runs on the Dart SDK every Flutter dev already has) and scripts/python/ (Python, for environments without the Dart SDK). Both implement the same behavior and CLI; pick whichever fits your environment.

Run Dart with dart run scripts/dart/.dart [args], or Python with python scripts/python/.py [args] (o

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.