プロダクトリリース ・ 小互解読

AIが止まって初めてMacを眠らせる、このOSSツールがスリープ防止を極めた

Claude Codeなど9種類のAgentをワンクリック連携、フタを閉じてもタスク継続、停止後50ms以内に自動でスリープ制御を解放
概要
  • 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つだけ公開、それ以外のロジックはすべてユーザー空間で動く。
1シナリオ

あなたはフタを閉じて眠るが、Agentはまだ動いている

OSS開発者kageroumadoは先日Adrafinilを公開した。これはmacOSのメニューバーツールで、AIコーディングAgentが実際に動いている間だけMacのスリープを阻止し、Agentが停止すると自動的に通常のスリープに戻る。

深夜3時、あなたは眠ったが、Agentは眠っていない。数時間前に立ち上げたあのセッションの中でまだ動き続けているのに、あなたはまぶたを閉じるようにノートパソコンのフタを閉じる。しかしこの「目」は本当には閉じていない。矛盾はここにある:Agentのタスクサイクルと Macのスリープポリシーは互いに相手が何をしているか知らない。フタを閉じれば、システムはいつも通りスリープに入り、タスクは途中で断ち切られる。

Adrafinilはスリープ防止をAI Agentの稼働状態に正確に紐づける:Agentが実際にタスクを実行している間は眠らせず(フタを閉じても)、タスクが止まった瞬間にスリープの制御権を即座に返す。
macOSのスリープ防止をAgentセッションの稼働状態に合わせて精密にオン・オフする、初めてのツール。CLIの往復は50ms未満、ワンクリックHookで主要9種のAgentに対応、参照カウントで複数セッションの並行処理に対応、root権限の範囲は単一のブール値インターフェースまで圧縮。
<50ms
CLIのacquire / releaseコマンドからDaemonまでの往復レイテンシ、Agentのワークフローを遅らせない
9
ワンクリックHookインストールに対応するAI Agentの数
3
権限の階層数(App/CLI → Daemon → Helper)、rootの接触面を最小化
1
Helperが公開するrootインターフェースの数:setSleepBlocked(Bool)

名前そのものがこのツールの設計思想を物語っている。Adrafinilは覚醒維持薬(eugeroic)から借りた名前だ。興奮剤(stimulant)とは違い、覚醒維持薬は必要な時だけ覚醒を助け、不要な時は干渉しない——これこそがcaffeinateのような「常に覚醒」型ツールとの根本的な違いだ:仕事がある時だけスリープを防ぐ。

2比較

旧来の方法ではなぜ足りないのか

Adrafinil以前、Macに長時間タスクを実行させながら眠らせないようにするには、両極端な2つの選択肢しかなく、どちらも「タスクが実際に動いている」時間帯には正確に合わせられなかった。

caffeinateとAmphetamineは興奮剤タイプで、起動すればずっと覚醒状態のまま、仕事があるかどうかは関係ない。タスクがとっくに終わっていても、マシンは空転して電力を消費し発熱し続ける。逆に何もインストールしなければ、フタを閉じればすぐ眠り、長時間タスクはそこで中断される。以下では3つのケースを同じ時間軸上に並べてみる:スリープ防止のウィンドウとタスクのウィンドウが噛み合っているかどうか、一目で分かる。

夜に長時間タスクを起動 ─────────────▶ タスク完了
タスクが実際に稼働中(基準)
caffeinate / Amphetamine
何もインストールしない
adrafinil
タスクウィンドウスリープ防止(休止をブロック)フタを閉じると即座にスリープ、タスク中断

caffeinateのスリープ防止バーは最初から最後まで点灯しっぱなしで、タスク終了後のあの長い区間は完全に無駄だ。何もインストールしていない行では、フタを閉じた箇所に赤いバツ印がつき、タスクが終わる前に打ち切られる。adrafinilのバーだけがタスクウィンドウにぴったり貼りつき、前後に1秒たりとも余分に維持しない。

3コア機構

Agentの「呼吸」に合わせる

Adrafinilのコアはシンプルだ:Agentが仕事を始めたらスリープ防止をリクエストし、手を止めたら解放する。MacはAgentが実際にタスクを実行している間だけ覚醒を保つ。メニューバーのアイコンもこの2状態しかない。

awake状態:Agentが稼働中
「awake」状態:Agentが稼働中、メニューバーアイコンはスリープ防止中を表示。出典:プロジェクトのREADME
sleeping状態:Agentなし、通常どおりスリープ
「sleeping」状態:Agentが動いていない、Macは通常どおりスリープ。出典:プロジェクトのREADME

AgentはAdrafinilと直接会話するのではなく、それぞれのHookシステムを通じて付属のコマンドラインを呼び出す。

adrafinil acquire <session-key> --tool claude-code --reason "long build" # 1ターン開始時 adrafinil release <session-key> # Agentがアイドルに戻ったとき

Claude Codeを例にすると、シグナルの流れ全体はこうなる:

UserPromptSubmit指示を送信
acquireカウント +1
Agent稼働中スリープを阻止
Stopタスク停止
releaseカウント −1
カウントがゼロに復帰
Macはスリープ可フタを閉じれば即スリープ
Hero ・ アクティビティ範囲スリープ防止

ポイントは、防いでいるのが「実際に作業している」区間であって、「プログラムが開いている」区間ではないということだ。Claude CodeはUserPromptSubmitでacquireし、Stopでreleaseする。だから開いてはいるが入力欄で待機しているだけのセッションなら、Macは通常どおり眠る。これをアクティビティ範囲のスリープ防止(activity-scoped)と呼び、セッション単位のスリープ防止(session-scoped)とは区別される。

開発者にとっての直接的な効果はこうだ:安心してフタを閉じて離席し、Agentにビルド・テスト・デプロイを任せられる。タスクが終わればMacは自動でスリープに戻るので、caffeinateを手動で切るのを覚えておく必要もなく、切り忘れて電力を無駄にする心配もない。

4マルチセッション

複数同時実行でも混乱しない

複数のAgentが同時に動く場合はどうするのか?Adrafinilは参照カウントを使う:各セッションが開始すると+1、終了すると−1、カウントがゼロになって初めてスリープ防止を解除する。

たとえるなら

オフィスで最後の1人が出るまで電気を消さない、誰かが帰るたびに消すわけではない、というのと同じだ。途中でどれか1つのタスクが終わっても、まだ動いている他のタスクを巻き込むことはない。

以下のカウントリングはこのページの目玉だ。いくつかAgentを試しに点灯させてみよう:リング内の数字が0より大きい限り、Macはスリープ防止状態になる(青いパルス)。1つずつオフにしていき、数字がゼロになった瞬間にリングはグレーに変わり、Macは本当に眠れるようになる。

アクティブなセッション

クリックで任意のAgentを起動/停止。リング内の数字=現在スリープ防止を保持しているセッション数、ゼロになって初めてスリープ防止が解除される。

5セーフティネット

フタを閉じても熱暴走しない

フタを閉じたまま長時間タスクを走らせて一番怖いのは、バッグに入れたまま放熱が追いつかず、マシンを痛めてしまうことだ。Adrafinilには温度保護機能が内蔵されており、これこそが安心してフタを閉じて離席できる要のセーフティネットだ。

SMC測温常時モニタリング
表面 / CPU温度閾値超過
強制release全アサーションを解放
Macは復帰通常どおりスリープして放熱

温度以外にも、もう1つ自動解放の仕組みがある:アサーションを保持しているプロセスが既に落ちている、あるいはCPUがN分以上アイドル状態が続いた場合、対応するスリープ防止は自動的に破棄され、「プログラムがクラッシュしたのにスリープ防止だけ残る」という抜け穴を塞ぐ。

フタを閉じた状態では画面が消えていて通知は出せないため、確認音を1つ鳴らしてスリープ防止が有効になったことを知らせる。再びフタを開けた時にはサマリーを表示する:離席中に何が動いていたか、最高温度は何度だったか、温度保護が発動したかどうか。

プロセス検知(オプション)

Hookを設定していなくても、Daemonは既知のAgentプログラムが動いていることを検知すると自動でacquireできる。これはオプション機能で、Hookを設定しづらい場面のための保険だ。

6セキュリティアーキテクチャ

rootは1つのことしかしない

クラムシェルスリープの阻止にはroot権限が避けられない、これはmacOSの厳格な仕様だ。Adrafinilのやり方は、rootの接触面を極限まで小さく圧縮することにある。

まずなぜrootが必須なのかを説明しよう。Macのスリープ防止には2種類ある:「アイドルスリープ」を阻止するなら普通のAPI(IOPMAssertion)で十分だが、「クラムシェルスリープ」(clamshell sleep)を阻止するにはroot権限のpmset disablesleepが必須だ。Adrafinilは両方を行うからこそ、フタを閉じたままタスクを維持できる。

たとえるなら

一般社員はオフィスの照明タイマーを延長できる(アイドルスリープ)が、ビル全体のドアロックを解除して人が閉じ込められないようにする(クラムシェルスリープ)には、管理者権限が必要になる。

その解決策は、このわずかなroot権限を最小の箱の中に閉じ込めることだ。アーキテクチャ全体は3層構造で、縦に見ていくとこうなる:

Adrafinil.app ユーザー空間 ・ メニューバー
ステータスアイコン、設定、インストールウィザードGUI、フタを開けた時のサマリー。純粋な表示層で、終了・再起動しても既に保持しているスリープ防止には影響しない。
XPC
AdrafinilDaemon ユーザー空間 ・ LaunchAgent
参照カウントの登録、プロセス監視(kqueue NOTE_EXIT +定期巡回)、温度監視(SMC)、フタを閉じた時の効果音、CLI socket。すべてのポリシーはここにあり、唯一の信頼できる情報源(source of truth)はこのコンポーネントだ。
XPC ・ 特権Machサービス
AdrafinilHelper root ・ LaunchDaemon
スリープ防止APIに触れる唯一のコンポーネント。公開しているのはsetSleepBlocked(Bool)と読み取り専用のステータス照会だけで、呼び出し元のコード署名を検証する。ポリシーロジックは一切含まない。
adrafinil CLIは.appにバンドルされ、PATHへシンボリックリンクされる。Daemonのsocketに直接接続し、往復は<50ms
Hero ・ root最小化

ポリシーはすべてユーザー空間にある。参照カウント、温度監視、プロセス監視、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にリセットしてから再適用するようにしている。

7対応範囲とインストール

どの9種類に対応、どうインストールするか

1つのコマンドですべてのAgentの設定にHookを書き込める。まず対応リストを見てみよう:

Claude CodeCodexCursorGemini CLIAiderHermesOpenCodeClinePi

インストールする

署名済みで公証(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 hold --for 30m --reason "deploy" # 最大30分間スリープ防止、その後自動解放 adrafinil mcp # stdio上でMCPプロトコルを話す、Agent向け
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)
出典:本記事はkageroumadoがGitHubで公開したadrafinilプロジェクトの説明(READMEおよびDocs/ARCHITECTURE.md)をもとに構成した。プロジェクトはMITライセンスでオープンソース化されている。本文中の性能・機構に関する記述はすべてプロジェクトのドキュメントに基づく。