cx-ouoxo: sidebar Now Playing card for browser tabs (preview)
Summary
With labs.previewFeatures on, the sidebar's bottom card slot shows what a cmux browser tab is playing (YouTube, Spotify web, SoundCloud, anything that uses Media Session or a media element). The card has the artwork, the title and artist, a scrubber you can click or drag to seek, and Previous, Play/Pause and Next. With the preview off, nothing changes. Proposal and the sources survey: https://github.com/manaflow-ai/cmuxterm-hq/issues/1976.
- Source:
BrowserTabsNowPlayingpicks the playing tab across both engines the same way macOS Now Playing already does (BrowserNowPlaying.pick, now shared), and loads the artwork through the tab. The card's controls run the media hub's commands on that tab.NowPlayingSourceis the seam, so system Now Playing can become a second source later. - Position: the page script now reports
position,durationandrate, andBrowserMediaCommand.seeksetscurrentTime. A report that only confirms the track is on course leaves the tab's state alone, so a playing tab costs no re-renders. A resume, a pause, a seek or a speed change takes the new position. - Theme and motion: the card sits on the same surface as the other sidebar cards and draws its text and track from the sidebar's theme. There's no visualizer. The scrubber fill is one render-server animation, so the app sets no timer while the card plays. Under Reduce Motion it steps every 5 s instead of gliding. VoiceOver reads the scrubber as a slider ("1:00 / 8:00") that steps by 10 s.
- Keys: none added. Media keys already reach the tab through MPRemoteCommandCenter.
Known limits:
- No dismiss button.
- The card outranks the "updated" and notice cards in the shared slot while something plays. Update status still wins.
- System Now Playing (Apple Music, Spotify app) isn't a source. Reading it needs MediaRemote, which macOS 15.4+ refuses to unsigned callers. hq#1976 asks for a security call.
- A failed artwork fetch isn't retried until the artwork URL changes.
Testing
Fleet runs of scripts/ci/run-swift-testing-suites.sh Packages/macOS/CmuxNext:
- Red, card:
NowPlayingCardTestsfailed on the test commit ca77a77a7232 (5 of 5; the card never showed). - Red, position:
NowPlayingPositionTestsfailed on its test commit 4c5bb3ca71c8. A resume 10 min after a pause read 418 s off, a pause read 120 s off, and a 2x speed change read 60 s off. The heartbeat test passed. - Green: both suites pass on the head (see the comment below).
- Release compile:
check-release-compile.shexited 0 on d261c2270d85. The head re-run is in the comment below. - The card tests drive a real
SidebarViewfrom a fakeNowPlayingSource: what shows, every control and the seek reaching the source, the theme's colors, nothing sliding under Reduce Motion, and no card with the preview off. - Base reds, the same on the base:
NewTabStyleSwitchTests, the suites runner's same-tree cmux-tui guard (AcpmuxBundleReplacedTests), andcheck-concurrencyonHomeBrainHost.swift:197. - Local checks: check-motion, crash_ratchet, check-no-godfiles (no "split it"), check-system-blue and check-theme-scope are clean.
- Not done: a live check in a tagged build.
- Localization: no new strings. The controls reuse the browser media row's localized Play, Pause, Previous and Next.
Changelog
Added: Preview: a Now Playing card in the sidebar shows what a browser tab plays, with artwork, play/pause, previous/next and seeking
Proof
No capture yet; the tests above cover the shown state, controls, theme and Reduce Motion.
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Adds a Now Playing card to the sidebar's bottom slot, behind labs.previewFeatures: it shows what a cmux browser tab plays (YouTube, Spotify web, SoundCloud, anything using Media Session) with artwork, title and artist, a scrubber that seeks, and Previous, Play/Pause and Next. With the preview off, nothing changes.
- The card picks the playing tab the same way macOS Now Playing does, loads artwork through the tab's cookies, and drives the tab through the media hub's commands. The pick and the card's source now live in their own
CmuxNextNowPlayingtarget; the App only wires them. - The page script now reports position, duration and rate; a heartbeat that only confirms the track is on course leaves the tab's state alone, so a playing tab costs no re-renders.
- The scrubber fill runs as one render-server animation (the app sets no timer while playing), steps every 5 s under Reduce Motion, and VoiceOver reads it as a slider that steps by 10 s.
Known limits
- No dismiss button; while something plays the card outranks the updated and notice cards, though update status still wins.
- System Now Playing (Apple Music, Spotify app) isn't a source; reading it needs MediaRemote, which macOS 15.4+ refuses to unsigned callers.
- A failed artwork fetch isn't retried until the artwork URL changes.
Before/after, recorded on a tagged DEV build of d496631 on macOS 27.0.1: a CEF tab plays a local test track behind a terminal; labs.previewFeatures is off for the first 2.5 s (no card), then switched on live, and the card appears with art, title, artist and a moving scrubber.
Showcase

Full quality:
