Skip to content

feat: add macOS microphone permission for voice mode#2122

Merged
rabanspiegel merged 4 commits into
mainfrom
emdash/voice-mode-ifx4t
Jul 7, 2026
Merged

feat: add macOS microphone permission for voice mode#2122
rabanspiegel merged 4 commits into
mainfrom
emdash/voice-mode-ifx4t

Conversation

@rabanspiegel

@rabanspiegel rabanspiegel commented May 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds com.apple.security.device.audio-input entitlement to build/entitlements.mac.plist (required for hardened runtime)
  • Adds NSMicrophoneUsageDescription to Info.plist via extendInfo in electron-builder.config.ts (required for macOS to show the permission prompt)
  • Requests microphone access on startup via systemPreferences.askForMediaAccess('microphone') in src/main/index.ts

This enables Claude Code's /voice command 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

  • Build a canary DMG and install it
  • On first launch, verify the macOS microphone permission dialog appears
  • Grant permission and confirm Emdash appears in System Settings → Microphone
  • Run /voice in a Claude Code session and verify audio is detected
  • On subsequent launches, verify the permission prompt does not re-appear

Note

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-input entitlement and injecting NSMicrophoneUsageDescription into the app’s Info.plist via electron-builder config.

On macOS startup, the main process now checks systemPreferences.getMediaAccessStatus('microphone') and calls askForMediaAccess('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.

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.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread apps/emdash-desktop/electron-builder.config.ts
@greptile-apps

greptile-apps Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR enables macOS microphone access for voice mode. The main changes are:

  • Adds the audio-input entitlement to the macOS signing plist.
  • Adds the microphone usage description to production and canary Electron Builder configs.
  • Requests microphone permission during macOS app startup.

Confidence Score: 4/5

This is close, but the denied-permission path should be fixed before merging.

  • The macOS packaging changes are mirrored across production and canary builds.
  • The startup permission request is guarded to macOS.
  • A user who already denied microphone access still gets no visible recovery guidance.

apps/emdash-desktop/src/main/index.ts

Important Files Changed

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

Comment on lines +144 to +150
if (process.platform === 'darwin') {
if (systemPreferences.getMediaAccessStatus('microphone') !== 'granted') {
systemPreferences.askForMediaAccess('microphone').catch((e) => {
log.warn('Failed to request microphone access:', e);
});
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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.

Comment thread src/main/index.ts Outdated
@rabanspiegel

Copy link
Copy Markdown
Contributor Author

@greptileai

Comment on lines +183 to +188
if (systemPreferences.getMediaAccessStatus('microphone') !== 'granted') {
systemPreferences
.askForMediaAccess('microphone')
.then((granted) => {
log.info('Microphone access request resolved:', { granted });
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

@rabanspiegel
rabanspiegel merged commit 7298bd7 into main Jul 7, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant