Skip to content
Nuvyntra Labs
All toolkits

Toolkit

MauiDev

Project-aware maui-dev CLI and VS Code / Cursor extension

Current 1.2.1

Developer productivity toolkit for .NET MAUI: a maui-dev dotnet tool plus a VS Code / Cursor extension. It reads csproj, manifests, and MAUI resource items, can apply a small allow-list of fixes, and emits JSON/SARIF for CI and the IDE Problems panel.

Abstract

Usual alternatives — maui-check (environment only), dotnet workload, Visual Studio’s MAUI installer, and the Microsoft maui CLI — stop at the machine. MauiDev is project-aware: it checks SDK, workloads, Android SDK, JDK, Xcode, CocoaPods, TFMs, min SDK, permissions, duplicate resources, UseMaui, signing, store identity, and leftover Xamarin / net8 TFMs. Install Plugin.Maui.MauiDev.Cli as a global tool. Do not add it as a PackageReference in the app. The VS Code / Cursor extension (nuvyntralabs.maui-dev) shells out to maui-dev and offers to install the tool if it is missing.

Install

dotnet tool install -g Plugin.Maui.MauiDev.Cli
maui-dev doctor

Package ID: Plugin.Maui.MauiDev.Cli

Plugin.Maui.MauiDev.Cli is a global dotnet tool (net10.0). The command stays maui-dev. Do not run dotnet add package Plugin.Maui.MauiDev.Cli in an app. nuget.org reserved the ID MauiDev.Cli. Publishing is pipeline-only on the MauiDev repository.

VS Code / Cursor: install the MauiDev extension (nuvyntralabs.maui-dev) from the Marketplace. The extension shells out to maui-dev and offers to install the tool if it is missing.

Commands (1.2.1)

CommandPurpose
maui-dev doctorSDK, workloads, Android SDK, JDK, Xcode, CocoaPods, TFMs, min SDK, permissions, duplicate resources, UseMaui, signing
maui-dev analyzeCheap C# heuristics (event retention, HttpClient, fire-and-forget, MainThread hops, platform guards)
maui-dev resourcesDuplicate / missing / unused MauiImage, splash, font
maui-dev permissionsAndroid unused/duplicate permissions, iOS usage strings, Android 13+ media/notification
maui-dev platformTFM ↔ Platforms/ folders, shared-code guards, Windows/Catalyst note, min OS
maui-dev signingKeystore / entitlements checklist. Never writes secrets
maui-dev workloadDiagnose the MAUI workload and print the install command. Never installs
maui-dev versionAlign packable Version values (--align) or --bump patch|minor|major
maui-dev dependenciesPackageReference duplicates, Maui.Controls drift, CPM clash, tool-as-library
maui-dev iconsMauiIcon / splash presence, adaptive background, iOS 1024 marketing size
maui-dev publishValidate store ApplicationId / CFBundleIdentifier, iOS privacy manifest, pack metadata. Never pushes
maui-dev migrateFlag net8/net9 TFMs, Xamarin.Forms / Essentials, Forms.Init / LoadApplication
maui-dev telemetryScan the app for crash / analytics SDKs. The CLI collects nothing
maui-dev benchmarkShell to maui-perf (Plugin.Maui.Performance.Cli). Android / iOS simulator only
maui-dev cleanDelete bin / obj (optional NuGet HTTP cache and workload temp behind flags)
maui-dev packageValidate pack metadata (--validate, default). --pack runs dotnet pack locally and never pushes

Global options: --path, --format human|json|sarif, --ci (JSON + warn-as-error), --fix, --dry-run, --warn-as-error, --timeout.

maui-dev doctor --fix --dry-run
maui-dev permissions --fix --dry-run
maui-dev version --align --dry-run
maui-dev publish --validate --ci
maui-dev migrate
maui-dev telemetry
maui-dev benchmark
maui-dev analyze --ci
maui-dev package --validate

Exit codes: 0 pass/skip, 1 fail (or warning with --warn-as-error / --ci), 2 usage error.

CI JSON

--ci (or --format json) prints this schema. The VS Code / Cursor extension maps diagnostics into the Problems panel. --format sarif is the same findings for GitHub code scanning.

{
  "command": "doctor",
  "exitCode": 1,
  "results": [
    {
      "id": "dotnet-sdk",
      "title": ".NET SDK",
      "category": "machine",
      "status": "pass",
      "detail": "10.0.102",
      "canFix": false,
      "diagnostics": []
    },
    {
      "id": "maui-resources",
      "title": "Duplicate resources",
      "category": "project",
      "status": "fail",
      "detail": "3 detected",
      "recommendation": "Remove duplicate MauiSplashScreen entries.",
      "canFix": true,
      "diagnostics": [
        {
          "id": "MD030",
          "message": "Duplicate MauiSplashScreen 'Resources/Splash/splash.svg'",
          "file": "App.csproj",
          "line": 12,
          "severity": "fail"
        }
      ]
    }
  ]
}

Usage and sample results

Each sample is a typical human report from a project with problems. A healthy tree prints green checks and exits 0. Run with --dry-run before --fix.

Diagnose

maui-dev doctor

SDK, workloads, Android SDK, JDK, Xcode, CocoaPods, TFMs, min SDK, permissions, duplicate resources, UseMaui, signing

Usage

maui-dev doctor
maui-dev doctor --path ./src/App
maui-dev doctor --fix --dry-run

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Machine
────────────────────────────────────

✓ .NET SDK               10.0.102
✓ MAUI workload          maui 10.0.0
✓ Android SDK            ANDROID_HOME set
✓ JDK                    17.0.12
· Xcode                  skipped (Linux)
· CocoaPods              skipped (Linux)

Project
────────────────────────────────────

✗ UseMaui                missing <UseMaui>true</UseMaui>
✗ Duplicate resources    3 detected
⚠ Android min SDK        21 (recommend 24+)

Recommendations
────────────────────────────────────

[1] Add <UseMaui>true</UseMaui> — the project already looks like MAUI.
[2] Remove duplicate MauiSplashScreen entries.

Fixes
────────────────────────────────────

Would insert <UseMaui>true</UseMaui> in App.csproj
Would keep one MauiSplashScreen Include and drop the extras
  App.csproj

--fix only inserts UseMaui and deduplicates identical MauiSplashScreen / MauiImage / MauiIcon / MauiFont items. Pass --dry-run first.

maui-dev analyze

Cheap C# heuristics (event retention, HttpClient, fire-and-forget, MainThread hops, platform guards)

Usage

maui-dev analyze
maui-dev analyze --ci

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Project
────────────────────────────────────

⚠ Analyze                5 findings

Recommendations
────────────────────────────────────

[1] MD100 MainPage.xaml.cs:12  event handler retained after the page is gone
[2] MD101 MainPage.xaml.cs:14  new HttpClient() inside a method — prefer IHttpClientFactory
[3] MD102 MainPage.xaml.cs:14  fire-and-forget Task.Run without observation
[4] MD103 MainPage.xaml.cs:15  repeated MainThread hops in one constructor
[5] MD105 MainPage.xaml.cs:18  Android API used without a platform guard

Heuristic, not a Roslyn analyzer. --ci emits JSON for the IDE Problems panel.

maui-dev resources

Duplicate / missing / unused MauiImage, splash, font

Usage

maui-dev resources
maui-dev resources --path ./src/App

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Resources
────────────────────────────────────

✗ Resources              missing MauiImage + unused splash

Recommendations
────────────────────────────────────

[1] MD201 App.csproj:18  MauiImage Include 'logo.png' has no file on disk
[2] MD202 Resources/Splash/splash.svg is never referenced

Project

maui-dev permissions

Android unused/duplicate permissions, iOS usage strings, Android 13+ media/notification

Usage

maui-dev permissions
maui-dev permissions --fix --dry-run

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Project
────────────────────────────────────

✗ Permissions            duplicate CAMERA + missing NSCameraUsageDescription

Recommendations
────────────────────────────────────

[1] Deduplicate identical Android UsesPermission nodes.
[2] Add an iOS usage string for the camera permission you declared.

Fixes
────────────────────────────────────

Would keep one android.permission.CAMERA and drop the duplicate
  Platforms/Android/AndroidManifest.xml

--fix only deduplicates identical Android UsesPermission / manifest nodes. It never removes a permission.

maui-dev platform

TFM ↔ Platforms/ folders, shared-code guards, Windows/Catalyst note, min OS

Usage

maui-dev platform
maui-dev platform --ci

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Project
────────────────────────────────────

⚠ Target frameworks      net10.0-android; net10.0-ios
⚠ Platforms              no Platforms/Windows folder for a Windows TFM
✓ Compile guards         shared code is platform-neutral

maui-dev signing

Keystore / entitlements checklist. Never writes secrets

Usage

maui-dev signing
maui-dev signing --ci

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Project
────────────────────────────────────

⚠ Signing                AndroidKeyStore not set for Release
⚠ Entitlements           no Entitlements.plist on the iOS TFM

Recommendations
────────────────────────────────────

[1] Point Release at a keystore from CI secrets — do not commit the file.
[2] Add Platforms/iOS/Entitlements.plist when the app uses push or iCloud.

Checklist only. maui-dev never writes keystore passwords, provisioning profiles, or signing secrets.

maui-dev workload

Diagnose the MAUI workload and print the install command. Never installs

Usage

maui-dev workload

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Machine
────────────────────────────────────

✗ MAUI workload          maui workload is not installed

Recommendations
────────────────────────────────────

[1] Run: dotnet workload install maui

Prints the install command. It never runs dotnet workload install.

maui-dev version

Align packable Version values (--align) or --bump patch|minor|major

Usage

maui-dev version --align --dry-run
maui-dev version --bump patch --dry-run
maui-dev version --bump minor

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Packaging
────────────────────────────────────

⚠ Version                Lib 1.0.0 and Cli 1.0.1 are not aligned

Fixes
────────────────────────────────────

Would set Version and PackageVersion to 1.0.1
  src/Lib/Lib.csproj
Would leave Cli at 1.0.1
  src/Cli/Cli.csproj
Would set extension/vscode/package.json version to 1.0.1

--align writes every packable Version to the highest existing value. --bump implies --align. Both honor --dry-run. Invalid --bump values exit 2.

maui-dev dependencies

PackageReference duplicates, Maui.Controls drift, CPM clash, tool-as-library

Usage

maui-dev dependencies
maui-dev dependencies --ci

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Packaging
────────────────────────────────────

✗ Dependencies           duplicate PackageReference + Maui.Controls drift

Recommendations
────────────────────────────────────

[1] App.csproj references Plugin.Maui.GeoLocator twice with different versions.
[2] Microsoft.Maui.Controls 10.0.10 drifts from the workload 10.0.0 pin.
[3] Do not PackageReference a PackAsTool project (Plugin.Maui.MauiDev.Cli).

maui-dev icons

MauiIcon / splash presence, adaptive background, iOS 1024 marketing size

Usage

maui-dev icons

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Resources
────────────────────────────────────

⚠ Icons                  MauiIcon present; iOS marketing size is 512

Recommendations
────────────────────────────────────

[1] Supply a 1024×1024 iOS marketing / App Store icon.
[2] Set an adaptive icon background color for Android.

Release

maui-dev publish

Validate store ApplicationId / CFBundleIdentifier, iOS privacy manifest, pack metadata. Never pushes

Usage

maui-dev publish --validate
maui-dev publish --validate --ci

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Packaging
────────────────────────────────────

✗ ApplicationId          missing ApplicationId / CFBundleIdentifier
⚠ Privacy manifest       no PrivacyInfo.xcprivacy on the iOS TFM
✓ Pack metadata          README, icon, and license are present

Recommendations
────────────────────────────────────

[1] Set ApplicationId (Android) and CFBundleIdentifier (iOS) before store upload.
[2] Add Platforms/iOS/PrivacyInfo.xcprivacy for iOS 17+ required-reason APIs.

--validate is the default. --push is rejected (exit 2). Publishing NuGet packages is pipeline-only.

maui-dev migrate

Flag net8/net9 TFMs, Xamarin.Forms / Essentials, Forms.Init / LoadApplication

Usage

maui-dev migrate
maui-dev migrate --ci

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Project
────────────────────────────────────

⚠ Migrate                net8 TFM + Xamarin leftovers

Recommendations
────────────────────────────────────

[1] TargetFrameworks still includes net8.0-android — move to net10.0-*.
[2] Xamarin.Forms / Xamarin.Essentials PackageReference found.
[3] Forms.Init / LoadApplication remain in App.xaml.cs — MAUI uses MauiProgram.

Flags only. It never rewrites TFMs or source.

maui-dev telemetry

Scan the app for crash / analytics SDKs. The CLI collects nothing

Usage

maui-dev telemetry

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Project
────────────────────────────────────

⚠ Telemetry              AppCenter + Firebase Analytics referenced

Recommendations
────────────────────────────────────

[1] Plugin.Maui.Diagnostics is the lab crash / ANR package if you want that surface.
[2] The CLI itself collects nothing — this command only scans the app.

Scan only. MauiDev does not send telemetry.

maui-dev benchmark

Shell to maui-perf (Plugin.Maui.Performance.Cli). Android / iOS simulator only

Usage

maui-dev benchmark
maui-dev benchmark startup

Sample result

maui-perf is not on PATH.

Install:  dotnet tool install -g Plugin.Maui.Performance.Cli
Then:     maui-dev benchmark startup

MD900  benchmark requires maui-perf (Plugin.Maui.Performance.Cli).

Does not reimplement maui profile. Extra args are forwarded to maui-perf. Android / iOS simulator only.

maui-dev clean

Delete bin / obj (optional NuGet HTTP cache and workload temp behind flags)

Usage

maui-dev clean
maui-dev clean --dry-run
maui-dev clean --nuget-http-cache --yes

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Project
────────────────────────────────────

✓ Clean                  deleted src/bin and src/obj

Fixes
────────────────────────────────────

Deleted src/bin
Deleted src/obj

--nuget-http-cache and --workload-temp require --yes. --nuget-global also requires --force.

maui-dev package

Validate pack metadata (--validate, default). --pack runs dotnet pack locally and never pushes

Usage

maui-dev package --validate
maui-dev package --validate --ci
maui-dev package --pack

Sample result

.NET MAUI Developer Doctor
────────────────────────────────────

Packaging
────────────────────────────────────

✗ Package                Version mismatch across packable projects

Recommendations
────────────────────────────────────

[1] MD401 Lib is 1.0.0 and Cli is 1.0.1 — align with maui-dev version --align.

--pack runs dotnet pack locally. It never pushes to nuget.org.

--fix allow-list

  • doctor: deduplicates identical MauiSplashScreen / MauiImage / MauiIcon / MauiFont items; inserts <UseMaui>true</UseMaui> when the project already looks like MAUI.
  • permissions: deduplicates identical Android UsesPermission / manifest nodes.
  • version --align / --bump: writes Version / PackageVersion and extension/vscode/package.json.

It never

  • Never bumps min SDK.
  • Never removes permissions.
  • Never writes signing secrets.
  • Never installs workloads.
  • Never rewrites TFMs or Xamarin leftovers.
  • Never publishes or pushes NuGet packages.

CI

- script: maui-dev doctor --ci
- script: maui-dev analyze --ci
- script: maui-dev permissions --ci
- script: maui-dev platform --ci
- script: maui-dev publish --validate --ci
- script: maui-dev migrate --ci
- script: maui-dev package --validate --ci

maui-check covers the environment only. dotnet workload, Visual Studio’s MAUI installer, and the Microsoft maui CLI install or list SDKs. MauiDev reads the project and can apply a small allow-list of fixes.

Use a plugin instead when

Later

  • MauiDev.Analyzers
  • MauiDev.Templates

Release notes

  • 1.2.1. PackageProjectUrl and docs links point at https://nuvyntralabs.github.io/toolkits/maui-dev/.
  • 1.2.0. publish --validate (store ApplicationId / CFBundleIdentifier, iOS privacy manifest). --push is rejected.
  • 1.2.0. migrate flags net8/net9 TFMs and Xamarin leftovers without rewriting.
  • 1.2.0. telemetry scans the app for crash / analytics SDKs. The CLI collects nothing.
  • 1.2.0. benchmark shells to maui-perf (Plugin.Maui.Performance.Cli); MD900 if the tool is missing.
  • 1.1.0. permissions, platform, signing, workload, version, dependencies, icons.
  • 1.1.0. permissions --fix deduplicates identical Android permission nodes.
  • 1.1.0. version --align / --bump patch|minor|major write packable Version values (honors --dry-run).
  • 1.1.0. .maui-dev.json ignore accepts diagnostic ids (MD020) as well as check ids.
  • 1.0.1. PackageId is Plugin.Maui.MauiDev.Cli. nuget.org reserved MauiDev.Cli. Command stays maui-dev.
  • 1.0.0. maui-dev doctor with machine and project checks, --ci, allow-listed --fix / --dry-run.

Discussion

Comment on MauiDev. The thread lives on this component's GitHub repository (nuvyntralabs/MauiDev). Sign in with GitHub — Giscus uses Discussions, Utterances uses Issues.