Imported from Vikram26141/Melodic-Focus (
MelodicFocus2.0/AGENTS.md). Install upstream withnpx skills add Vikram26141/Melodic-Focus --skill MelodicFocus2.0. Copyright stays with the author.
AGENTS.md - Apple MusicKit Implementation
This file contains essential information for AI coding agents working with the Melodic Focus project. This is a SwiftUI-based iOS productivity app that combines focus timers with Apple Music tracking via MusicKit.
Architecture: Apple MusicKit
IMPORTANT: The app uses Apple MusicKit for music integration. This is the native iOS framework for Apple Music.
Why MusicKit?
- Native iOS framework (no external dependencies)
- No external app required
- Full playback control
- Subscription status detection
- Rich catalog search and metadata
- Works on simulator (limited) and device
Project Overview
Melodic Focus is a productivity app that helps users manage focus sessions while tracking their Apple Music listening habits via MusicKit.
Key Features:
- Focus timer with task categorization
- Native MusicKit integration
- Real-time playback controls with animated UI
- Local listening time tracking (per song, per artist, most played)
- Album art with smooth transitions
- Progress bar with seek functionality
- Cross-device CloudKit sync for focus sessions
Technical Specs:
- Platforms: iOS 17+, iPadOS 17+
- Language: Swift 5.9+
- Framework: SwiftUI
- Architecture: Service pattern with manager wrapper
- Data Sync: CloudKit (iCloud Private Database)
- Music Integration: Apple MusicKit
- Local Storage: JSON-based listening time tracking
Project Structure
MelodicFocus2.0/
├── App/ # Application entry points
│ ├── MelodicFocusApp.swift # @main entry point
│ ├── AppState.swift # Global application state
│ └── ContentView.swift # Root tab view navigation
├── Features/ # Feature-based module organization
│ ├── Analytics/ # Analytics dashboard
│ │ ├── AnalyticsView.swift
│ │ └── AnalyticsViewModel.swift
│ ├── Music/ # Music integration UI
│ │ └── NowPlayingView.swift # Full-screen player with controls
│ ├── Library/ # Music library
│ │ └── LibraryView.swift # Playlist display
│ ├── Settings/ # App settings
│ │ └── SettingsView.swift # Music connection settings
│ ├── Tasks/ # Task category management
│ │ └── TaskCategoryPicker.swift
│ └── Timer/ # Focus timer functionality
│ ├── TimerView.swift # Main timer UI
│ └── TimerViewModel.swift # Timer logic and state
├── Models/ # Data models
│ ├── MusicTrack.swift # Track info from MusicKit
│ ├── FocusSession.swift # Focus session entity
│ ├── TaskCategory.swift # Task categories with colors
│ └── Track.swift # Track entity for CloudKit
├── Services/ # Core services
│ ├── AppleMusicService.swift # MusicKit implementation
│ ├── MusicManager.swift # Simplified wrapper for views
│ ├── CloudKitService.swift # iCloud sync operations
│ └── ListeningTimeTracker.swift # Local listening analytics
└── Utilities/ # Shared utilities
└── Extensions/ # Swift extensions
Build and Development Commands
Building the Project
# Open in Xcode (primary development method)
open MelodicFocus2.0.xcodeproj
# Build via command line
xcodebuild -scheme MelodicFocus2.0 -destination 'platform=iOS Simulator,name=iPhone 15 Pro'
# Run tests
xcodebuild test -scheme MelodicFocus2.0 -destination 'platform=iOS Simulator,name=iPhone 15 Pro'
Prerequisites
- Apple Developer Account - Required for CloudKit and MusicKit
- Xcode 15+ - Required for iOS 17+ features
- iOS 17+ / iPadOS 17+ - Minimum deployment targets
- Apple Music Subscription - Required for full playback features
- Physical iOS Device - Recommended for full testing
Initial Setup
-
Enable MusicKit Capability:
- Select project target → Signing & Capabilities
- Click "+" → Add "MusicKit" capability
-
Configure Info.plist:
- Add
NSAppleMusicUsageDescriptionwith permission prompt text
- Add
-
Enable Background Modes (optional):
- Add "Audio, AirPlay, and Picture in Picture" for background playback
-
Configure CloudKit (for session sync):
- Enable "iCloud" capability
- Check "CloudKit" checkbox
- Create default container
Architecture and Code Patterns
Service Architecture
Views → MusicManager.shared → AppleMusicService.shared → MusicKit (ApplicationMusicPlayer)
↓
ListeningTimeTracker (analytics)
AppleMusicService: Core MusicKit wrapper
- Handles authorization
- Manages playback via ApplicationMusicPlayer
- Observes queue changes for track detection
- Polls playback position via timer
MusicManager: View-friendly wrapper
- Mirrors AppleMusicService state via Combine
- Loads album art from URLs
- Provides clean interface for SwiftUI views
ListeningTimeTracker: Independent analytics
- Tracks every second of playback
- Calculates statistics per track/artist
- Persists to local JSON file
Key Implementation Patterns
Authorization:
let status = await MusicAuthorization.request()
isAuthorized = status == .authorized
Subscription Detection:
for await subscription in MusicSubscription.subscriptionUpdates {
hasSubscription = subscription.canPlayCatalogContent
}
Playback Control:
let player = ApplicationMusicPlayer.shared
// Play/pause
try await player.play()
player.pause()
// Skip
try await player.skipToNextEntry()
try await player.skipToPreviousEntry()
// Seek
player.playbackTime = position
Track Change Detection:
player.queue.objectWillChange.sink { [weak self] in
Task { @MainActor in
self?.updateCurrentTrack()
}
}
Getting Current Track:
if let entry = player.queue.currentEntry,
case .song(let song) = entry.item {
currentTrack = MusicTrack(from: song)
}
Code Style Guidelines
Naming Conventions
- Classes/Structs: PascalCase (e.g.,
FocusSession,MusicManager) - Properties/Methods: camelCase (e.g.,
isMusicAuthorized,togglePlayback()) - Enums: PascalCase for type, camelCase for cases
- Files: Match the primary type name
SwiftUI Patterns
// Use @EnvironmentObject for global state
@EnvironmentObject var appState: AppState
// Use @StateObject for view-specific view models
@StateObject private var viewModel = TimerViewModel()
// Use @ObservedObject for shared services
@ObservedObject private var music = MusicManager.shared
// Use @State for local view state
@State private var showingSettings = false
Testing Strategy
Physical Device Recommended
MusicKit has limited simulator support. Test on physical device for:
- Actual playback
- Subscription detection
- Album art loading
Manual Testing Checklist
Authorization Flow:
- Connect button requests authorization
- System dialog appears
- Authorization state updates correctly
- Subscription status detected
Playback Controls:
- Play/pause toggles playback
- Skip next/prev changes track
- Progress bar updates
- Seek via progress bar works
- Album art loads on track change
Listening Time Tracking:
- Time accumulates during playback
- Skip detection works (<30s or <50%)
- Data persists across app restarts
Known Issues and TODOs
Implemented
- MusicKit authorization
- Playback controls (play/pause/skip)
- Track change detection
- Album art loading
- Progress bar with seek
- Listening time tracking
Remaining
- Timer completion notifications
- CloudKit sync for listening data
- Playlist search/playback
- Background playback testing
- Automated test suite
External Dependencies
Apple Frameworks
- MusicKit (music integration)
- SwiftUI (UI)
- CloudKit (sync)
- Combine (reactive bindings)
External Services
- Apple Music (subscription required for playback)
- iCloud CloudKit (for session sync)
Common Development Tasks
Debugging Authorization
// Check authorization status
print("Auth status: \(MusicAuthorization.currentStatus)")
// Check subscription
print("Has subscription: \(hasSubscription)")
Adding Playlist Playback
// Search for playlist
var request = MusicCatalogSearchRequest(term: "focus", types: [Playlist.self])
let response = try await request.response()
// Set queue and play
player.queue = [response.playlists.first!]
try await player.play()
Deployment Notes
App Store Submission
Capabilities Required:
- MusicKit
- iCloud (CloudKit)
- Background Modes (Audio) - if using background playback
Privacy:
- Must include
NSAppleMusicUsageDescriptionin Info.plist - Privacy policy must mention Apple Music data access
Last Updated: 2026-01-31 Architecture: Apple MusicKit