2

I want to open a GUI application (most likely Electron based) periodically on a Mac Book. The period will be configured (daily, hourly etc..) within the application. How would I go about achieving this?

3 Answers 3

3

There are numerous approaches you can take.

launchd or Third Party Launcher

You can use tools like macOS's built-in launchd or third party tools like Power Manager (which I wrote, so feel free to ask me questions about its use):

DssW Power Manager on macOS

Power Manager includes a task covering How to Schedule an Application to Launch on Mac OS X.

Prefer launchd over cron

You probably want to avoid cron because it does not operate in the current user's graphical session. cron is good for command line tools and scripts, but less well suited to graphical Mac applications.

As gidds comments below, this limitation can be worked around using the reattach-to-user-namespace tool.

AppleScript and Calendar

A simple AppleScript application combined with a calendar event's Open File as an alarm may be enough. The AppleScript snippet below will open a specified application and bring it to the front:

tell application "My Electron Application" to activate

These related questions go into specifics:

2
  • Commands launched from cron can get access to the current user's graphical session using the reattach-to-user-namespace command, available in e.g. HomeBrew.
    – gidds
    Jul 25, 2022 at 19:09
  • 1
    It still works for me on macOS 12.4.
    – gidds
    Jul 26, 2022 at 7:38
2

How about an old school bash script, called by .bash_profile and .bashrc?

i.e. in your .bash_profile/.bashrc you can have:

# ...
bash /home/<user>/run.sh &

And in your run.sh you can sleep in a loop and activate the app.

1

Launchd .plist file

You can create a plist file that will describe the job to be carried out by launchd at intervals you can define in the plist. There's some terminology that is easiest to learn by just reading another plist file, such as the one I've written below.

Once you've done that, you can move the plist file into ~/Library/LaunchAgents, which will run the job under your username.

Finally, get the launchd daemon to load your configuration file, which will start the job:

launchctl load chri.sk.launchd.plist

From then on, the job specified in the plist file will be carried out at the defined intervals, and will continue being carried out forever, or until you unload it:

launchctl unload chri.sk.launchd.plist

It will launch automatically on every system reboot.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>chri.sk.launchd</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/open</string>
        <string>-a</string>
        <string>TextEdit</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <false/>
    <key>Nice</key>
    <integer>1</integer>
    <key>StartInterval</key>
    <integer>60</integer>
    <key>StandardErrorPath</key>
    <string>/Users/CK/Documents/launchd.err.txt</string>
    <key>StandardOutPath</key>
    <string>/dev/null</string>
</dict>
</plist>

This opens up TextEdit every 60 seconds. Here's a pretty useful guide on defining intervals.

Any errors are written to the file path specified by StandardErrorPath.

Make the filename and the label value the same. Apple's naming convention recommends using a reverse hostname identifier, but in the absence of a domain name that belongs to you, you could simply use something like surname.firstname.jobtitle.

The launchd.plist man page defines all the property list keys and explains what they each do. Go to Terminal and type man launchd.plist.

AppleScript

property hour : 3600
property day : 86400
property RunEvery : day
property AppName : "An Application"

on run
    idle
end run

on idle
    tell application named AppName to activate
    return RunEvery
end idle

on quit
    continue quit
end quit

If you save this AppleScript as a stay-open application, and then run it, it will stay open and run the idle commands every day. Currently, to stop this script from continuing, you'd have to terminate it from the dock or Activity Monitor.

4
  • The StartInterval setting in the plist file will be ignored since setting KeepAlive to true causes launchd to continuously run the program. (Each time the program exits it launched it again.)
    – nmgeek
    Jun 19, 2022 at 20:18
  • @nmgeek Although this was back in 2018, I remember testing the .plist file to make sure it did what I was expecting. Are you implying that the StartInterval key can be taken out completely and, provided that the KeepAlive flag is on, there would be no observable difference in how the .plist performs ? If that’s true, what dictates the regular execution of the shell code it contains, which at present would execute every 60 seconds ? KeepAlive doesn’t, as far as I know, doesn’t monitor time. Or have I got this wrong ?
    – CJK
    Jun 29, 2022 at 3:50
  • I did not test this with KeepAlive set to true. So I'm not sure it is waiting 60 seconds before relaunching the program. KeepAlive is telling launchd to immediately rerun the program after the program exits. As such, the timing depends upon how long the program takes to run. If the program runs too quickly, launchd will apply throttling, waiting before relaunching. The throttling delay is 10 seconds. So if your program was running every 60 seconds, it must have taken 60 seconds until it exited.
    – nmgeek
    Jul 21, 2022 at 21:31
  • @nmgeek I've amended the example XML in the above answer. Thanks for highlighting this.
    – CJK
    Jul 25, 2022 at 12:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .