@capgo/capacitor-llm

May 6, 2026 ยท View on GitHub

Capgo - Instant updates for capacitor

โžก๏ธ Get Instant updates for your App with Capgo ๐Ÿš€

Fix your annoying bug now, Hire a Capacitor expert ๐Ÿ’ช

Adds support for LLM locally run for Capacitor

It uses Apple Intelligence for the iOS system model, MediaPipe for existing .task models, and ExecuTorch .pte models on both iOS and Android.

Mac Catalyst: Native iOS functionality is disabled for Mac Catalyst builds. MediaPipe pods are skipped and native calls will return an unsupported response; use an iOS/iPadOS target for native features.

Documentation

The most complete doc is available here: https://capgo.app/docs/plugins/llm/

Compatibility

Plugin versionCapacitor compatibilityMaintained
v8.*.*v8.*.*โœ…
v7.*.*v7.*.*On demand
v6.*.*v6.*.*โŒ
v5.*.*v5.*.*โŒ

Note: The major version of this plugin follows the major version of Capacitor. Use the version that matches your Capacitor installation (e.g., plugin v8 for Capacitor 8). Only the latest major version is actively maintained.

Installation

bun add @capgo/capacitor-llm
bunx cap sync

iOS Additional Setup for Custom Models

Apple Intelligence works without bundled model files on supported iOS versions. For custom models, the plugin supports MediaPipe through CocoaPods and ExecuTorch when the host app links ExecuTorch with Swift Package Manager. The plugin package remains iOS 15 compatible; iOS ExecuTorch requires an iOS 17 or newer app target because ExecuTorch requires iOS 17.

Using CocoaPods: The MediaPipe dependencies are already configured in the podspec. Make sure to run pod install after adding the plugin.

ExecuTorch is not provided by the CocoaPods integration. CocoaPods installs MediaPipe only. CocoaPods builds reject engine: 'executorch' with a clear runtime error unless the app also links ExecuTorch separately.

Note about Static Framework Warning: When running pod install, you may see a warning about transitive dependencies with statically linked binaries. To fix this, update your Podfile:

# Change this:
use_frameworks!

# To this:
use_frameworks! :linkage => :static

# And add this to your post_install hook:
post_install do |installer|
  assertDeploymentTarget(installer)

  # Fix for static framework dependencies
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
    end

    # Specifically for MediaPipe pods
    if target.name.include?('MediaPipeTasksGenAI')
      target.build_configurations.each do |config|
        config.build_settings['ENABLE_BITCODE'] = 'NO'
      end
    end
  end
end

Using Swift Package Manager: The plugin's Package.swift does not link ExecuTorch directly because that would force every Swift Package Manager user onto iOS 17 or newer, even when they only use Apple Intelligence or MediaPipe.

To use ExecuTorch on iOS, add it to your app target:

  1. Set the app target deployment version to iOS 17 or newer.
  2. In Xcode, open the app project, select Package Dependencies, and add https://github.com/pytorch/executorch.git.
  3. Use the swiftpm-1.2.0 branch, or the ExecuTorch branch that matches the runtime version you want.
  4. Add these products to the app target: executorch_llm, backend_xnnpack, kernels_llm, kernels_optimized, kernels_quantized, and kernels_torchao.
  5. Add the .pte model and tokenizer file to the app target's Copy Bundle Resources, or download them at runtime.

If those ExecuTorch products are not linked into the app target, setModel({ engine: 'executorch' }) rejects with a clear runtime error. MediaPipe GenAI still does not officially support SPM, so use CocoaPods for MediaPipe .task models.

Adding a Model to Your App

The simplest cross-platform custom model path is ExecuTorch. It uses the same kind of .pte model file on iOS and Android, plus a tokenizer file.

ExecuTorch Models (iOS and Android)

iOS uses ExecuTorch only when the host app links the ExecuTorch Swift Package products. It is not included by CocoaPods or by the plugin's Package.swift, so an app without those products can use Apple Intelligence or MediaPipe but will refuse engine: 'executorch'. Android uses the ExecuTorch Maven package.

Bundle the model files:

  • iOS: add the .pte model and tokenizer file to your app target's Copy Bundle Resources.
  • Android: place the .pte model and tokenizer file under android/app/src/main/assets/, then reference them with /android_asset/....
import { Capacitor } from '@capacitor/core';
import { CapgoLLM } from '@capgo/capacitor-llm';

const isAndroid = Capacitor.getPlatform() === 'android';

await CapgoLLM.setModel({
  engine: 'executorch',
  path: isAndroid ? '/android_asset/model.pte' : 'model.pte',
  tokenizerPath: isAndroid ? '/android_asset/tokenizer.model' : 'tokenizer.model',
  maxTokens: 2048,
  sequenceLength: 2048,
  temperature: 0.8,
});

const { id: chatId } = await CapgoLLM.createChat();

engine: 'auto' also selects ExecuTorch when the model path ends in .pte or when tokenizerPath is provided. Passing engine: 'executorch' is recommended when loading ExecuTorch models so failures are explicit.

MediaPipe Models

MediaPipe remains available for existing .task models. Android models usually need both .task and .litertlm files. iOS MediaPipe support is available through CocoaPods and remains experimental for some .task files.

await CapgoLLM.setModel({
  path: '/android_asset/gemma-3-270m-it-int8.task',
  modelType: 'task',
  maxTokens: 2048,
  topk: 40,
  temperature: 0.8,
});

Apple Intelligence

On supported iOS devices, Apple Intelligence can be used without bundling a model.

await CapgoLLM.setModel({
  path: 'Apple Intelligence',
  engine: 'apple',
});

Downloading Models at Runtime

Use downloadModel to keep large model files out of the app bundle. For ExecuTorch, companionUrl can point at the tokenizer file.

const result = await CapgoLLM.downloadModel({
  url: 'https://your-server.com/models/model.pte',
  companionUrl: 'https://your-server.com/models/tokenizer.model',
  filename: 'model.pte',
});

await CapgoLLM.setModel({
  engine: 'executorch',
  path: result.path,
  tokenizerPath: result.companionPath,
  sequenceLength: 2048,
});

Usage Example

import { CapgoLLM } from '@capgo/capacitor-llm';

const { readiness } = await CapgoLLM.getReadiness();
console.log('LLM readiness:', readiness);

const { id: chatId } = await CapgoLLM.createChat();

CapgoLLM.addListener('textFromAi', (event) => {
  console.log('AI:', event.text);
});

CapgoLLM.addListener('aiFinished', (event) => {
  console.log('AI finished responding to chat:', event.chatId);
});

await CapgoLLM.sendMessage({
  chatId,
  message: 'Hello! How are you today?',
});

API

LLM Plugin interface for interacting with on-device language models

createChat()

createChat() => Promise<{ id: string; instructions?: string; }>

Creates a new chat session

Returns: Promise<{ id: string; instructions?: string; }>


sendMessage(...)

sendMessage(options: { chatId: string; message: string; }) => Promise<void>

Sends a message to the AI in a specific chat session

ParamTypeDescription
options{ chatId: string; message: string; }- The chat id and message to send

getReadiness()

getReadiness() => Promise<{ readiness: string; }>

Gets the readiness status of the LLM

Returns: Promise<{ readiness: string; }>


setModel(...)

setModel(options: ModelOptions) => Promise<void>

Sets the model configuration

  • iOS: Use "Apple Intelligence" as path for system model, provide a MediaPipe model, or set engine to "executorch"
  • Android: Path to a MediaPipe or ExecuTorch model file (in assets or files directory)
ParamTypeDescription
optionsModelOptions- The model configuration

downloadModel(...)

downloadModel(options: DownloadModelOptions) => Promise<DownloadModelResult>

Downloads a model from a URL and saves it to the appropriate location

  • iOS: Downloads to the app's documents directory
  • Android: Downloads to the app's files directory
ParamTypeDescription
optionsDownloadModelOptions- The download configuration

Returns: Promise<DownloadModelResult>


addListener('textFromAi', ...)

addListener(eventName: 'textFromAi', listenerFunc: (event: TextFromAiEvent) => void) => Promise<{ remove: () => Promise<void>; }>

Adds a listener for text received from AI

ParamTypeDescription
eventName'textFromAi'- Event name 'textFromAi'
listenerFunc(event: TextFromAiEvent) => void- Callback function for text events

Returns: Promise<{ remove: () => Promise<void>; }>


addListener('aiFinished', ...)

addListener(eventName: 'aiFinished', listenerFunc: (event: AiFinishedEvent) => void) => Promise<{ remove: () => Promise<void>; }>

Adds a listener for AI completion events

ParamTypeDescription
eventName'aiFinished'- Event name 'aiFinished'
listenerFunc(event: AiFinishedEvent) => void- Callback function for finish events

Returns: Promise<{ remove: () => Promise<void>; }>


addListener('downloadProgress', ...)

addListener(eventName: 'downloadProgress', listenerFunc: (event: DownloadProgressEvent) => void) => Promise<{ remove: () => Promise<void>; }>

Adds a listener for model download progress events

ParamTypeDescription
eventName'downloadProgress'- Event name 'downloadProgress'
listenerFunc(event: DownloadProgressEvent) => void- Callback function for progress events

Returns: Promise<{ remove: () => Promise<void>; }>


addListener('readinessChange', ...)

addListener(eventName: 'readinessChange', listenerFunc: (event: ReadinessChangeEvent) => void) => Promise<{ remove: () => Promise<void>; }>

Adds a listener for readiness status changes

ParamTypeDescription
eventName'readinessChange'- Event name 'readinessChange'
listenerFunc(event: ReadinessChangeEvent) => void- Callback function for readiness events

Returns: Promise<{ remove: () => Promise<void>; }>


getPluginVersion()

getPluginVersion() => Promise<{ version: string; }>

Get the native Capacitor plugin version.

Returns: Promise<{ version: string; }>

Since: 1.0.0


Interfaces

ModelOptions

Model configuration options

PropTypeDescription
pathstringModel path or "Apple Intelligence" for iOS system model
engine'auto' | 'apple' | 'mediapipe' | 'executorch'Runtime engine to use. - "auto": uses Apple Intelligence on iOS when path is "Apple Intelligence", ExecuTorch for .pte or tokenizerPath, otherwise MediaPipe - "apple": iOS Foundation Models / Apple Intelligence - "mediapipe": MediaPipe GenAI .task models - "executorch": ExecuTorch .pte models with a tokenizer file
modelTypestringModel file type/extension (e.g., "task", "bin", "litertlm"). If not provided, will be extracted from path.
tokenizerPathstringTokenizer path for ExecuTorch models. Required when engine is "executorch".
specialTokensstring[]Optional special tokens passed to iOS ExecuTorch tokenizers.
maxTokensnumberMaximum number of tokens the model handles
sequenceLengthnumberSequence length for ExecuTorch generation. Defaults to maxTokens when omitted.
topknumberNumber of tokens the model considers at each step
temperaturenumberAmount of randomness in generation (0.0-1.0)
randomSeednumberRandom seed for generation

DownloadModelResult

Result of model download

PropTypeDescription
pathstringPath where the model was saved
companionPathstringPath where the companion file was saved (if applicable)

DownloadModelOptions

Options for downloading a model

PropTypeDescription
urlstringURL of the model file to download
companionUrlstringOptional: URL of companion file (e.g., .litertlm for Android)
filenamestringOptional: Custom filename (defaults to filename from URL)

TextFromAiEvent

Event data for text received from AI

PropTypeDescription
textstringThe text content from AI - this is an incremental chunk, not the full text
chatIdstringThe chat session ID
isChunkbooleanWhether this is a complete chunk (true) or partial streaming data (false)

AiFinishedEvent

Event data for AI completion

PropTypeDescription
chatIdstringThe chat session ID that finished

DownloadProgressEvent

Event data for download progress

PropTypeDescription
progressnumberPercentage of download completed (0-100)
totalBytesnumberTotal bytes to download
downloadedBytesnumberBytes downloaded so far

ReadinessChangeEvent

Event data for readiness status changes

PropTypeDescription
readinessstringThe readiness status

Example App Model Setup

The example app can use either the older MediaPipe assets or the new ExecuTorch assets.

  1. Export or download an ExecuTorch .pte model and matching tokenizer file.
  2. Add both files to the iOS app bundle, or place both files in example-app/android/app/src/main/assets/ for Android.
  3. Call setModel with engine: 'executorch', path, and tokenizerPath.

Legacy MediaPipe Path

Android still supports Gemma 3 LiteRT assets from Kaggle. Download both files and place them in example-app/android/app/src/main/assets/:

  • gemma-3-270m-it-int8.task
  • gemma-3-270m-it-int8.litertlm

iOS MediaPipe remains experimental because some .task models can fail during prefill. Apple Intelligence or ExecuTorch is preferred on iOS.

Known Issues

  • ExecuTorch is native-only and is not available on web.
  • iOS ExecuTorch requires linking the ExecuTorch SwiftPM products in the app target, and that app target must support iOS 17 or newer.
  • Apple Intelligence requires iOS 26.0 or later and a supported device.
  • Android requires minSdkVersion 24 or higher.
  • Model files are large, so production apps should usually download them after install.