Shiny.Health.Extensions.AI 2.0.0-beta-0003

Prefix Reserved
This is a prerelease version of Shiny.Health.Extensions.AI.
dotnet add package Shiny.Health.Extensions.AI --version 2.0.0-beta-0003
                    
NuGet\Install-Package Shiny.Health.Extensions.AI -Version 2.0.0-beta-0003
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Shiny.Health.Extensions.AI" Version="2.0.0-beta-0003" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Shiny.Health.Extensions.AI" Version="2.0.0-beta-0003" />
                    
Directory.Packages.props
<PackageReference Include="Shiny.Health.Extensions.AI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Shiny.Health.Extensions.AI --version 2.0.0-beta-0003
                    
#r "nuget: Shiny.Health.Extensions.AI, 2.0.0-beta-0003"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Shiny.Health.Extensions.AI@2.0.0-beta-0003
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Shiny.Health.Extensions.AI&version=2.0.0-beta-0003&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Shiny.Health.Extensions.AI&version=2.0.0-beta-0003&prerelease
                    
Install as a Cake Tool

Shiny Health

Apple HealthKit and Android Health Connect for your .NET MAUI apps.

Features

  • Read summary values between timestamps at specified intervals
  • Write health data to Apple HealthKit and Android Health Connect
  • Real-time observation of health data changes via IAsyncEnumerable<HealthResult>
  • 30+ cross-platform data types covering activity, body, vitals, nutrition, reproductive/cycle tracking, and workouts
  • Query activity (distance, step count, calories, active/basal energy, floors climbed, wheelchair pushes, speed, power) and heart rate (average, resting, variability)
  • Query body metrics (weight, height, body fat, lean body mass) and vitals (blood pressure, oxygen saturation, blood glucose, body temperature, respiratory rate, VO2 max)
  • Query lifestyle (sleep duration, hydration, nutrition) and workouts/exercise sessions
  • Reproductive & cycle tracking (menstruation flow, sexual activity, ovulation tests, cervical mucus, intermenstrual bleeding)
  • Permission management for both platforms with read/write support

How To Use

IHealthService health; // inject via DI

// request read permissions
var result = await health.RequestPermissions(
    DataType.Calories,
    DataType.Distance,
    DataType.StepCount,
    DataType.HeartRate
);

// request per-metric read/write permissions in a single call
var result2 = await health.RequestPermissions(
    (PermissionType.Read, DataType.StepCount),
    (PermissionType.Read, DataType.HeartRate),
    (PermissionType.Write, DataType.Weight),
    (PermissionType.ReadWrite, DataType.BloodPressure)
);

var end = DateTimeOffset.Now;
var start = DateTimeOffset.Now.AddDays(-1);

// query data
var distance = (await health.GetDistances(start, end, Interval.Days)).Sum(x => x.Value);
var calories = (await health.GetCalories(start, end, Interval.Days)).Sum(x => x.Value);
var steps = (await health.GetStepCounts(start, end, Interval.Days)).Sum(x => x.Value);
var heartRate = (await health.GetAverageHeartRate(start, end, Interval.Days)).Average(x => x.Value);

// body metrics
var weight = (await health.GetWeight(start, end, Interval.Days)).Average(x => x.Value); // kg
var height = (await health.GetHeight(start, end, Interval.Days)).Average(x => x.Value); // meters
var bodyFat = (await health.GetBodyFatPercentage(start, end, Interval.Days)).Average(x => x.Value); // %
var restingHr = (await health.GetRestingHeartRate(start, end, Interval.Days)).Average(x => x.Value); // bpm

// vitals
var o2 = (await health.GetOxygenSaturation(start, end, Interval.Days)).Average(x => x.Value); // %
var bp = await health.GetBloodPressure(start, end, Interval.Days); // BloodPressureResult with Systolic/Diastolic (mmHg)

// lifestyle
var sleep = (await health.GetSleepDuration(start, end, Interval.Days)).Sum(x => x.Value); // hours
var water = (await health.GetHydration(start, end, Interval.Days)).Sum(x => x.Value); // liters

// --- Writing Data ---

// request write permissions (uniform)
await health.RequestPermissions(PermissionType.Write, DataType.Weight, DataType.StepCount, DataType.Hydration);

// or mix read/write per metric
await health.RequestPermissions(
    (PermissionType.Write, DataType.Weight),
    (PermissionType.ReadWrite, DataType.Hydration)
);

// write a weight measurement
await health.Write(new NumericHealthResult(DataType.Weight, DateTimeOffset.Now, DateTimeOffset.Now, 75.0)); // kg

// write step counts over a time range
await health.Write(new NumericHealthResult(DataType.StepCount, start, end, 500));

// write hydration
await health.Write(new NumericHealthResult(DataType.Hydration, start, end, 0.5)); // liters

// write blood pressure
await health.Write(new BloodPressureResult(DateTimeOffset.Now, DateTimeOffset.Now, 120.0, 80.0)); // mmHg

// --- Observing Real-Time Changes ---

// observe heart rate changes as they arrive
using var cts = new CancellationTokenSource();

await foreach (var result in health.Observe(DataType.HeartRate, cancelToken: cts.Token))
{
    if (result is NumericHealthResult numeric)
        Console.WriteLine($"Heart rate: {numeric.Value} bpm at {numeric.Start:T}");
}

// observe with custom polling interval (Android only, iOS ignores this - it's push-based)
await foreach (var result in health.Observe(DataType.StepCount, pollingInterval: TimeSpan.FromSeconds(10), cancelToken: cts.Token))
{
    if (result is NumericHealthResult numeric)
        Console.WriteLine($"Steps: {numeric.Value}");
}

Supported Metrics

Metric Unit iOS (HealthKit) Android (Health Connect)
Step Count count StepCount StepsRecord
Heart Rate bpm HeartRate HeartRateRecord
Calories kcal ActiveEnergyBurned TotalCaloriesBurnedRecord
Distance meters DistanceWalkingRunning DistanceRecord
Weight kg BodyMass WeightRecord
Height meters Height HeightRecord
Body Fat % % BodyFatPercentage BodyFatRecord
Resting Heart Rate bpm RestingHeartRate RestingHeartRateRecord
Blood Pressure mmHg BloodPressureSystolic/Diastolic BloodPressureRecord
Oxygen Saturation % OxygenSaturation OxygenSaturationRecord
Sleep Duration hours SleepAnalysis SleepSessionRecord
Hydration liters DietaryWater HydrationRecord
Blood Glucose mg/dL BloodGlucose BloodGlucoseRecord
Body Temperature °C BodyTemperature BodyTemperatureRecord
Basal Body Temperature °C BasalBodyTemperature BasalBodyTemperatureRecord
Respiratory Rate breaths/min RespiratoryRate RespiratoryRateRecord
VO2 Max mL/kg/min VO2Max Vo2MaxRecord
Heart Rate Variability ms HeartRateVariabilitySDNN HeartRateVariabilityRmssdRecord¹
Lean Body Mass kg LeanBodyMass LeanBodyMassRecord
Basal Energy Burned kcal BasalEnergyBurned BasalMetabolicRateRecord
Active Energy Burned kcal ActiveEnergyBurned ActiveCaloriesBurnedRecord
Floors Climbed count FlightsClimbed FloorsClimbedRecord
Wheelchair Pushes count PushCount WheelchairPushesRecord
Speed m/s WalkingSpeed² SpeedRecord
Power watts CyclingPower² PowerRecord
Menstruation Flow flow level MenstrualFlow MenstruationFlowRecord
Sexual Activity protection enum SexualActivity SexualActivityRecord
Ovulation Test result enum OvulationTestResult OvulationTestRecord
Cervical Mucus appearance enum CervicalMucusQuality CervicalMucusRecord
Intermenstrual Bleeding event IntermenstrualBleeding IntermenstrualBleedingRecord
Workout session HKWorkout ExerciseSessionRecord
Nutrition food/macros Food correlation NutritionRecord

¹ HealthKit reports HRV as SDNN while Health Connect reports RMSSD — both are in milliseconds but computed differently, so values are not directly comparable across platforms.

² Health Connect's SpeedRecord/PowerRecord are generic. HealthKit has no generic equivalents, so Speed maps to walking speed and Power maps to cycling power.

Categorical / event-based / structured metrics (menstruation flow, sexual activity, ovulation tests, cervical mucus, intermenstrual bleeding, workouts, nutrition) are not numeric. Each uses its own result record (e.g. MenstruationFlowResult, SexualActivityResult, WorkoutResult, NutritionResult), has no Interval bucketing, and is read via a dedicated method (GetMenstruationFlow, GetSexualActivity, GetOvulationTests, GetCervicalMucus, GetIntermenstrualBleeding, GetWorkouts, GetNutrition). The MenstrualFlow.None level and IsCycleStart flag are iOS-only; Health Connect has no None value and ignores IsCycleStart. A WorkoutResult's energy/distance are null on Android read (Health Connect stores them as separate records from the exercise session).

AI Tools

NuGet

Shiny.Health.Extensions.AI exposes IHealthService as Microsoft.Extensions.AI tool functions for LLM agents. It uses a few parameterized tools (one read tool covers all numeric metrics via a metric enum, instead of one tool per metric) so the model's tool list stays short. Opt-in exactly which areas the model can see — read-only by default, write per-area. Resolve HealthAITools from DI and pass .Tools to any IChatClient. AOT-compatible.

dotnet add package Shiny.Health.Extensions.AI
using Shiny.Health.Extensions.AI;

builder.Services.AddHealthIntegration();
builder.Services.AddHealthAITools(tools => tools
    .AddAllMetrics()                                          // read every numeric metric
    .AddMetric(DataType.Weight, HealthAICapabilities.ReadWrite)
    .AddBloodPressure(HealthAICapabilities.ReadWrite)
    .AddCycleTracking()
    .AddWorkouts(HealthAICapabilities.ReadWrite)
    .AddNutrition()
);

// later, hand the tools to a chat client
var tools = sp.GetRequiredService<HealthAITools>().Tools;
var response = await chatClient.GetResponseAsync(
    messages,
    new ChatOptions { Tools = [.. tools] }
);

Generated tools (only for areas you opt-in to): get_health_metric / write_health_metric, get_blood_pressure / write_blood_pressure, get_cycle_records / write_menstruation_flow, get_workouts / write_workout, get_nutrition / write_nutrition. The tools assume permissions are already granted — call RequestPermissions from your app first.

Setup

Install from NuGet: NuGet

dotnet add package Shiny.Health

In your MauiProgram.cs:

public static MauiApp CreateMauiApp()
{
    var builder = MauiApp
        .CreateBuilder()
        .UseMauiApp<App>()
        .UseShiny();

    builder.Services.AddHealthIntegration();
    return builder.Build();
}

iOS Setup

Your app requires a provisioning profile with HealthKit capabilities enabled.

Info.plist
<key>UIRequiredDeviceCapabilities</key>
<array>
    <string>healthkit</string>
</array>
<key>NSHealthUpdateUsageDescription</key>
<string>We need access to update your health data</string>
<key>NSHealthShareUsageDescription</key>
<string>We need access to read your health data</string>
Entitlements.plist
<key>com.apple.developer.healthkit</key>
<true />
<key>com.apple.developer.healthkit.background-delivery</key>
<true />

Android Setup (Health Connect)

Android uses Health Connect (the replacement for the deprecated Google Fit API). Health Connect requires Android 9 (API 28) or higher.

AndroidManifest.xml

<uses-permission android:name="android.permission.health.READ_STEPS" />
<uses-permission android:name="android.permission.health.READ_HEART_RATE" />
<uses-permission android:name="android.permission.health.READ_TOTAL_ENERGY_BURNED" />
<uses-permission android:name="android.permission.health.READ_DISTANCE" />
<uses-permission android:name="android.permission.health.READ_WEIGHT" />
<uses-permission android:name="android.permission.health.READ_HEIGHT" />
<uses-permission android:name="android.permission.health.READ_BODY_FAT" />
<uses-permission android:name="android.permission.health.READ_RESTING_HEART_RATE" />
<uses-permission android:name="android.permission.health.READ_BLOOD_PRESSURE" />
<uses-permission android:name="android.permission.health.READ_OXYGEN_SATURATION" />
<uses-permission android:name="android.permission.health.READ_SLEEP" />
<uses-permission android:name="android.permission.health.READ_HYDRATION" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />


<uses-permission android:name="android.permission.health.WRITE_STEPS" />
<uses-permission android:name="android.permission.health.WRITE_HEART_RATE" />
<uses-permission android:name="android.permission.health.WRITE_TOTAL_ENERGY_BURNED" />
<uses-permission android:name="android.permission.health.WRITE_DISTANCE" />
<uses-permission android:name="android.permission.health.WRITE_WEIGHT" />
<uses-permission android:name="android.permission.health.WRITE_HEIGHT" />
<uses-permission android:name="android.permission.health.WRITE_BODY_FAT" />
<uses-permission android:name="android.permission.health.WRITE_RESTING_HEART_RATE" />
<uses-permission android:name="android.permission.health.WRITE_BLOOD_PRESSURE" />
<uses-permission android:name="android.permission.health.WRITE_OXYGEN_SATURATION" />
<uses-permission android:name="android.permission.health.WRITE_SLEEP" />
<uses-permission android:name="android.permission.health.WRITE_HYDRATION" />


<queries>
    <package android:name="com.google.android.apps.healthdata" />
</queries>
Requirements
  • The Health Connect app must be installed on the device
  • Minimum SDK version must be set to 28 (Android 9)
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0-beta-0003 0 6/15/2026