expo-modules — apple healthkit integration expo-modules, apple-health, manavkushwaha10, community, apple healthkit integration, ai agent skill, mcp server, agent automation, ios health data access, react native health metrics, wearable data sync, healthcare application development

v1.0.0
GitHub

About this Skill

Perfect for Health and Fitness Agents needing native Apple HealthKit integration on iOS. expo-modules is a set of standards for designing native APIs, inspired by modern web modules, with a focus on backwards compatibility and native functionality exposure.

Features

Supports reading and writing health data using Apple HealthKit
Enables subscription to health data for real-time updates
Exposes native functionality directly, avoiding extraneous abstractions
Uses sync methods when possible, reducing unnecessary async operations
Employs string union types for API options, enhancing flexibility

# Core Topics

manavkushwaha10 manavkushwaha10
[0]
[0]
Updated: 3/16/2026

Quality Score

Top 5%
42
Excellent
Based on code quality & docs
Installation
SYS Universal Install (Auto-Detect)
> npx killer-skills add manavkushwaha10/apple-health/expo-modules
Supports 18+ Platforms
Cursor
Windsurf
VS Code
Trae
Claude
OpenClaw
+12 more

Agent Capability Analysis

The expo-modules MCP Server by manavkushwaha10 is an open-source community integration for Claude and other AI agents, enabling seamless task automation and capability expansion. Optimized for apple healthkit integration, ios health data access, react native health metrics.

Ideal Agent Persona

Perfect for Health and Fitness Agents needing native Apple HealthKit integration on iOS.

Core Value

Empowers agents to seamlessly interact with Apple HealthKit, supporting diverse health metrics and workouts through native APIs, while ensuring 100% backwards compatibility and utilizing string union types for API options.

Capabilities Granted for expo-modules MCP Server

Reading and writing health data from Apple HealthKit
Subscribing to health data updates for real-time tracking
Integrating workout data into fitness applications

! Prerequisites & Limits

  • iOS only
  • Requires Apple HealthKit compatibility
  • Native functionality exposure may require additional permissions
SKILL.md
Readonly

Great module standards

  • Design native APIs as if you contributing W3C specs for the browser, take inspiration from modern web modules. eg std:kv-storage, clipboard.
  • Aim for 100% backwards compatibility like the web.
  • Create escape hatches for single-platform functionality.
  • Avoid extraneous abstractions. Directly expose native functionality.
  • Avoid unnecessary async methods. Use sync methods when possible.
  • Prefer string union types for API options instead of boolean flags, enums, or multiple parameters. eg instead of capture(options: { isHighQuality: boolean }), use capture(options: { quality: 'high' | 'medium' | 'low' }).
  • Marshalling is awesome for platform-specific APIs.
  • New Architecture only. NEVER support legacy React Native architecture.
  • ALWAYS use only Expo modules API.
  • Prefer Swift and Kotlin.
  • Use optionality for availability checks as opposed to extraneous isAvailable functions or constants. eg snapshot.capture?.() instead of snapshot.isAvailable && snapshot.capture().
  • ALWAYS support the latest and greatest API features.

Example of a GREAT Expo module:

ts
1import { NativeModule } from "expo"; 2 3declare class AppClipModule extends NativeModule<{}> { 4 prompt(): void; 5 isAppClip?: boolean; 6} 7 8// This call loads the native module object from the JSI. 9const AppClipNative = 10 typeof expo !== "undefined" 11 ? (expo.modules.AppClip as AppClipModule) ?? {} 12 : {}; 13 14if (AppClipNative?.isAppClip) { 15 navigator.appClip = { 16 prompt: AppClipNative.prompt, 17 }; 18} 19 20// Add types for the global `navigator.appClip` object. 21declare global { 22 interface Navigator { 23 /** 24 * Only available in an App Clip context. 25 * @expo 26 */ 27 appClip?: { 28 /** Open the SKOverlay */ 29 prompt: () => void; 30 }; 31 } 32} 33 34export {};
  • Simple web-style interface.
  • Global type augmentation for easy access.
  • Docs in the type definitions.
  • Optional availability checks instead of extraneous isAvailable methods.

Example of a POOR Expo module:

ts
1import { NativeModulesProxy } from "expo-modules-core"; 2const { ExpoAppClip } = NativeModulesProxy; 3export default { 4 promptAppClip() { 5 return ExpoAppClip.promptAppClip(); 6 }, 7 isAppClipAvailable() { 8 return ExpoAppClip.isAppClipAvailable(); 9 }, 10};

Great documentation

  • If you have a function like isAvailable(), explain why it exists in the docs. Research cases where it may return false such as in a simulator or particular OS version.
  • Document OS version availability for functions and constants in the type definitions.

BAD module standards

  • APIs that are hard to import, e.g. import * as MediaLibrary from 'expo-media-library'; instead of import { MediaLibrary } from 'expo/media';
  • Extraneous abstractions over native functionality. The native module is installing on the global, do not wrap it in another layer for no reason.
  • Extraneous async methods when sync methods are possible.
  • Boolean flags instead of string union types for options.
  • Supporting legacy React Native architecture.

Views

Take API inspiration from great web component libraries like BaseUI and Radix.

Consider if you're building a control or a display component. Controls should have more interactive APIs, while display components should be more declarative.

Prefer functions on views instead of useImperativeHandle + findNodeHandle.

swift
1AsyncFunction("capture") { (view, options: Options) -> Ref in 2 return try capture(self.appContext, view) 3}

Remember to export views in the module:

swift
1import ExpoModulesCore 2 3public class ExpoWebViewModule: Module { 4 public func definition() -> ModuleDefinition { 5 Name("ExpoWebView") 6 7 View(ExpoWebView.self) {} 8 } 9}

Marshalling-style API

Consider this example https://github.com/EvanBacon/expo-shared-objects-haptics-example/blob/be90e92f8dba9b0807009502ab25c423c57e640d/modules/my-module/ios/MyModule.swift#L1C1-L178C2

Using @retroactive Convertible and AnyArgument to convert between Swift types and dictionaries enables passing complex data structures across the boundary without writing custom serialization code for each type.

swift
1extension CHHapticEventParameter: @retroactive Convertible, AnyArgument { 2 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 3 guard let dict = value as? [String: Any], 4 let parameterIDRaw = dict["parameterID"] as? String, 5 let value = dict["value"] as? Double else { 6 throw NotADictionaryException() 7 } 8 return Self(parameterID: CHHapticEvent.ParameterID(rawValue: parameterIDRaw), value: Float(value)) 9 } 10} 11 12extension CHHapticEvent: @retroactive Convertible, AnyArgument { 13 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 14 guard let dict = value as? [String: Any], 15 let eventTypeRaw = dict["eventType"] as? String, 16 let relativeTime = dict["relativeTime"] as? Double else { 17 throw NotADictionaryException() 18 } 19 let eventType = CHHapticEvent.EventType(rawValue: eventTypeRaw) 20 let parameters = (dict["parameters"] as? [[String: Any]])?.compactMap { paramDict -> CHHapticEventParameter? in 21 try? CHHapticEventParameter.convert(from: paramDict, appContext: appContext) 22 } ?? [] 23 return Self(eventType: eventType, parameters: parameters, relativeTime: relativeTime) 24 } 25} 26 27extension CHHapticDynamicParameter: @retroactive Convertible, AnyArgument { 28 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 29 guard let dict = value as? [String: Any], 30 let parameterIDRaw = dict["parameterID"] as? String, 31 let value = dict["value"] as? Double, 32 let relativeTime = dict["relativeTime"] as? Double else { 33 throw NotADictionaryException() 34 } 35 36 return Self(parameterID: CHHapticDynamicParameter.ID(rawValue: parameterIDRaw), value: Float(value), relativeTime: relativeTime) 37 } 38} 39 40extension CHHapticPattern: @retroactive Convertible, AnyArgument { 41 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 42 guard let dict = value as? [String: Any], 43 let eventsArray = dict["events"] as? [[String: Any]] else { 44 throw NotADictionaryException() 45 } 46 let events = try eventsArray.map { eventDict -> CHHapticEvent in 47 try CHHapticEvent.convert(from: eventDict, appContext: appContext) 48 } 49 let parameters = (dict["parameters"] as? [[String: Any]])?.compactMap { paramDict -> CHHapticDynamicParameter? in 50 return try? CHHapticDynamicParameter.convert(from: paramDict, appContext: appContext) 51 } ?? [] 52 return try Self(events: events, parameters: parameters) 53 } 54} 55 56internal final class NotAnArrayException: Exception { 57 override var reason: String { 58 "Given value is not an array" 59 } 60} 61 62internal final class IncorrectArraySizeException: GenericException<(expected: Int, actual: Int)> { 63 override var reason: String { 64 "Given array has unexpected number of elements: \(param.actual), expected: \(param.expected)" 65 } 66} 67 68internal final class NotADictionaryException: Exception { 69 override var reason: String { 70 "Given value is not a dictionary" 71 } 72} 73

Later this can be used to implement methods that accept complex data structures as arguments.

swift
1Function("playPattern") { (pattern: CHHapticPattern) in 2 let player = try hapticEngine.makePlayer(with: pattern) 3 try player.start(atTime: 0) 4}

Use shorthand where possible, especially when the JS value matches the Swift value:

swift
1Property("__typename") { $0.__typename }

Shared objects

Shared objects are long-lived native instances that are shared to JS. They can be used to keep heavy state objects, such as a decoded bitmap, alive across React components, rather than spinning up a new native instance every time a component mounts.

Interacting with AppDelegate

To interact with HealthKit, the module may need to respond to app lifecycle events. This can be done by implementing the ExpoAppDelegateSubscriber protocol.

swift
1import ExpoModulesCore 2 3public class ExpoHeadAppDelegateSubscriber: ExpoAppDelegateSubscriber { 4 5// Any AppDelegate methods you want to implement 6 public func application( 7 _ application: UIApplication, 8 continue userActivity: NSUserActivity, 9 restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void 10 ) -> Bool { 11 launchedActivity = userActivity 12 13 // ... 14 15 return false 16 } 17}

Then add the subscriber to the expo-module.config.json:

json
1{ 2 "platforms": ["apple", "android", "web"], 3 "apple": { 4 "modules": ["ExpoHeadModule", ...], 5 "appDelegateSubscribers": ["ExpoHeadAppDelegateSubscriber"] 6 } 7}

Expo ecosystem integration

Verification

  • Run yarn expo run:ios --no-bundler in an Expo app to headlessly compile the module and verify there are no compilation errors.

FAQ & Installation Steps

These questions and steps mirror the structured data on this page for better search understanding.

? Frequently Asked Questions

What is expo-modules?

Perfect for Health and Fitness Agents needing native Apple HealthKit integration on iOS. expo-modules is a set of standards for designing native APIs, inspired by modern web modules, with a focus on backwards compatibility and native functionality exposure.

How do I install expo-modules?

Run the command: npx killer-skills add manavkushwaha10/apple-health/expo-modules. It works with Cursor, Windsurf, VS Code, Claude Code, and 15+ other IDEs.

What are the use cases for expo-modules?

Key use cases include: Reading and writing health data from Apple HealthKit, Subscribing to health data updates for real-time tracking, Integrating workout data into fitness applications.

Which IDEs are compatible with expo-modules?

This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.

Are there any limitations for expo-modules?

iOS only. Requires Apple HealthKit compatibility. Native functionality exposure may require additional permissions.

How To Install

  1. 1. Open your terminal

    Open the terminal or command line in your project directory.

  2. 2. Run the install command

    Run: npx killer-skills add manavkushwaha10/apple-health/expo-modules. The CLI will automatically detect your IDE or AI agent and configure the skill.

  3. 3. Start using the skill

    The skill is now active. Your AI agent can use expo-modules immediately in the current project.

Related Skills

Looking for an alternative to expo-modules or building a community AI Agent? Explore these related open-source MCP Servers.

View All

widget-generator

Logo of f
f

widget-generator is an open-source AI agent skill for creating widget plugins that are injected into prompt feeds on prompts.chat. It supports two rendering modes: standard prompt widgets using default PromptCard styling and custom render widgets built as full React components.

149.6k
0
Design

linear

Logo of lobehub
lobehub

Linear is a workflow management system that enables multi-agent collaboration, effortless agent team design, and introduces agents as the unit of work interaction.

73.4k
0
Communication

testing

Logo of lobehub
lobehub

Testing is a process for verifying AI agent functionality using commands like bunx vitest run and optimizing workflows with targeted test runs.

73.3k
0
Communication

chat-sdk

Logo of lobehub
lobehub

chat-sdk is a unified TypeScript SDK for building chat bots across multiple platforms, providing a single interface for deploying bot logic.

73.0k
0
Communication