mute a specific macOS app
audio macos
README.md

app-mute #

mute an app from the macOS menu bar. built with Swift and Apple's Core Audio taps, with no third-party dependencies or audio driver to install.

install #

requires macOS 26+.

brew tap zzstoatzz.io/app-mute https://tangled.org/zzstoatzz.io/app-mute
brew install --cask zzstoatzz.io/app-mute/app-mute

or download the ZIP, unzip it, and move App Mute.app to Applications. the download is Developer ID-signed and notarized by Apple and runs on Apple Silicon and Intel Macs.

update with brew update and brew upgrade --cask zzstoatzz.io/app-mute/app-mute.

use #

click the speaker icon in the menu bar, then an app. a checkmark means muted; click again to unmute. choose Unmute all and quit to restore playback and exit.

the menu shows apps that are playing audio (speaker icon), apps that played within the last minute, and apps you have muted. every other running app is under Other running apps. clicking an app that is silent arms it (shown with a dash): nothing changes until it plays, and its first sound is muted.

macOS may ask for Screen & System Audio Recording permission. the app receives and discards selected audio; it never saves, replays, or sends it. helper processes are grouped with the app macOS holds responsible for them, so Safari's WebKit GPU process counts as Safari even though it lives outside Safari.app. helpers that cannot be attributed appear separately with their process ID.

design #

  • only while muted — an unmuted app keeps its normal audio path.
  • no device switching — mute uses a private tap-only device, leaving system input and output choices alone.
  • temporary state — mute lasts only while the app consumes the tap; quitting or a crash releases it.

develop #

requires the Xcode 26 command line tools.

git clone https://tangled.org/zzstoatzz.io/app-mute
cd app-mute

xcrun swift-format lint --strict Sources/*.swift Tests/*.swift          # check Swift formatting
bash scripts/build.sh                                    # build the app
bash scripts/install.sh                                  # install a local build in ~/Applications
bash scripts/test.sh                                     # tap lifecycle and device invariants
bash scripts/test.sh --loopback BlackHole2ch_UID           # measure mute, unmute, and crash recovery

local builds are signed with your Developer ID Application identity when one is installed (or set SIGNING_IDENTITY), falling back to ad-hoc signing. macOS pins System Audio Recording permission to an ad-hoc binary's exact code hash, so an ad-hoc build loses the permission every time it is rebuilt. the lifecycle suite relaunches itself as its own responsible process and asks for System Audio Recording permission once; allow it for AppMuteTests.

the optional signal test requires BlackHole 2ch. it refuses to run if BlackHole is active or selected as a default device, and sends its tone only through that virtual connection. BlackHole is not needed to use the app.

uninstall #

brew uninstall --cask zzstoatzz.io/app-mute/app-mute

for a manual install, choose Unmute all and quit, then move the app to Trash.

docs #

see docs/ for release signing, notarization, and Homebrew packaging.

credits #

the app icon and menu bar frog are bufo with noise-cancelling headphones.

license #

MIT