micpipe
micpipe is a lightweight macOS audio router service for sending your
microphone into BlackHole 2ch or another CoreAudio output. It is built for the
common workflow of using BlackHole as the microphone source in another app while
keeping the route alive in the background.
It can also run in the foreground while you are testing.
What it does
- Routes one input device to one output device.
- Runs as a per-user
launchdservice. - Follows the system default input, or pins a specific input by name.
- Restarts automatically when the default input disconnects.
- Waits for a pinned input to reconnect, then restarts automatically.
What it is not
micpipe is not a full multi-source mixer. It does not currently combine
multiple inputs, expose gain controls, or provide mute/solo controls. It is a
small background audio router for keeping a microphone-to-output route alive.
Requirements
- macOS
- Rust and Cargo
- BlackHole, or another CoreAudio output device to receive the microphone audio
- Microphone permission for the terminal or installed binary that runs
micpipe
Install
Install from crates.io:
Install from a source checkout:
Quick start
Run in the foreground with the default route:
By default, micpipe run follows the system default input device and routes it
to the first output device whose description contains BlackHole 2ch.
Install and start the background service:
Pin explicit devices when you want stable matching by device-name substring:
Use run instead of install for foreground testing:
Add --debug to log buffer occupancy once per second:
Common use cases
- Send your mic into BlackHole so another app can select BlackHole as its input.
- Keep that route alive as a background service.
- Follow whichever microphone is currently the macOS default.
- Pin a USB or external microphone and restart only after that same device reconnects.
macOS setup notes
Install BlackHole separately before using the default output route.
Run micpipe run once from the terminal if macOS needs to prompt for microphone
permission. The permission belongs to the app or binary that starts micpipe, so
the foreground test is the easiest way to confirm capture works before installing
the service.
CLI reference
micpipe run [--input <name>] [--output <name>] [--debug]
micpipe install [--input <name>] [--output <name>] [--debug]
micpipe status
micpipe restart
micpipe stop
micpipe start
micpipe uninstall
--output is a case-insensitive substring match and defaults to
BlackHole 2ch.
--input is optional:
- Without
--input,micpipefollows the system default input device. If that input disconnects,micpipelogs that the input device was disconnected and immediately asks the installed service to restart. - With
--input,micpipepins that input by case-insensitive substring. If the pinned input disconnects,micpipelogs the disconnected device, polls every 5 seconds until that input appears again, then asks the installed service to restart.
Output stream errors are logged, but do not currently trigger a restart.
Service
micpipe install records the current executable path in the plist. When you
install from crates.io, that is usually the micpipe binary under Cargo's bin
directory.
Useful service commands:
The service label is com.markarranz.micpipe, and the generated plist lives at:
~/Library/LaunchAgents/com.markarranz.micpipe.plist
Re-run micpipe uninstall followed by micpipe install ... when you want to
change the installed route arguments.
Logs
The service writes logs under:
~/.local/share/micpipe/out.log
~/.local/share/micpipe/err.log
Watch both logs with:
Log lines are timestamped in the user's local timezone with a numeric offset, for example:
[2026-06-29T13:04:05-07:00] Mic -> BlackHole running...
Human-facing lifecycle and recovery messages go to out.log. Raw stream errors
and restart-command failures go to err.log.
When the default input disconnects, out.log includes a recovery message like:
[2026-06-29T13:04:05-07:00] input device disconnected: MacBook Pro Microphone; attempting micpipe restart
When a pinned input disconnects, out.log records that micpipe is waiting for
that device before restarting:
[2026-06-29T13:04:05-07:00] input device disconnected: USB Microphone; waiting for pinned input device 'USB Microphone' to reconnect before restarting
[2026-06-29T13:04:10-07:00] pinned input device reconnected: USB Microphone; attempting micpipe restart
Troubleshooting
No output device matching BlackHole
Install BlackHole, confirm it appears in macOS audio devices, or pass a different output substring:
No default input device
Select a default microphone in macOS Sound settings, or pass an explicit input:
Service installed but not loaded
Start it again and then inspect status:
Logs show input device disconnected
If you are following the default input, micpipe attempts an immediate service
restart. If you pinned an input with --input, reconnect that same device;
micpipe polls every 5 seconds and restarts after it appears again.
Route arguments changed
Uninstall and reinstall the service so the plist is regenerated with the new arguments:
Development
Run the checks before committing changes:
After changing the binary for an installed service:
See DESIGN.md for implementation details.