> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runanywhere.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quick Start

> Build your first AI feature in minutes

## Complete Example

Here's a complete example to get you started with on-device text generation:

```kotlin MainActivity.kt theme={null}
import com.runanywhere.sdk.core.onnx.ONNX
import com.runanywhere.sdk.foundation.bridge.extensions.CppBridgeModelPaths
import com.runanywhere.sdk.llm.llamacpp.LlamaCPP
import com.runanywhere.sdk.public.RunAnywhere
import com.runanywhere.sdk.public.SDKEnvironment
import com.runanywhere.sdk.storage.AndroidPlatformContext

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 1. Initialize Android platform context (must be first)
        AndroidPlatformContext.initialize(this)

        // 2. Initialize SDK
        RunAnywhere.initialize(environment = SDKEnvironment.DEVELOPMENT)

        // 3. Set model storage path
        val runanywherePath = filesDir.resolve("runanywhere").also { it.mkdirs() }
        CppBridgeModelPaths.setBaseDirectory(runanywherePath.absolutePath)

        // 4. Register backends
        try {
            LlamaCPP.register(priority = 100)
        } catch (e: Exception) {
            Log.w("SDK", "LlamaCPP VLM registration failed (LLM still works): ${e.message}")
        }
        ONNX.register(priority = 100)

        // 5. Register models
        ModelService.registerDefaultModels()

        // 6. Download, load, and generate
        lifecycleScope.launch {
            RunAnywhere.downloadModel("smollm2-360m-instruct-q8_0").collect { progress ->
                updateProgress((progress.progress * 100).toInt())
            }

            RunAnywhere.loadLLMModel("smollm2-360m-instruct-q8_0")

            val response = RunAnywhere.chat("What is 2+2?")
            showResponse(response)
        }
    }
}
```

## Step-by-Step Guide

### 1. Initialize the SDK

Initialize RunAnywhere in your `Activity.onCreate()`. The order of initialization is critical:

```kotlin theme={null}
// Step 1: Android platform context (must be first)
AndroidPlatformContext.initialize(this)

// Step 2: SDK initialization
RunAnywhere.initialize(environment = SDKEnvironment.DEVELOPMENT)

// Step 3: Set model storage base directory
val runanywherePath = filesDir.resolve("runanywhere").also { it.mkdirs() }
CppBridgeModelPaths.setBaseDirectory(runanywherePath.absolutePath)
```

<Warning>
  `AndroidPlatformContext.initialize(this)` **must** be called before `RunAnywhere.initialize()`.
  `CppBridgeModelPaths.setBaseDirectory()` tells the C++ bridge where to find model files.
</Warning>

### Environment Options

| Environment   | Log Level | Description                         |
| ------------- | --------- | ----------------------------------- |
| `DEVELOPMENT` | Debug     | Full logging, local testing         |
| `STAGING`     | Info      | Staging backend, moderate logging   |
| `PRODUCTION`  | Warning   | Production backend, minimal logging |

### 2. Register Backend Modules

Register backends **after** initialization but **before** registering models:

```kotlin theme={null}
import com.runanywhere.sdk.llm.llamacpp.LlamaCPP
import com.runanywhere.sdk.core.onnx.ONNX

// Register LlamaCPP for LLM + VLM (wrap in try/catch — VLM may fail on some devices)
try {
    LlamaCPP.register(priority = 100)
} catch (e: Exception) {
    Log.w("SDK", "LlamaCPP VLM registration failed: ${e.message}")
}

// Register ONNX for STT/TTS
ONNX.register(priority = 100)
```

<Note>
  `LlamaCPP.register()` is wrapped in try/catch because VLM native registration may fail if the
  `.so` doesn't include `nativeRegisterVlm`. LLM text generation still works because it is
  registered before VLM internally.
</Note>

### 3. Register Models

Register models with their framework, modality, and download URL:

```kotlin theme={null}
import com.runanywhere.sdk.core.types.InferenceFramework
import com.runanywhere.sdk.public.extensions.Models.ModelCategory
import com.runanywhere.sdk.public.extensions.Models.ModelFileDescriptor
import com.runanywhere.sdk.public.extensions.registerModel
import com.runanywhere.sdk.public.extensions.registerMultiFileModel

// LLM model
RunAnywhere.registerModel(
    id = "smollm2-360m-instruct-q8_0",
    name = "SmolLM2 360M Instruct Q8_0",
    url = "https://huggingface.co/.../SmolLM2-360M.Q8_0.gguf",
    framework = InferenceFramework.LLAMA_CPP,
    modality = ModelCategory.LANGUAGE,
    memoryRequirement = 400_000_000L
)

// STT model (tar.gz archive)
RunAnywhere.registerModel(
    id = "sherpa-onnx-whisper-tiny.en",
    name = "Sherpa Whisper Tiny (ONNX)",
    url = "https://github.com/RunanywhereAI/sherpa-onnx/releases/.../sherpa-onnx-whisper-tiny.en.tar.gz",
    framework = InferenceFramework.ONNX,
    modality = ModelCategory.SPEECH_RECOGNITION
)

// VLM multi-file model
RunAnywhere.registerMultiFileModel(
    id = "smolvlm-256m-instruct",
    name = "SmolVLM 256M Instruct",
    files = listOf(
        ModelFileDescriptor(url = "https://...SmolVLM-Q8_0.gguf", filename = "SmolVLM-Q8_0.gguf"),
        ModelFileDescriptor(url = "https://...mmproj-f16.gguf", filename = "mmproj-f16.gguf"),
    ),
    framework = InferenceFramework.LLAMA_CPP,
    modality = ModelCategory.MULTIMODAL,
    memoryRequirement = 365_000_000L
)
```

### 4. Download and Load Models

Download with progress tracking using Kotlin Flows:

```kotlin theme={null}
// Download
RunAnywhere.downloadModel("smollm2-360m-instruct-q8_0")
    .catch { e -> showError("Download failed: ${e.message}") }
    .collect { progress ->
        updateProgress((progress.progress * 100).toInt())
    }

// Load by modality
RunAnywhere.loadLLMModel("smollm2-360m-instruct-q8_0")   // LLM
RunAnywhere.loadSTTModel("sherpa-onnx-whisper-tiny.en")   // STT
RunAnywhere.loadTTSVoice("vits-piper-en_US-lessac-medium") // TTS
RunAnywhere.loadVLMModel("smolvlm-256m-instruct")        // VLM
```

### 5. Generate Text

```kotlin theme={null}
// Simple chat (returns String)
val response = RunAnywhere.chat("What is 2+2?")

// STT transcription (takes ByteArray of 16kHz mono PCM)
val text = RunAnywhere.transcribe(audioData)

// TTS synthesis
val ttsOutput = RunAnywhere.synthesize("Hello!", TTSOptions())
// ttsOutput.audioData contains WAV ByteArray
```

### 6. Stream Responses

For real-time token streaming:

```kotlin theme={null}
RunAnywhere.generateStream("Tell me a story about AI")
    .collect { token ->
        textView.append(token)
    }
```

## What's Next?

<CardGroup cols={2}>
  <Card title="LLM Chat" icon="comments" href="/kotlin/llm/chat">
    Simple one-liner for quick responses
  </Card>

  <Card title="Streaming" icon="water" href="/kotlin/llm/stream">
    Real-time token streaming with Flows
  </Card>

  <Card title="Speech-to-Text" icon="microphone" href="/kotlin/stt/transcribe">
    Transcribe audio to text
  </Card>

  <Card title="Text-to-Speech" icon="volume-high" href="/kotlin/tts/synthesize">
    Convert text to spoken audio
  </Card>
</CardGroup>
