# OS integration permissions (TCC)

On macOS, access to Calendar, Reminders, Mail, and Notes is gated by Transparency, Consent and Control (TCC), the system behind the "allow access" dialogs. A spawned command-line helper needs a few extra details to work with TCC where a plain command would silently fail. See [OS integration internals](/docs/under-the-hood/os-integration-internals/) for how a request reaches these helpers in the first place.

## Embedded Info.plist

Each helper embeds its own `Info.plist` directly into its binary, so the usage-description text you see in a permission dialog and the app's identity travel with the helper across the process boundary. This matters on macOS 14 and later: without an embedded `NSCalendarsFullAccessUsageDescription`, a request for calendar access is rejected with no dialog at all, rather than asking you. Each helper also has its own identifier, for example `pl.speedwave.desktop.calendar`.

## TCC service mapping

The system permission behind each integration is not always named after the app. Mail and Notes are driven through Apple Events rather than a dedicated framework, so both fall under the same `AppleEvents` permission:

| Integration | TCC service |
| --- | --- |
| Calendar | `Calendar` |
| Reminders | `Reminders` |
| Mail | `AppleEvents` |
| Notes | `AppleEvents` |

## Unified permission gate

One orchestrator routes both EventKit and Apple Events permission checks through a single status model, so Speedwave can report a consistent state regardless of which framework backs an integration. When the target app, Mail or Notes, is not currently running, macOS reports that instead of a permission error, and Speedwave tells you to open the app rather than suggesting a permission reset.
**Caution:** A granted permission does not guarantee the data is actually readable, so Speedwave runs a second check that reads real data before treating an integration as working.

## Startup reconciliation

At every launch, Speedwave checks each OS integration you have toggled on against its current macOS permission and turns off any toggle whose permission is no longer granted. Which integrations are available to toggle at all is controlled in [Beta features](/docs/guides/beta-features/).