本文へ移動
記事一覧

Claude Codeの非対話モードをCIで使う|入出力・権限・失敗処理

公開 2026-09-16更新 2026-09-16読了目安 8分

Claude Code 非対話モードをCIで使う基本は、応答後に終了する `claude -p` です。終了コードを一次判定にし、JSON結果の権限拒否と完了条件も検査すれば、認証不足、タイムアウト、途中までの実行を成功と誤認しません。ただし、無人実行でどのツールまで許可するかは、ジョブの責務から先に決める必要があります。

SECTION 01

Claude Code 非対話モードは終了コードまで設計する

2026年9月16日に確認した公式仕様では、`claude -p` または `claude --print` は非対話で実行され、応答を出力して終了します。短い指示はコマンドライン引数で渡せ、ログや差分のような内容は標準入力からパイプできます。対話画面を自動操作する必要はありません。以下の仕様と例も同じ確認日を基準にしています。

ただし、画面にもっともらしい文章が出たことは成功の証拠になりません。`claude -p` は成功時に終了コード `0`、実行失敗時に非ゼロを返します。無効なフラグは実行前に標準エラーへ出る一方、認証不足など実行中の失敗は結果として標準出力へ出ます。さらに、許可されなかったツール呼び出しは実行中に拒否されても、モデルが別の手段で処理を続ける場合があります。CIは終了コードを一次判定にし、JSON結果の `subtype`、`is_error`、`permission_denials` と、ジョブ固有の完了条件をその後に検査します。

最小の一回実行は次の形です。シェルの `if` が `claude` 自体の終了状態を受け取り、失敗時はジョブを非ゼロで終わらせます。成功分岐の `require_success_result` は、`subtype` が `success`、`is_error` が `false`、`permission_denials` が空であることを検査するジョブ側の関数を表します。出力をファイルへ保存しても、`|| true` を付けたり、後続コマンドの成功で状態を上書きしたりしないことが要点です。 ```sh if claude -p "$CLAUDE_PROMPT" --output-format json > claude-result.json; then require_success_result claude-result.json || exit 1 else status=$? report_failure "$status" exit "$status" fi ```

標準入力を使う場合も契約は同じです。パイプできる入力は一回の呼び出しあたり `10MB` が上限で、超過すると明確なエラーと非ゼロ終了になります。大きな入力はファイルに置き、プロンプトからそのパスを参照させます。入力サイズを無視して再試行するのではなく、呼び出し前の条件として扱うべき制約です。

SECTION 02

一回実行と構造化出力を使い分ける

CIの出力は、人が読む回答と機械が受け取る結果を分けて考えます。`--output-format` に指定できるのは `text`、`json`、`stream-json` です。既定の `text` はプレーンテキスト、`json` は `result`、session ID、メタデータを含むJSON、`stream-json` はリアルタイム処理向けの改行区切りJSONを返します。

  • —一回の回答を人が読むだけなら `text` を使う。
  • —完了後の結果と会話識別子を機械処理するなら `json` を使う。
  • —進行中のイベントを逐次処理する必要があるなら `stream-json` を使う。
  • —固定フィールドを後続処理へ渡すなら `json` と `--json-schema` を組み合わせる。出力名ではなく、後続処理が完了後の一件を読むのか、途中のイベントも読むのかで決める。

SECTION 03

JSON Schemaで受け渡すフィールドを固定する

選択基準は「JSONなら安全」ではなく、後続処理が何を必要とするかです。業務用の固定フィールドが必要なら、`--output-format json` と `--json-schema` を併用します。構造化された値は `structured_output` フィールドに入り、無効なJSON Schemaを渡すと `claude` はエラー終了します。一方、Schemaの `format` キーワードは注釈として受理されるだけで、値の形式を強制検証しません。後続処理に固有の形式条件があるなら、そこで別途検査します。

次の例はSchemaを環境変数から与え、終了コードと `structured_output` の両方を検査する構成です。Schemaに適合する値を要求する責務と、プロセスが成功したかを判定する責務を混ぜていません。`require_structured_output` では `subtype`、`is_error`、`permission_denials` も併せて確認します。 ```sh if claude -p "$CLAUDE_PROMPT" \ --output-format json \ --json-schema "$CLAUDE_JSON_SCHEMA" > claude-result.json; then require_structured_output claude-result.json || exit 1 else status=$? report_failure "$status" exit "$status" fi ```

SECTION 04

継続会話はsession_idを明示して取り違えを防ぐ

一回実行で完結しない処理には会話の継続が必要です。直近の会話を続ける `--continue` と、session IDで特定の会話を続ける `--resume` があります。手元で直前の作業を続けるなら前者は簡潔ですが、複数ジョブが並行し得るCIで「直近」に依存すると、対象を機械的に固定できません。

初回を `--output-format json` で実行し、結果の成功条件を確認してから `session_id` をジョブの成果物として保持します。続きは明示したIDを `--resume` に渡します。 ```sh if claude -p "$INITIAL_PROMPT" --output-format json > first-turn.json; then require_success_result first-turn.json || exit 1 session_id=$(read_session_id first-turn.json) else status=$? exit "$status" fi if claude -p --resume "$session_id" "$FOLLOWUP_PROMPT" \ --output-format json > followup-turn.json; then require_success_result followup-turn.json || exit 1 else status=$? exit "$status" fi ```

SECTION 05

タイムアウトとターン上限を正常終了に変換しない

無人実行には終わり方の設計も必要です。`--max-turns` はprint modeのエージェントのターン数を制限し、上限へ達するとエラー終了します。既定ではターン数の上限がありません。したがって、上限到達を「指定したところまで処理できた成功」と読み替えるべきではありません。

外側のタイムアウト機構からSIGTERMで停止した場合、`claude -p` は終了コード `143` で終わり、進行中のターンは未完了のまま結果も記録されません。実行中のBashプロセスツリーも終了します。CIが `143` を許容したり、停止前の途中出力を完成結果として採用したりすれば、失敗を成功に見せてしまいます。

タイムアウト時間とターン上限はジョブの要件として外から渡し、どちらによる非ゼロ終了もそのまま失敗へ流します。数値をスクリプトへ埋め込むのではなく、ジョブごとに明示する例です。`run_with_sigterm_timeout` は、期限時に子プロセスへSIGTERMを送り、その終了状態を返すCI側のラッパーを表します。 ```sh if run_with_sigterm_timeout "$CLAUDE_TIMEOUT" -- \ claude -p "$CLAUDE_PROMPT" \ --max-turns "$CLAUDE_MAX_TURNS" \ --output-format json > claude-result.json; then require_success_result claude-result.json || exit 1 else status=$? report_failure "$status" exit "$status" fi ```

SECTION 06

無人CIの権限は必要なツールだけを許可する

非対話では、確認を待てないから全面許可するという判断が起こりがちです。しかし、`-p` の組み込みの開始時権限モードは全プランでManualです。`--allowedTools` は指定したツールを確認なしで実行可能にし、`--permission-mode dontAsk` は本来確認が必要な呼び出しを自動拒否します。作業ディレクトリ内のファイル読み取り、組み込みの読み取り専用コマンド、`--allowedTools` や `permissions.allow` で事前許可した操作は実行できます。CIでは、ジョブが必要とする最小限のツールを列挙し、未許可操作を止める実行で `dontAsk` を組み合わせます。

ただし、ツール拒否は必ずしもプロセス全体の非ゼロ終了を意味しません。最終結果の `permission_denials` が権限拒否の正本なので、空でない場合はジョブ側で失敗にします。Claude Code 2.1.259以降では、応答する人がいないジョブに `--permission-prompts none` を付けると、権限ホストを待たず、未解決の確認要求を拒否できます。権限モード、許可規則、`PermissionRequest`フックは先に評価されるため、このフラグだけを権限境界の代わりにはできません。

権限名はジョブの責務から環境変数へ明示し、失敗を握りつぶさない形に保てます。次の例はClaude Code 2.1.259以降を固定して使う前提です。 ```sh if claude --bare -p "$CLAUDE_PROMPT" \ --allowedTools "$CLAUDE_ALLOWED_TOOLS" \ --permission-mode dontAsk \ --permission-prompts none \ --output-format json > claude-result.json; then require_success_result claude-result.json || exit 1 else status=$? report_failure "$status" exit "$status" fi ```

許可設計そのものを整理したい場合は、Claude Codeの権限設定と安全な運用も参照できます。CI用の許可は、そこで定めた運用境界をジョブ単位へ落とし込むものです。

SECTION 07

スクリプトでは--bareで暗黙の読み込みを外す

同じコマンドでも、実行環境が暗黙に読み込む設定が違えばCIの挙動を説明しにくくなります。`--bare` は、フック、スキル、カスタムコマンド、サブエージェント、プラグイン、MCPサーバー、自動メモリ、`CLAUDE.md` の自動探索を省略し、CIやスクリプトでマシン差を減らす用途に向くモードです。公式ドキュメントでは、スクリプトとSDK呼び出しの推奨モードとされています。

ただし、`--bare` はOAuth資格情報やシステムキーチェーンも読みません。Anthropic APIを利用する場合は `ANTHROPIC_API_KEY` など必要な認証を別途与えます。暗黙の拡張を外すことと、必要な認証まで消して成功を期待することは別です。認証不足も実行中の失敗であり、終了コードに従ってジョブを失敗させます。

チームでこの境界を揃えるには、コマンドだけでなく、誰がSchema、権限、タイムアウト、再実行方針を管理するかも決める必要があります。Claude Code研修で身につける実践的な開発運用は、個人利用からチーム運用へ広げる際の検討材料になります。

SECTION 08

結論:入力・出力・終了・権限を一つの契約にする

`claude -p` をCIへ組み込むときの完成形は、呼び出せることではなく、結果を曖昧なく分類できることです。一回実行には引数または上限内の標準入力、機械処理には用途に合う出力形式、固定フィールドにはJSON Schema、継続会話には明示した `session_id` を使います。

  • —終了コード `0` を一次条件とし、標準出力の文面だけで成功と判定しない。
  • —非ゼロ、SIGTERM後の `143`、`--max-turns` 到達を失敗として保つ。
  • —`--allowedTools` を必要最小限にし、未許可操作を拒否する実行では `dontAsk` を使う。終了コードが `0` でも `permission_denials` が空でなければ失敗にする。
  • —環境差を減らすなら `--bare` を選び、必要な認証と設定は明示的に与える。この四点を同時に満たせないジョブは、無人実行へ移す前に責務を分割する。

SECTION 09

無人実行で最後に決めるべきこと

ツール権限は、プロンプトの都合ではなくジョブの責務から決めます。読み取りだけのジョブと変更を伴うジョブを同じ許可集合にせず、必要な操作だけを明示します。そのうえで、タイムアウトとターン上限は非ゼロ終了として保ち、権限拒否は `permission_denials` を検査してジョブ側で失敗にします。これで入力、出力、会話、終了、権限が一つの実行契約になり、途中まで動いた処理を成功扱いしない非対話運用になります。

無人CIの権限表、停止条件、結果検査、レビュー責任をチームの開発フローへ落とし込む場合、2026年9月16日時点でcotomuではAI駆動開発の導入研修を30万円/回、導入パッケージを50万円から、伴走顧問を月15万円から提供しています。いずれも参考価格・税別で、初回60分の相談は無料です。生産性や品質の向上を保証するものではなく、cotomuはClaude CodeやCodexの公式パートナー・認定事業者ではありません。

FAQ

よくある質問

Q. Claude Codeの非対話モードを起動する基本コマンドは何ですか?

`claude -p` または `claude --print` です。引数でプロンプトを渡すほか、標準入力から内容をパイプでき、応答を出力して終了します。

Q. CIでは標準出力に結果があれば成功と判定できますか?

できません。認証不足など実行中の失敗も標準出力へ出るため、まず終了コードを判定します。さらにJSON結果の `subtype`、`is_error`、`permission_denials` とジョブ固有の完了条件を検査し、許可拒否や未完了を成功扱いしないようにします。

Q. 並行するCIジョブで会話を継続するにはどうしますか?

初回のJSON出力から `session_id` を取得し、続く呼び出しの `--resume` へ明示します。直近の会話に依存する `--continue` より対象を固定できます。

公式情報・参考資料