AIが止まって初めてMacを眠らせる、このOSSツールがスリープ防止を極めた
- Adrafinilはmacosのメニューバーツールで、AIコーディングAgent(Claude Code、Cursorなど)がタスクを実行している間だけMacのスリープを阻止し、Agentが止まると即座に通常のスリープ動作(クラムシェルスリープを含む)に戻す。
- 主要な9種類のAgentに対応、それぞれのHookシステムを通じてacquire / releaseを自動で呼び出し、CLIの往復レイテンシは50ms未満。
- 複数Agentが同時に動く場合は参照カウント方式を採用:各セッションがそれぞれ+1 / −1し、カウントがゼロになって初めてスリープ防止を解除、最後のタスクが終わってからMacを眠らせる。
- 内蔵の温度保護機能:表面温度 / CPU温度が閾値を超えるとすべてのスリープ防止アサーションを強制解放し、フタを閉じた状態での放熱不足による過熱を防ぐ。
- アーキテクチャは権限を3層に分割、root権限は最小のHelperコンポーネントだけに集中させ、setSleepBlocked(Bool)というブール値インターフェースを1つだけ公開、それ以外のロジックはすべてユーザー空間で動く。
あなたはフタを閉じて眠るが、Agentはまだ動いている
OSS開発者kageroumadoは先日Adrafinilを公開した。これはmacOSのメニューバーツールで、AIコーディングAgentが実際に動いている間だけMacのスリープを阻止し、Agentが停止すると自動的に通常のスリープに戻る。
深夜3時、あなたは眠ったが、Agentは眠っていない。数時間前に立ち上げたあのセッションの中でまだ動き続けているのに、あなたはまぶたを閉じるようにノートパソコンのフタを閉じる。しかしこの「目」は本当には閉じていない。矛盾はここにある:Agentのタスクサイクルと Macのスリープポリシーは互いに相手が何をしているか知らない。フタを閉じれば、システムはいつも通りスリープに入り、タスクは途中で断ち切られる。
名前そのものがこのツールの設計思想を物語っている。Adrafinilは覚醒維持薬(eugeroic)から借りた名前だ。興奮剤(stimulant)とは違い、覚醒維持薬は必要な時だけ覚醒を助け、不要な時は干渉しない——これこそがcaffeinateのような「常に覚醒」型ツールとの根本的な違いだ:仕事がある時だけスリープを防ぐ。
旧来の方法ではなぜ足りないのか
Adrafinil以前、Macに長時間タスクを実行させながら眠らせないようにするには、両極端な2つの選択肢しかなく、どちらも「タスクが実際に動いている」時間帯には正確に合わせられなかった。
caffeinateとAmphetamineは興奮剤タイプで、起動すればずっと覚醒状態のまま、仕事があるかどうかは関係ない。タスクがとっくに終わっていても、マシンは空転して電力を消費し発熱し続ける。逆に何もインストールしなければ、フタを閉じればすぐ眠り、長時間タスクはそこで中断される。以下では3つのケースを同じ時間軸上に並べてみる:スリープ防止のウィンドウとタスクのウィンドウが噛み合っているかどうか、一目で分かる。
caffeinateのスリープ防止バーは最初から最後まで点灯しっぱなしで、タスク終了後のあの長い区間は完全に無駄だ。何もインストールしていない行では、フタを閉じた箇所に赤いバツ印がつき、タスクが終わる前に打ち切られる。adrafinilのバーだけがタスクウィンドウにぴったり貼りつき、前後に1秒たりとも余分に維持しない。
Agentの「呼吸」に合わせる
Adrafinilのコアはシンプルだ:Agentが仕事を始めたらスリープ防止をリクエストし、手を止めたら解放する。MacはAgentが実際にタスクを実行している間だけ覚醒を保つ。メニューバーのアイコンもこの2状態しかない。


AgentはAdrafinilと直接会話するのではなく、それぞれのHookシステムを通じて付属のコマンドラインを呼び出す。
Claude Codeを例にすると、シグナルの流れ全体はこうなる:
ポイントは、防いでいるのが「実際に作業している」区間であって、「プログラムが開いている」区間ではないということだ。Claude CodeはUserPromptSubmitでacquireし、Stopでreleaseする。だから開いてはいるが入力欄で待機しているだけのセッションなら、Macは通常どおり眠る。これをアクティビティ範囲のスリープ防止(activity-scoped)と呼び、セッション単位のスリープ防止(session-scoped)とは区別される。
開発者にとっての直接的な効果はこうだ:安心してフタを閉じて離席し、Agentにビルド・テスト・デプロイを任せられる。タスクが終わればMacは自動でスリープに戻るので、caffeinateを手動で切るのを覚えておく必要もなく、切り忘れて電力を無駄にする心配もない。
複数同時実行でも混乱しない
複数のAgentが同時に動く場合はどうするのか?Adrafinilは参照カウントを使う:各セッションが開始すると+1、終了すると−1、カウントがゼロになって初めてスリープ防止を解除する。
オフィスで最後の1人が出るまで電気を消さない、誰かが帰るたびに消すわけではない、というのと同じだ。途中でどれか1つのタスクが終わっても、まだ動いている他のタスクを巻き込むことはない。
以下のカウントリングはこのページの目玉だ。いくつかAgentを試しに点灯させてみよう:リング内の数字が0より大きい限り、Macはスリープ防止状態になる(青いパルス)。1つずつオフにしていき、数字がゼロになった瞬間にリングはグレーに変わり、Macは本当に眠れるようになる。
クリックで任意のAgentを起動/停止。リング内の数字=現在スリープ防止を保持しているセッション数、ゼロになって初めてスリープ防止が解除される。
フタを閉じても熱暴走しない
フタを閉じたまま長時間タスクを走らせて一番怖いのは、バッグに入れたまま放熱が追いつかず、マシンを痛めてしまうことだ。Adrafinilには温度保護機能が内蔵されており、これこそが安心してフタを閉じて離席できる要のセーフティネットだ。
温度以外にも、もう1つ自動解放の仕組みがある:アサーションを保持しているプロセスが既に落ちている、あるいはCPUがN分以上アイドル状態が続いた場合、対応するスリープ防止は自動的に破棄され、「プログラムがクラッシュしたのにスリープ防止だけ残る」という抜け穴を塞ぐ。
フタを閉じた状態では画面が消えていて通知は出せないため、確認音を1つ鳴らしてスリープ防止が有効になったことを知らせる。再びフタを開けた時にはサマリーを表示する:離席中に何が動いていたか、最高温度は何度だったか、温度保護が発動したかどうか。
プロセス検知(オプション)
Hookを設定していなくても、Daemonは既知のAgentプログラムが動いていることを検知すると自動でacquireできる。これはオプション機能で、Hookを設定しづらい場面のための保険だ。
rootは1つのことしかしない
クラムシェルスリープの阻止にはroot権限が避けられない、これはmacOSの厳格な仕様だ。Adrafinilのやり方は、rootの接触面を極限まで小さく圧縮することにある。
まずなぜrootが必須なのかを説明しよう。Macのスリープ防止には2種類ある:「アイドルスリープ」を阻止するなら普通のAPI(IOPMAssertion)で十分だが、「クラムシェルスリープ」(clamshell sleep)を阻止するにはroot権限のpmset disablesleepが必須だ。Adrafinilは両方を行うからこそ、フタを閉じたままタスクを維持できる。
一般社員はオフィスの照明タイマーを延長できる(アイドルスリープ)が、ビル全体のドアロックを解除して人が閉じ込められないようにする(クラムシェルスリープ)には、管理者権限が必要になる。
その解決策は、このわずかなroot権限を最小の箱の中に閉じ込めることだ。アーキテクチャ全体は3層構造で、縦に見ていくとこうなる:
ポリシーはすべてユーザー空間にある。参照カウント、温度監視、プロセス監視、CLI socketはすべて特権のないDaemon上で動く。root権限で動く唯一のHelperは、状態を変更するインターフェースsetSleepBlocked(Bool)を1つだけ公開し、最後のスイッチ操作だけを担う。このコード部分を監査するなら、対象はずっと小さくて済む。
LaunchAgent vs LaunchDaemon、そしてpmsetの副作用
LaunchAgentはユーザーログイン後に現在のユーザー権限で起動し、LaunchDaemonは起動時にroot権限で立ち上がる。Adrafinilは意図的にDaemonをLaunchAgent(ユーザー権限)にし、最小限のHelperだけをLaunchDaemon(root)にすることで、特権の範囲を縮小している。
もう2点、実装上の注意がある:公開のIOPMアサーション(つまりcaffeinateが使っているもの)はそもそもクラムシェルスリープを阻止できない。そのためv1ではより強引なpmset disablesleep 1を使っており、これはアイドルスリープも一緒に無効化してしまい、終了時に必ずクリアしないとリークする。そこでHelperは再起動時にまず状態をdisablesleep 0にリセットしてから再適用するようにしている。
どの9種類に対応、どうインストールするか
1つのコマンドですべてのAgentの設定にHookを書き込める。まず対応リストを見てみよう:
インストールする
署名済みで公証(notarize)されたdmgをダウンロードし、開いてApplicationsにドラッグ、起動する。初回起動時にadmin権限を1回リクエストし、あの特権Helperを登録する。その後install-hooksコマンド1つで、上記すべてのAgentの設定にHookを書き込める。使わなくなったら、uninstall-hooksが追加したHook項目をすべてきれいに削除してくれる。
システム要件
macOS Tahoe 26.4以上(それより前の26.xでも動く可能性はあるが、作者はテストしていない)。自分でビルドするならXcode 26以上が必要で、Swift 6の厳格な並行処理を有効にする。管理者権限なしでインストールした場合、CLIは/usr/local/binではなく~/.local/binに置かれる。
覚えておくと便利なコマンドがあと2つ
応答よりも長く生き続けるバックグラウンドタスク(長時間のビルドやデプロイなど)には、タイムアウト付きのholdコマンドで一定時間維持し、時間になれば自動的に解放できる。MCPに対応したAgentなら、adrafinil mcpが提供するツール呼び出しを直接使うこともできる:
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)
スリープ防止が「ずっと点けっぱなし」から「AIが働いている時だけ点灯、手を止めたら眠る」に進化
OSSツールAdrafinilは、AIコーディングAgentが実際にタスクを実行している時だけMacを眠らせないようにする。このページ1枚で、どう実現しているのか、何の役に立つのかを図解する。
↓ このページで完結 ・ 動く図が1枚あります
あなたはフタを閉じて眠るが、AI Agent(自分でコードを書き、ビルドを実行できるAIアシスタント)は数時間前に起動したあのタスクの中でまだ動いている。この時Macを眠らせたくなければ、これまではcaffeinateのような「常に覚醒」型の古いツールしかなかった。
✘ しかしタスクが終わったかどうかはまったく分からない
タスクがとっくに終わっていてもずっと覚醒したままで、一晩中無駄に電力を消費し発熱する。逆に何もインストールしなければ、フタを閉じればすぐ眠り、長時間タスクはそのまま途中で切れてしまう。どちらの極端も「タスクが実際に動いている」時間帯には合っていない。
Adrafinilは発想を変えた:常に覚醒し続けるのではなく、AIの「仕事開始」と「仕事終了」に合わせて動く。Agentが仕事を始めた瞬間に「眠らせないで」とリクエストし、手を止めた瞬間にスリープの制御権を返す。
# 起動すればずっと覚醒したまま
# タスクに合わせてオン・オフ
ではMacはAgentがいつ仕事を始め、いつ終えるのかをどうやって知るのか?下の図を見てほしい。
その仕組みはこうだ:Agentはそれぞれの Hook(フック、プログラムがあらかじめ用意した自動トリガーポイント)を通じて、仕事を始める時にacquire(カウント+1)、終える時にrelease(カウント−1)を呼び出す。複数のAgentが同時に動けばカウントは積み上がり、最後の1つが手を止めてカウントがゼロになった時、Macは本当に眠りにつく。
小互 は深夜にフタを閉じて眠ったが、Claude Codeはビルド中、Cursorはテスト中。タスクを1つ開始するごとにカウント+1、1つ終えるごとに−1。カウントが0より大きい限り、Macは眠らずに持ちこたえる(フタを閉じても)。ゼロになった瞬間、ようやく眠りにつく。
ここで大事なのは「どれだけ速いか」ではなく、どれだけ無駄な「覚醒」を省けるかだ。例を挙げて体感してみよう。
以上の数値はいずれも作者kageroumadoがmacOS Tahoe 26.4上で自ら計測した、またはプロジェクトのドキュメントに記載されたものであり、第三者による再現検証は行われていない。
数時間前に
もう起動済み
Macをずっと
覚醒させ続ける
- × タスクが終わっても覚醒したまま
- × 一晩中無駄に電力を消費し発熱
- × 何も入れなければフタを閉じて中断
最後の1人が
出るまで消灯しない
