Help us improve
Share bugs, ideas, or general feedback.
From shiny-permissions-msbuild
Generate Android manifest permissions/features and iOS Info.plist entries for .NET MAUI apps using Shiny.Permissions.MSBuild
npx claudepluginhub shinyorg/msbuildpermissionsHow this skill is triggered — by the user, by Claude, or both
Slash command
/shiny-permissions-msbuild:shiny-permissions-msbuildThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are an expert in Shiny.Permissions.MSBuild, an MSBuild task library that automatically generates Android manifest permissions/features and iOS Info.plist entries during the .NET MAUI build process.
Guides .NET MAUI runtime permissions: check/request status, PermissionStatus handling, custom BasePlatformPermission, Android manifest/Info.plist declarations, DI services. Use for permission requests/denials.
Building .NET MAUI apps. Project structure, XAML/MVVM, platform services, current caveats.
Advises on mobile lifecycle, permissions, deep linking, push notifications, and app store compliance. Covers iOS, Android, React Native, and Flutter.
Share bugs, ideas, or general feedback.
You are an expert in Shiny.Permissions.MSBuild, an MSBuild task library that automatically generates Android manifest permissions/features and iOS Info.plist entries during the .NET MAUI build process.
Invoke this skill when the user wants to:
MauiPermission items instead of manual platform XMLPackage: Shiny.Permissions.MSBuild
How it works: Declare MSBuild items in .csproj → the build task generates platform XML into $(IntermediateOutputPath) before the Build target runs.
There are four item types:
MauiPermission — high-level permission sets that generate both Android and iOS entriesAndroidManifestPermission — individual Android <uses-permission> entriesAndroidManifestFeature — individual Android <uses-feature> entriesInfoPlistPermission — individual iOS Info.plist key/value entriesThis is the primary API. One item generates all required platform entries.
<ItemGroup>
<MauiPermission Include="Camera" />
<MauiPermission Include="Location" />
<MauiPermission Include="BluetoothLE" />
</ItemGroup>
BLUETOOTH, BLUETOOTH_ADMIN, BLUETOOTH_CONNECT, BLUETOOTH_SCAN, ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATIONUIBackgroundModes → bluetooth-central, NSBluetoothAlwaysUsageDescriptionACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATIONLOCATION.GPS (required=false), LOCATION.NETWORK (required=false)UIBackgroundModes → location, NSLocationAlwaysUsageDescription, NSLocationWhenInUseUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescriptionFOREGROUND_SERVICE_LOCATION, FOREGROUND_SERVICE, ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATIONLOCATION.GPS (required=false), LOCATION.NETWORK (required=false)UIBackgroundModes → location, NSLocationAlwaysUsageDescription, NSLocationWhenInUseUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescriptionACCESS_BACKGROUND_LOCATION, ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATIONLOCATION.GPS (required=false), LOCATION.NETWORK (required=false)UIBackgroundModes → location, NSLocationAlwaysUsageDescription, NSLocationWhenInUseUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescriptionPOST_NOTIFICATIONSUIBackgroundModes → remote-notificationRECORD_AUDIONSMicrophoneUsageDescriptionREAD_CONTACTSNSContactsUsageDescriptionREAD_CALENDARNSCalendarsUsageDescriptionCAMERANSCameraUsageDescriptionREAD_EXTERNAL_STORAGENSPhotoLibraryUsageDescriptionACCESS_FINE_LOCATIONNSLocationWhenInUseUsageDescriptionUSE_BIOMETRICNSFaceIDUsageDescriptionWhen multiple MauiPermission items are declared:
UIBackgroundModes) are merged — values from all permission sets are combined into a single array, preserving insertion order and removing duplicatesAll iOS usage description strings default to: "Say something useful here that your users will understand". Users should override these with real descriptions for App Store submission.
<ItemGroup>
<AndroidManifestPermission Include="CAMERA" />
<AndroidManifestPermission Include="ACCESS_FINE_LOCATION" />
<AndroidManifestPermission Include="READ_EXTERNAL_STORAGE" MaxSdkVersion="32" />
<AndroidManifestPermission Include="WRITE_EXTERNAL_STORAGE" MinSdkVersion="19" MaxSdkVersion="28" />
</ItemGroup>
Metadata: MinSdkVersion (optional), MaxSdkVersion (optional)
Name resolution: Short names are prefixed with android.permission.. Fully qualified names (3+ dot segments) are used as-is.
<ItemGroup>
<AndroidManifestFeature Include="CAMERA" />
<AndroidManifestFeature Include="LOCATION.GPS" Required="true" />
<AndroidManifestFeature Include="BLUETOOTH" Required="false" />
</ItemGroup>
Metadata: Required (optional, true or false)
Name resolution: Short names are prefixed with android.hardware.. Fully qualified names (3+ dot segments) are used as-is.
<ItemGroup>
<InfoPlistPermission Include="NSCameraUsageDescription" Type="string" Value="We need camera access" />
<InfoPlistPermission Include="UIRequiresPersistentWiFi" Type="boolean" Value="true" />
<InfoPlistPermission Include="LSApplicationQueriesSchemes" Type="stringarray" Value="fb;instagram;twitter" />
<InfoPlistPermission Include="UIDeviceFamily" Type="integerarray" Value="1;2" />
</ItemGroup>
Metadata: Type (optional, default string — supports string, boolean/bool, stringarray, integerarray), Value (optional)
For arrays, separate items with ;. Use stringarray for <string> elements and integerarray for <integer> elements. The legacy type name array is accepted as an alias for stringarray.
All files are written to $(IntermediateOutputPath):
| Item Group | Output File |
|---|---|
MauiPermission | AndroidManifest.xml + Info.plist |
AndroidManifestPermission / AndroidManifestFeature | AndroidManifest.xml |
InfoPlistPermission | Info.plist |
src/Shiny.Permissions.MSBuild/
├── build/
│ ├── Shiny.Permissions.MSBuild.props # Defines item groups
│ └── Shiny.Permissions.MSBuild.targets # Registers tasks and targets
├── Generators/
│ ├── AndroidManifestGenerator.cs # Android XML generation
│ ├── InfoPlistGenerator.cs # iOS plist XML generation
│ └── MauiPermissionsGenerator.cs # Permission set resolution + orchestration
├── Models/
│ ├── AndroidPermission.cs # Name, MinSdkVersion, MaxSdkVersion
│ ├── AndroidFeature.cs # Name, Required
│ └── InfoPlistEntry.cs # Key, Type, Value
└── Tasks/
├── GenerateAndroidManifestTask.cs # MSBuild task for AndroidManifestPermission/Feature
├── GenerateInfoPlistTask.cs # MSBuild task for InfoPlistPermission
└── GenerateMauiPermissionsTask.cs # MSBuild task for MauiPermission
MauiPermission over individual items — it handles all platform details and deduplication automaticallyobj/ output to verify generated XML during development<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net9.0-android;net9.0-ios</TargetFrameworks>
<OutputType>Exe</OutputType>
<UseMaui>true</UseMaui>
</PropertyGroup>
<ItemGroup>
<MauiPermission Include="Camera" />
<MauiPermission Include="BluetoothLE" />
<MauiPermission Include="Location" />
<MauiPermission Include="Push" />
<MauiPermission Include="Biometric" />
<MauiPermission Include="Contacts" />
</ItemGroup>
</Project>
This single declaration generates:
<uses-permission> entries (deduplicated) + 2 <uses-feature> entriesUIBackgroundModes array with bluetooth-central, location, remote-notification + 6 usage description strings