WolfWave is a free, native macOS menu bar app for streamers who use Apple Music. Play a song and your Twitch chat, Discord profile, and OBS overlay all update on their own. Your chat can request songs, and you stay in charge of what plays.
Your music plays. Everything else keeps up.
You need: a Mac with Apple Silicon (M1 or later), macOS 26 (Tahoe) or newer, and the Music app.
Option 1: DMG (recommended)
- Download the latest
.dmgfrom GitHub Releases. - Open it and drag WolfWave to Applications.
- Launch WolfWave and follow the setup wizard.
Option 2: Homebrew
brew tap mrdemonwolf/den
brew install --cask wolfwaveWolfWave is signed and notarized by Apple, so macOS trusts it (it may ask
you to confirm the first launch). DMG installs update themselves. Homebrew
installs update with brew upgrade wolfwave.
Twitch song requests
- Requests from chat. Viewers type
!srwith a song name or an Apple Music, Spotify, or YouTube link. Songs play through Apple Music without stealing focus from OBS. - Channel points and Bits. WolfWave can add a "Request a Song" channel-point reward. A Bits cheer can request a song, or bump the viewer's queued song to the front. Failed channel-point requests are refunded.
- Require My Approval. Opt-in. Every request waits in the queue until you approve or decline it.
- Hold the queue. Requests still come in, but nothing plays until you resume.
- Fair-share order. Everyone's first request plays before anyone's second. On by default.
- Sub / VIP priority. Optional. Subs and VIPs skip the cooldown or jump ahead within a round. Off by default.
- Blocklist. Block a song, a whole artist, or a person.
- Vote-to-skip. Chat votes with
!voteskip, as a chat tally or a native Twitch Poll. - Fallback playlist. Pick an Apple Music playlist to play when the queue runs dry.
- Apple Music AutoPlay. Let Music choose what plays when the request queue empties. Turn on AutoPlay in Music's Playing Next panel; a fallback playlist takes priority.
- Clear requests. Clear the queue and the shared WolfWave Requests playlist together. When the queue is already empty, Music keeps playing. The songs stay in your Apple Music library.
- Live queue view. See what's playing, what's next, and who asked for it, right in the app.
Chat commands
- Built-in commands.
!song,!last,!queue,!stats, and more.!songand!lastare on for new installs. Turn each one on or off and add your own aliases. - Custom commands. Make your own, with variables (
$user,$touser,$args,$1-$9,$song,$lastsong), a cooldown, and a permission level. Each one replies to the chatter, posts a plain message, or sends a Twitch announcement.
Discord
- Rich Presence. Shows "Listening to WolfWave" on your Discord profile with Apple Music album art and buttons to open the song.
Stream overlay
- OBS browser source. A now-playing card with five themes
(
Default,Dark,Light,Glass,Neon) and five layouts (Horizontal,Vertical,Compact,Vinyl,Classic). - Queue ticker. Opt-in
?queueTicker=1panel showing the next 3 requests and who asked for them. - Two-PC setups. An OBS PC on the same network can show the overlay with a read-only token.
- Light on OBS. Progress updates are batched, rendering sleeps while hidden, and Reduce Motion turns off continuous animation.
- Smoother updates. Repeated snapshots preserve artwork and Vinyl rotation. Preset text contrast is checked against light and dark scenes; custom colors still need checking against your scene.
Stream Deck (optional)
- Thirteen keys. Play / Pause, Next Track, Hold / Resume Queue, Approve Next, Reject Request, Clear Queue, Block Song, Block Requester, Request Audience, Announce Song, Show / Hide Overlay, Now Playing, and Track Time.
- Manual install for now. The plugin is built from
apps/streamdeck/until it's on the Elgato Marketplace. See the Stream Deck guide.
History & Stats
- Listening history. Opt-in and on your Mac only. Top artists, listening time, a 7-day trend, and listening by hour.
- Monthly Wrap. A "wrapped"-style summary for any month, saved as a shareable image.
Everyday comfort
- Streamer Mode. One click masks your channel name, overlay links, and tokens so Settings is safe to show on camera.
- Song-change banners. Opt-in Mac notifications for song changes and vote-skips. A new banner replaces the last one of its kind.
- Backup & restore. Export your settings to a file in Settings > Advanced and import them on another Mac. Logins and tokens stay in each Mac's Keychain, so you sign in to Twitch once per Mac.
- Sync with iCloud. Opt-in, off by default. Mirrors that same export between your Macs. It needs a build signed with iCloud access; if your settings don't sync, Export and Import always work.
- Menu bar, Dock, or both. Plus launch at login and Light, Dark, or System appearance.
- Native settings controls. Standard macOS switches keep their labels, keyboard behavior, and readable descriptions together across settings panes.
- Updates your way. Stable by default, or opt into Nightly builds in Settings > Software Update.
- Helpful errors. Error messages name the cause and offer the fix. Export Logs and a pre-filled bug report live in Settings > Advanced.
Viewers on a stream running WolfWave can type the commands in Usage. In short:
- Request a song with
!sr <song name or link>. - See the song with
!song, or the one before with!last. - See the line with
!queue, or just your own with!myqueue. - Vote to skip with
!voteskipor!vs. - Spend channel points or Bits to request, if the streamer turned them on.
- Local WebSocket feed. Every play, pause, and skip as JSON on
ws://localhost:8765, authenticated with a read-only overlay token. See the Widget docs. - Stream Deck control API. A separate control token runs commands, and only from the same Mac. Documented in Stream Deck Control API.
- Settings deep links.
wolfwave://settings/<pane>/<section>opens Settings at a card. The names are listed in the Settings docs. - Native and open source. Swift 6, SwiftUI, sandboxed. GPL-3.0.
| Command | What it does |
|---|---|
!sr <song> !request !songrequest |
Requests a song (name or link) |
!song !currentsong !nowplaying |
Shows the current song |
!last !lastsong !prevsong |
Shows the previous song |
!queue !songlist !requests |
Shows the request queue |
!myqueue !mysongs |
Shows only your own requests |
!voteskip !vs |
Votes to skip the current song |
!playlist |
Links the streamer's request playlist |
!stats !musicstats |
Shows your listening stats |
!wolfwave |
Tells chat what WolfWave is (off by default) |
The streamer turns each command on or off and can add aliases in Settings > Twitch and Settings > Song Requests.
| Command | What it does |
|---|---|
!skip !next |
Skips the current request |
!hold !resume !unhold |
Holds or resumes the request queue |
!clearqueue !cq |
Clears requests and the shared playlist; songs stay in your library |
- Allow Music access. Step 2 of the setup wizard asks macOS to let WolfWave read the Music app.
- Connect Twitch. In the wizard, or Settings > Twitch. Sign in
with the code WolfWave shows you.
!songand!lastare ready. - Turn on requests. Settings > Song Requests > Enable Song Requests. Add Require My Approval if you want to screen them.
- Turn on Discord. Settings > Discord.
- Add the overlay. Settings > Stream Widgets. Turn it on, then add the browser source link to OBS.
| Layout | Recommended OBS canvas |
|---|---|
| Horizontal | 532 x 132 |
| Vertical | 252 x 312 |
| Compact | 382 x 88 |
| Vinyl | 292 x 332 |
| Classic | 472 x 144 |
Sizes include the widget's transparent padding. On the same Mac, use the localhost link. For a second computer, use the LAN link on a trusted network only.
Full docs live at wolfwave.mrdemonwolf.dev.
Read released updates on the public Changelog, or explore the Design system for typography, measured color pairs, components, and motion. Unreleased notes stay in the repository and are excluded from the website's changelog and search.
| Layer | Technology |
|---|---|
| Language | Swift 6.0 |
| UI | SwiftUI, AppKit |
| Platform | macOS 26.0+ (Tahoe), Apple Silicon, Apple Music app required |
| Music | ScriptingBridge, MusicKit, AppleScript |
| Twitch | EventSub WebSocket, Helix API |
| Discord | Rich Presence via local IPC Unix domain socket |
| Networking | URLSession, Network framework, NWListener (WebSocket overlay) |
| Updates | Sparkle (EdDSA-signed appcast) |
| Charts | SwiftUI Charts (History & Stats) |
| Diagnostics | MetricKit (opt-in) |
| Tests | XCTest, Swift Testing, XCUITest |
| Security | macOS Keychain (Security framework) |
| Docs | Fumadocs (Next.js), bun, Turborepo |
| Marketing | Remotion |
The short version is below. The full guide is in the Development docs and CONTRIBUTING.md.
- macOS 26.0+ (Tahoe) on Apple Silicon
- Xcode 26+ and Swift 6.0
- bun (the version pinned in
package.json) for the docs, widget, and Stream Deck workspaces - Command Line Tools:
xcode-select --install
- Clone the repo:
git clone https://github.com/MrDemonWolf/WolfWave.git
cd WolfWave- Copy the config template:
cp apps/native/WolfWave/Config.xcconfig.example apps/native/WolfWave/Config.xcconfig-
Add your Twitch Client ID (dev.twitch.tv/console/apps) and Discord Application ID (discord.com/developers/applications) to
Config.xcconfig. -
Open the project and press
Cmd+R:
make open-xcodeNative app:
make buildruns a debug build.make testruns the unit tests.make test-uiruns the XCUITest suite against the real app.make clean-devresets WolfWave Dev to a fresh first run. It never touches the production app.make check-driftregenerates the widget, tokens, sponsor config, and Debug icon, and fails on drift (the same gate as CI).make prod-buildbuilds a release DMG inbuilds/.
Monorepo (bun + Turborepo):
bun installinstalls every workspace.bun run buildbuilds every workspace in order.bun run dev --filter docsstarts the docs site.bun run --filter widget testruns the OBS widget tests.bun run --filter streamdeck testruns the Stream Deck plugin tests.bun run tokensregenerates the design tokens.
The full list of make and bun targets is in Makefile,
package.json, and CLAUDE.md.
- SwiftLint, plus blocking crash-safety (no force unwrap,
try!, oras!), file-header, and docs-sync checks:make lint,make lint-crash-safety,make lint-headers,make lint-sync. - Design-system lint:
bun run ds:lint. - Swift 6 async/await, MVVM with
@Observableview models. - Credentials always go through the Keychain, never
UserDefaults.
wolfwave/
├── apps/
│ ├── native/ # Native macOS app (Swift, SwiftUI, AppKit)
│ │ ├── WolfWave/ # App source
│ │ ├── WolfWaveTests/ # Unit tests
│ │ ├── WolfWaveUITests/ # XCUITest suite (drives the real app)
│ │ ├── docs/ # Internal design and protocol docs
│ │ └── WolfWave.xcodeproj # Xcode project
│ ├── docs/ # Fumadocs documentation site
│ ├── marketing/ # Remotion-based promo videos
│ ├── streamdeck/ # Elgato Stream Deck plugin (TypeScript)
│ └── widget/ # OBS overlay widget source (builds Resources/widget.html)
├── assets/ # Brand assets, logos
├── design-system/ # Design tokens + component catalog
├── docs/ # Repo-level engineering standards
├── scripts/ # Release, versioning, and lint helper scripts
├── CHANGELOG.md # Release history
├── CONTRIBUTING.md # How to build, test, and submit changes
├── Makefile # Build, test, lint, release targets
├── package.json # bun workspaces root
└── turbo.json # Turborepo pipeline config
WolfWave is released under the GNU General Public License v3.0 (GPL-3.0).
Questions or feedback?
- Discord: Join my server
- Issues: GitHub Issues
- Docs: wolfwave.mrdemonwolf.dev
- Contributing: CONTRIBUTING.md
- Conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Made with love by MrDemonWolf, Inc.
