Claude CodeやCodexに指示を出して、応答を待って、また次の指示を出す。

その繰り返しで、気づくと2〜3時間座りっぱなしになっています。

タイマーをかけても、通知は「あとで」と流してしまいがち。

それなら、いつも見ているエージェントの画面そのものに休憩の合図を出してもらおうと、僕はagent-recessという小さなツールを作りました。

フック(決まったタイミングで自分のコマンドを呼び出す仕組み)のUserPromptSubmitとStopにagent-recess hookを登録すると、連続90分を超えた応答終了のタイミングで休憩の提案文を返します。

エージェントの作業は止めません。

入れるコマンドは次の2つです。

ollama pull gemma4:e2b-it-qat
npm install -g github:spa77k/agent-recess

提案文は、手元のOllama(ローカルでLLMを動かすツール)で動くGemma 4が作ります。

メモリ16GBのMacなら、4.3GBのgemma4:e2b-it-qatを選んでください。

モデルへ渡す情報は次の4つだけ。

  • 連続作業時間
  • 現在時刻
  • 天気
  • 言語

コードや会話は渡しません。

しかも、フックへ登録する前に、モデルへ送られる文の全文を自分の目で確かめられます。

目次

連続90分を超えたら応答の終わりに休憩を提案する仕組み

プロンプト送信と応答終了のたびに時刻を記録し、15分以上あいたら0に戻し、連続90分以上なら応答終了のときに休憩を提案する流れの図

agent-recess hookは、プロンプトを送ったときのUserPromptSubmitと、エージェントが応答を終えたときのStopで呼ばれます。

呼ばれるたびに、その時刻を~/.agent-recess/state.jsonへ記録していく仕組み。

前の記録から15分以上あいていれば休憩したとみなし、連続作業時間を0に戻します。

連続作業時間が90分以上になると、次のStopで提案文を返します。

一度提案したあとは、30分たつまで次の提案を出しません。

項目既定値
提案を始める連続作業時間90分
休憩とみなす間隔15分
次の提案までの間隔30分

連続作業時間はターミナルやエージェントごとに分けず、Claude Codeを2つ開いていてもCodexと併用していても、1つの値を共有します。

提案のせいで作業が止まることもありません。

agent-recessは提案文をsystemMessageという項目に入れて返すだけで、エージェントを止める指示は出さない作りです。

Claude Codeの公式ドキュメントにも、Stopフックはdecision: "block"を返さない限り停止を妨げないと書かれています。

入れる前に確かめておきたい対象は、次の3つに分けられます。

  • 外へ送られる情報
  • モデルの選び方
  • フックの設定場所

インストールして提案文を先に見る

フックの登録は後回しにして、先に提案文を出してみてください。

必要なのはNode.js 20以上とOllamaで、agent-recess自体は外部パッケージに依存しません。

  1. モデルを取得する

    ollama pull gemma4:e2b-it-qat
  2. agent-recessをインストールする

    npm install -g github:spa77k/agent-recess
  3. 提案文を出してみる

    agent-recess preview

ターミナルでagent-recess statusとagent-recess preview 94を実行した画面。モデルへ送った文の全文と、Gemma 4が返した休憩の提案文が表示されている

agent-recess previewを実行すると、モデルへ送った文の全文と、返ってきた提案文が表示されます。

この2つが出ていれば、インストールは成功です。

待ち時間は、モデルを読み込んだ直後の1回目が約7秒、2回目以降は1〜3秒でした。

agent-recess preview 94のように分数を付けると、その連続作業時間で作業した想定の提案文を確かめられます。

Ollamaから返事がない場合は、固定の文が返ります。

提案文の見出しがfallbackになっていたら、Ollamaが起動しているか、モデルを取得済みかを確かめてください。

モデルへ送られるのは作業時間と時刻と天気と言語だけ

作業中のコードや会話が外へ出ないかは、導入前にいちばん気になるところでしょう。

agent-recessが情報を渡す相手は2つあります。

送り先渡す情報
手元のOllamaで動くgemma4:e2b-it-qat連続作業時間、現在時刻、天気、言語
Open-Meteo(天気のAPI)設定ファイルに書いた緯度と経度

モデルへ渡す文にコードや会話は入りません。

確かめ方は、先ほどのagent-recess previewの出力を読むだけです。

送った文の全文がそのまま出るので、余計な情報が混ざっていないかを自分の目で見てください。

インターネットへ出ていくのは、天気を取るためにOpen-Meteoへ送る緯度と経度だけ。

Open-MeteoはAPIキーが要らないので、登録や鍵の管理は発生しません。

緯度と経度を設定ファイルに書かなければ、天気なしで提案文を作ります。

位置を外へ出したくないなら、何も書かずに使えば済む話です。

取得した天気は30分キャッシュするため、提案のたびに問い合わせることもありません。

16GBのMacで選ぶGemma 4のタグ

メモリ16GBのMacなら、選ぶタグはgemma4:e2b-it-qatです。

gemma4:e4bでも試しましたが、短い返事ひとつに1分以上かかりました。

タグサイズ応答時間
gemma4:e4b9.5GB7トークンの返答に78秒、合計91秒
gemma4:e2b-it-qat4.3GB1回目は約7秒、2回目以降は1〜3秒

測った環境はApple M4、メモリ16GB、Ollama 0.40.0。

gemma4:e4bに送ったのは「Say hi in five words.」という短い依頼だけでした。

9.5GBは、16GBのメモリに対して大きなサイズです。

短い返事ひとつに合計91秒かかるようでは、休憩の合図には使えないでしょう。

4.3GBのgemma4:e2b-it-qatへ替えると、同じMacで数秒に収まりました。

メモリに余裕があるMacで別のモデルを使いたい場合は、設定ファイルのmodelにOllamaのモデル名を書いてください。

Claude CodeとCodexでフックを登録する場所

agent-recess previewで提案文を見て、合いそうならフックへ登録します。

設定ファイルの場所はツールごとに別々です。

  • Claude Codeの設定
  • Codexの設定と信頼の手順

登録するイベントはどちらもUserPromptSubmitとStopで、呼び出すコマンドも同じagent-recess hookになります。

ツール設定ファイル
Claude Code~/.claude/settings.json
Codex~/.codex/hooks.json

Codexでは、書いたあとに/hooksで内容を確認して信頼する操作が加わります。

僕の環境で確かめた範囲は次のとおりです。

ツールとバージョンUserPromptSubmitStop対話画面での表示
Codex CLI 0.160.0のcodex exec呼ばれた呼ばれて提案が生成された見ていない
Claude Code 2.1.284呼ばれて成功した確かめていない見ていない

Codexで試したのは、対話画面ではなくcodex execです。

その出力に提案文は出ませんでした。

提案が生成されたことは、状態ファイルの記録で確認しています。

Claude Codeの設定

~/.claude/settings.jsonに次の内容を書きます。

{
  "hooks": {
    "UserPromptSubmit": [
      { "hooks": [{ "type": "command", "command": "agent-recess hook" }] }
    ],
    "Stop": [
      { "hooks": [{ "type": "command", "command": "agent-recess hook", "timeout": 30 }] }
    ]
  }
}

すでにhooksの項目がある場合は、UserPromptSubmitとStopの配列へ追記してください。

timeoutの単位は秒です。

公式ドキュメントによると、StopはClaudeが応答を終えたときに呼ばれ、フックが返すsystemMessageはユーザーへ警告として表示される項目とされています。

agent-recessは提案文をこのsystemMessageに入れて返す作りです。

Claude Code 2.1.284で僕が確かめたのは、UserPromptSubmitでフックが呼ばれて成功するところまで。

Codexの設定と信頼の手順

Codexは設定を書くだけでは動かず、信頼の操作まで必要です。

  1. ~/.codex/hooks.jsonに下の内容を書く
  2. Codexを起動して/hooksを開く
  3. 追加したフックの内容を確認して信頼する
{
  "hooks": {
    "UserPromptSubmit": [
      { "hooks": [{ "type": "command", "command": "agent-recess hook", "timeout": 30 }] }
    ],
    "Stop": [
      { "hooks": [{ "type": "command", "command": "agent-recess hook", "timeout": 30 }] }
    ]
  }
}

設定を書いたのにフックが動かないときは、最初に/hooksを見てください。

Codexでは、新しく追加したフックや内容を変えたフックは、/hooksで確認して信頼するまでスキップされます。

フック自体は既定で有効なので、有効化のための設定を別に足す必要はありません。

Codex向けのフックを自作する人は、Stopの出力形式にも気をつけてください。

公式ドキュメントでは、Stopは終了コード0のとき標準出力にJSONを求め、平文は無効とされています。

systemMessageについては、UIやイベントストリームに警告として出ると書かれています。

応答が遅くならないかと、提案を止める方法

フックを足すと毎回の応答が重くなりそうですが、提案しない回の処理時間は約0.03秒でした。

モデルを呼ぶのは、提案を返す回だけです。

Ollamaを起動し忘れていても、応答が固まることはありません。

Ollamaが動いていないときや12秒以内に返事がないときは、あらかじめ用意した固定の文を返します。

提案が何度も続く心配も要らないでしょう。

一度提案したら30分は出ませんし、集中したい時間はagent-recess snoozeで止められます。

コマンド動き
agent-recess snooze60分のあいだ提案を止める
agent-recess snooze 120指定した分数だけ提案を止める
agent-recess snooze 0止めていた提案を再開する
agent-recess statusいまの連続作業時間と、提案が始まる90分までの残り時間を見る

時間の区切りや言語を変えたいときは、~/.agent-recess/config.jsonを作ります。

{
  "latitude": 35.68,
  "longitude": 139.76,
  "thresholdMinutes": 90,
  "breakGapMinutes": 15,
  "cooldownMinutes": 30,
  "model": "gemma4:e2b-it-qat",
  "language": "en"
}

緯度35.68と経度139.76は東京駅付近を指す例の値なので、天気を使うなら自分の地域の値へ書き換えてください。

キー既定値意味
latitudeとlongitudeなし天気を調べる場所。書かなければ天気なしで提案する
thresholdMinutes90提案を始める連続作業時間
breakGapMinutes15休憩とみなす間隔
cooldownMinutes30次の提案までの間隔
modelgemma4:e2b-it-qat提案文を作らせるOllamaのモデル名
languageen提案文の言語。enかja

languageの既定はenなので、何も設定しないと提案文は英語になります。

日本語で提案させたい場合は、"language": "ja"と書いてください。

雨の日に外へ誘われた失敗と、判断をコードへ移した設計

作っている途中で、雨のデータを渡したのに外へ誘う提案が返ってきました。

最初のプロンプトでは、乾いていれば外、濡れていれば屋内という両方の選択肢を箇条書きで渡し、どちらにするかをモデルに選ばせていました。

そのときにgemma4:e2b-it-qatが返した文がこちらです。

Since it is dark and rainy outside, take a 10-minute break to step outside and just watch the rain and the sky.

日本語の設定でも結果は同じでした。

外は雨が降っていますから、5分から10分ほど、外の空を眺めながら軽く歩いてみるのはどうでしょう。

雨だと分かったうえで、外を歩かせようとしています。

そこで、屋内か屋外かの判断はコードで決めるように変えました。

条件提案の向き
雨・雪・雷・霧雨のいずれか、または降水量が0より大きい屋内で休む
乾いていて暗い玄関先やベランダに出るか、室内でストレッチ
乾いていて明るい外を歩く

モデルには決まった向きだけを伝え、文面を作る仕事だけを任せます。

変更後、雨の昼に返ってきた日本語の提案はこうなりました。

94分も集中していたね。今日は天気が残念だから、窓を開けて体を伸ばしたり、水を補給したりして、10分くらい休憩しよう。

晴れの昼ではこう変わります。

94分も集中していたね、そろそろ休憩のサインだよ。外の景色を見るために5分から15分くらい、ちょっと散歩に出かけて、空を眺めてごらん。

小さいローカルモデルを自分のツールへ組み込むときも、この分け方はそのまま使えるでしょう。

判断はコードで決めて、モデルには文面だけを作らせてください。

まとめ:Claude CodeとCodexの休憩フックは提案文を見てから登録する

Claude CodeとCodexの休憩フックは、登録する前にagent-recess previewで提案文とモデルへ送る文を見られます。

入れるかどうかは、その出力を読んでから決めれば十分です。

迷ったときに見る場所は次の3つ。

  • 外へ送られる内容は、agent-recess previewの出力で確かめる
  • メモリ16GBのMacなら、モデルはgemma4:e2b-it-qatにする
  • Codexは~/.codex/hooks.jsonに書いたあと、/hooksでの信頼まで済ませる

フックへ登録しなければ、Claude CodeやCodexの動きは何も変わりません。

登録したあとで邪魔に感じたら、agent-recess snoozeで止められます。

まずはollama pull gemma4:e2b-it-qatとnpm install -g github:spa77k/agent-recessを済ませて、agent-recess previewを1回動かしてみてください。

ソースコードはagent-recessのリポジトリで公開しています。

Codexを複数のアカウントで使い分けている場合は、こちらの記事も参考になります。

関連記事Codexで複数アカウントをログアウトせずに切り替える方法【Mac/zsh】MacのzshでCODEX_HOMEを分け、Codexの複数アカウントをcodex1/codex2で切り替える設定手順を解説。ログアウト不要で個人用と仕事用のCodexアカウントを使い分ける方法です。