@capacitor/local-llm
[!WARNING]
CapacitorLABS - This project is experimental. Support is not provided. Please open issues when needed.
Run large language models entirely on-device using Apple Intelligence (Foundation Models) on iOS and Gemini Nano on Android. No network requests, no API keys, no data leaving the device.
Note: On-device LLMs require physical hardware. Android emulators are not supported. iOS simulators are supported so long as the host device is capable of running Apple Intelligence and has it enabled.
Install
npm install @capacitor/local-llm
npx cap sync
Platform Requirements
| Platform | Minimum OS | Notes |
|---|---|---|
| iOS | 15 | Image generation requires iOS 18.4+. Text LLM (Foundation Models / Apple Intelligence) requires iOS 26+. |
| Android | 9 (API 28) | Gemini Nano via ML Kit requires a device that supports on-device AI (e.g. Pixel 9+). |
iOS Setup
No additional configuration is required. Foundation Models and Image Playground are system frameworks available automatically on supported devices with Apple Intelligence enabled.
Call systemAvailability() at runtime to check whether the model is ready before sending prompts.
On iOS 18 and below, systemAvailability() returns 'unavailable' for the text LLM. If prompt() or warmup() are called anyway, the promise will reject with an error. Image generation via generateImage() is fully functional on iOS 18.4+.
Android Setup
The plugin's minimum android SDK is 28, higher than Capacitor's current minimum (24). You'll need to change the android/variables.gradle file in your application:
ext {
minSdkVersion = 28
}
Gemini Nano is distributed via Google Play Services and must be downloaded to the device before use. The model is not bundled with your app.
Check availability and download
Call systemAvailability() to inspect the current state. If the status is downloadable, trigger the download with download() and poll systemAvailability() until the status becomes available.
import { LocalLLM } from '@capacitor/local-llm';
const { status } = await LocalLLM.systemAvailability();
if (status === 'downloadable') {
await LocalLLM.download();
// Poll systemAvailability() until status === 'available'
// Alternatively, use addListener('systemAvailabilityChange', {}) to get notified of status updates
}