A macOS menubar app that automatically prevents Bluetooth headsets (AirPods, etc.) from hijacking your microphone.
When you connect AirPods or any Bluetooth headset, macOS automatically switches the default input device to the headset's microphone. This causes:
- Your external USB mic to be ignored
- Terrible audio quality (HFP/SCO codec)
- Garbage call/recording quality
Mic Guardian detects this behavior and immediately switches back to your protected microphone.
- Real-time Monitoring: Listens to CoreAudio default input device changes via
AudioObjectAddPropertyListenerBlock - Instant Block: When a Bluetooth mic tries to become default input, it gets blocked immediately
- Restore Protected Mic: Switches back to your chosen (or auto-selected) non-Bluetooth microphone
- Re-assertion (45s total): macOS retries aggressively after connection, so Mic Guardian keeps re-asserting:
- Phase 1: 0.5s interval × 10s (aggressive blocking)
- Phase 2: 2s interval × 30s (relaxed blocking)
| Feature | Description |
|---|---|
| 🛡️ Auto Block | Prevents AirPods mic takeover automatically |
| 🎤 Protected Mic Selection | Choose any non-Bluetooth mic (USB, built-in, etc.) |
| 📊 Block Counter | Shows how many times BT mic was blocked today |
| ⚡ Real-time Status | Live display of current input device |
| ✅ Toggle ON/OFF | Enable/disable blocking as needed |
- macOS 13.0 (Ventura) or later
- At least one non-Bluetooth microphone to protect
- Bluetooth headset (AirPods, AirPods Pro, Bose, Sony, etc.)
git clone https://github.com/vkehfdl1/MicGuardian.git
cd MicGuardian
swift build -c release# Create .app bundle and copy to /Applications
mkdir -p MicGuardian.app/Contents/MacOS
cp .build/release/OpenToothFairy MicGuardian.app/Contents/MacOS/MicGuardian
cp OpenToothFairy/Resources/Info.plist MicGuardian.app/Contents/Info.plist
codesign --sign - --force --deep MicGuardian.app
cp -R MicGuardian.app /Applications/Or run directly:
.build/release/OpenToothFairy- Launch the app — 🛡️ icon appears in your menu bar
- Click the icon — check the current status:
- Protected: Name of your protected microphone
- Current: Currently active input device
- Blocked today: Number of blocks today
- Change Protected Mic → Select your preferred mic (USB mic recommended)
- Ensure Block Bluetooth Mics toggle is ON
- Connect your AirPods — Blocked today counter should increment
- AirPods audio stays on AAC codec (Option+click Bluetooth menu to verify)
OpenToothFairy/
├── App/
│ ├── OpenToothFairyApp.swift # @main, MenuBarExtra scene
│ └── AppDelegate.swift # LSUIElement, lifecycle
├── Models/
│ └── AudioDevice.swift # CoreAudio device model
├── Protocols/
│ └── AudioDeviceManaging.swift # Protocol for audio manager
├── Services/
│ ├── AudioDeviceManager.swift # CoreAudio C API wrapper
│ └── MicGuardian.swift # Mic blocking business logic
└── Views/
└── MenuBarView.swift # Menubar popover UI
| File | Purpose |
|---|---|
MicGuardian.swift |
Core logic. Detects input changes → blocks BT mic → restores protected mic |
AudioDeviceManager.swift |
Raw CoreAudio C API. Enumerates devices, switches input, listens for changes |
MenuBarView.swift |
SwiftUI menubar UI. Toggle, status display, mic picker |
Inspired by ToothFairy.
- Zero external dependencies
- Non-sandboxed (required for system audio device switching)
MIT