Keep the screen awake while script (app) running


I assumed that the following script, run as a stay-open application, would keep the screen and computer awake, but for some reason they fall asleep after the 1st minute (setting in the system power settings).

Apparently I missed something? Or is the caffeinate utility no longer working? It’s like a built-in Mac OSX utility. I have Catalina.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

on run
	addObserver("screensDidSleepNotification:", "NSWorkspaceScreensDidSleepNotification")
	-- addObserver("workspaceWillSleepNotification:", "NSWorkspaceWillSleepNotification")
end run

on addObserver(selectorHandler, notificationName)
	set aCenter to current application's NSWorkspace's sharedWorkspace()'s notificationCenter()
	aCenter's addObserver:me selector:selectorHandler |name|:notificationName object:(missing value)
end addObserver

on workspaceWillSleepNotification:aNotif
	do shell script "caffeinate -u -t 60"
end workspaceWillSleepNotification:

on screensDidSleepNotification:aNotif
	do shell script "caffeinate -u -t 60"
end screensDidSleepNotification:

I found 2 problems:

  1. caffeinate as part of the script works, but only in a special way,
  2. NSWorkspace does not catch system notifications about falling asleep on the workspace and screens (“NSWorkspaceScreensDidSleepNotification” and “NSWorkspaceWillSleepNotification”.

The problem is that there is no information on the web about this (in connection with AppleScript) at all. In short, the 2nd problem is unsolvable, the observer is useless and I abandoned it altogether.

The following script works as it should. It should be tested as an usual application for the purity of the experiment, but you can use this trick in any other forms as well. The caffeinate time should be setted bigger than the app or script execution time (you can set 3600, a hour, for example):

do shell script "caffeinate -u -t 180 > /dev/null 2>&1 &" -- 3 minutes to not sleep

repeat 2 times -- test, 2 min to execute  (setting for disply sleep = 1 min in Power Manager)
	delay 60
end repeat

One cleaner script should kilall the caffeinate process at the end of script.

The point of this test is that without the 1st line of code, the screen would go to sleep about a 1 minute after the application was launched. And so it does not fall asleep, while the application is executed for about 2 minutes.

Other approach is using pmset command to set/reset the displaysleep time, but this requires the user password inserting.

Returning to the topic. Killing a caffeinate process after script stuff executed is very easy with the killall shell command:

do shell script "caffeinate -u -t 36000 > /dev/null 2>&1 &" -- big number, 10 hours to not sleep here

delay 5 -- do stuff like this

	do shell script "killall 'caffeinate'"
end try
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property theTask : missing value

my startPreventFromSleep()
delay 60 -- do what you want…
my stopPreventFromSleep()

on startPreventFromSleep()
	my stopPreventFromSleep()
	set theTask to current application's NSTask's new()
	theTask's setLaunchPath:"/bin/sh"
	theTask's setArguments:{"-c", "caffeinate -i"}
	theTask's |launch|()
end startPreventFromSleep

on stopPreventFromSleep()
	if theTask is not missing value then
		if (theTask's isRunning() as boolean) then
			theTask's terminate()
		end if
	end if
end stopPreventFromSleep

An very simple approach would be to use Hot Corners in Mission Control
If top-right corner is prevent the screen from sleep. You could set the mouse cursor x, y
in that corner and next run your script.

1 Like


it is useful info, but I want the “none sleep” state to terminate after script execution automatically. I can move and restore the mouse after script execution, but that requires Python or AsObjC. My solution is plain AppleScript.

You could use do shell script GitHub - BlueM/cliclick: macOS CLI tool for emulating mouse and keyboard events

The info is not correct. The default settings do not prevent the monitor from going off or the sleep mode. Not even when Mission Control is displayed (tested with Monterey and Ventura) and there is no setting for the corners that would indicate this. You can only disable the screen saver.

1 Like

I have tested this twice with or without *hot corners. If the mouse cursor is not in top-right corner (that is my configuration). It will dim the display after 1 minute and later go off or make brightness 0%. If I move the mouse cursor to top-right corner it will not dim the display after 1 minute.

I never said the default configuration was enough to do what the OP like, sorry if I was not clear on that.

My machine is Monterey 12.6.4

That may be, but by doing so you do not change the system’s energy saving settings (pmset) and prevent the display from being switched off at some point and the computer from going into sleep mode.
The script execution will be interrupted in the latter case and I think that’s what it’s all about.

My setup allow the screen to be off… but it doesn’t allow the computer to go to sleep when the screen is off. The reason I have this I have service I access from other computers or devices.

I also run VM’s and I do not like the host to go to sleep if a guest is running.