原典: Run Claude Code programmatically / 日本語版

一行要約

claude -p は Agent SDK の CLI 版であり、CI やスクリプトで再現性が要るなら --bare(hook / skill / カスタムコマンド / subagent / plugin / MCP サーバ / auto memory / CLAUDE.md の自動発見をすべて飛ばす)を付けるのが推奨。

要点

基本

claude -p "Find and fix the bug in auth.py" --allowedTools "Read,Edit,Bash"
  • -p は --print の別名
  • 成功で exit code 0、失敗で非ゼロ。スクリプトは exit status で分岐できる
  • 不正なフラグは実行前に stderr へ報告される。実行中の失敗(認証エラーなど)は stdout に結果として出る
  • -p と併用できないオプションがある — --bg は拒否される。--cloud はタスク記述と併用すると拒否され、セッション ID と併用するとそのクラウドセッションにメッセージを積んで終了する

--bare(CI での推奨)

Add --bare to reduce startup time by skipping auto-discovery of hooks, skills, custom commands, subagents, plugins, MCP servers, auto memory, and CLAUDE.md.

--bare を付けると、hook・skill・カスタムコマンド・subagent・plugin・MCP サーバ・auto memory・CLAUDE.md の自動探索を省略して起動時間を短縮できる。

A hook in a teammate’s ~/.claude or an MCP server in the project’s .mcp.json won’t run, because bare mode never reads them.

teammate の ~/.claude にある hook や、プロジェクトの .mcp.json にある MCP サーバは動かない。bare モードはそれらを一切読まないからである。

--bare を付けないと、信頼していないフォルダの設定がそのまま走る:

Without --bare, a -p session runs the hooks in a project’s .claude/settings.json and connects the servers in its .mcp.json, even in a folder you’ve never trusted. A -p session shows no workspace trust dialog and no per-server approval prompt.

--bare が無いと、-p のセッションはプロジェクトの .claude/settings.json にある hook を走らせ、.mcp.json にあるサーバに接続する。一度も信頼していないフォルダでもそうなる。 -p のセッションには workspace trust のダイアログもサーバごとの承認プロンプトも出ない。

--add-dir は部分的な例外: bare mode はそのディレクトリの .claude/skills/ から skill を読む。.claude/commands/ と .claude/agents/ は読まない。

認証の注意: bare mode は OAuth 認証情報も system keychain も読まない。Anthropic API を使うなら ANTHROPIC_API_KEY を環境に設定する(Bedrock / Agent Platform / Foundry は各プロバイダの認証情報を通常どおり読む)。

bare mode で使えるツールは Bash、ファイル読み取り、ファイル編集。必要な context はフラグで渡す。

走っている間も制限が効く(v2.1.286 以降。それより前は一部しか効いていなかった):

  • MCP サーバ —— --mcp-config などコマンドラインで渡したものだけがつながる。対話セッションでは --ide を付けない限り IDE への自動接続もしない
  • system reminder —— Claude はプロンプトとツール結果だけを受け取る。前に読んだファイルがディスク上で変わっても知らされず、使える skill の一覧(--add-dir のフォルダの skill を含む)も届かない
  • バックグラウンドタスク —— 走らない。タイムアウトに達したコマンドはバックグラウンドに移らず止まる
ロードしたいものフラグ
system prompt への追記--append-system-prompt, --append-system-prompt-file
設定--settings <file-or-json>
MCP サーバ--mcp-config <file-or-json>
カスタムエージェント--agents <file-or-json>
plugin--plugin-dir <path>, --plugin-url <url>

出力形式

--output-format内容
text(既定)プレーンテキスト
json結果・セッション ID・メタデータを含む構造化 JSON。total_cost_usd とモデル別のコスト内訳も含む(クライアント側の推定値。--continue / --resume で続けた実行は、以前の実行の分も含めた会話全体の合計を出す)
stream-json改行区切り JSON。リアルタイムストリーミング

スキーマに従わせるには --output-format json + --json-schema。結果は structured_output フィールドに入る。

Claude Code accepts schemas that use the format keyword, such as "format": "email", but treats format as an annotation and doesn’t enforce it.

Claude Code は "format": "email" のように format キーワードを使うスキーマを受け付けるが、format は注釈として扱い、強制はしない。

スキーマが JSON Schema として不正なら Error: --json-schema is not a valid JSON Schema とバリデータの診断を出して終了する(v2.1.205 より前は不正なスキーマを黙って無視し、構造化されていないテキストを返していた。format を含むスキーマも一律に不正扱いだった)。

ストリーミング

--output-format stream-json --verbose --include-partial-messages でトークンごとに受け取る。最後の行は result メッセージで、最終応答テキスト・コスト・セッションメタデータを含む。

読み手が遅いとき、Claude Code は溜まった出力を吐き切るまで終了を待つ。待ち時間は残量に応じて伸び、上限は30秒(v2.1.214 より前は約2秒が上限で、大きな応答の末尾が切れることがあった)。

subagent のメッセージは parent_tool_use_id にそれを起こしたツール呼び出し(Agent ツール、または fork で走る skill なら Skill ツール)の ID を持つ(メイン会話は null)。foreground の subagent の最初のメッセージは、それを動かすプロンプトを載せた user メッセージ(subagent で走る skill も同じ形)。既定では subagent の tool_use / tool_result ブロックだけが出る。 --forward-subagent-text または CLAUDE_CODE_FORWARD_SUBAGENT_TEXT でテキストと thinking も出せる。入れ子の subagent も全深さで転送されるので、ID を辿れば入れ子ツリーを再構築できる。

主要なイベント:

イベント用途
system/initセッションメタデータ(モデル、ツール、MCP サーバ、plugin)。通常は最初のイベント
system/api_retryリトライ可能なエラーでの再試行。attempt / max_retries / retry_delay_ms / error_status / error
system/plugin_installmarketplace plugin のインストール進捗(CLAUDE_CODE_SYNC_PLUGIN_INSTALL 設定時)

CI で plugin / MCP のロード失敗を検知する(system/init のフィールド):

フィールド内容
pluginsロードに成功した plugin
plugin_errorsロード時エラー。エラーがなければキー自体が省略される。--plugin-dir のディレクトリやアーカイブ自体が読めなかったときは、解決後の絶対パスが path に入る(複数の --plugin-dir のどれが落ちたかが分かる。v2.1.283 以降)
mcp_serversセッション内の MCP サーバと status
mcp_server_errors検証で skip された --mcp-config エントリ。エラーがなければキーが省略されるので、非空配列で CI を落とせる

system/init の capabilities 配列を見ればプロトコル挙動を feature-detect できる。バージョン文字列の比較ではなくこちらを使う。

--mcp-config を -p と併用すると、最初のターンの前に pending のサーバを待つ —— 上限は MCP_TIMEOUT(既定30秒)。ツール一覧がキャッシュされているリモートサーバはこの待ちを飛ばし、system/init には pending と出て、最初のツール呼び出しのときに接続する。

権限の扱い

  • 何も permission mode を決めていない -p は組み込みの開始モードで走り、それは auto になりうる(permission-modes)。基準を決めたいなら自分で渡す
  • --allowedTools で個別ツールを事前承認する。ただし auto mode で始まる run では、裸の Bash は広すぎる allow として落とされ、コマンドごとに auto mode が審査する
  • セッション全体の基準を決めるなら permission mode を渡す
    • auto — 分類器がほとんどの操作を代わりに審査する
    • dontAsk — permissions.allow と読み取り専用コマンド以外を拒否。ロックダウンした CI 向け。AskUserQuestion、組織が ask にした connector ツール、requiresUserInteraction の MCP ツールは、allow ルールに一致していても拒否される
    • acceptEdits — ファイル書き込みと mkdir / touch / mv / cp を自動承認。読み取り専用のコマンド以外のシェルコマンドとネットワークリクエストには、まだ --allowedTools か permissions.allow のルールが要る(確認に答える相手のいない -p では、他に何も決めないリクエストは拒否され、run は続く)

無人実行で prompt を止める --permission-prompts none(v2.1.259 以降。それより前は unknown-option で拒否される):

  • 効くのは応答役がいる run —— Agent SDK の canUseTool コールバックや --permission-prompt-tool で渡した MCP ツール。このフラグが無いと、run はその応答役の返事を1件ずつ待つ
  • 付けると応答役に問い合わせも待ちもしない。PermissionRequest hook が許可しない限り拒否され、Claude には「承認できる者はいない、再試行するな」と伝わって run は続く
  • 人の答えを要するツール(AskUserQuestion など)は取り除かれ、Claude は呼べなくなる。Elicitation hook が答えない MCP の elicitation 要求は cancel される
  • --output-format stream-json では拒否が permission_denied の system メッセージとして出て、最後の result メッセージの permission_denials に並ぶ

The --allowedTools flag uses permission rule syntax. The trailing * enables prefix matching, so Bash(git diff *) allows any command starting with git diff. The space before * is important: without it, Bash(git diff*) would also match git diff-index.

--allowedTools フラグは permission ルールの構文を使う。末尾の * が前方一致を有効にするので、Bash(git diff *) は git diff で始まる任意のコマンドを許可する。* の前の空白が重要である。空白がないと Bash(git diff*) は git diff-index にも一致してしまう。

バックグラウンドタスクの扱い

  • バックグラウンド Bash タスク(dev server や watch build)は、最終結果が返り stdin が閉じてから約5秒後に終了させられる
  • バックグラウンドの subagent と workflow はこの5秒の対象外 — 結果が最終出力の一部なので claude -p は完了を待つ。待ち時間は既定で最大10分(CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS で調整、0 で無制限)。上限に達すると走っているものを止め、その部分結果は捨てる
  • Monitor の watch も待つ。watch がタイムアウトするか10分の上限に達するかの早いほうまで。watch の既定のタイムアウトは開始から5分。待っている間も Claude は watch の報告に応え続ける

SIGTERM で停止したとき(kill や process supervisor から):

Claude Code exits with code 143. Claude Code leaves the turn that was in progress unfinished and records no result for it. To end the turn instead, send SIGINT, or call the Agent SDK’s interrupt(), before you stop the process.

Claude Code は exit code 143 で終了する。進行中だったターンは未完了のまま残り、その結果は記録されない。ターンのほうを終わらせたいなら、プロセスを止める前に SIGINT を送るか、Agent SDK の interrupt() を呼ぶ。

  • 実行中の Bash のプロセスツリーを終了させ、SessionEnd hook を走らせて終了する。終了処理の間は、新しいツール呼び出しもモデルへのリクエストも起こらず、SessionEnd 以外の hook も走らない
  • コマンド実行中だった場合、そのコマンドはセッションに killed として記録される
  • permission prompt の返事を待っていた場合、SIGTERM では未応答のまま残る。Agent SDK 側からセッションを閉じた場合は、SDK が先に入力を閉じるので prompt は cancel される
  • セッションを resume しても、SIGTERM が中断したターンはそのまま残り、次のプロンプトで会話が進む。中断したターンの続きから再開させたいなら CLAUDE_CODE_RESUME_INTERRUPTED_TURN=1

作業ディレクトリがセッションの途中で消えたとき: -p と Agent SDK のセッションは走り続ける。ディレクトリが無い状態でターンが始まると stream-json 出力に警告メッセージが出て、ディレクトリが戻るまでシェルコマンドは失敗する。

その他の注意

  • パイプで渡す stdin は 10MB が上限。 超えるとエラーで非ゼロ終了する。大きい入力はファイルに書いてパスをプロンプトで参照する
  • -p モードでも user-invocable な skill とカスタムコマンドは使える — プロンプト文字列に /skill-name を入れれば展開される。/login のような端末専用の組み込みコマンドは使えない
  • /model、/effort、/fast、/color、/rename は値を引数として受け取る(/model sonnet)。引数なしの /mcp はサーバ状態のテキスト要約を出す(v2.1.205 以降)。設定変更は /config thinking=false の形、/output-style <style> で出力スタイルを切り替える(v2.1.269 以降)
  • stdin が読めないとき(起動元が自分の端を切ったなど)は、stderr に警告を出してコマンドラインのプロンプトで続行する
  • --continue は終了済みのバックグラウンドセッションは開くが、まだ走っているものは開かない(v2.1.257 以降)
  • --resume にはセッション ID のほか、セッションの .jsonl トランスクリプトの絶対パスも渡せる。ID はこのマシンのどのプロジェクトからでも見つかる(v2.1.223 より前は、同じディレクトリから実行しないと見つからなかった)
  • --append-system-prompt は既定の挙動を保ったまま追記する。既定のプロンプトごと置き換えたいなら --system-prompt

そのまま使える具体例

CI 向けの最小形:

claude --bare -p "Summarize README.md" --allowedTools "Read"

パイプで渡してファイルに書き出す:

cat build-error.txt | claude -p 'concisely explain the root cause of this build error' > output.txt

package.json に typo linter として組み込む(diff をパイプするので Bash 権限が不要になるのが巧い):

{
  "scripts": {
    "lint:claude": "git diff main | claude -p \"you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else.\""
  }
}

構造化出力:

claude -p "Extract the main function names from auth.py" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'

jq で取り出す:

claude -p "Summarize this project" --output-format json | jq -r '.result'
 
claude -p "Extract function names from auth.py" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
  | jq '.structured_output'

ストリーミングしてテキストだけ流す:

claude -p "Write a poem" --output-format stream-json --verbose --include-partial-messages | \
  jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'

ツールを事前承認する:

claude -p "Run the test suite and fix any failures" \
  --allowedTools "Bash,Read,Edit"
 
claude -p "Apply the lint fixes" --permission-mode acceptEdits

コミットを作らせる(接頭辞マッチの空白に注意):

claude -p "Look at my staged changes and create an appropriate commit" \
  --allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"

PR のセキュリティレビュースクリプト(review.sh、bash review.sh 123 で実行):

gh pr diff "$1" | claude -p \
  --append-system-prompt "You are a security engineer. Review for vulnerabilities." \
  --output-format json

会話を継続する:

# First request
claude -p "Review this codebase for performance issues"
 
# Continue the most recent conversation
claude -p "Now focus on the database queries" --continue
 
# 特定のセッションを resume する
session_id=$(claude -p "Start a review" --output-format json | jq -r '.session_id')
claude -p "Continue that review" --resume "$session_id"

原典で言及されている関連文書

  • permission-modes — dontAsk / acceptEdits の詳細
  • sub-agents — バックグラウンド subagent の待機とツールセット
  • hooks-guide — -p モードで走る hook(--bare では走らない)
  • workflows — -p では workflow が待機実行になる
  • costs — --output-format json の total_cost_usd
  • cli-reference — 全 CLI フラグ
  • env-vars