The Mac Sleeps Only After the AI Stops — This Open-Source Tool Nails Keep-Awake
- Adrafinil is a macOS menu-bar tool that blocks sleep only while an AI coding Agent (Claude Code, Cursor, etc.) is actively running a task. Once the Agent stops, it instantly restores normal sleep behavior — including lid-closed (clamshell) sleep.
- Supports 9 mainstream Agents, automatically calling acquire / release through each one's Hook system, with CLI round-trip latency under 50ms.
- For concurrent Agents it uses reference counting: each session does its own +1 / −1, and keep-awake lifts only when the count hits zero — the Mac sleeps only after the last task ends.
- Built-in thermal protection: when skin / CPU temperature crosses a threshold, it force-releases every keep-awake assertion to avoid cooking the machine when closed-lid cooling can't cope.
- The architecture splits into three privilege tiers; root is confined to the smallest Helper component, which exposes just one boolean interface, setSleepBlocked(Bool) — all other logic runs in user space.
You Close the Lid and Sleep — the Agent Keeps Running
Open-source developer kageroumado recently released Adrafinil, a macOS menu-bar tool that blocks sleep only while an AI coding Agent is actively working, then automatically restores normal sleep once the Agent stops.
3 a.m. — you're asleep, the Agent isn't. It's still churning away in the session you started hours ago, and you closed the laptop lid the way you'd close your eyelids — except this eye never truly shut. That's the conflict: the Agent's task cycle and the Mac's sleep policy have no idea what the other is doing. Close the lid, the system sleeps on schedule, and the task snaps off halfway.
The name itself is the design spec. Adrafinil borrows from a eugeroic (a wakefulness-promoting drug). Unlike a stimulant, a eugeroic perks you up only when needed and stays out of the way otherwise — exactly what separates it from "always awake" tools like caffeinate: it keeps awake only when there's work to do.
Why the Old Approaches Fall Short
Before Adrafinil, keeping a Mac awake for a long task left you only two extremes — and neither lined up with the window when the task is actually running.
caffeinate and Amphetamine are the stimulant approach: switch them on and the machine stays awake the whole time, work or no work. The task finishes early and the machine idles on, burning power and heat. The flip side: install nothing, close the lid, and it sleeps right away, cutting the long task off. Below, all three sit on one timeline — whether the keep-awake window aligns with the task window is clear at a glance.
caffeinate's keep-awake bar is lit from start to finish — that long stretch after the task ends is pure waste; the "install nothing" row has a red X at the lid-close point, severed before the task is done. Only adrafinil's lit bar hugs the task window exactly, not a second extra on either side.
Breathing in Step with the Agent
Adrafinil's core is simple: when the Agent starts working it requests keep-awake; when it stops, it releases. The Mac stays awake only for the stretch the Agent is actually running a task. The menu-bar icon has just these two states.


The Agent doesn't talk to Adrafinil directly — it calls Adrafinil's bundled command line through its own Hook system:
Take Claude Code as an example — the full signal chain flows like this:
The key: it holds for the "actively working" stretch, not the "program is open" stretch. Claude Code calls acquire on UserPromptSubmit and release on Stop, so a session that's open but parked at the prompt waiting for you to type lets the Mac sleep normally. This is activity-scoped keep-awake, as opposed to session-scoped.
The direct payoff for developers: you can close the lid and walk away with confidence, letting the Agent run builds, tests, and deploys; the moment the task ends, the Mac restores sleep on its own — no remembering to turn caffeinate off, no worrying you forgot and left it idling forever.
Run Several at Once Without the Mess
What about several Agents running together? Adrafinil uses reference counting: +1 when each session starts, −1 when it ends, and keep-awake lifts only when the count reaches zero.
The office lights go off only when the last person leaves — not whenever just anyone heads out. Any single task ending in between never hurts the others still running.
The counter ring below is the centerpiece of this whole page. Try lighting up a few Agents: as long as the number in the ring is greater than 0, the Mac stays awake (blue pulse); switch them off one by one, and the instant the count hits zero, the ring goes gray and the Mac can finally sleep.
Click to start / stop any Agent. The number in the ring = sessions currently holding keep-awake; only zero lifts it.
Closed Lid, No Cooked Machine
Running long tasks with the lid closed, the real fear is shoving it in a bag where cooling can't keep up and the machine bakes. Adrafinil has built-in thermal protection — the key safety net that makes closing the lid and leaving feel safe.
Beyond temperature, there's a second auto-release: if the process holding an assertion has already died, or the CPU has been idle for more than N minutes, the matching keep-awake is dropped automatically — plugging the "program crashed but keep-awake never withdrew" hole.
With the lid closed the screen is off and can't pop a notification, so it confirms keep-awake took effect with a chime; when you reopen the lid it hands you a summary: what ran while you were away, the peak temperature, and whether thermal protection ever fired.
Process sniffing (optional)
Even without Hooks installed, the Daemon can auto-acquire when it spots a known Agent program running. This is optional — a fallback for cases where configuring Hooks isn't convenient.
Root Does Exactly One Thing
Blocking lid-closed sleep can't sidestep root privileges — that's a hard macOS rule. Adrafinil's move is to shrink root's footprint to the bare minimum.
First, why root is unavoidable. The Mac has two kinds of sleep-prevention: blocking "idle sleep" needs only an ordinary API (IOPMAssertion); but blocking "clamshell sleep" (lid-closed) requires the root-level pmset disablesleep. Adrafinil does both, so it can hold up while running tasks with the lid closed.
An ordinary employee can extend the office lights' timer (idle sleep), but unlocking the whole building's access control so no one gets trapped (clamshell sleep) takes admin privileges.
Its fix is to lock that bit of root into the smallest possible box. The whole architecture is three tiers, read top to bottom:
All policy lives in user space. Reference counting, thermal monitoring, process monitoring, and the CLI socket all run in the unprivileged Daemon; the only root-running Helper exposes a single state-changing interface, setSleepBlocked(Bool), responsible solely for flipping that final switch. Auditing this code? Far less of it to read.
LaunchAgent vs LaunchDaemon, and pmset's side effects
A LaunchAgent starts after the user logs in, running as that user; a LaunchDaemon starts at boot, running as root. Adrafinil deliberately makes the Daemon a LaunchAgent (user privileges) and only the minimal Helper a LaunchDaemon (root), shrinking the privileged surface.
Two more engineering notes: public IOPM assertions (the very set caffeinate uses) simply can't stop clamshell sleep, so v1 went with the blunter pmset disablesleep 1, which disables idle sleep along with it and must be cleared at shutdown or it leaks — so on restart the Helper first resets the state to disablesleep 0 and then re-applies it.
Which 9 It Supports, and How to Set It Up
One command writes the Hook into every Agent's config. First, the support list:
Install It
Download the signed and notarized dmg, open it, drag it into Applications, and launch. The first launch asks once for admin privileges to register that privileged Helper. After that, a single install-hooks command writes the Hook config into all the Agents above; when you're done with it, uninstall-hooks clears out every Hook entry it added.
System Requirements
macOS Tahoe 26.4 or later (earlier 26.x may work, but the author hasn't tested it). Building it yourself needs Xcode 26 or later with Swift 6 strict concurrency enabled. A non-admin install puts the CLI in ~/.local/bin instead of /usr/local/bin.
Two More Commands Worth Knowing
For background tasks that outlive the reply (a single long build or deploy), you can use the timed hold command to hold on for a while and auto-release when time's up; Agents with MCP support can also call the tools provided by adrafinil mcp directly:
Adrafinil only intervenes when an agent (Claude Code, Codex, Cursor, …) is mid-task, and gets out of the way the moment that work finishes. kageroumado · adrafinil README(GitHub)