macOS permissions

ParrotFlow asks for Microphone, Accessibility and Input Monitoring. What each one is for, what works without it, and how to check or reset a grant.

ParrotFlow asks for three macOS permissions. Only you can grant them, by clicking in the prompt or in System Settings.

Permission Needed for When it is asked
Microphone Dictation. Required. At first launch
Accessibility Typing the text into the app you use, spoken corrections, and telling a shortcut from a dictation During setup
Input Monitoring The keyboard shortcuts on the pill’s buttons The first time the pill offers a button

Microphone

Dictation needs the microphone. macOS asks at first launch. If you said no, turn it on in System Settings → Privacy & Security → Microphone.

Accessibility

ParrotFlow uses Accessibility for three things.

  • It types the transcript into the app you are using. This is insert_mode: paste, the default.
  • It reads your selection for spoken corrections and for “hey parrot” commands.
  • It watches for a key or a click while you hold a bare modifier hotkey, such as Right Command. This is how it tells ⌘S from a dictation. Without Accessibility, it only notices a second modifier.

To open the right pane in System Settings:

open "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"

Use the clipboard instead

If you do not want to grant Accessibility, ParrotFlow can copy the text instead of typing it. You press ⌘V yourself.

transcription:
  insert_mode: clipboard

Dictation works the same. Fixing a word by voice and “hey parrot” commands do not work, because both need to read the text you selected. You can grant Accessibility later without reinstalling.

Input Monitoring

After a dictation, the pill can show buttons, for example V for Vocabulary or a transform with offer: true and a key:. The pill never takes focus. To catch the letter before it reaches the app you were typing in, ParrotFlow needs a system-wide key tap, and macOS gates that with Input Monitoring.

Without it, the buttons still show and still work with the mouse. The letter types into your document instead. ParrotFlow asks for it the first time the pill shows a button.

Choosing a pipeline step by app does not need any extra permission. ParrotFlow reads the frontmost app from NSWorkspace.

Check a permission

--check-config reports the microphone:

/Applications/ParrotFlow.app/Contents/MacOS/ParrotFlow --check-config

You want ✓ microphone Granted.

It cannot report Accessibility. macOS credits a check made from a terminal to the terminal, not to ParrotFlow, so it reads as missing even when it is granted. The app checks it at launch and writes the result to its log. Restart the app, then read the last launch line:

pkill -f "ParrotFlow.app/Contents/MacOS/ParrotFlow"; sleep 1
open -a ParrotFlow; sleep 3
grep "launched —" ~/Library/Logs/ParrotFlow.log | tail -1

You want accessibility=Granted. Not granted means the switch is off, or a different app was ticked.

Reset a permission

Sometimes System Settings shows ParrotFlow as ticked and the app still says the permission is missing. Turning the switch off and on does not fix it. It reuses the same broken record. Reset the record instead:

tccutil reset Accessibility com.parrotflow.app
tccutil reset Microphone com.parrotflow.app

Then restart ParrotFlow and grant the permissions again.

Updates keep your grants

macOS ties a grant to the app’s code signature, not to its path. Releases are signed with the same Developer ID, so an update keeps your grants.

Releases up to v0.9.0 used a different certificate. Moving from one of those to a newer release asks for Microphone and Accessibility once more. See Install.

If you build from source

A build with an ad-hoc signature gets a new identity on every build, so macOS forgets the grants each time. Create a self-signed certificate once, then install:

make dev-certificate    # asks for your password
make install

Grant the permissions after that install. If a grant is already stuck, make reset-permissions deletes the record. The dev build is a separate app, so this never touches the grants of the released app.

The full reference is permissions.md on GitHub.