12k
All articles

`caffeinate`を使ってMacを夜通し起動させ続ける方法

MacのcaffeinateでClaude Code、Codex、ビルドを夜通し起動維持し、pmsetでassertionsを確認し、ふた閉じの制限も把握できます。

OpenReplay Team
OpenReplay Team
`caffeinate`を使ってMacを夜通し起動させ続ける方法

caffeinateは、macOSに標準搭載されたコマンドラインツールで、タスクの実行中にMacがスリープするのを防ぎます。最も実用的な使い方はcaffeinate -i <コマンド>という形式で、プロセスをラップし、そのプロセスが実行されている間はシステムを起動状態に保ち、終了した瞬間に自動的に解放します。ラップトップのふたを閉じたり、その場を離れて戻ってきたら、夜通し実行していたClaude Code、Codex、または長時間のビルドジョブが停止していた、という経験がある方には、インストール不要のこの組み込みツールが解決策となります。本記事では、重要なフラグ、夜通し実行のための定番レシピ、アサーションが実際に保持されているかの確認方法、そしてcaffeinateが越えられない唯一のハードリミットについて解説します。

重要なポイント

  • caffeinateはmacOSに標準搭載されており(OS X 10.8以降)、インストールもadmin権限も不要です。IOKitの電源管理アサーションを作成しますが、これはXcodeなどのアプリがMacを起動状態に保つために使用するのと同じ仕組みです。
  • ラップトップでは-iを使用してアイドルスリープを防ぎましょう。-sはAC電源接続時のみ有効で、バッテリー駆動時は無効化されても通知されません。-dはディスプレイを点灯させ続けるため、不必要に電力を消費します。
  • コマンドをラップする(caffeinate -i npm run build)と、プロセスの終了時にアサーションが自動的に解放されるため、解除し忘れる心配がありません。
  • caffeinateだけでは、ふたを閉じた状態のMacBookを起動させ続けることはできません。ふたを閉じるとクラムシェルスリープが発動し、バッテリー駆動時はソフトウェアのアサーションでこれをオーバーライドできません。
  • ターミナルウィンドウが閉じられたりクラッシュしてもアサーションが維持されるよう、夜通し実行するエージェントはtmuxの中で起動しましょう。

caffeinateとは何か(10秒でわかる答え)

caffeinateは、スリープ動作を変更するための電源管理アサーションを作成する、macOS公式のコマンドラインツールです。OS X 10.8(2012年)以降、/usr/bin/caffeinateとして標準搭載されており、インストールもadmin権限も必要ありません。内部的には、IOKitの電源アサーションAPIであるIOPMAssertionCreateWithNameを呼び出します。これは、電源管理システムに対してシステムの動作を動的にリクエストする仕組みであり、アプリケーションが作業中にMacを起動状態に保つために使用する公式の手段と同じものです。

長時間実行するジョブにとって重要な動作は「ラップ」です。ユーティリティが指定された場合、caffeinate はそのユーティリティの代わりにアサーションを作成し、そのアサーションはユーティリティの実行中ずっと持続します。指定されない場合、caffeinate は直接アサーションを作成し、caffeinate 自体が終了するまで持続します。manページの典型的な例caffeinate -i makeです。caffeinateはプロセスをフォークして”make”をexecし、そのプロセスが実行されている間、アイドルスリープを防ぐアサーションを保持します。

重要なcaffeinateフラグ

ラップトップで重要なフラグはcaffeinate -iの1つだけです。これはディスプレイの輝度が下がることを許容しながら、システムのアイドルスリープを防ぎます。バックグラウンドで動作するエージェントやビルドに必要なのはまさにこの動作です。公式ドキュメントに記載されたフラグは、多くのガイドが紹介するよりも多くあります。

フラグ防ぐ動作備考
-iアイドルスリープ開発者向けのデフォルト。ディスプレイはオフになる場合あり
-dディスプレイスリープ画面を点灯し続ける。ヘッドレスジョブでは電力の無駄
-mディスクのアイドルスリープCPU/ネットワーク主体のエージェントではほぼ不要
-sシステムスリープAC電源接続時のみ有効
-uユーザーアクティビティを宣言ワンショット。アイドルタイマーをリセット
-t NN秒後に自動終了
-w pid指定したPIDが終了するまでアサーションを保持

他のガイドがよく間違える点が2つあります。まず、-sアサーションはAC電源接続時のみ有効で、バッテリー駆動時は無効化されても通知されません。そのため、電源未接続のラップトップではデフォルトとして不適切です。次に、ディスプレイがオフの場合、-uはディスプレイをオンにしてアイドルスリープを防ぎますが、-tでタイムアウトを指定しない場合、このアサーションはデフォルトで5秒後にタイムアウトします。タスクをラップする方が、単独のアサーションよりも安全です。ジョブよりも長く存続することがないためです。caffeinate -i npm run buildはビルド中のスリープを防ぎ、完了した瞬間に解放されます。

夜通し実行のレシピ

Claude CodeCodex CLI、またはAiderを夜通し動かし続けるには、エージェントの起動コマンドを直接ラップし、ターミナルマルチプレクサの中で実行することで、ターミナルウィンドウが開いていることに依存しない構成にします。アサーションはcaffeinateプロセスの中に存在するため、ターミナルが閉じられたりクラッシュすると消滅します。tmuxを使うことで真の耐久性が得られます。

# アサーションをセッション全体で保持するデタッチされたtmuxセッションを開始する
tmux new-session -d -s agent 'caffeinate -i claude'

エージェントがすでに別のペインで実行中の場合は、再起動せずに-wを使って既存のプロセスIDに新しいアサーションを紐付けましょう。

# PIDを確認し、そのプロセスが終了するまでアサーションを保持する
pgrep -f claude
caffeinate -i -w <pid>

8時間の実行を開始してその場を離れる前に、アサーションが実際に保持されていることを確認してください。別のペインで以下を実行します。

pmset -g assertions

この出力にPreventUserIdleSystemSleepのエントリが表示されていれば、ジョブの実行中はmacOSがアイドルスリープしないことが確認できます。ラップしたコマンドが終了すると、この行は消えます。この診断コマンドを実行するかどうかが、夜通し実行が保護されていると「期待する」か「確信する」かの違いです。

caffeinateはふたを閉じたMacBookを起動させ続けられるか?

caffeinateだけでは、ふたを閉じた状態のMacBookを起動させ続けることはできません。ふたを閉じるとクラムシェルスリープが発動し、バッテリー駆動時はソフトウェアの電源アサーションでこれをオーバーライドすることは不可能です。これは、いかなるCLIツールも越えられない限界であり、ラップトップを折りたたんで電源を抜いた瞬間にジョブが停止する理由です。

ふたを閉じた状態での動作が機能するのは、公式にサポートされた2つのケースのみです。1つ目はAppleのクラムシェルモードです。Appleはふたを閉じた状態でMacBookを使用することをサポートしていますが、外部ディスプレイ、キーボード、マウスを接続する必要があり、厳格な要件があります。外部モニターなしでは機能せず、熱管理上のトレードオフが生じる場合もあります。Appleの推奨構成は、外部ディスプレイ、電源アダプタ、外部キーボードとマウスまたはトラックパッドを接続することです。2つ目は「システム設定」→「バッテリー」→「オプション」の「ディスプレイがオフのときに自動スリープしない」トグルですが、これはバッテリー駆動ではなく電源に接続されている状態でのみ意図通りに機能します。

バッテリー駆動かつふたを閉じた状態、つまりバッグの中のラップトップでエージェントを実行する必要がある場合、caffeinateは適切なツールではありません。Amphetamineはまさにそのようなケースのために作られています。そのドキュメントには、Amphetamineを使用すれば、クローズドディスプレイモードの使用にディスプレイ、キーボード、マウス、電源アダプタが不要であると記載されています。これはAppleの要件を無効化する公開APIを使用しているためです。

以下に全体像を真理値表として示します。

シナリオcaffeinate -iバッテリー > オプションAmphetamine
ふたを開けた状態、アイドル、バッテリー駆動起動を維持起動を維持起動を維持
ふたを閉じた状態、バッテリー駆動スリープスリープ起動を維持
ふたを閉じた状態、AC電源 + 外部ディスプレイ/キーボード起動を維持起動を維持起動を維持
ターミナルウィンドウが閉じられたりクラッシュした場合アサーションが消滅影響なし影響なし
ラップしたコマンドが終了した場合自動解放影響なしセッションは継続

停止方法と注意点

caffeinateをフォアグラウンドで実行している場合はCtrl+Cで停止できます。あるいはラップしたコマンドが終了すれば自動的に終了します。ラップパターンは意図的に、誤って実行し続けることが難しい設計になっています。失敗のパターンについても触れておく価値があります。ユーティリティをラップせず-tも指定しない素のcaffeinateは、手動で停止するまで実行し続けます。Macを継続的に起動させ続けるとバッテリーの消耗が増し、部品の温度が上がり、長期的にはSSDへの書き込み回数が増加します。そのため、アサーションはジョブの範囲に限定してください。また、アサーションはプロセスに紐付いているため、ターミナルを閉じたりクラッシュすると即座に消滅します。これが、caffeinateと入力してウィンドウが一晩中開いていることを祈るよりも、エージェントをtmuxでラップすべき理由です。

さらに強力なツールが必要なとき

caffeinateは、Macが電源に接続されているか、ふたが開いた状態で、特定の夜通しジョブを自動クリーンアップ付きで保護したい場合に適したツールです。バッテリー駆動かつふたを閉じた状態が必要な場合は、Amphetamineとそのセッションベースのコントロールに切り替えましょう。ビルドやエージェントの実行が数日間に及ぶほど重い場合は、ラップトップの電源状態を管理し続けることをやめて、常時起動のリモートマシンでワークロードを実行するのがよりクリーンな解決策です。そのようなマシンはスリープしないよう設計されているためです。自分のMacで夜通し実行する場合は、コマンドをラップし、pmset -g assertionsでアサーションを確認してから、安心して眠りにつきましょう。

よくある質問

`caffeinate -i`と`caffeinate -d`の違いは何ですか?

`-i`フラグはシステムのアイドルスリープを防ぎながら、ディスプレイはオフになることを許容します。これはバックグラウンドで動作するエージェントやビルドに必要な動作であり、ラップトップでの正しいデフォルト設定です。`-d`フラグはディスプレイのスリープを防ぎ、画面を点灯させ続けるため、ヘッドレスジョブでは電力の無駄になります。夜通しのターミナル作業には`-i`を使用し、監視ダッシュボードなどディスプレイ自体を点灯させ続ける必要がある場合にのみ`-d`を使用してください。

`caffeinate`の実行にsudoやadmin権限は必要ですか?

不要です。`caffeinate`はIOKitの公開電源アサーションAPIを使用するため、インストールもadmin権限も必要ありません。これはXcodeなどのアプリケーションがMacを起動状態に保つために使用する公式の仕組みと同じです。どのユーザーもターミナルから直接実行できます。OS X 10.8以降、`/usr/bin/caffeinate`としてmacOSに標準搭載されているため、インストールも昇格した権限の付与も不要です。

ターミナルウィンドウを閉じると`caffeinate`はどうなりますか?

アサーションは即座に消滅します。電源管理アサーションは`caffeinate`プロセスの中に存在するため、ターミナルウィンドウを閉じたりクラッシュするとそのプロセスが終了し、アサーションが解放されてMacがアイドルスリープできる状態になります。ウィンドウが閉じられても動作し続けるようにするには、`tmux`セッション内でcaffeinateがコマンドをラップする形で実行してください。そうすることで、アサーションはターミナルの生存に依存しないデタッチされたプロセスに紐付けられます。

`caffeinate`を指定した時間だけ実行するにはどうすればよいですか?

`-t`フラグに秒単位のタイムアウトを指定して使用します。たとえば、`caffeinate -i -t 28800`はちょうど8時間アイドルスリープを防いだ後、自動的に終了してアサーションを解放します。これは特定のコマンドの実行時間ではなく、固定の時間枠でアサーションを保持したい場合に便利です。`-t`もラップするユーティリティも指定しない素の`caffeinate`は、Ctrl+Cで手動停止するまで実行し続けます。

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.