feat: AI feature toggles in menubar dropdown - #34
Open
mattthewong wants to merge 5 commits into
Open
Conversation
Add four checkbox menu items under an "AI Features" section in the menubar: AI post-processing, Prompt mode, Voice commands, and Context-aware formatting. Each toggle sends a bool on a Go channel following the same pattern as Play sounds and Auto-paste. Users can now enable/disable AI features at runtime from the menubar without restarting vox or editing config files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The menubar AI feature checkboxes (AI post-processing, prompt mode, voice commands, context-aware) were not connected to any consumer. Clicks silently dropped after filling the buffer-1 channels, checkboxes never visually toggled, and the toggles had no effect on runtime behavior. Changes: - Add AIPostProcess/PromptMode/VoiceCommands/ContextAware atomic.Bool fields to runtimeSettings - Seed them from flagClient at startup and sync checkbox UI state - Add 4 case arms in settingsWatcher: store atomic, update UI, persist to preferences.json via config.SavePref - Update pipeline stages (classifyStage, postProcessStage, promptModeStage, commandStage) to read settings.* instead of flagClient.* so menubar toggles control behavior at runtime - Add corresponding *bool fields to config.Prefs for persistence - Fix aiHeader NSMenuItem alloc without autorelease
alohaninja
previously approved these changes
May 13, 2026
alohaninja
left a comment
Collaborator
There was a problem hiding this comment.
What we fixed
- Dead channels / non-functional checkboxes — Added 4
casearms insettingsWatcher(cmd/vox/main.go) so the Go side actually drainsaiPostProcessCh,promptModeCh,voiceCommandsCh, andcontextAwareCh. Clicks now flow through to runtime settings and persist topreferences.json. - Checkboxes never visually toggled — Because
settingsWatchernow callsui.SetAIPostProcess(on)etc. on each toggle, the Obj-C round-trip completes andsetState:fires. Checkboxes reflect the actual state. - No startup sync — Added
ui.SetAIPostProcess(settings.AIPostProcess.Load())etc. afterui.Init(), seeded fromflagClient.*(). Checkboxes now show the correct initial state from LD flags / env vars / config. - No persistence — Added
AIPostProcess,PromptMode,VoiceCommands,ContextAware*boolfields toconfig.Prefs. Each toggle persists viaconfig.SavePrefon click, survives restarts. - No runtime effect — Updated all 4 pipeline stages (
classifyStage,postProcessStage,promptModeStage,commandStage) to readsettings.*atomic bools instead offlagClient.*(). Menubar toggles now actually enable/disable AI features at runtime. aiHeadermemory nit — Addedautoreleaseto theNSMenuItemalloc for the "AI Features" section header, matching the pattern used byshowLogItemandquitItem.
What we didn't fix
send()drops events on rapid toggling — The existingsend()helper uses a non-blockingdefaultbranch on buffer-1 channels. If the user clicks faster thansettingsWatchercan process (e.g., disk I/O inSavePref), intermediate clicks are silently dropped. This is a pre-existing design decision shared by all toggles (sounds, auto-paste, etc.) — not introduced by this PR. The last-written value is always correct; only intermediate transitions are lost.- Repetitive boilerplate — 4 identical channel/setter/callback/handler patterns across Go and Obj-C. A table-driven or generic approach could reduce this but would be a refactor beyond this PR's scope.
- No unit tests for
internal/ui/— The cgo/AppKit nature of this code makes it impractical to unit test without mocking the Cocoa runtime. Pre-existing gap, not worsened by this PR.
…tthewong/menubar-ai-toggles * origin/main: docs: align README with go auto-install fix: check for go in setup and install via Homebrew if missing readme: refresh with icon, pipeline flow diagram, and badges fix: prevent multiple vox instances with file lock fix: address review feedback — trigger lowercasing, per-token validation, duplicate detection feat: show command name and status in menubar Last: row fix(classify): treat punctuation as word boundary for Whisper transcription docs: add commands.yaml.example for user-configurable voice commands refactor(classify): remove deprecated package-level Classify function feat: wire user-configurable commands into pipeline feat(commandconfig): add ToCommand conversion and Merge logic feat(commandconfig): add YAML loading and validation for user-defined commands refactor(classify): add Classifier struct with configurable command prefixes refactor(classify): export PrefixEntry type and DefaultCommandPrefixes() # Conflicts: # cmd/vox/main.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Menubar Layout (after this PR)
Moonshot
Part of Moonshots XXIII: Vox 2.0 -- P2: AI Feature Toggles in Menubar
Test plan
make build+make lint+make test-shortall passmake start, verify AI Features section appears in menubar dropdown🤖 Generated with Claude Code