Apple Music Sync
Sync a playlist from this repository to Apple Music using Playwright browser automation of the Apple Music web player. Works on any platform. No Apple Developer enrollment, API keys, or native apps are required.
When to Use This Skill
Activate this skill when the user:
- •Wants to save a playlist to Apple Music
- •Asks to sync, export, or push a playlist to their library
- •Wants to create an Apple Music playlist from a markdown file
- •Mentions "Apple Music," "sync," or "add to my library" in the context of a playlist
Prerequisites
- •An Apple Music subscription
- •Node.js (v18+)
- •Playwright — install with
npm install playwright && npx playwright install chromium
Tools
sync.mjs — Sync playlist to Apple Music
A single cross-platform script that manages playlists entirely through the Apple Music web player.
# Sync a playlist (create if needed, or reorder existing to match markdown) node .github/skills/apple-music-sync/sync.mjs playlists/<name>.md [--headless] # Rename an existing playlist (old name → new name from markdown heading) node .github/skills/apple-music-sync/sync.mjs playlists/<name>.md --rename-from="Old Name" [--headless] # Only add tracks to library (no playlist management) node .github/skills/apple-music-sync/sync.mjs playlists/<name>.md --library-only [--headless]
The script:
- •Parses the playlist name from the
# headingand tracks from the markdown table - •Appends the 🤖 emoji to the playlist name — all managed playlists are suffixed with this marker
- •Creates a daily backup before any sync operation (see Backups below)
- •Opens Chromium with the Apple Music web player
- •Waits for the user to sign in (persistent browser profile — only needed once)
- •If the playlist doesn't exist, creates it and adds all tracks
- •If the playlist exists, compares current order to the markdown and fixes any mismatches by deleting out-of-sync tracks and re-adding them in the correct order
- •Reports any tracks that couldn't be found or added
Playlist safety: The script will only ever modify playlists that end with the 🤖 suffix. User-created playlists without this marker are never touched.
Backups
Before every sync, the script creates a backup by renaming the existing 🤖 playlist to <name> 🔙 (yyyy-MM-dd). This preserves all tracks and the description. The sync then creates a fresh 🤖 playlist from scratch.
⚠️ Backups are immutable. Once created, a backup must NEVER be modified, renamed, or deleted by automation. The assertManaged guard will throw an error if any operation attempts to touch a playlist containing the 🔙 marker. Only one backup per playlist per day is created; if today's backup already exists, it is skipped.
Flags:
- •
--rename-from="Old Name"— Rename an existing playlist. The old name is looked up in Apple Music; the new name comes from the markdown# heading. - •
--library-only— Only add tracks to the user's library without managing the playlist - •
--headless— Run in headless browser mode (no visible window)
Workflow
Step 1: Identify the Playlist
Determine which playlist markdown file to sync from the playlists/ folder.
Step 2: Launch as an Independent Process
⚠️ CRITICAL: Never run the sync script as a direct shell command or Start-Job. The agent's shell sessions recycle between turns, which kills child processes and background jobs — including the browser the user is trying to sign into. Instead, always launch the sync as a fully independent process using Start-Process with a wrapper script so the process survives session recycling.
# Ensure node is on the PATH
$env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") + ";" + $env:PATH
$nodePath = (Get-Command node).Source
$logFile = "$env:TEMP\apple-music-sync.log"
$workDir = (Get-Location).Path
# Write a wrapper script so the process is fully independent
$wrapper = "$env:TEMP\run-sync.ps1"
@"
Set-Location '$workDir'
& '$nodePath' '.github/skills/apple-music-sync/sync.mjs' 'playlists/<name>.md' *> '$logFile'
"@ | Set-Content $wrapper -Encoding utf8
# Launch as a fully independent process (survives shell recycling)
Start-Process pwsh -ArgumentList "-NoProfile", "-File", $wrapper -WindowStyle Hidden
Write-Output "Launched sync process. Log: $logFile"
For renaming, add '--rename-from=Old Name' to the sync command in the wrapper. For headless mode, add '--headless'.
Step 3: Monitor Sign-In
Check the log output periodically:
Get-Content "$env:TEMP\apple-music-sync.log" -Tail 10
If the log shows the sign-in prompt, tell the user the browser is open and to take their time signing in (2FA may be needed). Do not poll aggressively — check every 30-60 seconds at most.
When the user confirms they are signed in, create the signal file:
New-Item "$env:TEMP\apple-music-signed-in" -ItemType File -Force
The script uses a persistent browser profile, so if the user has previously signed in, it will detect this automatically and proceed without prompting.
Step 4: Monitor Sync Progress
Continue checking the log file until the sync completes:
Get-Content "$env:TEMP\apple-music-sync.log" -Tail 20
When the log shows "Done!" or "Browser will close", the sync is complete. Read the full log to check for any failed tracks.
Step 5: Verify
Ask the user to check the playlist in Apple Music. Confirm the track count and order look correct.
Error Handling
- •If a track cannot be found in search results, the script reports it and continues with the remaining tracks
- •If the playlist already exists, the script compares it to the markdown and fixes any mismatches
- •The user may need to manually add tracks that the script couldn't find (e.g., region restrictions, name mismatches)
- •If Playwright or Chromium is not installed, the script will fail with an import error — run
npm install playwright && npx playwright install chromiumto fix