pubghost

Detect ghosts in your Flutter/Dart project:

  • Unused dependencies in pubspec.yaml
  • Unused classes/widgets in your app lib/
  • Unused intl keys from .arb files or .json files (ignores generated l10n).

Fast, lightweight CLI you can run locally or in CI.

Features

  • -d: (--deps) Scans lib/ imports to find dependencies declared in pubspec.yaml but never imported.
  • -c: (--widgets) Finds classes defined in your app and reports ones never referenced anywhere else.
  • -t: (--intl) Parses .arb (or .json translations when json_intl_path is specified in pubspec.yaml) files and reports keys not used in code via common localization access like S.of(context).keyName, AppLocalizations.current.keyName, context.l10n.keyName, or 'keyName'.tr. Generated l10n sources are ignored.

Installation

Add as a dev dependency:

dev_dependencies:
  pubghost: ^1.0.7

Then get packages:

dart pub get

Optionally, activate globally:

dart pub global activate pubghost

Usage

Run via Dart:

dart run pubghost -d  # deps
dart run pubghost -c  # classes/widgets
dart run pubghost -t  # translations (arb)

# You can chain flags:
dart run pubghost -dc
dart run pubghost -ct
dart run pubghost -dct

Or if globally activated:

pubghost -d
pubghost -c
pubghost -t

# You can chain flags:
pubghost -dc
pubghost -ct
pubghost -dct

Commands

  • -d: (--deps) Check for unused dependencies declared in pubspec.yaml.

See Configuration and Conventions to ignore specific dependencies.

  • -c: (--widgets) Check for unused classes/widgets under your project lib/ directory.
  • -t: (--intl) Check for .arb and .json translation keys not referenced in your code. Generated l10n directories are excluded.

Output

  • Success:
    • ✅ All packages are used.
    • ✅ All classes are used.
    • ✅ All intl keys are used.
  • Findings:
    • ⚠️ Unused packages (N):
    • ⚠️ Unused classes (N):
    • ⚠️ Unused intl keys (N):

How it works

  • Unused dependencies: Looks for import 'package:<dep>/...' in your lib/ Dart files. Any dependency in pubspec.yaml without a matching import is reported.
  • Unused widgets: Lists classes defined in lib/, then searches combined project code (excluding tests) for references such as usage, generics, inheritance, mixins, and constructor calls.
  • Unused intl: Reads .arb files or json translations (if json_intl_path is specified in pubspec.yaml), collects keys, then scans your code (excluding tests and generated l10n folders) for .keyName occurrences next to a localization object. Keys seen only in generated sources are not counted as “used.”

Configuration and Conventions

  • Excludes scanning of:
    • test/
    • .dart_tool/, build/
    • gen_l10n/, l10n/generated/
  • Assumes common Flutter gen-l10n usage patterns:
    • S.of(context).myKey
    • AppLocalizations.of(context).myKey
    • AppLocalizations.current.myKey
    • context.l10n.myKey
  • Supports the exclusion of specific dependencies and classes by adding a pubghost section in pubspec.yaml:
pubghost:
  ignore_dependencies:
    - flutter_launcher_icons
  ignore_classes:
    - ExactClassName              # Exact class name match
    - ".*Model$"                  # Regex pattern: classes ending in "Model"
    - "^MyPrefix.*"               # Regex pattern: classes starting with "MyPrefix"

JSON translations:

  • When your project uses JSON translations, it is mandatory to add the json_intl_path option in pubspec.yaml.
  • It is also possible to specify a translation_accessor.
pubghost:
  json_intl_path: lib/l10n/json   # Path to JSON translations for --intl checks.
  translation_accessor: tr        # Optional: Accessor to use for translation scanning.

Limitations

  • Heuristic-based scanning may produce false positives/negatives in advanced scenarios:
    • Dynamically constructed imports/usages
    • Reflection or code generation outside the excluded folders
    • Intl keys used through non-standard access patterns

Made with 💙 from Belgium. "Buy Me A Coffee"

License

MIT

Libraries

pubghost