A native music player for macOS, iOS, and Apple TV.
Imports your Apple Music library into a fast local SQLite database,
with AI-powered tagging, a voice assistant, and cross-device streaming.
Untune is a three-platform music player built around your local Apple Music library:
- macOS Desktop β Full-featured player with 62k+ track support, AI tagging, visualizer, smart playlists, and a Claude-powered voice assistant
- iOS Companion β Offline playback with synced playlists, CarPlay, and Siri integration
- tvOS Streaming β Stream your library to Apple TV over your local network
All three apps share a common sync protocol: the desktop runs an HTTP server that mobile and TV clients discover via Bonjour and connect to with a 4-digit pairing code.
| Layer | Technology |
|---|---|
| Desktop backend | Tauri v2 + Rust (rodio, rusqlite, lofty, axum, symphonia) |
| Desktop frontend | React 19 + TypeScript + Vite 6 + Tailwind CSS v4 |
| Table rendering | TanStack Table + Virtual (62k rows, virtualized) |
| State management | Zustand (7 stores) |
| Database | SQLite with WAL mode + FTS5 full-text search |
| iOS / tvOS | SwiftUI + GRDB.swift 7 + AVQueuePlayer |
| AI | Claude API (Haiku for tagging, assistant for chat) |
| Sync | axum HTTP server + Bonjour/mDNS discovery |
- Full Apple Music import via JXA scripts (62k+ tracks, 47 metadata fields)
- Filesystem scanning with parallel audio file parsing (lofty + rayon)
- FTS5 full-text search across all metadata
- iTunes-style column browser (genre / artist / album filtering)
- Smart playlists with rule-based editors (field/operator/value)
- Playlist folder hierarchy with drag-and-drop
- Star ratings, play counts, last played tracking
- MusicBrainz artwork search and replacement
- M3U/M3U8 playlist import and export
- Gapless playback with pre-buffering
- Crossfade (0β12s configurable overlap with fade curves)
- Shuffle with back-navigation history
- Repeat modes: off, all, one
- Sleep timer with gradual fade-out
- Radio mode (auto-queue similar tracks)
- AirPlay device switching
- Real-time FFT visualizer (5 modes: bars, waveform, particles, geometry, digital)
- Mini player mode (always-on-top, 350Γ48px)
- AI Tagging β Batch-tag tracks with mood, energy, BPM, danceability, acousticness, and vibe tags via Claude Haiku
- Voice Assistant β Claude-powered chat with 13 music tools (search, play, queue, create playlists, get stats)
- Speech Input β Native macOS speech recognition for voice commands
- Artist Bios β AI-generated biographies in artist detail views
- Smart Radio β Auto-queue tracks similar to what's playing
- Now Playing widget with artwork
- Media key support (play/pause, next, previous)
- Dock menu (play/pause, next, previous)
- Keyboard shortcuts (volume, seek, navigation, search)
- Background artwork as app backdrop
- Synced lyrics display (LRCLIB integration)
- Deep link support (
untune://add?url=...)
- Built-in HTTP sync server (port 8485)
- Bonjour/mDNS service discovery on LAN
- 4-digit pairing code authentication
- Per-device playlist selection
- Metadata, artwork, and audio file transfer
- Bidirectional play stat syncing
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β macOS Desktop β
β ββββββββββββββββ IPC βββββββββββββββββββββ β
β β React 19 + ββββββββββββΊβ Rust Backend β β
β β TanStack β invoke() β ββ playback.rs β β
β β Virtual β events β ββ db/ β β
β β Zustand β β ββ import/ β β
β ββββββββββββββββ β ββ assistant/ β β
β β ββ sync/ βββββββ β β
β β ββ commands/ β β β
β ββββββββββββββββββΌββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββΌβββββββ
β HTTP :8485
ββββββββββββββββββΌβββββββββββββββββ
β β β
βββββββββββΌβββββββ ββββββββΌββββββββββ β
β iOS App β β tvOS App β β
β Download+Play β β Stream Only β β
β Offline Cache β β Metadata Cache β β
β CarPlay, Siri β β 10-foot UI β β
ββββββββββββββββββ βββββββββββββββββββ β
β
Bonjour (_untune._tcp) ββ
| Directory | Purpose |
|---|---|
src-tauri/src/lib.rs |
Tauri setup, native menu, menu event dispatch |
src-tauri/src/commands/ |
16 IPC command modules (import, tracks, playback, playlists, artwork, ai_tags, assistant, sync, lyrics, speech, airplay, preferences, browse, bios, url_download) |
src-tauri/src/db/ |
SQLite: schema + migrations, queries, inserts |
src-tauri/src/import/ |
Multi-phase import pipeline (JXA β scan β match β merge β artwork β AI tags) |
src-tauri/src/playback.rs |
Audio engine: rodio + symphonia, crossfade, FFT, sleep timer |
src-tauri/src/assistant/ |
Claude API client with streaming + 13 music tools |
src-tauri/src/sync/ |
axum HTTP server, Bonjour advertisement, pairing, file serving |
src-tauri/src/models/ |
Track (47 fields), Playlist, MergedTrack, JxaTrack |
| Directory | Purpose |
|---|---|
src/components/ |
31 React components (TrackTable, PlaybackBar, Sidebar, Visualizer, AssistantPanel, etc.) |
src/stores/ |
7 Zustand stores (library, playback, navigation, theme, columnBrowser, activity, assistant) |
src/lib/commands.ts |
Typed wrappers for all invoke() calls |
src/lib/types.ts |
TypeScript interfaces matching Rust models |
SQLite with WAL mode at ~/Library/Application Support/com.untune.app/library.db.
- tracks β ~50 columns including AI tag fields (mood, energy, vibe_tags, bpm, danceability, acousticness)
- tracks_fts β FTS5 virtual table for full-text search
- playlists β Hierarchical with parent_id for folder trees
- playlist_tracks β Junction table with sort order
- preferences β Key-value store for app settings
- smart_playlists β Rule-based playlist definitions (JSON rules)
- sync_devices β Paired mobile devices with tokens
- sync_playlist_selections β Per-device playlist sync choices
- sync_track_state β Per-device per-track sync progress
Native SwiftUI app (untune-ios/) for iOS 17+ with offline playback.
Bundle ID: com.untune.ios
Build: xcodegen (project.yml) β Xcode project
Database: GRDB.swift 7 (mirrors desktop schema)
- Syncs selected playlists + tracks from desktop over LAN
- Offline playback via AVQueuePlayer
- Background audio with lock screen controls
- CarPlay support (tabbed browsing)
- Siri media intents ("Play [artist] in Untune")
- Bonjour discovery + 4-digit pairing
- Play stat upload back to desktop
untune-ios/Untune/
βββ App/ # UntuneApp, ContentView, SplashView
βββ Models/ # Track (39 fields), Playlist
βββ Database/ # GRDB schema, manager, records
βββ Playback/ # AVQueuePlayer, NowPlayingManager
βββ Networking/ # DesktopDiscovery, PairingManager, SyncClient
βββ Sync/ # SyncEngine (state machine)
βββ Siri/ # PlayMediaIntentHandler
βββ CarPlay/ # CarPlaySceneDelegate, CarPlayBrowser
βββ Views/ # Library, Playback, Settings, Common
βββ Utilities/ # TimeFormatting, MockData, AccentColor
Native SwiftUI app (untune-tvos/) for tvOS 18+ with streaming playback.
Bundle ID: com.untune.tvos
Build: xcodegen (project.yml) β Xcode project
Database: GRDB.swift 7 (metadata cache only)
- Streaming-first β Audio streams via HTTP from desktop (no file downloads)
- Metadata cache β Only syncs track/playlist metadata and artwork thumbnails
- 10-foot UI β Grid layouts, large text, focus engine for Siri Remote
- Minimal storage β Artwork in Caches directory, no audio files stored
untune-tvos/Untune/
βββ App/ # UntuneApp, ContentView
βββ Models/ # Track (fileExtension instead of localFilePath)
βββ Database/ # GRDB (cachesDirectory for tvOS sandbox)
βββ Playback/ # AVURLAsset + HTTP auth headers for streaming
βββ Networking/ # Discovery, Pairing, SyncClient, ArtworkLoader (actor)
βββ Sync/ # SyncEngine (metadata-only, no file downloads)
βββ Views/ # Library grids, NowPlaying, Pairing
βββ Utilities/ # TimeFormatting, MockData, ArtworkCache
- Node.js 20+
- pnpm 10+
- Rust 1.77+
- macOS (required for Tauri, Apple Music integration, and building iOS/tvOS)
- xcodegen (for iOS/tvOS project generation)
- Xcode 16+ (for iOS/tvOS builds)
make install # Install frontend dependencies
make dev # Run app in development (Tauri + Vite HMR)
make build # Build production app bundle
make check # Type-check frontend (tsc) and backend (cargo check)
make clean # Remove build artifactsOr without Make:
pnpm install
pnpm tauri devPlayStation Sound Format playback uses the Highly Experimental emulator core, which has no upstream license. Official releases ship without it β Untune is MIT-licensed and can't redistribute unlicensed code. You can opt in for a personal local build at your own discretion:
git submodule update --init src-tauri/vendor
pnpm tauri build --features psf # or: cargo check --features psfPS2 PSF additionally needs a Sony PS2 BIOS image at
src-tauri/vendor/Highly_Experimental/Core/hebios.bin (generated by mkhebios
from your own PS2 BIOS dump). Sony BIOS files cannot be distributed.
cd untune-ios
xcodegen generate
open Untune.xcodeproj
# Build and run from Xcode (iOS 17+ device or simulator)cd untune-tvos
xcodegen generate
open Untune.xcodeproj
# Build and run from Xcode (tvOS 18+ device or simulator)- Start the sync server from the desktop app (Settings β Sync β Start Server)
- On iOS/tvOS, go to Settings β Pair with Desktop
- Select your desktop from the Bonjour discovery list
- Enter the 4-digit pairing code shown on the desktop
- Select playlists to sync (iOS) or start streaming (tvOS)
GitHub Actions workflow in .github/workflows/:
- build.yml β One workflow handles everything:
- Push to main / PRs: type-check,
cargo check, full Tauri build foraarch64-apple-darwin+x86_64-apple-darwin, uploads DMG artifacts - Manual dispatch (Actions β Build & Release β Run workflow) with
bump_version = patch/minor/major: bumps version acrosspackage.json,Cargo.toml,tauri.conf.json, publishes a tagged GitHub Release with both architectures and achecksums.txt - Signs with the Developer ID cert when
APPLE_CERTIFICATE/APPLE_CERTIFICATE_PASSWORD/APPLE_SIGNING_IDENTITYsecrets are present; otherwise produces an unsigned DMG that still works via right-click β Open
- Push to main / PRs: type-check,
| Document | Description |
|---|---|
| docs/ROADMAP.md | Feature roadmap with completion status |
| docs/IOS-SYNC-PLAN.md | iOS companion app design and sync protocol |
| docs/TVOS-PLAN.md | tvOS streaming app design |
| docs/SERVER-ARCHITECTURE.md | Long-term vision for self-hosted server mode |
| docs/ITUNES_DATA.md | Apple Music/iTunes metadata schema reference |
| CHANGELOG.md | Development history by phase |
MIT