Volume Limiter is a lightweight macOS app that caps your maximum output volume. I built it to stop a newly-connected headset from suddenly blasting audio and hurting your ears: it holds every output device to a maximum volume you choose, and pushes the volume back down the moment it goes above that limit. Control it from a pane in System Settings, or from a small command-line tool.
⬇ Download the latest release — open the DMG and double-click VolumeLimiter.prefPane to install, or run brew install --cask HackwoodL/tap/volume-limiter.
Requirements: macOS 13 (Ventura) or later, on Apple Silicon or Intel.
- Caps the maximum output volume — turn it up past the limit and it snaps back.
- A default cap for every device, plus optional per-device caps.
- Headphone-only mode: only limit headphone-like outputs (Bluetooth, USB, Type-C).
- Optional notification when the volume is capped.
- Stops the Bluetooth volume-key "burst" (rapid presses briefly blasting to ~100%) by intercepting the volume-up key at the cap — needs Accessibility permission.
- A System Settings GUI and a
volume-limitcommand line, always in sync.
Download VolumeLimiter-<version>.dmg from the latest release, open it, then double-click VolumeLimiter.prefPane inside. Click Install when System Settings asks. The background service starts automatically — set your cap and you're done. No Terminal, clone, or Homebrew required.
To uninstall, open System Settings ▸ Volume Limiter and click Uninstall.
The build is ad-hoc signed and not notarized (no paid Apple Developer account), so on first install macOS may ask you to approve the pane in System Settings ▸ Privacy & Security, or to right-click ▸ Open it.
git clone https://github.com/HackwoodL/volume-limiter.git
cd volume-limiter
scripts/install-local.sh # one-command install (daemon + CLI + prefPane)install-local.sh builds the universal binaries and installs everything into
~/Library/Application Support/VolumeLimiter, with the LaunchAgent and prefPane
under ~/Library, so nothing runs out of your checkout directory. Prefer a DMG?
Run scripts/build-dmg.sh instead and double-click the pane inside it.
The CLI installs to ~/Library/Application Support/VolumeLimiter/bin. Add it to
your PATH to call volume-limit directly:
echo 'export PATH="$HOME/Library/Application Support/VolumeLimiter/bin:$PATH"' >> ~/.zshrcFor development you can also build and test without installing:
swift build
swift run volume-limiter-tests
scripts/test-cli-daemon.pyOne command installs and starts everything (the cask carries the self-contained pane, which bundles the service and CLI):
brew install --cask HackwoodL/tap/volume-limiterUninstalling is also one command — it stops the service and removes the agent, config, and pane:
brew uninstall --cask HackwoodL/tap/volume-limiterThe main interface is a pane in System Settings ▸ Volume Limiter:
- A master switch to turn limiting on or off.
- A default cap slider that applies to every device.
- Per-device caps — add specific devices and give each its own cap.
- Toggles for headphone-only mode and limit notifications.
- A one-click Uninstall button.
It shows the current volume and output device live, and the background service keeps your cap enforced even when the pane is closed.
On some Bluetooth headphones, rapidly pressing volume-up can momentarily blast the volume to ~100% before the cap is re-applied — an audible "burst". That is macOS's own volume-key handling racing ahead of any after-the-fact correction, so lowering the volume reactively can't fully prevent it.
To stop it at the source, Volume Limiter intercepts the volume-up key once you're already at the cap, so the volume never overshoots. This needs Accessibility permission:
- Open System Settings ▸ Privacy & Security ▸ Accessibility (when permission is missing, the Volume Limiter pane shows a one-click button that opens it).
- Enable volume-limiterd.
Protection turns on within a few seconds. If it doesn't activate, log out and back in (or restart) once so the background service picks up the permission. Without it, Volume Limiter still caps the volume reactively — only the rapid-press burst on Bluetooth remains.
volume-limit set <0-100> # set the default cap for all devices
volume-limit on # turn the limiter on
volume-limit off # turn the limiter off
volume-limit status # show the full daemon status and diagnostics
volume-limit device on|off # enable/disable per-device caps
volume-limit device set <uid> <n> # cap a specific device by UID
volume-limit device remove <uid> # remove a device's per-device cap
volume-limit device list # list per-device caps and connected devices
volume-limit headphone-only on|off # only limit headphone-like outputs
volume-limit --help # show usageIf the daemon is not running, the CLI prints:
volume-limiterd is not running.
Open System Settings > Volume Limiter to start it.
Open System Settings ▸ Volume Limiter and click Uninstall at the bottom of the pane. It stops the background service and removes the LaunchAgent, the saved configuration, and the preference pane itself in one step. Quit and reopen System Settings afterwards to clear it from the sidebar.
Equivalent to the button, if you prefer the command line:
launchctl bootout gui/$(id -u)/com.hackwoodl.volumelimiter 2>/dev/null || true
rm -rf ~/Library/Application\ Support/VolumeLimiter \
~/Library/PreferencePanes/VolumeLimiter.prefPane \
~/Library/LaunchAgents/com.hackwoodl.volumelimiter.plistbrew uninstall --cask HackwoodL/tap/volume-limiter┌────────────────────────────────────────────────────────────┐
│ volume-limiterd │
│ - Core Audio listeners │
│ - volume clamp policy │
│ - config owner │
│ - Unix domain socket server │
└────────────────────────────────────────────────────────────┘
▲
│ /tmp/volume-limiter-$UID.sock
┌────────────┴────────────┐
│ │
┌────────────────────────────┐ ┌────────────────────────────┐
│ volume-limit │ │ VolumeLimiter.prefPane │
│ CLI thin client │ │ System Settings thin client│
└────────────────────────────┘ └────────────────────────────┘
The daemon is the only process that calls Core Audio to read or set output volume. CLI and GUI clients only send newline-delimited JSON requests over the per-user Unix socket.
Released under the MIT License.
