Complete Kotlin Multiplatform migration with iOS parity: - All 13 modules converted to KMP (commonMain + androidMain + iosMain) - 100% feature parity: auth, chat, SSE streaming, conversations, settings, agents, files, voice input, TTS, OAuth, file picker, clipboard paste - Platform consolidation: DataStore path, SessionCacheCleaner, bubble layouts, ChatInput core, MIME types, mention parsing, TextField styling, FilterChip components extracted to commonMain - iOS crash reporting via Kotlin/Native exception hook - YAML parsing via custom pure-Kotlin parser (zero dependencies) - Dependency health: Timber removed, kaml replaced, FuzzyWuzzy removed, security-crypto stabilized - CONTRIBUTING.md - Gradle configuration cache enabled
3.5 KiB
3.5 KiB
Contributing to LibreChat Native KMP
Prerequisites
| Tool | Version |
|---|---|
| JDK | 17+ |
| Android Studio | Latest stable |
| Xcode | 15+ (iOS development) |
| Gradle | 8.11.1 (via wrapper) |
| Kotlin | 2.1.20 |
Getting Started
# Clone with submodules (upstream LibreChat server reference)
git clone --recursive https://github.com/anthropics/LibreChat-Android.git
cd LibreChat-Android
Android
./gradlew assembleDebug
Open the project in Android Studio and run on an emulator or device. Debug APK output: app/build/outputs/apk/debug/app-debug.apk.
iOS
# Build the shared KMP framework
./gradlew :shared:linkDebugFrameworkIosSimulatorArm64
Open iosApp/iosApp.xcodeproj in Xcode and run on an iOS simulator. The shared framework must be rebuilt whenever shared code changes.
Project Structure
The project is a Kotlin Multiplatform (KMP) app with shared business logic and platform-specific UI layers.
Modules
app/ -> Android entry point, adaptive navigation (phone/tablet)
shared/ -> KMP umbrella module (commonMain, androidMain, iosMain)
core/common/ -> Result type, dispatcher DI, coroutine scopes, extensions
core/model/ -> @Serializable data classes (pure Kotlin)
core/network/ -> Ktor client, API services, SSE client, auth interceptor
core/data/ -> Room DB, DataStore, repositories
core/ui/ -> Material 3 theme, shared composables
feature/auth/ -> Login, Register, 2FA, OAuth, Forgot Password
feature/chat/ -> Real-time chat with SSE streaming, message rendering
feature/conversations/ -> Paginated list, CRUD, tags, search, export/import
feature/settings/ -> Account, appearance, about
feature/agents/ -> Agent marketplace with search and categories
feature/files/ -> File upload, management, image viewer
Source sets: commonMain = shared code, androidMain / iosMain = platform-specific implementations.
Convention Plugins
build-logic/convention/ contains 13 convention plugins (8 Android + 5 KMP) that standardize module configuration. See CLAUDE.md for details.
Adding a New Feature Module
- Create the module directory under
feature/ - Apply the
librechat.kmp.featureconvention plugin inbuild.gradle.kts - Create
di/<Feature>Module.ktwith a Koinmodule { }containingviewModelOf(::YourViewModel)definitions - Register the module in the application startup Koin configuration
- Use
koinViewModel()in screen composables to inject ViewModels
Code Style
- Follow Kotlin coding conventions
- ViewModels live in
commonMainonly — no platform-specific ViewModels - Handle platform differences via
expect/actualdeclarations or delegate factories - Use Kermit for logging (
co.touchlab.kermit.Logger), notprintln,Log.d, orNSLog - Feature modules depend on
:core:*only, never on each other
Testing
- Unit tests go in
commonTestorandroidUnitTest - Maestro flows for E2E testing (8 existing flows in
.maestro/) - Run tests before submitting:
./gradlew test
Architecture Rules
- Feature modules depend on
:core:*only, never on each other - Unidirectional data flow: UI -> ViewModel -> Repository -> API/Room
- Room is a read-through cache; server is source of truth
- Custom SSE parser over raw
ByteReadChannel(not Ktor SSE plugin)
See CLAUDE.md for the full architecture overview and backend quirks.