Skip to main content
Pomeroy asks macOS for five permissions, and asks you directly for one file. This page is all of them. It also names two grants Pomeroy will never ask for, for any reason: Accessibility and Screen Recording. That second list is the point of this page. A permission an app does not hold is the only kind of restriction a buyer can check for themselves, in five seconds, in System Settings. Everything else is a promise. This page is the sibling of what leaves your Mac. That one is about egress: which requests go out and what is in them. This one is about the grants Pomeroy holds on the Mac itself. Neither is a summary of the other, and both are checked against the code by tests rather than trusted (ADR-0008, ADR-0011).

What Pomeroy will never ask for

No Swift source in app/ may name any of those symbols. A test reads every file under src/app/Sources and fails if one appears, and the same test fails if this table and that list stop matching, in either direction. There are zero such references today, so nothing here is a plan to remove something: it is a gate in front of a future change.

Why the refusal binds the grant, not the use

The obvious middle position is to hold Accessibility but only read with it: report what is on screen, never click. Pomeroy does not do this, because the Accessibility grant is binary. macOS draws no line between reading the interface tree and posting input into it. A process holding the grant to call read_text can post a click into a banking app, and nothing in the operating system stands in the way. So “read-only Accessibility” is a restriction Pomeroy would impose on itself, and a buyer would have to take on trust. Refusing the grant is a restriction macOS imposes, and a buyer can confirm it: Pomeroy does not appear in System Settings → Privacy & Security → Accessibility, because it never asks. This costs real features, and they are declined on purpose: knowing which window is frontmost, attaching a screenshot to a support report, reading the text you have selected in an app that publishes nothing. See ADR-0011 for the full argument.

What Pomeroy does instead

Pomeroy reaches an app only through a published interface: the automation surface the app itself offers. EventKit for Calendar and Reminders, the Contacts framework for Contacts, Apple events for Mail, Notes and Shortcuts, MapKit for Maps. Messages is the odd one out and gets its own section below. An app with no published interface is reached by a Shortcut you built. You make it in the Shortcuts app, you decide what it does, and Pomeroy runs it by the exact name you ask for. Pomeroy cannot create a shortcut, cannot edit one, and cannot run one you have not already made.

The permissions Pomeroy does ask for

Each one is requested by the setup wizard, at the moment you switch the matching app on, and never before (ADR-0003). Switching an app off leaves the grant in place: macOS owns it, and you take it back in System Settings. Every key in that table is in the app’s Info.plist, and every usage description in the Info.plist is in that table. Adding a sixth without adding a row here fails the test, and so does promising a grant the app does not declare. Automation is not one switch. macOS asks separately for each app Pomeroy sends an Apple event to, so approving Mail says nothing about Notes. Maps and Weather have no prompt of their own: MapKit and WeatherKit answer any app that asks, and switching those toggles on records your intent, which is the whole gate those tools have (ADR-0003).

The entitlements that go with them

TCC consent stopped being sufficient on macOS 26: EventKit denies events without a matching entitlement even after you agree to the prompt. Grants and entitlements are two gates, and Pomeroy declares only these five. This table is checked against Pomeroy.entitlements in both directions too. Four of the five are granted by the entitlement alone. The WeatherKit one is different: declaring it only claims it, and Apple’s servers check the claim against the signature. A signed release carries the authorization as a provisioning profile inside the bundle (Contents/embedded.provisionprofile), issued to this bundle identifier and this team. Nothing on your Mac is opened by it, and it grants Pomeroy no access to anything here. It is the reason Apple answers the one request weather-data.apple.com in what leaves your Mac describes.

Messages, and why Full Disk Access is not here

Messages is the one app whose grant is not a prompt, and it is the clearest case of the same principle. Your messages live in one SQLite file, ~/Library/Messages/chat.db, which macOS guards behind Full Disk Access. Full Disk Access would work and is refused. It is one switch that hands Pomeroy every file on the Mac, including your mail, your browser history and your backups, in order to read one database. Nothing in the app, the wizard or these docs asks for it (ADR-0005). Instead, switching Messages on opens a standard file dialog at ~/Library/Messages with chat.db already selected and every other file greyed out. You hand over that one file. What Pomeroy keeps is a security-scoped bookmark to it, minted read-only with securityScopeAllowOnlyReadAccess, and every read opens the database with mode=ro. Pomeroy holds no grant over any other file on your Mac, so there is nothing else it could read even if it tried. The grant is proved rather than remembered: the wizard resolves the bookmark and opens the file each time it reports status. A stored “granted” flag would outlive a file the app can no longer read.

The local address, and why macOS asks nothing for it

Pomeroy has a local address an assistant can connect to, off until you switch it on, and it is the one part of the app that opens a listening port. It is mentioned here because the reasonable expectation is that macOS would ask for something, and it does not. There is no entitlement to add and no prompt to expect. Accepting incoming TCP connections is not a Local Network operation on any interface, so macOS asks for nothing when a non-sandboxed app opens a port. That is a fact about macOS rather than a permission Pomeroy declined, which is why there is no row for it in either table above: those tables are what Pomeroy asks macOS for, and this is not one of them. The consequence is worth being blunt about, because it is the reason the address is guarded the way it is. macOS will not tell Pomeroy who connected. A connection over the local address carries no process id, no code signature and no identity of any kind, so there is nothing for Pomeroy to check a caller against. Whatever credential you choose for the address is therefore the whole boundary, not one check among several. That is ADR-0016 and ADR-0017, and what the address does and does not reach is in what can reach Pomeroy. There is one refusal here even so, and it takes the shape this page prefers: the listener binds this Mac only and refuses every other interface, held by a test rather than by a promise (ADR-0014). It is not in the table above because that table is a list of macOS grants, and a bind address is not one.

Reading this against the code

Every claim above is checked by permissionsDiscipline.test.ts, which needs only a checkout: no macOS, no build, no app process. It runs in the bridge’s plain unit suite with the egress pledge’s test beside it, so both pledges are held by the same gate on every pull request. The sources it reads are Info.plist, Pomeroy.entitlements, MessagesDatabaseBookmark.swift and every Swift file under src/app/Sources.