feat: add macOS microphone permission for voice mode#2122
Conversation
Add the audio-input entitlement, NSMicrophoneUsageDescription in Info.plist, and request microphone access on startup so that Claude Code's /voice command works inside Emdash on macOS.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6748462. Configure here.
Greptile SummaryThis PR enables macOS microphone access for voice mode. The main changes are:
Confidence Score: 4/5This is close, but the denied-permission path should be fixed before merging.
apps/emdash-desktop/src/main/index.ts
|
| Filename | Overview |
|---|---|
| apps/emdash-desktop/build/entitlements.mac.plist | Adds the macOS audio-input entitlement needed for microphone access. |
| apps/emdash-desktop/electron-builder.config.ts | Adds the production macOS microphone usage description. |
| apps/emdash-desktop/electron-builder.canary.config.ts | Adds the canary macOS microphone usage description. |
| apps/emdash-desktop/src/main/index.ts | Adds the macOS startup microphone permission request and logs the result. |
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
apps/emdash-desktop/src/main/index.ts:183-188
**Denied state stays silent**
When macOS has microphone access already set to denied, `askForMediaAccess('microphone')` will not show another permission dialog and resolves `false` immediately. This branch records that result only in the app log, so a user who previously declined access still gets no visible instruction to re-enable Emdash in System Settings. Voice mode can continue to fail with no actionable feedback. Handle the explicit denied status before requesting access and surface a user-visible warning or recovery path.
Reviews (2): Last reviewed commit: "merge: resolve main conflicts for macOS ..." | Re-trigger Greptile
| if (process.platform === 'darwin') { | ||
| if (systemPreferences.getMediaAccessStatus('microphone') !== 'granted') { | ||
| systemPreferences.askForMediaAccess('microphone').catch((e) => { | ||
| log.warn('Failed to request microphone access:', e); | ||
| }); | ||
| } | ||
| } |
There was a problem hiding this comment.
Denied status silently suppressed with no user feedback
When getMediaAccessStatus returns 'denied', askForMediaAccess is still called but macOS will not show a dialog — it resolves immediately to false with no UI. Users who accidentally declined the prompt will have no indication that they need to visit System Settings → Privacy & Security → Microphone to re-enable access; voice mode will simply fail silently. Adding a branch for the 'denied' case to log a warning or (on first detection) show a notification would surface the issue to the user.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/main/index.ts
Line: 144-150
Comment:
**Denied status silently suppressed with no user feedback**
When `getMediaAccessStatus` returns `'denied'`, `askForMediaAccess` is still called but macOS will not show a dialog — it resolves immediately to `false` with no UI. Users who accidentally declined the prompt will have no indication that they need to visit System Settings → Privacy & Security → Microphone to re-enable access; voice mode will simply fail silently. Adding a branch for the `'denied'` case to log a warning or (on first detection) show a notification would surface the issue to the user.
How can I resolve this? If you propose a fix, please make it concise.Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
| if (systemPreferences.getMediaAccessStatus('microphone') !== 'granted') { | ||
| systemPreferences | ||
| .askForMediaAccess('microphone') | ||
| .then((granted) => { | ||
| log.info('Microphone access request resolved:', { granted }); | ||
| }) |
There was a problem hiding this comment.
Denied state stays silent
When macOS has microphone access already set to denied, askForMediaAccess('microphone') will not show another permission dialog and resolves false immediately. This branch records that result only in the app log, so a user who previously declined access still gets no visible instruction to re-enable Emdash in System Settings. Voice mode can continue to fail with no actionable feedback. Handle the explicit denied status before requesting access and surface a user-visible warning or recovery path.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/emdash-desktop/src/main/index.ts
Line: 183-188
Comment:
**Denied state stays silent**
When macOS has microphone access already set to denied, `askForMediaAccess('microphone')` will not show another permission dialog and resolves `false` immediately. This branch records that result only in the app log, so a user who previously declined access still gets no visible instruction to re-enable Emdash in System Settings. Voice mode can continue to fail with no actionable feedback. Handle the explicit denied status before requesting access and surface a user-visible warning or recovery path.
How can I resolve this? If you propose a fix, please make it concise.
Summary
com.apple.security.device.audio-inputentitlement tobuild/entitlements.mac.plist(required for hardened runtime)NSMicrophoneUsageDescriptionto Info.plist viaextendInfoinelectron-builder.config.ts(required for macOS to show the permission prompt)systemPreferences.askForMediaAccess('microphone')insrc/main/index.tsThis enables Claude Code's
/voicecommand to work inside Emdash on macOS. Without these changes, macOS silently denies microphone access to child processes (PTY sessions) and the app never appears in System Settings → Privacy & Security → Microphone.Test plan
/voicein a Claude Code session and verify audio is detectedNote
Medium Risk
Moderate risk because it changes macOS app signing/entitlements and introduces a permission prompt at startup, which can affect notarization and user startup flow.
Overview
Enables macOS microphone access for voice features by adding the
com.apple.security.device.audio-inputentitlement and injectingNSMicrophoneUsageDescriptioninto the app’s Info.plist viaelectron-builderconfig.On macOS startup, the main process now checks
systemPreferences.getMediaAccessStatus('microphone')and callsaskForMediaAccess('microphone')when not yet granted, logging the result.Reviewed by Cursor Bugbot for commit d8a629b. Bugbot is set up for automated code reviews on this repo. Configure here.