A production-ready reference app demonstrating the RunAnywhere Flutter SDK capabilities for on-device AI. This app showcases how to build privacy-first, offline-capable AI features with LLM chat, speech-to-text, text-to-speech, and a complete voice assistant pipelineβall running locally on your device.
Important: This sample app consumes the RunAnywhere Flutter SDK as local path dependencies. Before opening this project, you must first build the SDKβs native libraries.
# 1. Navigate to the Flutter SDK directory
cd runanywhere-sdks/sdk/runanywhere-flutter
# 2. Run the setup script (~10-20 minutes on first run)
# This builds the native C++ frameworks/libraries and enables local mode
./scripts/build-flutter.sh --setup
# 3. Navigate to this sample app
cd ../../examples/flutter/RunAnywhereAI
# 4. Install dependencies
flutter pub get
# 5. For iOS: Install pods
cd ios && pod install && cd ..
# 6. Run the app
flutter run
# Or open in Android Studio / VS Code and run from there
This sample appβs pubspec.yaml uses path dependencies to reference the local Flutter SDK packages:
This Sample App β Local Flutter SDK packages (sdk/runanywhere-flutter/packages/)
β
Local XCFrameworks/JNI libs (in each package's ios/Frameworks/ and android/jniLibs/)
β
Built by: ./scripts/build-flutter.sh --setup
The build-flutter.sh --setup script:
runanywhere-commonspackages/*/ios/Frameworks/.so files to packages/*/android/src/main/jniLibs/.testlocal marker files (enables local library consumption)flutter run again (hot reload works for most changes)runanywhere-commons):
cd sdk/runanywhere-flutter
./scripts/build-flutter.sh --local --rebuild-commons
Try the native iOS and Android apps to experience on-device AI capabilities immediately. The Flutter sample app demonstrates the same features using the cross-platform Flutter SDK.
This sample app demonstrates the full power of the RunAnywhere Flutter SDK:
| Feature | Description | SDK Integration |
|---|---|---|
| AI Chat | Interactive LLM conversations with streaming responses | RunAnywhere.generateStream() |
| Thinking Mode | Support for models with <think>...</think> reasoning |
Thinking tag parsing |
| Real-time Analytics | Token speed, generation time, inference metrics | MessageAnalytics |
| Speech-to-Text | Voice transcription with batch & live modes | RunAnywhere.transcribe() |
| Text-to-Speech | Neural voice synthesis with Piper TTS | RunAnywhere.synthesize() |
| Voice Assistant | Full STT to LLM to TTS pipeline with auto-detection | VoiceSession API |
| Model Management | Download, load, and manage multiple AI models | ModelManager |
| Storage Management | View storage usage and delete models | RunAnywhere.getStorageInfo() |
| Offline Support | All features work without internet | On-device inference |
The app follows Flutter best practices with a clean architecture pattern:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Flutter/Material UI β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββββ β
β β Chat β β STT β β TTS β β Voice β β Settings β β
β βInterface β β View β β View β βAssistant β β View β β
β ββββββ¬ββββββ ββββββ¬ββββββ ββββββ¬ββββββ ββββββ¬ββββββ βββββββ¬βββββββ β
βββββββββΌβββββββββββββΌβββββββββββββΌβββββββββββββΌββββββββββββββΌβββββββββ€
β βΌ βΌ βΌ βΌ βΌ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Provider State Management β β
β β (ModelManager, Services) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β RunAnywhere Flutter SDK β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Core API (generate, transcribe, synthesize) β β
β β Model Management (download, load, unload, delete) β β
β β Voice Session (STT β LLM β TTS pipeline) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββ΄βββββββββββββββββββ β
β βΌ βΌ β
β βββββββββββββββββββ βββββββββββββββββββ β
β β LlamaCpp β β ONNX Runtime β β
β β (LLM/GGUF) β β (STT/TTS) β β
β βββββββββββββββββββ βββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ChangeNotifier + Provider for state managementModelManager, AudioRecordingService, AudioPlayerServiceAppColors, AppTypography, AppSpacing tokensRunAnywhereAI/
βββ lib/
β βββ main.dart # App entry point
β β
β βββ app/
β β βββ runanywhere_ai_app.dart # SDK initialization, model registration
β β βββ content_view.dart # Main tab navigation (5 tabs)
β β
β βββ core/
β β βββ design_system/
β β β βββ app_colors.dart # Color palette with dark mode support
β β β βββ app_spacing.dart # Spacing constants
β β β βββ typography.dart # Text styles
β β β
β β βββ models/
β β β βββ app_types.dart # Shared type definitions
β β β
β β βββ services/
β β β βββ model_manager.dart # SDK model management wrapper
β β β βββ audio_recording_service.dart # Microphone capture
β β β βββ audio_player_service.dart # TTS playback
β β β βββ permission_service.dart # Permission handling
β β β βββ conversation_store.dart # Chat history persistence
β β β βββ device_info_service.dart # Device capabilities
β β β
β β βββ utilities/
β β βββ constants.dart # Preference keys, defaults
β β βββ keychain_helper.dart # Secure storage wrapper
β β
β βββ features/
β β βββ chat/
β β β βββ chat_interface_view.dart # LLM chat with streaming
β β β
β β βββ voice/
β β β βββ speech_to_text_view.dart # Batch & live STT
β β β βββ text_to_speech_view.dart # TTS synthesis & playback
β β β βββ voice_assistant_view.dart # Full STTβLLMβTTS pipeline
β β β
β β βββ models/
β β β βββ models_view.dart # Model browser
β β β βββ model_selection_sheet.dart # Model picker bottom sheet
β β β βββ model_list_view_model.dart # Model list logic
β β β βββ model_components.dart # Reusable model UI widgets
β β β βββ model_status_components.dart # Status badges, indicators
β β β βββ model_types.dart # Framework enums, model info
β β β βββ add_model_from_url_view.dart # Import custom models
β β β
β β βββ settings/
β β βββ combined_settings_view.dart # Storage & logging config
β β
β βββ helpers/
β βββ adaptive_layout.dart # Responsive layout utilities
β
βββ pubspec.yaml # Dependencies, SDK references
βββ android/ # Android platform config
βββ ios/ # iOS platform config
βββ README.md # This file
# Clone the repository
git clone https://github.com/RunanywhereAI/runanywhere-sdks.git
cd runanywhere-sdks/examples/flutter/RunAnywhereAI
# Install dependencies
flutter pub get
# Run on connected device
flutter run
# Android APK
flutter build apk --release
# Android App Bundle
flutter build appbundle --release
# iOS (requires Xcode)
flutter build ios --release
The SDK is initialized in runanywhere_ai_app.dart:
import 'package:runanywhere/runanywhere.dart';
import 'package:runanywhere_llamacpp/runanywhere_llamacpp.dart';
import 'package:runanywhere_onnx/runanywhere_onnx.dart';
// 1. Initialize SDK in development mode
await RunAnywhere.initialize();
// 2. Register LlamaCpp module for LLM models (GGUF)
await LlamaCpp.register();
LlamaCpp.addModel(
id: 'smollm2-360m-q8_0',
name: 'SmolLM2 360M Q8_0',
url: 'https://huggingface.co/prithivMLmods/SmolLM2-360M-GGUF/resolve/main/SmolLM2-360M.Q8_0.gguf',
memoryRequirement: 500000000,
);
// 3. Register ONNX module for STT/TTS models
await Onnx.register();
Onnx.addModel(
id: 'sherpa-onnx-whisper-tiny.en',
name: 'Sherpa Whisper Tiny (ONNX)',
url: 'https://github.com/RunanywhereAI/sherpa-onnx/releases/download/runanywhere-models-v1/sherpa-onnx-whisper-tiny.en.tar.gz',
modality: ModelCategory.speechRecognition,
memoryRequirement: 75000000,
);
// Download with progress tracking (via ModelManager)
await ModelManager.shared.downloadModel(modelInfo);
// Load LLM model
await sdk.RunAnywhere.loadLLMModel('smollm2-360m-q8_0');
// Check if model is loaded
final isLoaded = sdk.RunAnywhere.isModelLoaded;
// Generate with streaming (real-time tokens)
final streamResult = await RunAnywhere.generateStream(prompt, options: options);
await for (final token in streamResult.stream) {
// Display each token as it arrives
setState(() {
_responseText += token;
});
}
// Or non-streaming
final result = await RunAnywhere.generate(prompt, options: options);
print('Response: ${result.text}');
print('Speed: ${result.tokensPerSecond} tok/s');
// Load STT model
await RunAnywhere.loadSTTModel('sherpa-onnx-whisper-tiny.en');
// Transcribe audio bytes
final transcription = await RunAnywhere.transcribe(audioBytes);
print('Transcription: $transcription');
// Load TTS voice
await RunAnywhere.loadTTSVoice('vits-piper-en_US-lessac-medium');
// Synthesize speech with options
final result = await RunAnywhere.synthesize(
text,
rate: 1.0,
pitch: 1.0,
volume: 1.0,
);
// Play audio (result.samples is Float32List)
await audioPlayer.play(result.samples, result.sampleRate);
// Start voice session
final session = await RunAnywhere.startVoiceSession(
config: VoiceSessionConfig(),
);
// Listen to session events
session.events.listen((event) {
if (event is VoiceSessionTranscribed) {
print('User said: ${event.text}');
} else if (event is VoiceSessionResponded) {
print('AI response: ${event.text}');
} else if (event is VoiceSessionSpeaking) {
// Audio is being played
}
});
// Stop session
session.stop();
chat_interface_view.dart)What it demonstrates:
<think>...</think> tags)Key SDK APIs:
RunAnywhere.generateStream() β Streaming generationRunAnywhere.generate() β Non-streaming generationRunAnywhere.currentLLMModel() β Get loaded model infospeech_to_text_view.dart)What it demonstrates:
Key SDK APIs:
RunAnywhere.loadSTTModel() β Load Whisper modelRunAnywhere.transcribe() β Batch transcriptionRunAnywhere.isSTTModelLoaded β Check model statustext_to_speech_view.dart)What it demonstrates:
Key SDK APIs:
RunAnywhere.loadTTSVoice() β Load TTS modelRunAnywhere.synthesize() β Generate speech audioRunAnywhere.isTTSVoiceLoaded β Check voice statusvoice_assistant_view.dart)What it demonstrates:
Key SDK APIs:
RunAnywhere.startVoiceSession() β Start voice sessionRunAnywhere.isVoiceAgentReady β Check all components loadedVoiceSessionEvent β Session event streamcombined_settings_view.dart)What it demonstrates:
Key SDK APIs:
RunAnywhere.getStorageInfo() β Get storage detailsRunAnywhere.getDownloadedModelsWithInfo() β List modelsRunAnywhere.deleteStoredModel() β Remove model| Model | Size | Memory | Description |
|---|---|---|---|
| SmolLM2 360M Q8_0 | ~400MB | 500MB | Fast, lightweight chat |
| Qwen 2.5 0.5B Q6_K | ~500MB | 600MB | Multilingual, efficient |
| LFM2 350M Q4_K_M | ~200MB | 250MB | LiquidAI, ultra-compact |
| LFM2 350M Q8_0 | ~350MB | 400MB | Higher quality version |
| Llama 2 7B Chat Q4_K_M | ~4GB | 4GB | Powerful, larger model |
| Mistral 7B Instruct Q4_K_M | ~4GB | 4GB | High quality responses |
| Model | Size | Description |
|---|---|---|
| Sherpa Whisper Tiny (EN) | ~75MB | Fast English transcription |
| Sherpa Whisper Small (EN) | ~250MB | Higher accuracy |
| Model | Size | Description |
|---|---|---|
| Piper US English (Medium) | ~65MB | Natural American voice |
| Piper British English (Medium) | ~65MB | British accent |
# Run all tests
flutter test
# Run with coverage
flutter test --coverage
# Run specific test file
flutter test test/widget_test.dart
# Analyze code quality
flutter analyze
# Format code
dart format lib/ test/
# Fix issues automatically
dart fix --apply
The app uses debugPrint() extensively. Filter logs by:
# Flutter logs
flutter logs | grep -E "RunAnywhere|SDK"
| Log Prefix | Description |
|---|---|
SDK |
SDK initialization |
SUCCESS |
Success operations |
ERROR |
Error conditions |
MODULE |
Module registration |
LOADING |
Loading/processing |
AUDIO |
Audio operations |
RECORDING |
Recording operations |
flutter run --profilep in terminalThe SDK automatically detects the environment:
// Development mode (default)
if (kDebugMode) {
await RunAnywhere.initialize();
}
// Production mode
else {
await RunAnywhere.initialize(
apiKey: 'your-api-key',
baseURL: 'https://api.runanywhere.ai',
environment: SDKEnvironment.production,
);
}
User preferences are stored via SharedPreferences:
| Key | Type | Default | Description |
|---|---|---|---|
useStreaming |
bool | true |
Enable streaming generation |
defaultTemperature |
double | 0.7 |
LLM temperature |
defaultMaxTokens |
int | 500 |
Max tokens per generation |
We welcome contributions! See CONTRIBUTING.md for guidelines.
# Fork and clone
git clone https://github.com/YOUR_USERNAME/runanywhere-sdks.git
cd runanywhere-sdks/examples/flutter/RunAnywhereAI
# Create feature branch
git checkout -b feature/your-feature
# Make changes and test
flutter pub get
flutter analyze
flutter test
# Commit and push
git commit -m "feat: your feature description"
git push origin feature/your-feature
# Open Pull Request
This project is licensed under the Apache License 2.0 - see LICENSE for details.