Claude Code 実践検証 Day 9|Headlessモードの設定反映と終了コードの謎
Claude Codeの-pオプション、使ってますか?
ワンライナーでClaude Codeにタスクを投げられる機能です。自動化スクリプトでの活用を想定した「Headlessモード」ですね。
claude -p "このコードのバグを修正して"
公式ドキュメントを読むと、これで自動化できそうな印象を受けます。でも実際にやってみると…「あれ?設定反映されてない?」「エラーなのに終了コード0?」みたいな事態に遭遇するんですよね。
私も最初、思うように自動化できず調査が難航しました。
公式ドキュメントの説明
まずは公式が何を言っているか整理しておきましょう。
公式ドキュメント(CLI Usage)によると、Headlessモードでは以下のオプションが使えます。
基本オプション
| オプション | 説明 |
|---|---|
-p, --print |
プロンプトを送信し、応答を出力して終了 |
--output-format |
出力形式(text/json/stream-json) |
--max-turns |
エージェントのターン数上限 |
--allowedTools |
使用可能なツールの制限 |
--dangerously-skip-permissions |
承認プロンプトをスキップ |
設定ファイル
-
CLAUDE.mdはプロジェクトルートから読み込まれる -
settings.local.jsonの設定が適用される - Hooksも設定すれば発火する
…と、公式にはこう書いてあるんですが。
検証したい観点
自動化スクリプトで実際に使おうとすると、いくつか疑問が出てきます。
疑問1:Hooksは本当に発火するのか?
対話モードでは、PreToolUseやPostToolUseでスクリプトを実行できます。ログを取ったり、特定の操作を禁止したり、便利ですよね。
でもHeadlessモードではどうなんでしょう。
「対話なしで動く」のがHeadlessモードの特性です。ということは、Hooksの発火タイミングも変わってくる?そもそも発火する?公式には明確な記載がないんですよね。
疑問2:終了コードはエラー時に0以外になる?
自動化スクリプトでは終了コードが生命線です。
claude -p "テストを実行" || exit 1
こういう書き方をしたいわけですが、パーミッションエラーやmax-turns制限に達した場合、ちゃんと非0で終了してくれるんでしょうか。
「失敗したのに終了コード0」だと、スクリプトが正常終了扱いになってしまいます。これ、かなり怖いですよね。
疑問3:Windows環境でどのシェルを使うべき?
既存のClaude Code記事はMac/Linux前提が多いです。でもWindows環境でも使いたい人はいるはず。
PowerShellから呼び出す場合と、Git Bashから呼び出す場合で差異があるか。日本語出力は文字化けしないか。確認しておきたいポイントです。
疑問4:設定ファイルは読み込まれるのか?
対話モードでは確実に読み込まれるCLAUDE.mdやsettings.local.json。
Headlessモードで起動した場合も同じように読み込まれるのか。permissions.allowやpermissions.denyは機能するのか。この辺の一貫性が気になります。
疑問5:スラッシュコマンドは使えるのか?
/compactでコンテキストを圧縮したり、カスタムコマンド/my-commandを呼び出したり。対話モードでは便利な機能ですよね。
ただ、公式ドキュメントには「Control Claude's behavior during an interactive session with slash commands.」と書いてあります。「interactive session」と明記されている以上、Headlessモードでは非対応と考えるのが妥当でしょう。
これについては検証しません。仮に動作したとしても、公式がサポートを保証していない使い方になるので。
検証項目の一覧
明日の検証では、以下を確認します。
| 項目 | 検証内容 | 判定基準 |
|---|---|---|
| 設定ファイル読み込み | CLAUDE.md、settings.local.jsonの反映 | 対話モードと同じルールが適用されるか |
| Hooks発火 | PreToolUse/PostToolUseの発火有無 | ログファイルが生成されるか |
| 終了コード | エラー時(deny、max-turns等)の終了コード | 非0で終了するか |
| シェル比較 | Git Bash vs PowerShellの動作差異 | 日本語出力、エラー処理の差 |
| 出力形式 | json、stream-jsonの動作 | コスト情報、エラー情報が取得できるか |
| タイムアウト | 長時間実行時のハング回避 | timeoutコマンドとの併用可否 |
検証環境
今回の検証環境は以下の通りです。バージョンによって挙動が変わる可能性があるので、明記しておきます。
| 項目 | 値 |
|---|---|
| OS | Windows 11 Pro |
| Claude Code | v2.0.60 |
| Git Bash | Git for Windows付属 |
| PowerShell | 7.x(UTF-8設定済み) |
シェルは主にGit Bashを使用しますが、PowerShellとの比較検証も行います。
明日の予告
検証は完了しています。結果を先に言うと、公式ドキュメントとの差異がいくつか見つかりました。
特に大きかったのは2点。
- HooksはHeadlessモードでは発火しない
- 終了コードは常に0(エラーでも!)
自動化スクリプトを書こうとしている方、この2点は要注意です。回避策も含めて、明日詳しく解説します。
Windows環境でのシェル選択についても、明確な結論が出ました。PowerShellでの日本語出力は…ちょっと残念な結果でしたね。
Headlessモードをスクリプトから呼び出そうとしている方、ぜひ参考にしてください。
シリーズ情報
- シリーズ名:Claude Code 実践検証ガイド 2025
- 著者:Akira
- 検証環境:Windows 11 / Git Bash / Claude Code v2.0.60
次回:Day 10「Headless検証結果:Hooks無効、終了コード常に0の衝撃」
Discussion