# AGENTS.md This repository is the native macOS SwiftUI port of BearWave, originally a Linux/KDE internet radio app. Do not treat it as a Qt compatibility port. The current repo is a native macOS desktop app focused on internet radio. ## What This Repo Is - SwiftPM macOS app targeting `macOS 26` - SwiftUI desktop UI - `AVPlayer`-based playback for radio streams - Radio Browser as the station source - Local persistence for favorites, recents, manual stations, station folders, and resume state ## Architecture Overview - `Sources/BearWaveApp/BearWaveApp.swift` App scene entrypoint, window sizing, commands, menu bar extra, settings scene - `Sources/BearWaveCore/App/AppModel.swift` Top-level app coordinator; owns `StationLibrary`, `PlaybackController`, and artwork services - `Sources/BearWaveCore/Stores/StationLibrary.swift` Source of truth for station pages, search results, favorites, recents, manual entries, and station folders - `Sources/BearWaveCore/Stores/PersistenceStore.swift` JSON-based persistence for radio state - `Sources/BearWaveCore/Services/RadioBrowserClient.swift` Radio Browser API wrapper plus local search normalization and ranking - `Sources/BearWaveCore/Services/PlaybackController.swift` Shared `AVPlayer` wrapper with explicit playback states, retries, stream metadata via `AVPlayerItemMetadataOutput`, and Now Playing updates - `Sources/BearWaveCore/Services/StationArtworkLoader.swift` Favicon and artwork fetch with disk cache - `Sources/BearWaveCore/Services/NowPlayingArtworkResolver.swift` Artwork resolution for current playback state - `Sources/BearWaveCore/Views/` Sidebar, station list, station detail, player bar, settings, menu bar, mini player ## Current Product Behavior - Dedicated pages: `Top`, `Germany`, `Netherlands`, `World`, `Search Results`, `Favorites`, `Recent`, `Manual` - Search is global and stays independent from the current browse page - Search ranking intentionally filters naive mid-word matches such as `slam` matching `Islamabad` - Playback UI exposes explicit states: connecting, buffering, playing, paused, stopped, failed - A right-side detail panel shows station metadata and current stream metadata when available - Player controls remain radio-focused: play/pause, stop, volume - Mini Player is available via `Cmd+M` - Mini Player target size is `555x110` - Station folders support create, rename, delete, and station assignment - Menu bar extra remains active while playback continues ## Build and Run Conventions Use these commands unless there is a strong reason not to: ```bash swift build --disable-index-store CLANG_MODULE_CACHE_PATH=/private/tmp/bearwave-clang-cache swift run --disable-index-store BearWaveChecks ./script/build_and_run.sh ``` The run script: - kills the previous process - builds via SwiftPM - stages a local `.app` into `dist/` - copies SwiftPM resource bundles manually - copies `.lproj` localization directories into the bundle - launches the app bundle Do not remove the manual resource-bundle copy step from `script/build_and_run.sh` unless the bundle pipeline is replaced deliberately. ## Important Constraints - Prefer the internal SSD workspace: `/Users/sebastian/Development/radioappmac` - Do not assume the mounted share copy is current. - The staged app bundle uses ATS exceptions so that `http://` radio streams can play. - Debug signing and sandbox behavior are intentionally pragmatic and not yet release-ready. - `PlaybackController` uses `AVPlayerItemMetadataOutput` for stream metadata. - `MediaPlayer` is imported with `@preconcurrency`. - `MPMediaItemArtwork` is built from a `CGImage`-backed request handler. - Main window launch width is dynamic: `1255` on smaller displays, `1600` on wide displays. - Mini Player target size is `555x110`. ## What To Preserve - Keep the project native-first for macOS. - Keep search global and ranking strict. - Keep explicit playback states; do not regress to a plain boolean model. - Keep the current split between `BearWaveApp` and `BearWaveCore`. - Keep the build/run script compatible with local staged app execution. ## Good Next Steps - Improve release packaging, signing, and notarization - Add more playback diagnostics per stream failure mode - Expand tests around playback-state transitions and search ranking - Add cache eviction for memory and disk caches - Keep folders clearly positioned as lightweight saved-station organization ## Bad Changes - Reintroducing page-coupled search behavior - Replacing explicit playback states with only `isPlaying` - Moving back toward Qt/KDE abstractions in this repo - Assuming every stream will provide usable metadata or artwork