LIVEupkeep 0.2.0 — scan, fix and explain

Your dependencies are dying. Know first. Fix fast.

upkeep is an open source CLI for Flutter and Dart. It finds the packages that are discontinued, incompatible or abandoned, checks that your Android build matrix actually builds, and fixes what can be fixed safely. Every verdict shows its reasons.

dart pub global activate upkeep

Then run upkeep scan. If your shell says command not found, add pub's bin folder to your PATH: export PATH="$PATH:$HOME/.pub-cache/bin"

Watch the demo Web app coming soon
MIT licensedNo account, no tokenPublic pub.dev data onlyCI-ready exit codes
~/code/my_app
$ upkeep scan

upkeep 0.2.0   my_app   Dart 3.11.0

DEPENDENCIES   23 direct

  DISCONTINUED   telephony  0.2.0
      marked discontinued by its publisher on pub.dev

  AT RISK        hive  2.2.3
      declares support only up to Dart >=2.12.0 <3.0.0; it resolves today
      through pub's Dart 3 allowance, not because it was updated
      no release in 50 months

  AT RISK        hive_flutter  1.1.0
      declares support only up to Dart >=2.12.0 <3.0.0; it resolves today
      through pub's Dart 3 allowance, not because it was updated
      no release in 62 months

  SDK BLOCKED    6 packages have a newer release your Dart is too old for
      flutter_riverpod, go_router, lottie, pdf, printing, shimmer
      upgrade Flutter to pick these up: flutter upgrade

  13 healthy  .  1 stale  .  2 skipped (sdk, git or path)

ANDROID BUILD

  FAIL       Gradle 8.4 is too old for AGP 8.11.1
             AGP 8.11.1 requires Gradle 8.13 or newer. This combination does not build.
             fix: ./gradlew wrapper --gradle-version=8.13   (run inside android/)

  PASS       JDK 17 satisfies AGP 8.11.1

1 blocking, 2 at risk, 1 build failure
exit 1

Real output from a real Flutter app, renamed. The Android failure is from a copy with its Gradle wrapper set back to 8.4.

Demo

See it find what is dying, and fix it.

46 seconds. Real output, real projects.

The web app shown in the demo is coming soon. The CLI and the GitHub Action are ready today.


How it works

Three commands. Zero guesswork.

Diagnose, plan, then apply only what is safe. Nothing on disk changes until you say so.

01 / SCAN

upkeep scan

Reads your pubspec, lockfile and Gradle files, checks every direct dependency against pub.dev, and prints a verdict with its reasons.

02 / PLAN

upkeep fix

Splits what is wrong into changes upkeep can make on its own and a to-do list for the rest, with the file and line to start from.

03 / APPLY

upkeep fix --apply

Makes the automatic changes, then confirms pub get still resolves. If it does not, every file is restored.


The problem, measured by Google

44% of Flutter developer frustration is version guesswork.

Not a pitch. Google's own Q2 2026 Flutter survey found platform and ecosystem maturity drives 44% of developer dissatisfaction, and named the cause outright: hours lost juggling Flutter, Dart, Gradle, Kotlin and JVM versions. Meanwhile packages die quietly, and nothing tells you.

44%of developer dissatisfaction traced to ecosystem and version-matrix problems
18%say the critical packages they need do not exist yet
872kdownloads last month of pedantic, a package its own publisher discontinued years ago

Sources: Flutter Q2 2026 user survey, flutter.dev · pub.dev API for pedantic, 13 September 2026.


LIVE IN 0.2.0

upkeep fix

From diagnosis to treatment.

Knowing a package is dead is half the job. upkeep fix makes the changes that are safe to make, proves they work, and turns everything else into a checklist that points at the exact line.

  1. 01

    Plan

    upkeep fix

    Shows what it can change on its own and what needs you. Touches nothing.

  2. 02

    Apply

    upkeep fix --apply

    Makes only the safe changes, and refuses to edit files with uncommitted work.

  3. 03

    Verify

    pub get

    Runs the resolver on the result. If it fails, every file is put back and it exits 2.

~/code/my_app
$ upkeep fix

upkeep 0.2.0   my_app   fix plan

AUTOMATIC   2 changes upkeep can make, each one reversible

  1  Raise the Gradle wrapper to 8.13
     AGP 8.11.1 requires Gradle 8.13 or newer; the wrapper is on 8.4
     android/gradle/wrapper/gradle-wrapper.properties

  2  Remove pedantic, which nothing imports
     marked discontinued by its publisher on pub.dev
     the publisher nominates lints as the replacement
     no Dart file imports package:pedantic, and no config file names it
     pubspec.yaml

TO DO   3 changes need a person

  [ ] Replace telephony
      marked discontinued by its publisher on pub.dev
      no maintained replacement is known yet; choose one on pub.dev
      used in 2 files:
        lib/features/shield/sms_listener.dart:4
        lib/features/shield/services/sms_parser_service.dart:13

  [ ] Plan a move off hive   not blocking
      declares support only up to Dart >=2.12.0 <3.0.0; it resolves today through pub's Dart 3 allowance, not because it was updated
      no release in 50 months
      used in 4 files:
        lib/features/stock/models/stock_model.dart:7
        lib/features/shield/models/sms_receipt_model.dart:9
        lib/features/sales/models/sale_model.dart:6
        lib/features/sales/services/sync_service.dart:15

  [ ] Plan a move off hive_flutter   not blocking
      declares support only up to Dart >=2.12.0 <3.0.0; it resolves today through pub's Dart 3 allowance, not because it was updated
      no release in 62 months
      used in 1 file:
        lib/core/storage/local_db.dart:1

Run upkeep fix --apply to make the 2 automatic changes.
exit 1
What --apply changed+1 −2
android/gradle/wrapper/gradle-wrapper.properties
- distributionUrl=…/distributions/gradle-8.4-all.zip
+ distributionUrl=…/distributions/gradle-8.13-all.zip
pubspec.yaml
  dependencies:
-   pedantic: ^1.11.1
    telephony: ^0.2.0

Nothing else in the project was touched. flutter pub get resolved the result.

It will not guess

  • Only edits files that git can restore
  • Never removes a dev dependency or a Flutter plugin
  • Keeps anything a Dart file or config file mentions
  • Puts every file back if pub get fails
  • Everything else becomes a to-do, with file and line

Real output on a real Flutter app with an outdated Gradle wrapper and an unused discontinued package.


LIVE IN 0.2.0

upkeep explain

Disagree with a verdict? Check the evidence.

upkeep explain <package> shows every fact a verdict rests on: release dates, the SDK constraint, pub points, downloads, the Dart 3 tag, whether pub.dev's own analysis succeeded, and every file and line where your code uses it.

Before you add a package

Works outside a project, and exits 1 on a blocking verdict: upkeep explain x && dart pub add x

The replacement, when one is named

When a publisher retires a package, explain names its successor. For packages that died without being retired, a curated list names one too, links to the source that says so, and only when that successor is healthy today.

$ upkeep explain pedantic

upkeep 0.2.0   pedantic   explain, against Dart 3.11.0

VERDICT

  DISCONTINUED   fails a CI build
      marked discontinued by its publisher on pub.dev
      the publisher nominates lints as the replacement
      move to lints   named by its publisher

FACTS FROM PUB.DEV

  latest release    1.11.1, published 2021-06-17 (62 months ago)
  sdk constraint    >=2.12.0-0 <3.0.0
  discontinued      yes, replaced by lints
  publisher         google.dev
  pub points        160 of 160
  downloads         869k in the last 30 days
  dart 3            compatible, per pub.dev

exit 1

Real output, 12 September 2026. A perfect score and 869k monthly downloads do not outrank the publisher's word.


What it checks

Two engines. Built on published facts, not opinion.

Your dependencies

Every direct dependency, scored against pub.dev's own data.

  • Release recency and pub points
  • Dart 3 compatibility, as the resolver sees it
  • SDK constraints that block an upgrade
  • The official discontinued flag, and the named replacement

Your Android build matrix

Validated against Google's published requirements for AGP 8.0 through 9.4.

  • Gradle wrapper against the AGP in use
  • JDK against the AGP minimum
  • compileSdk against the documented ceiling
  • The exact command that fixes each failure

Five verdicts, each one explained

DISCONTINUED

The publisher said stop. Popularity does not override it.

INCOMPATIBLE

Its own ceiling excludes your Dart. No release is coming.

AT RISK

More than one warning sign, each one named.

SDK BLOCKED

Your Flutter is behind. One line, never fails your build.

HEALTHY

Checked, and nothing to say.


Principles

A tool that judges your dependencies has one asset. Trust.

Each rule exists because an earlier version of the engine got a verdict wrong.

01

Missing data is never evidence

When pub.dev cannot be reached, the verdict is unknown, not dead. An early build accused a perfectly maintained package of neglect over one truncated HTTP response.

02

Popularity never overrides a discontinued flag

pedantic is discontinued, scores 160 of 160, and is still downloaded hundreds of thousands of times a month. The publisher's word wins.

03

The resolver gets the last word

isar and hive cap themselves below Dart 3 yet still resolve. Where pub.dev's tag contradicts the arithmetic, the tag wins.

04

Stable is not abandoned

A small, finished, widely used package that has not needed a release in two years is not dying. It is done.

05

No guessing

Where Google does not publish a number, upkeep says it cannot check. Inferred values soften a verdict, never harden it.

06

Every verdict prints its reasons

Never a bare label. If you disagree, you can see exactly which fact it acted on, and check it yourself.


LIVE IN 0.2.0

GitHub Action

It opens the fix pull request for you.

One workflow file. Every pull request gets a health check in its job summary, and once a week upkeep applies the safe fixes, verifies them, and opens one pull request with the rest as a checklist.

.github/workflows/upkeep.yml
name: upkeep

on:
  pull_request:
  schedule:
    - cron: "0 6 * * 1"   # Mondays

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Minas-27/upkeep@main

  fix:
    if: github.event_name == 'schedule'
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: Minas-27/upkeep@main
        with:
          command: fix-pr
0

Clean.

1

Blocking: a discontinued, incompatible or dead dependency, or an Android matrix that does not build.

2

The command could not run, or fix --apply refused or rolled back.

The pull request only ever contains the files the automatic fixes touched, and its description is the full plan. Flutter or plain Dart is picked from your pubspec.yaml.

Not on GitHub? upkeep scan works in any pipeline, and --format json gives tools a versioned report while --format markdown suits any job summary.


Roadmap

Today it keeps one project healthy. Next, the whole ecosystem.

Everything in 0.2.0 is live on pub.dev, tested on real Flutter apps. Everything after it is a direction, not a promise, and is labelled that way.

  1. scanLive

    Verdicts with reasons, the Android build matrix, CI exit codes. On pub.dev since 0.1.

On the horizon

EXPLORING

Upgrade forecast

Resolve your whole dependency tree against the next Flutter release before you install it, and know on day one whether your project survives the upgrade.

EXPLORING

Verified migrations

Move from a dead package to its successor automatically: imports and renamed APIs rewritten, then proven with dart analyze and your own tests, or rolled back.

EXPLORING

The iOS matrix

Xcode, CocoaPods, Swift and deployment targets checked against every plugin's minimums, the way Android is today.

EXPLORING

A living compatibility atlas

An open dataset of known-bad version combinations, built from opt-in, anonymous CI results, so one team's broken build warns everyone else before theirs.

EXPLORING

Every repository at once

One view across an organisation: which of your forty apps still depend on a package that died this morning, and the pull requests already open to fix them.

EXPLORING

Inside your editor

Verdicts inline on every line of pubspec.yaml in VS Code and Android Studio, with the fix one click away.

The CLI is free and MIT licensed, and stays that way. The compounding asset is the knowledge base behind it: the compatibility matrix, the successor map, the known-bad combinations.

Know before it breaks.

One command. No configuration. The truth about your project's health.

dart pub global activate upkeep