dangi_doctor 0.3.1 copy "dangi_doctor: ^0.3.1" to clipboard
dangi_doctor: ^0.3.1 copied to clipboard

Flutter app health CLI — crawls every screen, analyses widget trees, measures performance, detects bugs, and generates integration tests.

Dangi Doctor 🩺 #

Your Flutter app's personal physician.

Dangi Doctor connects to your live Flutter app, crawls every screen automatically, finds real bugs through static analysis, measures performance, and generates Flutter integration tests — all without you writing a single line of test code.


What's new in v0.3.0 #

  • The weekly knowledge updater works again — all the Flutter doc sources had moved and were silently 404ing; they're repaired, the updater now fails loudly instead of shipping placeholders, and each release bundles current knowledge.
  • Generated tests compile — the interaction and performance tests referenced a helper that was never emitted; that's fixed, along with import paths, dynamic keys, and Cupertino-app support.
  • Crawler correctness (verified on a live Android device) — accurate screen naming through pushed route stacks, navigation that returns home without exiting the app, whole-word dialog-button matching, and coordinate re-resolution after returning from a child screen. It also no longer kills unrelated flutter run/adb sessions on your machine.
  • Real performance numbers — frames read from Flutter.Frame events, actual memory usage, and a jank budget that follows the device's real refresh rate (120 Hz → 8.3 ms, not a hardcoded 16 ms).
  • Faster, safer AI diagnosis — cross-screen prompt caching (~90% cheaper input), real retries/timeouts, current model defaults, and the Gemini key no longer travelling in the request URL.
  • Proper CLI--help, --version, --project, --vm-url, --device, --no-ai; honest exit codes; safe to run in CI.

What it does #

1. Live app crawling #

Connects to your running Flutter app via the Dart VM service. Walks every reachable screen by tapping navigation triggers (bottom nav, buttons, drawers). No emulator required — works on real physical devices.

2. Static analysis — detects real bugs before they reach production #

Scans your lib/ source code for patterns that cause crashes at runtime:

Bug type What it catches
late_field_double_init late field assigned in a method called from didChangeDependencies() without a guard → LateInitializationError
setState_after_dispose setState() in async method without if (mounted) → "setState called after dispose"
stream_subscription_leak StreamSubscription field with no .cancel() in dispose() → memory leak
build_side_effects setState() or await directly inside build() → infinite rebuild loop

3. Generated integration tests — with exact fix instructions #

For every screen and every detected bug, Dangi Doctor writes Flutter integration tests directly into your project at integration_test/dangi_doctor/. Each failing test tells you:

  • Exact file and line number
  • Plain-English explanation of the bug
  • Copy-pasteable fix code
BUG: pages/SplashScreen/splashScreenPage.dart:74 —
late field `_appLinks` double-init in `initDeepLinks()`

━━━ BUG DETECTED ━━━
File: pages/SplashScreen/splashScreenPage.dart:74

Problem:
Late field `_appLinks` is assigned in `initDeepLinks()` which is called
from `didChangeDependencies()` without an initialization guard...

Fix:
  bool _initDeepLinksCalled = false;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    if (!_initDeepLinksCalled) {
      _initDeepLinksCalled = true;
      initDeepLinks();
    }
  }
━━━━━━━━━━━━━━━━━━━

4. HTML health report #

After every diagnosis, Dangi Doctor opens a health report in your browser automatically.

  • Overall health score (0–100)
  • Per-screen performance grade (A–F) with build time, jank %, memory
  • All issues listed with severity (error / warning / info)
  • Static analysis bugs table with file locations and fix code
  • Saved to .dangi_doctor/report_<timestamp>.html

5. AI diagnosis (optional) #

If you have a Claude, OpenAI, Gemini, Groq, or Ollama API key, Dangi Doctor gives each screen a written diagnosis — what's wrong, why it matters, and a prioritised fix list.

The AI is powered by a 3-layer knowledge system that stays current automatically:

  • Layer 1 — Flutter official knowledge: widget lifecycle, performance rules, state management error patterns for Provider / BLoC / Riverpod / GetX, common Flutter errors by category, and the last 5 Flutter version changelogs. Updated weekly by pulling directly from the Flutter GitHub repo.
  • Layer 2 — Community anti-patterns: most common mistakes found across thousands of real production Flutter apps.
  • Layer 3 — Your project: auto-detected on first run. State management, dependencies, folder structure, naming conventions, largest files. Stored at .dangi_doctor/project.json.

Requirements #

  • Dart SDK ≥ 3.0
  • Flutter project with a physical Android device or emulator
  • adb installed (Android Debug Bridge)

Installation #

dart pub global activate dangi_doctor

Or add to your Flutter project's dev dependencies:

dev_dependencies:
  dangi_doctor: ^0.3.0

Usage #

From the root of your Flutter project:

cd /path/to/your/flutter/app
dangi_doctor

Dangi Doctor auto-detects your project from the current directory. If you need to point it at a different path, use the DANGI_PROJECT env var.

On first run, Dangi Doctor will ask how to connect:

┌─────────────────────────────────────────────┐
│  How do you want to connect?                │
│                                             │
│  1. Launch app now (Dangi Doctor runs it)   │
│  2. App already running — paste VM URL      │
└─────────────────────────────────────────────┘

Choose 1 to let Dangi Doctor launch your app, or 2 to paste the VM service URL from a running flutter run --debug session.

Command-line options #

Flag Description
--project <path> Flutter project path (overrides DANGI_PROJECT and cwd auto-detection)
--vm-url <ws://…> VM service URL of an already-running app (skips the connect prompt)
--device <id> ADB device id for widget taps (auto-detected if omitted)
--no-ai Crawler + static analysis only; skip AI diagnosis
--version Print the version and exit
--help Print usage and exit

Fully non-interactive runs are supported for CI — pass --project, --vm-url, and --no-ai and Dangi Doctor never prompts; a crash exits non-zero.

Run generated tests #

flutter test integration_test/dangi_doctor/<screen>_smoke_test.dart \
  -d <device_id>

With auth token (for apps requiring login):

flutter test integration_test/dangi_doctor/<screen>_smoke_test.dart \
  --dart-define=TEST_TOKEN=your_token \
  -d <device_id>

AI diagnosis — free options #

You do not need a paid subscription to get AI diagnosis.

Provider Cost How to get a key
Groq Free tier (14,400 req/day) Sign up at console.groq.com — no credit card
Ollama Free, runs locally Install from ollama.com, run ollama pull llama3.1
Claude Paid console.anthropic.com
OpenAI Paid platform.openai.com
Gemini Paid aistudio.google.com

If no API key is set, Dangi Doctor asks at runtime which provider to use. Choose Groq for the quickest free setup, or Ollama for fully offline diagnosis.

Environment variables #

Variable Description
DANGI_PROJECT Path to your Flutter project (auto-detected from cwd; --project takes precedence)
ANTHROPIC_API_KEY Claude API key for AI diagnosis (CLAUDE_API_KEY also accepted)
OPENAI_API_KEY OpenAI API key for AI diagnosis
GEMINI_API_KEY Gemini API key for AI diagnosis
GROQ_API_KEY Groq API key for AI diagnosis

Model choices default to current models but are all overridable, so a model rename never requires an update:

Variable Default
DANGI_CLAUDE_MODEL claude-opus-4-8
DANGI_OPENAI_MODEL gpt-4o
DANGI_GEMINI_MODEL gemini-2.5-pro
DANGI_GROQ_MODEL llama-3.1-8b-instant
DANGI_OLLAMA_MODEL llama3.1
DANGI_OLLAMA_URL http://localhost:11434
DANGI_MAX_TOKENS 4096

How it works #

dart run dangi_doctor
        │
        ├── 1. Detect AI provider (Claude / OpenAI / Gemini / Groq / Ollama)
        │
        ├── 2. Connect to Flutter app via Dart VM service WebSocket
        │         └── Port remapping: reads /proc/net/tcp on device to find
        │             the real VM port, then adb forward tcp:8181 tcp:<actual>
        │
        ├── 3. Wait for splash screen to dismiss
        │
        ├── 4. Static analysis
        │         └── Scan lib/ for KnownRisk patterns + detect routes
        │         └── LateInitializationError, setState after dispose,
        │             stream leaks, build() side effects
        │
        ├── 5. Crawl all screens
        │         └── Tap nav triggers (bottom nav, buttons, drawers)
        │         └── Capture widget tree per screen via VM service
        │         └── Measure frame performance via Flutter.Frame events
        │         └── Detect widget tree issues (nesting, anti-patterns)
        │
        ├── 6. AI diagnosis per screen (if API key present)
        │         └── 3-layer knowledge prompt → Claude/GPT/Gemini
        │
        ├── 7. Generate integration tests
        │         └── integration_test/dangi_doctor/<screen>_smoke_test.dart
        │         └── integration_test/dangi_doctor/<screen>_interaction_test.dart
        │         └── integration_test/dangi_doctor/<screen>_perf_test.dart
        │         └── integration_test/dangi_doctor/test_helper.dart
        │
        └── 8. Generate HTML report → open in browser
                  └── .dangi_doctor/report_<timestamp>.html

Knowledge auto-update #

Layer 1 knowledge is bundled as a Dart constant in the package. A weekly GitHub Actions workflow refreshes it in the repo from the Flutter GitHub repo and flutter.dev docs, and every dangi_doctor release ships the knowledge current at release time — so dart pub upgrade dangi_doctor picks up whatever the newest published version bundles. Layer 2 (community anti-patterns) is maintained in knowledge/community_patterns.md — PRs welcome.

To update manually (for contributors):

dart run tool/update_knowledge.dart

Output files #

After a diagnosis run, your Flutter project will contain:

integration_test/
  dangi_doctor/
    test_helper.dart                  ← shared setup: Firebase init, auth injection
    <screen>_smoke_test.dart          ← launch test + bug-specific targeted tests
    <screen>_interaction_test.dart    ← tap every button, verify navigation
    <screen>_perf_test.dart           ← frame timing assertions

.dangi_doctor/
  project.json                        ← Layer 3 project fingerprint
  report_<timestamp>.html             ← HTML health report
  vm_url.txt                          ← cached VM URL for reconnection

License #

MIT

7
likes
160
points
178
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter app health CLI — crawls every screen, analyses widget trees, measures performance, detects bugs, and generates integration tests.

Repository (GitHub)
View/report issues

Topics

#flutter #testing #cli #performance #analysis

License

MIT (license)

Dependencies

args, http, path, vm_service, yaml

More

Packages that depend on dangi_doctor