Problem
You need to run a program (like icalBuddy) which requires access to protected macOS resources like your Calendar, Reminders, or Contacts. When you run it from the terminal, you are prompted as usual and grant access. Later, you try to run that program via some other process and nothing happens or you get some obtuse error.
In my case, I was trying to run icalBuddy to pull my calendar appointments into Obsidian, following Ben’s example. Worked great from the command line but not so much from within Obsidian. The problem, as it turns out, is that the privacy grant applies to the “top most app” which launches the process, in this case iTerm.app
, and there’s no way to manually grant access directly to icalBuddy or Obsidian.
Solution
After struggling to find a working solution via lots and lots of github reports of similar problems, I finally found a working solution in this comment. I’m writing up here my full solution here as I’m sure I won’t be the last to run into this.
In simple terms, we create an Automator application which simply runs the program we need with whatever arguments we like. We can even pass extra arguments on the command line. The program is saved as a .app
and when executed, the privacy prompts are opened and the grants assigned to our new .app
.
1. Open /System/Applications/Automator.app and create a new Application:
2. Search for ‘Run Shell Script’ and drag it into the workflow area:
3. Change the pass input setting and add script:
Here’s the script for easier copying:
rm -f /tmp/getCalEvents.out /usr/local/bin/icalBuddy -npn -nc -ps "/: /" -iep "datetime,title" \ -po "datetime, title" -b "\n\n### " \ -tf "%H%M" -ic "$1" \ eventsToday 2>&1 >>/tmp/getCalEvents.out
4. Save the application somewhere, e.g., ~/bin/getCalEvents.app
and run it once. You should get the privacy prompts as usual which results in the following access grant:
5. Finally, to integrate it into our application, we create another small wrapper which opens the app and returns the output from the tmp file:
#!/bin/bash rm -f /tmp/getCalEvents.out open --wait-apps $HOME/bin/getCalEvents.app --args Calendar cat /tmp/getCalEvents.out
Save that script to, e.g., ~/bin/getCalEvents
and call it from your application.