Changelog
Every WolfWave release. New features, fixes, and breaking changes. Auto-updating via Sparkle. macOS menu bar app for Apple Music streamers.
All notable changes to WolfWave are documented here. When an update is ready, the same notes show up right inside the app's update window.
v2.1.0 (Unreleased)
The next release. These ship on the Nightly channel off main until 2.1.0 is tagged.
Security
- Safer local widget credentials. Token-bearing HTML is served only to a true loopback peer using a literal local Host and is marked
no-store; token changes are saved to Keychain before connected clients rotate.
Added
- Custom bot commands. Make your own chat commands with a fixed reply, in Settings → Twitch → Custom Commands. Use variables like
$user,$touser,$args,$1–$9,$song, and$lastsongand they fill in live. Each command gets its own aliases and Everyone / Per-person cooldowns, same as the built-ins. See Bot Commands. - Pick who can run a command. Set any custom command to Everyone, Subscribers, VIPs, Moderators, or Broadcaster only. Custom commands are included in your settings backup.
- Approve songs before they play. New opt-in "Require My Approval" toggle in Settings → Song Requests → Access. When it's on, every request (chat, channel points, bits) waits in the Queue tab until you approve or decline it. Off by default, so requests still auto-queue unless you turn it on.
- Fair-share song ordering. The queue interleaves requests round-robin, so everyone's first request plays before anyone's second. A regular who re-types fast no longer plays back-to-back while newcomers wait. On by default; flip "Fair-Share Ordering" off in Settings → Song Requests → Queue for classic first-in, first-out.
- Sub / VIP request priority. Reward your subs, VIPs, and mods: pick a perk in Settings → Song Requests → Queue. "Skip cooldown" lets them request without the wait; "Jump the queue" also moves their song ahead of regular requests within the same fair-share round (a nudge up, not a queue takeover). Off by default.
- Two new overlay layouts: Vinyl and Classic. Vinyl is a spinning record with your album art as the label and a circular progress ring. Classic sets the album tile beside a card with the title, artist, and a progress bar. Pick either in Settings → Stream Widgets. See Themes & layouts.
Changed
- Settings toggles all look the same now. Launch at Login, "Check automatically" (Software Update), and "Collect on-device diagnostics" (Advanced) now use the standard row: name and short description on the left, switch on the right. Same layout as every other toggle in Settings.
- Lighter OBS overlay. Progress painting is batched at 10 Hz, and animation work stops while the page is hidden or unloaded and when reduced motion is enabled.
- Less background work. WolfWave pauses unused overlay, Twitch, song-request, and Discord tasks instead of polling or retrying while those features are idle, disconnected, held, hidden, or disabled.
Fixed
- Settings sidebar no longer opens too narrow. The sidebar could come back squeezed from a previous session and cut off section names like "Stream Widgets". It now uses a fixed width, matching System Settings.
- No more freezes from song requests. WolfWave now talks to Apple Music off the main thread, so a slow or busy Music.app can't beachball the app while the request queue auto-advances or when you hit play, pause, or skip.
- Stream Deck overlay key stays connected. The action hides or shows overlay cards without dropping the authenticated control socket, so the next key press and its acknowledgement still work.
- Album art stays current. A slow old lookup can no longer replace the current track's art, temporary download failures remain retryable, and the tray's decoded-art cache is bounded.
- Advanced settings opens instantly. Log size and line count load in the background now, so a large log file no longer stalls the pane when it appears.
- Accurate lifetime stats after a hard quit. Listening History no longer double-counts old plays if WolfWave is force-quit or crashes while it's trimming its history.
- Clean Twitch sign-in cancel. Cancelling the Twitch connect flow no longer flashes a false "OAuth setup failed" error.
- Steadier under the hood. Hardened Discord Rich Presence against a rare bad-playback-position crash, stopped a Twitch rate-limit wait from spinning the CPU when a connection drops, and made LAN IP detection skip a bad network interface instead of showing a blank overlay address.
Developer
- Stream Deck control API. Groundwork for the upcoming Stream Deck plugin. The overlay WebSocket is now bidirectional: it parses a protocol-versioned inbound
commandenvelope, routes 11 actions to existing services, and replies with anack; newqueue_state/healthbroadcasts drive counter/health keys. Still gated by the per-installwolfwave.token.<hex>handshake. The plugin itself ships separately. - Crash/lockup/data-race review pass.
AppleMusicControllerrunsNSAppleScripton a dedicatedAppleScriptExecutorthread (own run loop) instead of the main thread;playbackSnapshot()and the playback commands are nowasyncso the main-actor poll suspends rather than blocking.RateLimiter.awaitCapacityunwinds on cancellation,LifetimeTallygained alastFoldedTimestamphigh-water mark for idempotent crash-recovery reloads, andListeningHistoryServicecoalesces concurrent loads. - OBS resource pass. The browser batches progress paint at 10 Hz and suspends when hidden/unloaded/reduced-motion; native progress work exists only while enabled, visible, playing, and serving clients, and JSON fan-out encodes once.
- Idle-service pass. Twitch owns one keepalive/session with bounded classified retries and tears network work down on leave; Song Requests stops auto-advance polling while idle/held/disabled; Discord polls only while enabled and disconnected; decoded tray art is single-flight and bounded to 64 items / 32 MiB; startup duplicate warming was removed and reduced-power policy applies immediately.
- DRY pass. 20 mechanical extractions with no behaviour change: shared HTTP-response / widget-config / now-playing / JSON-guard helpers, an EventSub body + form-POST + custom-rewards URL builder, shared day-bucketing and history-store filesystem helpers, a shared song-request dedup predicate and capacity insert,
BotCommand.commandToken(in:)shared across the command match loops,SectionHeaderWithStatusreused at 10 hand-rolled header sites, and centralized setting + widget-appearance defaults. - Swift file headers normalized. Every file now carries the header Xcode generates from
IDETemplateMacros.plist, with eachCreated bydate reset to the file's real git creation date. Newscripts/check-headers.mjs(make lint-headers, plus a blocking CI job) keeps them from drifting.
v2.0.1. July 11, 2026
Fixed
- Update notes now load. Sparkle's "What's New" window no longer 404s when you check for updates. (It broke in 2.0.0.)
- Fewer crashes. Fixed a crash for people who opted into diagnostics, a crash from an out-of-range widget port, and hard failures when a log write hit a full disk.
- Music.app can't freeze WolfWave. Every command to Apple Music now times out instead of hanging the app if Music gets stuck.
- Snappier menu bar. Play/pause state reads from cache instead of pinging Music.app while the menu is open.
- No double actions. Twitch events that arrive twice (chat commands, channel-point redemptions) only run once now.
- Overlays keep updating. Closing the Settings window no longer stops now-playing updates from reaching your overlay.
- Vote-skip won't get stuck. A Twitch poll that never closes now falls back cleanly, and chat votes reset between songs.
- Accurate history. Listening History no longer double-counts a play, and tells apart songs that share a title.
!playlistsurvives hiccups. A brief network blip while checking your playlist link no longer switches the command off.
v2.0.0. July 1, 2026
Security
- Stream Widgets now need an access token. Every WebSocket client must authenticate with a per-install token kept in the Keychain. Localhost HTML receives it from WolfWave; LAN links carry it as connection bootstrap. Existing OBS sources keep working. Reveal, regenerate, or replace the token in Settings → Stream Widgets.
- Streamer Mode. One tray toggle hides anything you wouldn't want on camera: channel name, overlay and widget URLs, and the access token. Copy and Open buttons switch off too. On-screen only. Your overlay, Discord, and chat output are untouched. See Streamer Mode.
Added
Song requests
- Song Requests. Viewers request tracks with
!sr <song>. Plays through Apple Music without stealing focus from your stream. See Bot Commands. - Guided setup. A quick walk-through (Twitch, Apple Music access, your requests playlist) runs before song requests can be switched on, so nothing goes live half-configured. If your requests playlist is ever deleted or un-shared, WolfWave catches it and shows a "set up again" banner.
- Queue commands.
!queueand!myqueueshow the queue.!skip/!next,!clearqueue, and!hold/!resumeare for mods and the broadcaster. - Chat Vote-Skip. Chat votes out a song with
!vs. Counts unique voters, or opens a native Twitch poll (Affiliate/Partner). Set it up in Settings → Song Requests. - Song Request Queue view. A now-playing card, who asked for each track, and Skip / Hold / Clear.
- Hold the queue. New requests pile up without auto-playing, so you can line them up first. From the queue view or the menu bar.
- Requests wait while Apple Music is closed. Saved, then played when Music reopens.
- Fallback playlist. Plays an Apple Music playlist whenever the queue runs dry.
- Limits and controls. Per-user and global limits, subscriber-only mode, on/off per command, and custom aliases.
- Recreate Reward button. Rebuilds the "Request a Song" Channel-Point reward if you delete it by hand.
Your music, tracked
- Listening History. An opt-in, on-device log of what you play. Stays on your Mac, never uploaded. Off by default. Skips don't count. See Listening History.
- Stats and Charts. Top artists, listening time, a 7-day trend, and a by-hour breakdown. Needs Listening History on.
- Monthly Wrap. A personal "Wrapped" for any month. Save it as a PNG or share it.
- History retention picker. Keep history forever, or for 7 / 30 / 90 / 180 / 365 days.
!statscommand. Chat asks for today's top track. Only replies while you're live.
On stream
!wolfwavecommand. A one-tap chat shoutout for the app. Four reply styles. Off by default.- Widget themes and layouts. Five selectable themes (Default, Dark, Light, Glass, Neon), plus a hidden internal WolfWave theme, and five layouts (Horizontal, Vertical, Compact, Vinyl, Classic). See Stream Widget.
- Live widget preview. See your overlay update as you tweak the theme, layout, font, and colors.
- Smoother OBS widget. Songs slide in, fade out calmly, and crossfade on fast skips. No strobing.
- Discord idle and pause controls. Keep an idle marker when nothing plays, or clear your profile while paused. Both off by default.
- Discord playlist in your presence. Shows the current Apple Music playlist next to the track.
- Song-change notifications. An optional macOS banner on every track change. Off by default.
- Skip-vote notifications. Optional banners when a vote starts and when it passes. Off by default.
The app
- Light, Dark, or System appearance. Pick one in Settings → General. The menu bar follows too. See Appearance.
- Back up and restore your settings. Export to a JSON file, restore on another Mac. Accounts and secrets stay in the Keychain. On import, you choose whether to reconnect Twitch. See Back Up & Restore.
- macOS 26 Liquid Glass redesign. Settings, menu bar, and a rebuilt onboarding wizard for Tahoe.
- Nightly update channel. Opt into dev builds off main from Settings → Software Update. Clearly warned, easy to leave, and Stable stays the default. See Nightly Builds.
- Diagnostics and bug reporting. Export/Clear Logs and a one-click Report a Bug, with sensitive details redacted.
- On-device diagnostics. An opt-in MetricKit report with a share card. Stays on your Mac. Off by default.
- Branded About window. A native WolfWave About replaces the macOS default.
- WolfMark branding. A new album-art placeholder and brand polish across the app and overlay.
- Faster overlay URLs. WolfWave caches your local IP, so settings no longer pause looking it up.
Changed
- Clearer settings headings. Every pane has one big title with section titles a step below, so it reads top to bottom at a glance. VoiceOver can jump between them by heading.
- Redesigned Settings sidebar. A branded header, grouped rows with round icon chips, and an accent-colored selection pill. Sections are grouped by what they're for.
- Calmer destructive buttons. Reset, Clear Logs, and Clear Artwork Cache drop the loud red bar for a neutral button with a red label. The Danger Zone card gets a red heading instead of a red wash.
- Type RESET to wipe everything. The Reset confirmation spells out what it erases and makes you type RESET first, so a stray click can't reset the app.
- Apple Music playback keeps your focus. Music never steals focus from OBS or other streaming tools.
- MusicKit is only used for search, never for playback.
- Steadier under stress. A safety net catches the rare hard crash. If WolfWave goes down, it shows a one-time "Recovered from a crash" notice in Advanced with a one-click bug report.
- Permissions live in one onboarding step. Apple Music access, the notification prompt, and the per-alert toggles are now together.
- Onboarding polish. Repeated success rows gone, tighter wording, and pinned sizes so nothing jumps around. VoiceOver announces each step by name.
- Music permission row is actionable. Tap it to re-request access or jump into System Settings.
- App Visibility is a single-column picker for the menu bar, the Dock, or both. General lays Startup and Display Mode side by side.
- Tighter wording across onboarding, settings, and the menu bar.
Performance
- Lower idle energy use. Background timers now let macOS batch their wakeups together, which saves power for an all-day menu bar app. Real-time track changes still arrive instantly.
- No more jank when switching between settings sections.
- Faster first paint and an instant Now-Playing Server row, thanks to off-main-thread font lookup and the cached local IP.
Developer
Developer-facing changes. Not visible to end users.
- Unified design system. One
design-system/tokens.jsonfeeds a generator that emits four platform outputs (Swift, docs CSS, widget JS, marketing TS), with a component catalog and a Turbotokensbuild prerequisite. - OBS widget build pipeline. The widget source moved to a new
apps/widget/Tailwind + TypeScript workspace;widget.htmlis now a generated, fully-inlined artifact rebuilt explicitly or by CI and committed for Xcode to bundle. See OBS Widget Architecture. - Sparkle hardening. Opted out of system-profile telemetry, and the release pipeline turns each version's CHANGELOG section into styled HTML embedded in the appcast (
scripts/release-notes.mjs). - Crash safety net. An uncaught-exception and signal handler records a breadcrumb and chains the previous handler, plus a blocking force-unwrap CI lint gate on production source.
- Concurrency and architecture cleanup.
HelixClient, a typedPreferencesaccessor, typed NotificationCenter payloads, actor adoption forSongBlocklistandSkipVoteManager, and Combine fully removed from the app target. - DEBUG-only Debug settings tab with inspectors, service controls, log/event views, and What's New previews.
- New unit tests and an expanded design-token roster. The suite is now more than 2,200 tests across 90 files.
Fixed
- Twitch bot no longer goes silent after a relaunch. It reconnects to your saved channel on its own, so chat commands work without reopening Twitch settings. The reconnect is silent.
- One recovery card for denied Music access. No more stacking the same "Music access denied" warning three times. A single card owns the explanation and the Open System Settings button. "Try again" shows a spinner instead of feeling like a dead button.
- Now-playing survives Apple Music quirks. The player-state reader accepts every value Music returns, instead of blanking the now-playing card, Discord presence, and overlay while music is playing.
- Apple Music control under the sandbox. The "WolfWave wants to control Music" prompt now appears and WolfWave can actually drive Music.
- Two-PC stream widget works. Open your overlay from a second computer or your phone on the same network. The Network Address URL in Settings → Stream Widgets now works (gated by the access token).
- Twitch settings card stops jumping between the signed-out, authorizing, and error states.
- Onboarding is steadier. Steps are centered again, the header no longer drifts between steps, and the Preferences step stops overlapping the nav bar on short windows.
- Recheck and the Sync toggle force a fresh now-playing read, so the UI catches up right after you grant permission.
- Apple Music Recheck button visibly responds when tapped, instead of looking broken.
- Stats card layout no longer jumps around and is gated on Apple Music access.
- Export Logs no longer crashes on empty or very large logs.
- About window Check for Updates now actually runs Sparkle, and Release Notes points at this changelog.
- Intel Homebrew detection. Intel Macs installed via Homebrew now disable Sparkle and show the Homebrew update card.
- Keychain self-heals a duplicate item that could appear after onboarding.
- Settings sidebar toggle cleaned up: one toggle, no floating reveal control.
- Cleaned up build warnings, layout glitches, duplicate log lines, and small icon and window-sizing issues.
Removed
WallpaperBloomBackground, in favor of native macOS chrome.- Repeated onboarding success rows.
v1.2.0. April 4, 2026
Added
- Shared UI components. Reusable settings components for a more consistent look
Changed
- Music architecture. Refactored to a pluggable source system, laying groundwork for future music sources beyond Apple Music
- AppDelegate decomposed. Split into focused extensions for maintainability
- Logger. Streamlined format with local time and emoji prefixes
- Widget settings. Compact 2-per-row layout, auto-sizing dropdowns
- Settings UI. Unified headers and test buttons across Discord & Twitch sections
Fixed
- Settings window not appearing when opened from menu bar in menu-bar-only mode
- 4 Xcode build warnings (actor isolation and unreachable code)
- Widget favicon broken reference
v1.1.0. March 31, 2026
Added
- Discord buttons. Rich Presence now shows two clickable buttons: Open in Apple Music (direct track link) and song.link (opens on Spotify, YouTube Music, Tidal, and more)
- Launch at Login. New toggle in Settings → App Visibility. Uses SMAppService, appears in System Settings → General → Login Items
- Custom DMG background. Installer window has a polished dark background with WolfWave brand colors
- Homebrew auto-update. GitHub Actions now automatically opens a pull request on the Homebrew tap on new releases
Fixed
- iTunes Search API URL encoding. Track/artist names with &, +, or = no longer break artwork lookups
- Launch at Login toggle now reverts if SMAppService registration fails
v1.0.2. March 31, 2026
Fixed
- App icon missing in CI-built releases
- Sparkle updater unable to detect new versions (build number now incremented per release)
- Sparkle initialization race condition fixed
v1.0.1. March 30, 2026
Changed
- Dropped Intel (x86_64) support. Apple Silicon only
- Raised minimum macOS version to 26.0 (Tahoe)
- Logger: replaced NSLock with serial DispatchQueue for thread-safe file I/O
- TwitchChatService/DiscordRPCService: documented thread safety patterns
- KeychainService: added error logging for all Keychain operations
- AppConstants: cached GitHub repo resolution
- Migrated TwitchViewModel and OnboardingViewModel to @Observable macro
- WhatsNewView: dynamic version string, native button style, v1.0.1 feature highlights
- Narrowed entitlements file exception path
- Added Twitch user ID redaction to log output
- NotificationCenter observers properly cleaned up on app termination
- Windows (Settings, Onboarding, What's New) properly released on close
- Deferred Sparkle/onboarding init past initial layout to fix layoutSubtreeIfNeeded warning
- Removed duplicate "up to date" alert (Sparkle handles it natively)
- Added VoiceOver accessibility labels across all settings and onboarding views
v1.0.0. March 30, 2026
Added
- Native macOS menu bar app for Apple Music integration
- Real-time now-playing detection via ScriptingBridge
- Twitch chat bot with !song, !currentsong, !nowplaying, !lastsong, !last, !prevsong commands
- Discord Rich Presence with dynamic album art
- OBS stream widget via built-in WebSocket server
- Automatic updates via Sparkle (DMG) or Homebrew
- First-launch onboarding wizard
- macOS Keychain credential storage
- Bot command cooldowns and broadcaster bypass
- Settings UI with NavigationSplitView sidebar
- Diagnostic log export
For the full changelog, see CHANGELOG.md on GitHub.
Security
How WolfWave keeps your Twitch and Discord tokens safe. MacOS Keychain storage, App Sandbox, OAuth Device Code flow, and EdDSA-signed Sparkle updates.
Design System
WolfWave's visual language. Design tokens, reusable SwiftUI components, and brand assets. One source of truth powering the native app, docs, widget, and marketing.