注記: 本記事の調査(Claude Code の内部動作や権限モデルの裏取り)には、Claude と、そのリサーチ機能を利用しています。細部は更新が速い領域なので、参考にされる場合は、必ず公式ドキュメントで確認してください。本記事は2026年7月時点の情報をもとにしています。
はじめに
前回の記事では、Claude Code や aider、cline といったエージェント型コーディングツールを「ハーネス」として横並びに眺めました。ハーネスとは、固定されたモデル(δ)を取り囲み、テープ(コンテキスト)を組み立ててモデルに投入し、返ってきた出力に応じてツールを動かし、その結果をテープに書き戻して、また投入する。この読み書きループを成立させる実行環境でした。UVMのテストベンチが DUT を駆動して応答を検査するのと同じ構図です。
前回は複数のハーネスを俯瞰しましたが、今回はそのうちの一つ、Claude Code を取り上げます。なお、Claude Code の内部システムプロンプトやループ実装は公式に完全公開されているわけではありません。ですので本記事は「内部を暴く」ものではなく、公開ドキュメントと観測できる挙動をもとに、処理モデルを分解して理解するものだとご理解ください。題材にするのは、日常でよく使う2つの GitHub プルリクエスト(PR)操作です。
- PRを出す側: 「今の変更をコミットして feature ブランチを切って push し、main 向けの PR を作成して」
- PRを処理する側: 「開いている PR を確認して、指定した PR を checkout して diff をレビューし、
gh pr reviewでコメントを投稿して」
どちらも自然言語の一文です。この一文を投げると、Claude Code の内部で「思考 → コマンド実行 → 結果の観察 → 次の判断」というループが何周も回ります。本記事の狙いは、その一周ずつを分解して、ハーネスの内部で何が起きているかを追うことです。使いこなすには、この内部フローを理解しておくのが近道だと考えています。
前回が「ハーネスを外から眺める話」だったとすれば、今回は「一台のハーネスの動きを、外から観察できる範囲で分解する話」になります。
エージェントループ ─ 一周の解剖
まず全体像です。Claude Code に限らず、エージェント型ハーネスの心臓部は、モデル呼び出しとツール実行を交互に回すループです。前回の言葉で言えば「テープを投入 → 出力 → ツール実行 → テープに追記 → また投入」の反復に当たります。
Claude Code の一周は、おおむね次の5段階に分けられます。
ここで押さえておきたいのは、ループを回すか止めるかの起点になっているのが、モデル応答に付く stop_reason であるという点です。モデルが応答を返すとき、API は「なぜ生成を止めたか」を示す stop_reason を一緒に返します。これが tool_use なら「ツールを使いたいので実行結果をくれ」という意味で、ハーネスはツールを実行して結果を返し、ループを継続します。end_turn なら「言いたいことは終わった」という意味で、ハーネスはループを抜けてユーザーに制御を戻します。
ただし、stop_reason だけでループが回っているわけではありません。API レベルでも end_turn / tool_use のほかに max_tokens(トークン上限で打ち切り)、pause_turn(長時間実行の一時停止)、stop_sequence、refusal、model_context_window_exceeded といった値があり、それぞれで振る舞いが変わります。さらに Claude Code 側には、次章で見る権限チェックのほか、hooks(実行前後のフック)、コンテキストのコンパクション(圧縮)、失敗時のリトライといった制御層が重なっています。ですので正確には、モデルの stop_reason を起点に、ハーネス側の複数の制御が組み合わさってループが進むと捉えるのがよいでしょう。前回「δ は状態を持たない純粋関数」と書きましたが、その純粋関数が毎回「次はツールを呼びたい/もう終わり」というフラグを吐き、ハーネスがそれを起点に外部世界を操作している、という関係になります。
段階ごとに何が起きているかを表にします。
| 段階 | 名前 | 中身 | テープの言葉で言うと |
|---|---|---|---|
| 1 | コンテキスト構築 | システムプロンプト、ツール定義、CLAUDE.md、会話履歴を組む | 毎ターンの初期テープを敷く |
| 2 | モデル呼び出し | 次の行動を1手だけ決める | テープを読んで次の記号を書く |
| 3 | 権限チェック | 実行しようとするツールを許可するか判定 | 書き込み先への到達可否を判定 |
| 4 | ツール実行 | Bash / Read / Edit などを実際に走らせる | ヘッドを動かして外界を操作 |
| 5 | 結果の観察 | 実行結果を tool_result として履歴に追記 |
外界の事実をテープに書き戻す |
そしてこの1〜5が、stop_reason が end_turn になるまで何周も繰り返されます。PR作成のような多段の作業は、この周回が5回にも10回にもなる、というだけの話です。
ツールという「ヘッドの動かし方」
エージェントループの4段目、ツール実行を掘り下げます。前回の比喩では、ハーネスは「テープの読み書きヘッド」に相当する部分を担っていました。そのヘッドの具体的な動かし方が、ツールです。
Claude Code の組み込みツールは、おおまかに次のように分類できます。
| 分類 | ツール | 役割 |
|---|---|---|
| シェル実行 | Bash(macOS/Linux)/ PowerShell(Windows) | 任意のコマンドを実行。git も gh もここを通る |
| ファイル読み | Read | ファイル内容をテープに載せる |
| ファイル書き | Write / Edit | ファイルを新規作成・部分編集する |
| 検索 | Grep / Glob | パターンやファイル名で探し、必要な断片だけ載せる |
| タスク管理 | TaskCreate / TaskUpdate / TaskGet / TaskList | 多段タスクの計画と進捗を管理する |
| 委譲 | Agent(サブエージェント) | 別のコンテキスト窓に下請けを出す |
| 外部接続 | MCP 経由のツール | 外部システムへテープを延長する |
ツール名についての補足です。以前は多段タスクの管理に
TodoWrite、サブエージェント起動にTaskという名前が使われていましたが、現行仕様ではタスク管理はTaskCreate/TaskUpdate/TaskGet/TaskListに、サブエージェント起動はAgentツールに整理されています(Task*はタスクリスト管理系、Agentは委譲系、という住み分け)。ツール名は版によって変わるので、最新は公式ドキュメントで確認してください。
ここで本題に直結する重要な事実があります。git コマンドも gh(GitHub CLI)コマンドも、専用ツールがあるわけではなく、シェル実行ツールを経由して実行されるという点です。macOS/Linux/WSL では Bash ツール、Windows では PowerShell ツールが主な経路になりますが、いずれにせよ「シェルにコマンド文字列を渡して外部プロセスを起動する」という構造は共通です。以下では説明を簡潔にするため、代表として Bash 経由の例で書きます。
つまり Claude Code は、PR を作るために「PR作成ツール」を持っているわけではありません。モデルが「gh pr create --title ... --body ... というコマンドを Bash で実行したい」と判断し、そのコマンド文字列を組み立て、Bash ツールに渡し、GitHub CLI が実際の GitHub API を叩く、という多段の間接構造になっています。
この構造を理解しておくと、いくつかのことが腑に落ちます。
-
ghの認証は Claude Code とは独立です。事前にgh auth loginで認証を済ませておく必要があり、これが未設定だとghコマンドがそのまま失敗します。Claude Code は失敗した標準エラー出力をテープに書き戻し、それを読んで「認証が必要そうだ」と次の手を考えます。 - モデルが生成するのは、あくまでコマンド文字列です。だから GitHub の操作能力は、突き詰めれば
ghCLI が持つ機能そのものに等しくなります。gh pr create、gh pr checkout、gh pr review、gh pr list、gh pr mergeといったサブコマンドが、そのまま Claude Code のできることの上限を決めます。 - Bash 経由であるということは、権限管理も Bash コマンド単位でかかる、ということです。次章の話につながります。
前回、ハーネスを「読み書きヘッド」と言い切るのは雑だと書きました。この間接構造がまさにそれで、ヘッドは単純に動くのではなく、モデルの生成したコマンドを解釈し、権限を確認し、外部プロセスを起動し、結果を回収してテープに戻す、という何段もの仲介をしています。
権限モデル ─ ハーネスは境界装置でもある
前回の最後に「ハーネスは能力の増幅器であると同時に、権限の境界装置でもある」と書きました。Claude Code でこの境界を担うのが、パーミッション(権限)システムです。PR操作は git push や gh pr merge のように外界へ影響を及ぼすコマンドを含むので、この仕組みの理解は実務で効いてきます。
許可の3分類と評価順
Claude Code は、ツール実行のたびに、そのコマンドを allow / deny / ask のどれに当てるかを判定します。設定は settings.json(プロジェクト単位・ユーザー単位・エンタープライズ単位で階層化)に書けます。
評価は deny → ask → allow の順に行われます(概念図)。
ポイントは評価の順序です。ここで注意したいのは、ask が allow より先に評価される点です。つまり、あるコマンドに対してより具体的な allow ルールを書いていても、ask にマッチすれば確認を求められます。「自動許可したつもりが毎回聞かれる」という現象は、たいていこの順序が原因です。
そして deny が最優先で、ここにマッチすれば他の設定に関わらず必ず拒否されます。破壊的なコマンドを禁止したいときは、allow を絞るより deny に明示的に書くほうが確実です。
なお上の図は概念を示したもので、実際にはこのほかに、読み取り専用コマンドの扱い、hooks、サンドボックス、危険な削除に対する回路遮断(後述)などが絡みます。厳密な挙動は公式の permissions ドキュメントを参照してください。
パーミッションモード
Claude Code は、セッション全体の挙動を決めるモードを持っています。主要なものを表にします。
| モード | 挙動 | PR操作での使いどころ |
|---|---|---|
| default | 影響のある操作ごとに確認を求める | 通常運用。push や merge の直前で止まる |
| acceptEdits | ファイル編集は自動承認、コマンドは確認 | レビュー指摘の反映など編集主体の作業 |
| plan | 読み取りのみ。書き込み・実行はしない | 実行前に計画だけ立てさせる |
| bypassPermissions | 通常の確認を大きく省略。ただし明示的な ask ルールや一部の安全弁は残る | 隔離した CI など非対話環境。対話では非推奨 |
plan モードは特に PR ワークフローと相性が良い場面があります。「何をやるつもりか」を先に立てさせ、破壊的な操作に入る前に人間がゲートを通す、という運用ができます。ターミナルでは Shift+Tab でモードを切り替えられます。
bypassPermissions(いわゆる --dangerously-skip-permissions)は、名前から「承認を全部飛ばす」と誤解されがちですが、正確には通常の確認プロンプトを大きく省略するモードです。すべてを無制限に実行するわけではなく、明示的に書いた ask ルールは依然として確認を強制しますし、rm -rf / や rm -rf ~ のような root/ホームディレクトリを消す操作には回路遮断(circuit breaker)が働きます。ですので「完全に無制限」というより、隔離環境で使うべき強い自動承認モードと捉えるのが実態に近いです。
とはいえ、対話セッションで常用すれば、モデルが git push --force や gh pr merge を確認なしで走らせる余地はぐっと広がります。前回の言葉で言えば、テープを外界へ延ばすほど攻撃面も外界へ広がるので、ここは能力と安全のトレードオフを意識して設定すべきところです。使うなら、CI や使い捨てコンテナのように「壊れても影響が閉じる」環境に限るのが安全です。
allowlist 設計の実務
PR操作を快適かつ安全に回すには、settings.json で「安全な読み取り系は自動許可、影響のある書き込み系は確認」と切り分けるのが定石です。考え方の例を挙げます(具体的な記法は公式ドキュメントで確認してください)。
| コマンド | 分類の目安 | 理由 |
|---|---|---|
git status / git diff / git log
|
allow | 読み取りのみ、副作用なし |
gh pr list / gh pr view
|
allow | 読み取りのみ |
git add / git commit
|
allow か ask | ローカルに閉じるが履歴を作る |
git push |
ask | リモートに影響 |
gh pr create |
ask | PR という外向き成果物を作る |
gh pr merge |
ask か deny | main への統合。慎重に |
git push --force |
deny 寄り | 破壊的。明示許可がなければ止める |
こうしておくと、レビューのための git diff や gh pr view はループを止めずに流れ、git push や gh pr merge の手前でだけ人間の確認が入る、というテンポの良い運用になります。
ケーススタディ1:PRを出す側
補足: 現在の Claude Code には、PR 系ワークフローに寄せた組み込みコマンド(
/code-reviewなど。--commentを付けると GitHub PR へのコメント投稿を意識した動きになるとされます)も用意されています。本記事の主題は「素の自然言語プロンプトが shell/ghを通じてどう分解・実行されるか」を見ることなので、以下ではあえて専用コマンドを使わず、一文のプロンプトがループに展開される様子を追います。実務では専用コマンドのほうが速い場面も多い、という点は補足しておきます。
ここから、実際のプロンプトを題材に内部フローを追います。まずは出す側です。
「今の変更をコミットして feature ブランチを切って push し、main 向けの PR を作成して」
この一文が、内部では複数ターンのループに展開されます。シーケンス図で追います。
一周ずつの内部動作を、テープの観点で言い直すとこうなります。
- 計画の書き出し: 多段作業なので、モデルはまずタスク管理ツール(
TaskCreateなど)で「状況把握 → コミット → ブランチ → push → PR作成」という骨格をテープに書きます。前回の表現なら「テープに作業の骨格を書いておく」に当たります。これで長いループの途中で目的を見失いにくくなります。 - 状況把握:
git statusとgit diffを実行します。これらは読み取り系なので allowlist で自動許可され、ループは止まりません。ここで得た diff が、後段のコミットメッセージや PR 本文の材料になります。diff の中身をテープに載せてはじめて、モデルは意味のあるメッセージを書ける、という依存関係があります。 - ブランチ作成:
git checkout -b feature/...を実行します。ブランチ名は、載せた diff の内容からモデルが推測して組み立てます。 - コミット:
git addとgit commitを実行します。複数行のコミットメッセージを安全に渡すために、Claude Code はしばしば HEREDOC(git commit -m "$(cat <<'EOF' ... EOF)"の形)を使ってメッセージを流し込みます。これはシェルのエスケープ事故を避けるための定石です。 - push:
git push -u origin feature/...はリモートに影響するので、ここで承認ゲートが入ります(default モードの場合)。 - PR作成:
gh pr createを実行します。タイトルと本文は、2で載せた diff とコミット履歴からモデルが生成します。リポジトリに PR テンプレートがあれば、それを読み込んで従わせることもできます。
ここで前回のテープ理論が効いてくるのは、2で diff をテープに載せる工程です。diff を載せなければ、モデルは「何を変えたか」を知らないまま PR 本文を書くことになり、中身のない説明文になります。良い PR 本文は、良いテープ(適切な diff がコンテキストに載っていること)があってはじめて書ける。前回の「動かせるのはテープだけ」が、そのまま成果物の質に直結します。
ケーススタディ2:PRを処理する側
次にレビュー側です。
「開いている PR を確認して、指定した PR を checkout して diff をレビューし、
gh pr reviewでコメントを投稿して」
こちらは「大きな出力をどうテープに載せるか」という、前回で言う窓の管理が主役になります。
内部で注目すべき点を挙げます。
- diff がテープを圧迫しうる: 大きな PR の
gh pr diffは、数千行の出力になることがあります。これがそのままテープ(コンテキスト窓)に載ると、窓を圧迫します。前回書いたとおり、Claude Code は用途の違う複数段の圧縮を持っていて、古いツール出力を削ったり履歴を畳んだりして、有限の窓に収めます。レビュー対象が巨大なときは、まずgh pr diff --name-onlyで変更ファイルの一覧だけを取り、そのうえでgit diff <base>...<head> -- path/to/fileのようにファイル単位で差分を絞るのが有効です(gh pr diff自体にはファイルパスを渡す pathspec 指定はなく、絞り込みは主に--name-onlyや--patchなどのオプションで行う点に注意してください)。あるいはサブエージェント(Agentツール)に「このファイル群だけ調べて要約を返せ」と委譲し、本線のテープを汚さない、という戦略も効きます。 - 周辺コードの参照: diff だけでは判断できない指摘(この変更が別の呼び出し元を壊さないか等)では、モデルは Grep や Read を追加で呼んで、変更箇所の周辺をテープに載せます。これが前回言う「エージェント的探索型」の動きで、事前に索引を作らず、必要になった時点で自分で読みにいきます。
- レビュー投稿は書き込み系:
gh pr review --request-changesは PR に外向きのコメントを残すので、承認ゲートの対象になります。読み取り(list / diff)は流れるが、投稿の手前で止まる、という非対称が、ここでもテンポを作ります。
前回、自己修正ループの土台として「ハーネスはモデルに『間違っているぞ』とフィードバックを与えられる」と書きました。レビューはその人間版で、gh pr review の結果や、投稿後に返ってくる CI の状態(gh pr checks)を再びテープに書き戻せば、「レビュー指摘 → 修正 → 再チェック」という閉ループを Claude Code の中で回せます。UVMでスコアボードのミスマッチを次のシーケンスにフィードバックするのと、同じ構図です。
CLAUDE.md ─ 文脈に常駐する前提テープ
前回、メモリファイルを「載っていることが前提になる固定の記号列」と表現しました。Claude Code ではこれが CLAUDE.md です。正確には、CLAUDE.md はセッション開始時に読み込まれ、各リクエストの文脈(コンテキスト)に含められるもので、毎回プロンプトに書き直さなくても前提として効いてくれます。PR ワークフローでこれが効くのは、レビュー観点やコミット規約を毎回プロンプトに書かずに済ませられる点です。
ここで一つ注意があります。CLAUDE.md はあくまでコンテキスト(メモリ)であって、権限境界ではないという点です。前章の deny/ask ルールは実行を機械的に止めますが、CLAUDE.md に「force push は禁止」と書いても、それは強制ルールではなくモデルへの指示にすぎません。守らせたい安全制約は permissions 側に、守ってほしい方針や観点は CLAUDE.md 側に、と役割を分けて考えるのが正解です。
たとえば CLAUDE.md にこう書いておけば、レビュー系プロンプトを短く保ったまま、毎回同じ観点を反映させられます。
## コミット規約
- Conventional Commits 形式で書く
- 1コミット1論理変更
## レビュー観点
- 境界条件とエラー処理の漏れ
- テストの追加有無
- (SystemVerilog の場合)プロトコル準拠、アサーション漏れ、
UVM phase の使い方、リセット処理
前回書いたとおり、ここは冗長に書けばノイズになって窓を圧迫し、薄すぎれば前提が伝わりません。「常時載る前提知識」として何を書くかは、良いテープ設計そのものです。
まとめ
前回はハーネスを外から横並びに眺めました。本記事は、そのひとつである Claude Code について、PR プロンプトが内部でどう処理されるかを追いました。
- Claude Code の心臓部は、モデル呼び出しとツール実行を交互に回すエージェントループです。継続の起点はモデルが返す
stop_reason(tool_useかend_turnか等)ですが、実際にはそこに権限チェック・hooks・コンパクション・リトライといったハーネス側の制御が重なって進みます。 -
gitもghも専用ツールではなく、シェル実行ツール(macOS/Linux は Bash、Windows は PowerShell)経由で実行されます。だから GitHub 操作能力はghCLI の機能そのものに等しく、認証も権限もコマンド単位でかかります。 - 権限モデルは deny → ask → allow の順で評価します。ask が allow より先なので、具体的な allow を書いても ask にマッチすれば確認されます。読み取り系は流し、
pushやmergeの手前でだけ止める、という設計がテンポと安全を両立させます。bypassPermissionsでも一部の安全弁は残ります。 - PRを出す側では、
git diffをテープに載せる工程が要でした。diff を載せてはじめて意味のあるコミットメッセージと PR 本文が書けます。前回の「動かせるのはテープだけ」が成果物の質に直結します。 - PRを処理する側では、大きな diff をどう窓に収めるかという窓の管理が主役でした。
--name-onlyでの絞り込みやファイル単位のgit diff、サブエージェントへの委譲が効きます。 - CLAUDE.md はセッション開始時に読み込まれ、各リクエストの文脈に常駐する前提テープです。レビュー観点やコミット規約を置けますが、権限境界ではない点に注意します。
前回の結論は、ここでも変わりません。ハーネスはモデルの δ そのものを賢くはしません。しかし、ツール・権限・検証・メモリを接続することで、LLM単体とは別物の計算システムを作ります。内部動作を理解するとは、この「どこでテープを組み、どこで外界に触れ、どこで人間が止めるか」を把握することにほかなりません。それがわかっていれば、プロンプトを短く保ちつつ、危険な操作にだけゲートを置く、という使いこなしが自然にできるようになると思われます。
次にプルリクエストのプロンプトを一文投げるとき、その裏でループが何周も回り、diff がテープに載り、gh が Bash 越しに叩かれ、push の手前で承認を待っている ── その様子が見えていれば、ハーネスはもう黒箱ではありません。
参考にした公式ドキュメント
- Claude Code 公式ドキュメント(overview / settings / permissions / hooks / subagents / memory): https://docs.claude.com/en/docs/claude-code/overview
- Claude Code GitHub Actions: https://code.claude.com/docs/en/github-actions
- anthropics/claude-code-action(GitHub): https://github.com/anthropics/claude-code-action
- Anthropic Engineering「Building effective agents」等: https://www.anthropic.com/engineering
- GitHub CLI マニュアル(
gh prサブコマンド): https://cli.github.com/manual/
本記事のうち、システムプロンプトの逐語やコンテキスト圧縮の具体的な段数など、公式に完全公開されていない部分については、公開情報とツールの観測される挙動からの整理であり、実装の詳細は版により変わりうる点をお断りしておきます。