Setupフックを init と maintenance の2系統で使い分け始めた人向け
日次バッチや週次の定期メンテで「セッション本体が始まる前に、しばらく走る掃除や整備のスクリプトを仕込みたい」場面で <code>claude -p --maintenance "クエリ"</code> の形で叩く。cron や CI(自動実行の仕組み)から呼ぶことを想定した起動形態で、対話モードでは Setup フックを発火させない仕様のため、自動運用専用の道具と割り切って使う
日次バッチや週次の定期メンテで「Claude Codeの本体セッションが動き出す前に、しばらく走る掃除スクリプトを仕込みたい」場面で叩く起動スイッチです。素の claude を立ち上げてもメンテ用のフックは動かない仕様で、これを claude -p --maintenance のように足したときだけ、設定ファイルに書いた maintenance 区分のSetupフックが先に走ります。
cronと組み合わせて、「毎晩2時に一時保存の中身を掃除してから、その日の作業ログを要約させる」みたいな運用に向いてます。
噛み砕くと
家電のタイマー予約に近いです。普段は手で電源を入れる家電と別に、決まった時間に動く「お掃除モード」のスイッチが用意されている。--maintenance がそのスイッチで、押されたときだけ事前掃除のスクリプトが走って、その後に本来のセッションが始まる。
普段触る本体スイッチを汚さず、定期メンテ用の流れだけ別系統で持てる構造です。
大事な前提:このスイッチは print mode 専用で、しかも設定ファイルに仕掛けが要る
2つ前提があります。1つ目は -p と組み合わせないと --maintenance は無効。素の claude --maintenance だけだと、Setupフックは発火しません。
2つ目は設定ファイル側で maintenance 区分のSetupフックを書いておかないと、スイッチを押しても走るものがありません。家のホームディレクトリにある ~/.claude/settings.json に書きます。
「日次バッチで一時保存の掃除+ログ要約」を例に、実際の手順を見る
毎晩2時にClaude Codeに作業ログの要約を出させたい。ただし要約を作る前に、その日溜まった一時ファイル類を掃除しておきたい。これを --maintenance で組み立てます。
ステップ1: 掃除スクリプトを用意する
家のホームディレクトリに ~/scripts/maintenance-cleanup.sh を作ります。中身はシンプルでよくて、たとえば「7日より古いログを消す」と「アプリの一時保存フォルダを空にする」だけ。
#!/bin/bash
# 7日より古いログファイルを削除
find ~/myapp-data -name "*.log" -mtime +7 -delete
# 一時保存フォルダを空にする
rm -rf ~/myapp-data/tmp/*
echo "cleanup done at $(date)" >> ~/maintenance.log
実行できる状態にしておきます。
$ chmod +x ~/scripts/maintenance-cleanup.sh
ステップ2: Claude Codeの設定ファイルに maintenance フックを登録する
~/.claude/settings.json を開いて、hooks の中に Setup を追加します。matcher を maintenance にして、さっき作ったスクリプトを呼ぶ形。
{
"hooks": {
"Setup": [
{
"matcher": "maintenance",
"hooks": [
{
"type": "command",
"command": "~/scripts/maintenance-cleanup.sh"
}
]
}
]
}
}
この書き方だと、--maintenance が押されたときだけ maintenance-cleanup.sh が走ります。普通に claude を立ち上げたときは無視されます。Setupフックのmatcherはこの maintenance と init の2系統だけで、startup はSetupでは使えない(あちらはSessionStartフック用のラベル)。
ステップ3: cronに毎晩2時起動を仕込む
crontab -e でcronの登録画面を開いて、1行追加します。
0 2 * * * cd ~/work/myproject && claude -p --maintenance "今日の作業ログを3行で要約して" >> ~/daily-summary.log 2>&1
これで毎日午前2時に、掃除スクリプトが走ってから「今日の作業ログを3行で要約して」のクエリ処理が動き、結果が ~/daily-summary.log に追記されます。
ステップ4: ここで初心者がやりがちな勘違いがある
掃除スクリプトの echo "cleanup done at $(date)" を、最初は標準出力にそのまま流しがちです。これだとClaude側のターミナル画面で確認できると思いがち。実はSetupフックのプレーンな出力はデバッグログにしか書かれず、画面には出ません。
だから上の例では >> ~/maintenance.log で自分のログファイルに書き出してます。後で tail -20 ~/maintenance.log でその場所を読むと、ちゃんと「cleanup done at ...」が並んでます。
ステップ5: 動作確認は手動で1回叩く
cronに入れる前に、手動で1回試します。
$ cd ~/work/myproject
$ claude -p --maintenance "テスト:今日の作業ログを3行で要約して"
掃除スクリプトが走った痕跡は ~/maintenance.log に、要約結果は標準出力に出ます。これが両方確認できれば、cron側に仕込んでOK。
ステップ6: 失敗時の挙動を知っておく
掃除スクリプトが何らかの理由で異常終了しても、本体のセッション処理は止まらず進みます。スクリプトが exit code 2 で終わった場合だけ、エラー出力(stderr)が画面に出る仕様。それ以外のゼロでない終了コードは --verbose を足さない限り見えません。だから「掃除が失敗してたのに気づかなかった」を防ぐには、スクリプト側で失敗時に exit code 2 を返すか、自前ログに記録するクセを持っておいた方がいいです。
つまり --maintenance は何をしてくれるのか
- やってくれる:
maintenance区分で登録したSetupスクリプトを、本体セッションの前に走らせる。スクリプトが終わってから print mode のクエリ処理が始まる - やってくれる: cronやCI(自動実行の仕組み)から呼びやすい起動形態を提供する。対話画面が開かないので、自動運用に向いてる
- やってくれない: 普通の
claude起動(対話モード)でmaintenance用スクリプトを発火させること。print modeとセットでしか効かない - やってくれない: スクリプトのプレーンな出力をClaudeに伝えること。Claudeに渡したいときは JSON で
additionalContextを返す書き方が必要 - 意味が薄い場面: 手動でその場限りの掃除をしたいとき。それなら
--maintenanceを使わずに、ターミナル側で直接掃除スクリプトを叩いた方が早い
使いどころ3シナリオ
シナリオ1: 開発用の一時保存を毎晩2時に掃除する
Node.jsやPythonの開発をしてると、ビルドの一時ファイルや古いダウンロード履歴が溜まります。毎晩 claude -p --maintenance "今日の変更履歴を5行で要約して" をcronに仕込んでおけば、掃除スクリプトが先に ~/.npm/_cacache や ~/Library/Caches/pip の古いものを消してから、その日の作業要約が ~/work-summary.log に書かれます。朝起きてログを開けば、前日のメモと一緒にディスクの状態も整ってる。
シナリオ2: 週次でログを7日でローテーションする
個人プロジェクトでも作業ログが溜まりすぎて検索が遅くなる。週次バッチで find ~/work-logs -mtime +7 -delete を maintenance 用スクリプトに仕込んで、毎週日曜の深夜に claude -p --maintenance "今週のhighlightを3つ抜いて" を回す。掃除と要約が1回の起動で済むので、別々のスクリプトに分けるより構造がシンプル。
シナリオ3: CI環境で「事前掃除→静的解析→Claude判定」を一連でつなぐ
GitHubのActions等で自動チェックを組むとき、maintenance 用スクリプトに「前回の中間生成物を消す」処理を置いておくと、CI用の claude -p --maintenance "コード差分の懸念点を箇条書きで" を呼ぶたびに毎回クリーンな状態から始まる。本体セッションの前段で掃除が走ってる保証が取れるので、結果のブレが減ります。
初心者が踏みやすい落とし穴
- 素の
claude --maintenanceだけだと無反応。必ず-pと組み合わせる。これは公式の起動スイッチ一覧に「print mode only」と明記されてる仕様 - matcher を間違える。
~/.claude/settings.jsonの matcher をinitにしたまま--maintenanceを叩いても、初期化用のフック扱いになっていて発火しない。matcher はmaintenanceと書く。なお Setup フックで使える matcher はinitとmaintenanceの2つだけで、startupは SessionStart フック用のラベル(Setupでは使えない) - スクリプトの出力が画面に出ない。Setupフックのプレーンな出力はデバッグログ行きで、ターミナルに流れません。確認したいなら自分でログファイルに書き出すか、
--verboseを足してエラー時の出力を見る - スクリプトの失敗が静かに無視される。exit code 2 以外の異常終了は、
--verboseなしだと画面に出ません。失敗時は2を返すように作るか、ログ監視を別に組む --init-onlyと混同する。--init-onlyはフックを走らせた後そのまま終了(exit)するクエリを渡せない終了専用の起動形態。後ろにクエリを書いても受け付けない。--maintenanceは--init-onlyと違い、フック実行後にそのまま print mode のクエリ処理に進んでセッション本体も実行される。「前処理スクリプトを走らせてからClaudeに要約を頼む」なら--maintenanceを使う- 対話モードで使おうとする。対話モードでは
--initと--maintenanceはSetupフックを発火させない仕様。CIやcronなど、自動運用専用の道具と割り切る - スクリプトの結果をClaudeに伝えたい場合の書き方。プレーンな
echoではなく、JSON形式でadditionalContextを返す必要があります。普通のprintfで満足してると、Claude側はその情報を知らないまま回答を作る
書き方
claude -p --maintenance "クエリ"
やってみるとこうなる
入力
claude -p --maintenance "今日の作業ログを3行で要約して"
出力例
(Setupフックの maintenance 区分に登録されたスクリプトが先に走り、その後に print mode のクエリ処理が動いて、3行の要約が標準出力に表示される)
たとえばこんな出力:
- 認証画面のバリデーションを修正
- 商品検索のレスポンス時間を改善
- 設定画面のテストを追加
このページに出てきた言葉
- Setupフック
- Claude Code起動時に、本体が動き出す前に差し込めるユーザー独自スクリプトの仕組み
- matcher
- Setupフックの中で「どのタイミング用か」を区別するラベル。Setupフック専用は <code>init</code> と <code>maintenance</code> の2種類で、<code>startup</code> は別フック(SessionStart)のラベル(Setupでは使えない)
- print mode (-p)
- 対話画面を開かず、質問1つに答えて即終了する起動形態。スクリプトやcronから自動呼び出しする用途向け
- cron
- 「毎日何時にこの命令を実行する」を予約しておけるパソコン側の機能
- stderr
- エラー専用の出力先。Setupフックは exit code 2 のときだけ stderr を画面に出す特別扱い
- additionalContext
- Setupフックの結果をClaude本体の文脈に渡したいとき、JSON形式で返すフィールド名。プレーンな出力はデバッグログ行きで本体に届かない