You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace the demo with an SVG animation and cut the SketchyBar docs (#3)
* Replace the demo GIFs with an SVG animation
A single looping SMIL animation shows the hijack side by side: without
MicGuard the input stays on AirPods, with MicGuard it snaps back to the
preferred mic. One small vector file replaces the GIF/MP4 media and
renders in both the README and the docs site.
* Remove the SketchyBar integration docs
The step-by-step SketchyBar walkthrough drowned out the actual
integration surface. The integrations page now documents just the
building blocks (notifications, ping-on-start, CLI commands, health
check); building a specific status-bar plugin is left to the reader.
* Drop the screenshots section
The animated demo covers what the static screenshots showed; the
menubar and settings UI are simple enough to not need a gallery.
---------
Co-authored-by: Przemysław Szypowicz <2733699+pszypowicz@users.noreply.github.com>
<imgsrc="docs/images/how-it-works.svg"width="830"alt="Side-by-side animation: without MicGuard the input stays hijacked by AirPods; with MicGuard it snaps back to the preferred microphone">
60
47
</p>
61
48
62
49
## Modes
@@ -73,7 +60,7 @@ Always reverts to your chosen preferred device, no matter when or why the switch
73
60
74
61
## Documentation
75
62
76
-
See the full docs at **[pszypowicz.github.io/MicGuard](https://pszypowicz.github.io/MicGuard/)**— covering [CLI reference](https://pszypowicz.github.io/MicGuard/cli.html), [debugging](https://pszypowicz.github.io/MicGuard/debugging.html), [integrations](https://pszypowicz.github.io/MicGuard/integrations.html), [notifications](https://pszypowicz.github.io/MicGuard/notifications.html), and [releasing](https://pszypowicz.github.io/MicGuard/releasing.html).
63
+
See the full docs at **[pszypowicz.github.io/MicGuard](https://pszypowicz.github.io/MicGuard/)**- covering [CLI reference](https://pszypowicz.github.io/MicGuard/cli.html), [debugging](https://pszypowicz.github.io/MicGuard/debugging.html), [integrations](https://pszypowicz.github.io/MicGuard/integrations.html), [notifications](https://pszypowicz.github.io/MicGuard/notifications.html), and [releasing](https://pszypowicz.github.io/MicGuard/releasing.html).
Copy file name to clipboardExpand all lines: docs/cli.md
+14-14Lines changed: 14 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,21 +6,21 @@ title: CLI Reference
6
6
7
7
MicGuard doubles as a CLI tool. The `mic-guard` binary is symlinked to `/usr/local/bin` on install.
8
8
9
-
Commands perform direct work — CoreAudio calls for volume/mute, config file writes for set/enable/disable/toggle — and then post a `requestStatus` distributed notification so the daemon re-reads state and broadcasts `statusChanged`. The daemon is not required for the commands themselves to take effect, but without it no `statusChanged` notification will be broadcast to external integrations.
9
+
Commands perform direct work - CoreAudio calls for volume/mute, config file writes for set/enable/disable/toggle - and then post a `requestStatus` distributed notification so the daemon re-reads state and broadcasts `statusChanged`. The daemon is not required for the commands themselves to take effect, but without it no `statusChanged` notification will be broadcast to external integrations.
|`current`| Boolean |`true` if this is the active input device|
65
65
|`preferred`| Boolean |`true` if this is the configured preferred device |
66
-
|`volume`| Integer | Input volume 0–100 |
67
-
|`muted`| Boolean | Mute state |
66
+
|`volume`| Integer | Input volume 0–100|
67
+
|`muted`| Boolean | Mute state|
68
68
69
69
### `mic-guard current`
70
70
@@ -141,7 +141,7 @@ disabled
141
141
142
142
### `mic-guard ping`
143
143
144
-
Ask the running MicGuard daemon to re-broadcast its current status via a `com.pszypowicz.MicGuard.statusChanged` distributed notification. Useful for forcing external integrations (e.g. SketchyBar) to refresh.
144
+
Ask the running MicGuard daemon to re-broadcast its current status via a `com.pszypowicz.MicGuard.statusChanged` distributed notification. Useful for forcing external integrations to refresh.
Copy file name to clipboardExpand all lines: docs/debugging.md
+19-20Lines changed: 19 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,11 +4,10 @@ title: Debugging
4
4
5
5
# Debugging
6
6
7
-
MicGuard uses Apple's [unified logging system](https://developer.apple.com/documentation/os/logging) (`os.Logger`) with subsystem `com.pszypowicz.MicGuard`. This is the macOS equivalent of `journalctl` on Linux — all log messages go to a centralized system log store that you can query, stream, and filter.
7
+
MicGuard uses Apple's [unified logging system](https://developer.apple.com/documentation/os/logging) (`os.Logger`) with subsystem `com.pszypowicz.MicGuard`. This is the macOS equivalent of `journalctl` on Linux - all log messages go to a centralized system log store that you can query, stream, and filter.
|`debug`| Memory only, near-zero cost when not observed | Volume/mute changes, listener register/unregister, status notifications, "no action" decisions |
|`error`| Always persisted to disk | Failed listener registration, failed device set, failed config writes|
54
53
55
54
Debug messages are only captured when a consumer is attached (e.g. `log stream --level debug` or Console.app with debug enabled). This means high-frequency events like volume slider changes have near-zero overhead during normal operation.
56
55
57
56
## Duplicate CoreAudio callbacks
58
57
59
-
When a Bluetooth device connects or disconnects, CoreAudio fires `DEVICE_LIST_CHANGED` and `DEFAULT_INPUT_CHANGED` notifications multiple times — typically two or three times per event. This is normal macOS behavior (CoreAudio notifies once per internal phase of the Bluetooth negotiation) and not a MicGuard bug.
58
+
When a Bluetooth device connects or disconnects, CoreAudio fires `DEVICE_LIST_CHANGED` and `DEFAULT_INPUT_CHANGED` notifications multiple times - typically two or three times per event. This is normal macOS behavior (CoreAudio notifies once per internal phase of the Bluetooth negotiation) and not a MicGuard bug.
60
59
61
60
You will see duplicate log lines like:
62
61
@@ -65,7 +64,7 @@ DEVICE_LIST_CHANGED: added=["AirPods Pro 3 (Przemek)"] removed=[]
65
64
DEVICE_LIST_CHANGED: added=["AirPods Pro 3 (Przemek)"] removed=[]
66
65
```
67
66
68
-
The handlers are idempotent — the second call is harmless since the device was already added to the tracked set on the first call.
67
+
The handlers are idempotent - the second call is harmless since the device was already added to the tracked set on the first call.
69
68
70
69
## Running from the terminal
71
70
@@ -76,7 +75,7 @@ To run MicGuard directly from a terminal (useful during development):
MicGuard acquires an `fcntl` advisory lock on `~/.config/mic-guard/lock` at startup. If another instance is already running, the new process logs the existing PID and exits immediately. The lock is kernel-managed — it is released automatically when the process exits, crashes, or is killed (including `SIGKILL`). The lock file itself persists on disk but does not block the next launch; only an active file descriptor holding the lock does.
78
+
MicGuard acquires an `fcntl` advisory lock on `~/.config/mic-guard/lock` at startup. If another instance is already running, the new process logs the existing PID and exits immediately. The lock is kernel-managed - it is released automatically when the process exits, crashes, or is killed (including `SIGKILL`). The lock file itself persists on disk but does not block the next launch; only an active file descriptor holding the lock does.
80
79
81
80
Since MicGuard uses `os.Logger` instead of stderr, you won't see log output directly in the terminal. Use `log stream` in a separate terminal tab to observe the logs.
82
81
@@ -93,6 +92,7 @@ make dev
93
92
```
94
93
95
94
This:
95
+
96
96
1. Builds a release `.app` bundle (`scripts/bundle.sh`)
97
97
2. Adds `ProgramArguments` to the embedded LaunchAgent plist (launchd needs the absolute path; `SMAppService` resolves it automatically but raw `launchctl` doesn't)
98
98
3. Registers the LaunchAgent via `launchctl bootstrap`
@@ -108,25 +108,25 @@ This kills the daemon and unregisters the LaunchAgent from launchd.
108
108
109
109
### Why not Xcode debug?
110
110
111
-
When Xcode launches MicGuard directly, the binary runs outside of launchd's context — no LaunchAgent plist is loaded, so the Mach service isn't advertised. To test the daemon UI (menu bar, settings, CoreAudio listeners), Xcode debug works fine. To test XPC communication, use `make dev`.
111
+
When Xcode launches MicGuard directly, the binary runs outside of launchd's context - no LaunchAgent plist is loaded, so the Mach service isn't advertised. To test the daemon UI (menu bar, settings, CoreAudio listeners), Xcode debug works fine. To test XPC communication, use `make dev`.
0 commit comments