SimpMusic is a FOSS (Free and Open Source Software) YouTube Music client for Android and Desktop, built with Compose Multiplatform.
- Stream music from YouTube Music and YouTube for free, ad-free, with background playback
- Provide advanced features like Spotify Canvas, AI song suggestions, synced lyrics
- Support both Android and Desktop (Windows, macOS, Linux)
- Package name:
com.maxrave.simpmusic - Primary language: Kotlin
- UI Framework: Jetpack Compose / Compose Multiplatform
- Architecture: Clean Architecture + MVVM
- Build system: Gradle (Kotlin DSL)
┌─────────────────────────────────────┐
│ Presentation Layer (UI) │
│ - Jetpack Compose / Compose MP │
│ - ViewModels (MVVM) │
│ - UI States │
├─────────────────────────────────────┤
│ Domain Layer │
│ - Use Cases │
│ - Domain Models │
│ - Repository Interfaces │
├─────────────────────────────────────┤
│ Data Layer │
│ - Repository Implementations │
│ - Data Sources (Remote/Local) │
│ - Database (Room) │
├─────────────────────────────────────┤
│ Service Layer │
│ - YouTube Music Scraper │
│ - Spotify Service │
│ - AI Service │
│ - Lyrics Service │
│ - Discord RPC (Kizzy) │
└─────────────────────────────────────┘
- Shared Compose Multiplatform module - main module containing shared code
- Supports: Android, Desktop (JVM), iOS (future)
- Contains all UI (Compose) and business logic
- Source sets:
commonMain/: Shared code for all platformsandroidMain/: Android-specific codedesktopMain/: Desktop-specific code
- Can run Desktop app directly from this module
- Android-specific module to build Android app
- Depends on
composeAppas a shared module - Contains Android-specific configuration:
- AndroidManifest.xml
- Android build configuration
- Android resources (if needed)
- Entry point for Android app
Contains core modules organized by functionality:
- Shared utilities
- Extension functions
- Constants
- Helper classes
- Domain models
- Use cases
- Repository interfaces
- Business logic rules
- Repository implementations
- Data sources (Remote & Local)
- Database schemas (Room)
- Data mappers
- media3/: Media3 ExoPlayer integration (includes
CrossfadeExoPlayerAdapterfor DJ-style crossfade on Android) - media3-ui/: Media3 UI components
- media-jvm/: JVM media playback (VLCJ - replaced GStreamer post-1.0.4)
- media-jvm-ui/: JVM media UI components
Service modules:
- kotlinYtmusicScraper/: YouTube Music API scraper
- spotify/: Spotify Web API integration (Canvas, Lyrics)
- aiService/: AI features (OpenAI, Gemini integration)
- lyricsService/: Lyrics fetching (LRCLIB, SimpMusic Lyrics, BetterLyrics)
- kizzy/: Discord Rich Presence
- ktorExt/: Ktor extensions for networking
- crashlytics/: Full version with Sentry crash reporting
- crashlytics-empty/: FOSS version without tracking
- Jetpack Compose: Modern UI toolkit
- Material Design 3: Design system
- Media3 (ExoPlayer): Media playback
- Room: Local database
- Coroutines & Flow: Async programming
- Hilt/Koin: Dependency injection
- Compose for Desktop: UI
- VLCJ: Audio playback (replaced GStreamer since post-1.0.4)
- VLC native libraries are bundled per platform via
vlc-setupGradle plugin
- Ktor Client: HTTP client
- Kotlin Serialization: JSON parsing
- YouTube Music hidden API: Data source
- Spotify Web API: Canvas and lyrics
- OpenAI/Gemini API: AI features
- Room Database: Local persistence
- DataStore: Preferences
- Caching: Offline playback support
- SponsorBlock: Skip sponsors
- ReturnYouTubeDislike: Vote information
- LRCLIB: Lyrics provider
- BetterLyrics: Additional lyrics provider (added in v1.0.4)
- Sentry: Crash reporting (Full version only)
- Kotlin coding conventions: Follow Kotlin official guidelines
- Compose best practices: Single source of truth, unidirectional data flow
- Clean Architecture: Strict layer separation, dependency rule
UI Layer (composeApp)
↓
Domain Layer (core/domain)
↓
Data Layer (core/data)
↓
Service Layer (core/service/*)
↓
Common (core/common)
Dependency Rule: Higher layer modules can only depend on lower layer modules, NOT vice versa.
- Use Jetpack Compose for all new UI
- Follow Material Design 3 guidelines
- State management with StateFlow or State<T>
- Side effects with LaunchedEffect, DisposableEffect
- Repository pattern for all data operations
- Use cases for complex business logic
- Mapping between Data models ↔ Domain models ↔ UI models
- Room for local persistence
- Ktor for network requests
Before implementing code, researching code, or answering technical questions, the AI agent MUST follow this research workflow:
- Use MCP Context7 (
resolve-library-id→query-docs) to fetch up-to-date documentation for any library/framework about to be used - Understand the latest API surface, breaking changes, and recommended usage patterns
- Use WebSearch to research:
- Pros and cons of the library/approach
- Alternative libraries or approaches that solve the same problem
- Known issues, performance concerns, or deprecation notices
- Compare and evaluate whether the chosen library/approach is the best fit for this project
- Use Grep (on GitHub via web search) or WebSearch to find how well-known open-source projects implement similar features
- Verify the approach follows established best practices before adopting it
- Pay attention to patterns used in projects with similar architecture (Clean Architecture, Compose Multiplatform, etc.)
- Only proceed with implementation after completing steps 1-3
- If a library/approach has significant drawbacks or better alternatives exist, recommend the better option to the user before proceeding
- Document the rationale briefly when introducing new dependencies or patterns
This workflow applies to: Adding new libraries, choosing architectural patterns, implementing new features with unfamiliar APIs, answering "how should we do X?" questions, and evaluating technical approaches.
This workflow does NOT apply to: Simple bug fixes in existing code, minor refactoring, or tasks using libraries already well-established in the project.
- Do NOT build the app to verify code changes. Instead, use JetBrains MCP tools (
get_file_problems,getDiagnostics) to check for compile errors and warnings in real-time. - Only run Gradle build when explicitly requested by the user or for final release verification.
- Unit tests for Domain layer (Use cases)
- Repository tests with fake data sources
- UI tests with Compose Testing
Location: composeApp/src/commonMain/kotlin/
- Create Composable function in appropriate package
- Use ViewModel for state management
- Follow Material 3 design patterns
Location: core/service/kotlinYtmusicScraper/
- Implement endpoint in corresponding service
- Create data model for response
- Map to domain model
Location: core/data/src/main/java/.../database/
- Define Entity with Room annotations
- Create DAO interface
- Update Database class
- Create migration if needed
Location: core/domain/src/main/java/.../usecase/
- Create use case class
- Inject repository dependencies
- Implement business logic
- Return Result/Flow
Location: core/media/media3/ (Android) or core/media/media-jvm/ (Desktop)
- Media3/ExoPlayer + CrossfadeExoPlayerAdapter for Android
- VLCJ (VlcPlayerAdapter) for Desktop
- Queue management in
core/data/src/.../mediaservice/ - Playback controls
Location: core/service/lyricsService/
- Implement lyrics fetcher interface
- Add fallback logic
- Handle synced/unsynced lyrics
Location: core/service/aiService/
- OpenAI integration
- Gemini integration
- AI lyrics translation
- Song recommendations
build.gradle.kts(root): Root build configurationgradle/libs.versions.toml: Version catalog for dependenciessettings.gradle.kts: Module inclusion
composeApp/src/commonMain/kotlin/: Shared Compose codecomposeApp/src/androidMain/kotlin/: Android-specific codecomposeApp/src/desktopMain/kotlin/: Desktop-specific code
core/data/src/main/java/.../database/: Room database schemas- Migrations in Database class
core/service/kotlinYtmusicScraper/: YouTube Music APIcore/service/spotify/: Spotify APIcore/service/ktorExt/: Ktor utilities
composeApp/src/commonMain/composeResources/: Shared resourcescomposeApp/src/androidMain/res/: Android resources- Crowdin integration for translations
- Full: With Sentry crash reporting (module:
crashlytics) - FOSS: No tracking (module:
crashlytics-empty)
- Windows:
.msiinstaller - macOS:
.dmg(ARM and x86-64) - Linux:
.AppImage(DEB and RPM removed post-1.0.4)
- FOSS version: NO tracking
- Full version: Only Sentry crash reporting
- "Send back to Google" feature: Optional, only when user enables
- Min SDK: Check
androidApp/build.gradle.kts - Target SDK: Latest stable
- Android Auto support
- Background playback with MediaSession
- Required Dependencies:
- VLCJ: Audio playback (bundled via vlc-setup plugin)
- Features:
- Deep link support (
simpmusic://andsimpmusic.org) - Mini Player window (always-on-top, resizable, draggable)
- Crash dialog
- Custom title bar (disabled in VM environments)
- Deep link support (
- Limitations:
- No offline playback
- No video playback
- YouTube Music: Hidden/unofficial API (may change anytime)
- Spotify: Requires login for lyrics
- OpenAI/Gemini: User must provide API key
- SponsorBlock: Public API
- LRCLIB: Public lyrics API
Location: core/media/media-jvm/src/main/java/com/simpmusic/media_jvm/VlcPlayerAdapter.kt
- Uses VLCJ library for audio playback (GStreamer was removed)
- VLC native libraries bundled per platform via
vlc-setupGradle plugin incomposeApp/build.gradle.kts - Bundled natives stored in
vlc-natives/{linux,macos,windows}/ - Supports crossfade transition with dual-player approach
- Configurable duration: 1-15 seconds (default: 5 seconds)
- Audio-only: Crossfade is skipped for video playback
- Settings persisted via DataStore
Location: core/media/media3/src/main/java/com/maxrave/media3/exoplayer/CrossfadeExoPlayerAdapter.kt
- DJ-style crossfade with adjustable duration
- Requires 320kbps stream preference to enable DJ mode
- Auto crossfade mode (like AutoMix)
CrossfadeFilterAudioProcessorfor audio processing- Edge cases: disabled for video, repeat one, last track
See CODE_OF_CONDUCT.md
- Fork and create branch from
dev - Follow coding conventions
- Test thoroughly before submitting
- Update documentation if needed
- PR title: Clear and descriptive
- PR description: Explain changes and reasoning
- Use Crowdin: https://crowdin.com/project/simpmusic
- Don't edit translation files directly
- InnerTune: YouTube Music data extraction inspiration
- SmartTube: YouTube streaming URL extraction
- SponsorBlock: Sponsor skip functionality
- LRCLIB: Lyrics provider
- Website: https://simpmusic.org
- Discord: https://discord.gg/Rq5tWVM9Hg
- GitHub Issues: Bug reports and feature requests
When working with this project:
- Always check layer dependencies: Don't violate Clean Architecture rules
- Use existing patterns: Review current code to follow established patterns
- Platform-aware: Code in
commonMainmust work for both Android and Desktop - Test thoroughly: Especially critical for media playback and network code
- Consider privacy: FOSS version must NOT have tracking
- Check external API stability: YouTube Music API may change at any time
- Check Discord server for known issues
- Review recent commits and PRs
- View dependency graph:
asset/dependencies_graph.svg - Test on both Android and Desktop if code is in commonMain
Example: Desktop-only UI settings
if (getPlatform() == Platform.Desktop) {
// Desktop-specific UI or logic
}Example: Android-only features
if (getPlatform() == Platform.Android) {
// Android-specific UI or logic
}- Desktop: GStreamer → VLCJ: Completely replaced GStreamer with VLCJ for desktop audio playback
- DEB/RPM builds removed: Desktop Linux now only ships AppImage
- Android Crossfade & DJ-style transition:
CrossfadeExoPlayerAdapterwith auto mode (like AutoMix) - BetterLyrics provider: Additional lyrics source integrated into lyricsService
- 320kbps audio stream option: Higher quality streaming preference
- Parallel download: Improved download speed
- Character-level animated lyrics: Word-by-word lyrics with spring animations
- SimpMusic Chart: Chart playlists integrated into Library screen
- Favorites: Liked songs feature with UI integration
- Custom OpenAI base URL: Support for compatible API endpoints
- Desktop Mini Player: Always-on-top, resizable, draggable mini player window with volume/like controls
- Analytics/Local Tracking: Track top artists, albums, and tracks locally (no remote tracking)
- Auto Backup: Automatic backup settings
- Custom Title Bar: Desktop window control with transparency support
- SimpMusic Lyrics voting: Vote functionality for community lyrics
- Deep link support:
simpmusic://andsimpmusic.orgURL schemes - Desktop Crash dialog: Error reporting UI for desktop
- Playback speed/pitch controls: Redesigned UI with improved animations
- VM environment detection: Disable transparency and custom titlebar in VMs
After completing any of the following types of changes, the AI agent MUST update this CLAUDE.md file:
- Architecture changes: Module additions/removals, dependency changes (e.g., library swaps like GStreamer → VLCJ), build system changes
- New major features: New modules, new service integrations, new platform capabilities
- API/Technology migrations: Swapping core libraries, changing data flow patterns
- Build/CI changes: New build variants, changed packaging formats, CI workflow changes
- Module structure changes: Adding/removing modules in settings.gradle.kts
What to update:
- Relevant sections in this document (Module Structure, Key Technologies, etc.)
- Add entry to Changelog Summary section with date/version context
- Update "Last updated" date at the bottom
What NOT to update for:
- Bug fixes, minor UI tweaks, translation updates
- Simple refactoring within existing patterns
- Dependency version bumps without API changes
This document helps AI Agents quickly understand the SimpMusic project. Update regularly when there are major changes to architecture or structure.
Last updated: 2026-03-14 Project version: Check latest release on GitHub Maintained by: maxrave-dev and contributors