Bloc
VeryGoodOpenSource/vgv-ai-flutter-plugin
Best practices for Bloc state management in Flutter/Dart, covering Cubit versus Bloc, event and state naming, sealed classes with Equatable, the Page/View split with BlocProvider, BlocBuilder…
Fix Dart/Flutter services where calling start() after stop() is a silent no-op because stop() sets a disposed (or similar) flag that start()'s guard short-circuits on.
$ npx skills add divinevideo/divine-mobile --skill dart-lifecycle-disposed-flag-overload -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install divinevideo/divine-mobile dart-lifecycle-disposed-flag-overload --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/dart-lifecycle-disposed-flag-overload .claude/skills/dart-lifecycle-disposed-flag-overload && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "dart-lifecycle-disposed-flag-overload" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/dart-lifecycle-disposed-flag-overload into .claude/skills/dart-lifecycle-disposed-flag-overload/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dart-lifecycle-disposed-flag-overload", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/dart-lifecycle-disposed-flag-overloadType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add divinevideo/divine-mobile --skill dart-lifecycle-disposed-flag-overload -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install divinevideo/divine-mobile dart-lifecycle-disposed-flag-overload --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/dart-lifecycle-disposed-flag-overload .agents/skills/dart-lifecycle-disposed-flag-overload && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "dart-lifecycle-disposed-flag-overload" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/dart-lifecycle-disposed-flag-overload into .agents/skills/dart-lifecycle-disposed-flag-overload/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dart-lifecycle-disposed-flag-overload", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add divinevideo/divine-mobile --skill dart-lifecycle-disposed-flag-overload -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install divinevideo/divine-mobile dart-lifecycle-disposed-flag-overload --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/dart-lifecycle-disposed-flag-overload .cursor/skills/dart-lifecycle-disposed-flag-overload && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "dart-lifecycle-disposed-flag-overload" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/dart-lifecycle-disposed-flag-overload into .cursor/skills/dart-lifecycle-disposed-flag-overload/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dart-lifecycle-disposed-flag-overload", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/divinevideo/divine-mobile.git --path .agents/skills/dart-lifecycle-disposed-flag-overload--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add divinevideo/divine-mobile --skill dart-lifecycle-disposed-flag-overload -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install divinevideo/divine-mobile dart-lifecycle-disposed-flag-overload --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/dart-lifecycle-disposed-flag-overload .gemini/skills/dart-lifecycle-disposed-flag-overload && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "dart-lifecycle-disposed-flag-overload" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/dart-lifecycle-disposed-flag-overload into .gemini/skills/dart-lifecycle-disposed-flag-overload/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dart-lifecycle-disposed-flag-overload", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install divinevideo/divine-mobile dart-lifecycle-disposed-flag-overloadInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add divinevideo/divine-mobile --skill dart-lifecycle-disposed-flag-overload -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/dart-lifecycle-disposed-flag-overload .github/skills/dart-lifecycle-disposed-flag-overload && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "dart-lifecycle-disposed-flag-overload" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/dart-lifecycle-disposed-flag-overload into .github/skills/dart-lifecycle-disposed-flag-overload/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dart-lifecycle-disposed-flag-overload", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add divinevideo/divine-mobile --skill dart-lifecycle-disposed-flag-overload -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install divinevideo/divine-mobile dart-lifecycle-disposed-flag-overload --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/dart-lifecycle-disposed-flag-overload .opencode/skills/dart-lifecycle-disposed-flag-overload && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "dart-lifecycle-disposed-flag-overload" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/dart-lifecycle-disposed-flag-overload into .opencode/skills/dart-lifecycle-disposed-flag-overload/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dart-lifecycle-disposed-flag-overload", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
dart-lifecycle-disposed-flag-overloadFix Dart/Flutter services where calling start() after stop() is a silent no-op because stop() sets a disposed (or similar) flag that start()'s guard short-circuits on.
Dart Lifecycle Disposed Flag Overload is an agent skill from divinevideo/divine-mobile. Fix Dart/Flutter services where calling start() after stop() is a silent no-op because stop() sets a disposed (or similar) flag that start()'s guard short-circuits on. Use when: (1) A repository/service/controller has startListening/stopListening, subscribe/unsubscribe, open/close, or similar lifecycle methods, (2) Re-opening the service after closing it appears to do nothing — no subscription, no events, no error, (3) Unit tests that only exercise a single mount/open/start cycle pass while the real app breaks on…
Its SKILL.md is about 2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Mobile, covering Cross-platform mobile apps and Unit testing. It works with Dart and Flutter. The licence is MPL-2.0.
2 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit c3d6f7e. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are dart).
From the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
api.dart.devapi.flutter.devFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Dart Lifecycle Disposed Flag Overload loads about 2k tokens when it runs. Until then it costs about 225 tokens; SKILL.md has 658 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from divinevideo/divine-mobile at commit c3d6f7e, republished under its MPL-2.0 licence (© divinevideo). 658 words, ~1,955 tokens.
.claude/skills/dart-lifecycle-disposed-flag-overload/SKILL.md (or your agent's skills folder)._disposed Flag OverloadA Dart/Flutter class with start/stop lifecycle methods sets a "disposed"/"stopped"
boolean inside stop(), but the guard clause in start() short-circuits whenever
that boolean is true. After a stop→start cycle, start() silently returns without
doing anything. The class has two distinct concerns conflated into one flag:
start() calls.When those concerns share a single flag, the second concern silently breaks the first.
startListening() / stopListening()subscribe() / unsubscribe()connect() / disconnect()open() / close()stop() includes a line like _disposed = true; or _stopped = true;start() begins with a guard like:if (_subscription != null || _disposed || !isInitialized) return;Separate the two concerns. Reserve the permanent-teardown flag for the code path
that actually tears the instance down for good (typically a _resetState() called on
user-switch or full logout), and do NOT set it inside stop().
class MyRepository {
bool _disposed = false;
StreamSubscription<Event>? _subscription;
void startListening() {
if (_subscription != null || _disposed || !isInitialized) return;
_subscription = _client.subscribe(...).listen(...);
}
Future<void> stopListening() async {
_disposed = true; // ← THE BUG
await _subscription?.cancel();
_subscription = null;
}
void _resetState() {
_disposed = true;
// ... wipe credentials ...
_disposed = false;
}
}After stopListening(), _disposed == true forever until _resetState() is called
(which only happens on user switch). Any subsequent startListening() hits the guard
and returns silently.
class MyRepository {
bool _disposed = false;
StreamSubscription<Event>? _subscription;
void startListening() {
// Guard still checks _disposed for the permanent-teardown case — that
// window is only open during _resetState()'s synchronous body.
if (_subscription != null || _disposed || !isInitialized) return;
_subscription = _client.subscribe(...).listen(...);
}
Future<void> stopListening() async {
// Do NOT set _disposed here — _disposed is reserved for _resetState()
// (permanent teardown, e.g. user switch). Setting it would make a
// subsequent startListening() call a silent no-op and break re-open
// flows like "user leaves the screen and comes back later".
await _subscription?.cancel();
_subscription = null;
}
void _resetState() {
_disposed = true;
// ... wipe credentials, cancel subscription, etc. ...
_disposed = false;
}
}The _subscription != null half of the guard is still sufficient to make
startListening() idempotent against double-calls within a single listening lifetime.
Add a regression test that exercises start → stop → start and asserts the start work happened twice:
test('startListening after stopListening re-opens the subscription', () async {
final repo = createRepository();
repo.initialize(...);
repo.startListening();
await repo.stopListening();
repo.startListening();
// Both opens must hit the client.
verify(() => mockClient.subscribe(any(), ...)).called(2);
await repo.stopListening();
});Manual QA: visit the screen that drives the lifecycle, back out of it, visit it again. The feature should work on the second visit identically to the first.
Run the existing test for the permanent-teardown path (e.g. user switch /
_resetState()) and confirm it still passes. The fix should not affect that path.
From divine-mobile (PR #2769, April 2026): DmRepository drove NIP-17 gift-wrap
subscription lifecycle from the inbox screen's initState/dispose. On the second
visit to the inbox, DMs silently stopped arriving. Root cause: stopListening() had
_disposed = true; as its first line. Fix: delete that line, leave an explanatory
comment, add a regression test that asserts mockNostrClient.subscribe was called
twice after an open → close → open cycle. Commit
bd1420eb3 fix(dm): allow startListening() to succeed after stopListening().
NostrClient) only verify that the repository calls subscribe() once when
startListening() is called. They don't exercise the real state machine across
multiple cycles unless the test explicitly cycles start→stop→start and verifies
the second start also called subscribe. Add that cycle to your lifecycle test
suite preemptively._permanentlyDisposed (or
_torn_down) vs _isListening (or _started). A single bool with an overloaded
meaning is the root smell.startListening() in initState and stopListening() in dispose and
the user can leave and return to the screen. If that flow is new, always add a
"visit twice" test to your widget test for that screen.onDone callbacks on cancelled streams
may also read the flag and decide whether to schedule a reconnect. After separating
the flags, audit every read of the old flag to confirm the new semantics still
match the callsite's intent.StreamSubscription.cancel() docs: https://api.dart.dev/stable/dart-async/StreamSubscription/cancel.html
(cancellation does not deliver a done event to the listener, which is relevant
when auditing onDone reconnect paths after this fix.)State.initState / State.dispose): https://api.flutter.dev/flutter/widgets/State-class.html© divinevideo, MPL-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/dart-lifecycle-disposed-flag-overload of divinevideo/divine-mobile.
Open the folder on GitHubat commit c3d6f7e
Dart Lifecycle Disposed Flag Overload next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Dart Lifecycle Disposed Flag Overload this skilldivinevideo/divine-mobile | 266 | — | ~2k | Automated safety check: Pass | MPL-2.0 | |
| BlocVeryGoodOpenSource/vgv-ai-flutter-plugin | 170 | — | ~2k | Automated safety check: Pass | MIT | |
| TestingVeryGoodOpenSource/vgv-ai-flutter-plugin | 170 | — | ~3.2k | Automated safety check: Pass | MIT | |
| Flutter TestingMADTeacher/mad-agents-skills | 110 | — | ~1.5k | Automated safety check: Pass | MIT | |
| Testingevanca/flutter-ai-rules | 650 | — | ~1.1k | Automated safety check: Pass | MIT | |
| Native Testing Strategybladeofgod/flutter-ai-harness | 116 | — | ~345 | Automated safety check: Pass | MIT |
VeryGoodOpenSource/vgv-ai-flutter-plugin
Best practices for Bloc state management in Flutter/Dart, covering Cubit versus Bloc, event and state naming, sealed classes with Equatable, the Page/View split with BlocProvider, BlocBuilder…
VeryGoodOpenSource/vgv-ai-flutter-plugin
Best practices for Dart unit tests, Flutter widget tests, and golden file tests, covering group and test naming, setUp lifecycle and isolation, mocking with package:mocktail, and the shared pumpApp…
MADTeacher/mad-agents-skills
Write, fix, review, debug, and validate Flutter tests for apps, packages, and plugins.
evanca/flutter-ai-rules
A skill your agent uses when writing or reviewing Flutter/Dart tests (unit, widget, golden), fixing flaky tests, adding coverage, or choosing between unit and widget tests.
bladeofgod/flutter-ai-harness
适用:设计或审查 Kotlin/Swift 原生模块、Bridge Adapter、Host 编译、模拟器/设备和系统能力验证。不适用:纯 Dart/Flutter 测试或用 Fake 代替相机和权限真机验证。触发词:JUnit、XCTest、Robolectric、instrumented test、Swift Testing、Framework Fake、Gradle…
FNOSP/FlyNarwhal
A skill your agent uses when creating, writing, fixing, or reviewing tests in a Flutter project.
divinevideo/divine-mobile
Fix ArgoCD ExternalSecret deployment failing with "namespace X is not permitted in project Y".
divinevideo/divine-mobile
Art direction for any content — reads text, PDF, Word, HTML, PPT, then proposes 2-3 creative directions with photography style, mood, and visual language.
divinevideo/divine-mobile
Fix "Null check operator used on a null value" errors when an object is set to null during an async await.
divinevideo/divine-mobile
Add custom metadata headers (x-amz-meta-) to AWS v4 signed requests for GCS S3-compatible API.
divinevideo/divine-mobile
Fix password/secret authentication failures caused by trailing newlines when creating Google Cloud secrets (or similar) with bash here-strings.
divinevideo/divine-mobile
Fix silent video/media processing failures caused by URL extraction code that filters on file extensions (.mp4, .webm, .webp).
Categories
Fix Dart/Flutter services where calling start() after stop() is a silent no-op because stop() sets a disposed (or similar) flag that start()'s guard short-circuits on. Dart Lifecycle Disposed Flag Overload is an agent skill from divinevideo/divine-mobile. Fix Dart/Flutter services where calling start() after stop() is a silent no-op because stop() sets a disposed (or similar) flag that start()'s guard short-circuits on.
Dart Lifecycle Disposed Flag Overload fits situations like: A repository/service/controller has startListening/stopListening; subscribe/unsubscribe; similar lifecycle methods; re-opening the service after closing it appears to do nothing — no subscription.
Run `npx skills add divinevideo/divine-mobile --skill dart-lifecycle-disposed-flag-overload -a claude-code`. Or copy the skill folder (.agents/skills/dart-lifecycle-disposed-flag-overload in divinevideo/divine-mobile) into .claude/skills/dart-lifecycle-disposed-flag-overload in your project. Claude Code loads it when a task matches its description.
Run `npx skills add divinevideo/divine-mobile --skill dart-lifecycle-disposed-flag-overload -a codex`. Or copy the skill folder (.agents/skills/dart-lifecycle-disposed-flag-overload in divinevideo/divine-mobile) into .agents/skills/dart-lifecycle-disposed-flag-overload in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add divinevideo/divine-mobile --skill dart-lifecycle-disposed-flag-overload -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/dart-lifecycle-disposed-flag-overload, .gemini/skills/dart-lifecycle-disposed-flag-overload, .github/skills/dart-lifecycle-disposed-flag-overload and .opencode/skills/dart-lifecycle-disposed-flag-overload in your project.
SKILL.md names no scripts, command-line tools or credentials: Dart Lifecycle Disposed Flag Overload is instructions for the agent only.
SKILL.md names 2 domains. As links in the text: api.dart.dev and api.flutter.dev. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Dart Lifecycle Disposed Flag Overload is published under the MPL-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2k tokens (SKILL.md is roughly 7.8k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Dart Lifecycle Disposed Flag Overload: Bloc (VeryGoodOpenSource/vgv-ai-flutter-plugin, 170 stars), Testing (VeryGoodOpenSource/vgv-ai-flutter-plugin, 170 stars), Flutter Testing (MADTeacher/mad-agents-skills, 110 stars) and Testing (evanca/flutter-ai-rules, 650 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
divinevideo (a GitHub organization) maintains it in divinevideo/divine-mobile, which has 266 GitHub stars. The repository holds 103 skills in this directory. The repository was last updated on October 10, 2026.
Source: divinevideo/divine-mobile on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.