---
title: "付録 A 1 ターンの解剖 —— リクエストに何が載っているか"
author: garplab
publisher: TypingTube
license: All rights reserved
license_scope: 記事の全体（序論・最終回は CC BY 4.0 の対象外）。引用は法の範囲で自由
canonical: https://typing-tube.net/articles/furoku-a-request-anatomy
series: "付録"
language: ja
---


先に結論です。**Claude Code は、あなたが 1 回送るたびに、会話の全文を 1 つの API リクエストとして送り直しています。** モデルはリクエストの間で何も覚えていません。system prompt も、指示ファイルも、これまでの会話も、ツールの出力も、毎回まとめて送られます。本編が「足すほど薄まる」と言い、「索引だけが読まれる」と言い、「hook は読まれなくても落ちる」と言ったことは、全部このリクエストの中身の話です。

この章は、そのリクエストを解剖します。何がどの部分に載るか、1 ターンの中で hook がどこに割り込むか、ツールの出力はどこまで届くか、そして記録には何が残らないか。読み終えたら、本編の各回が「なぜそこに置いたか」を、リクエストの側から言い直せるはずです。

## A.1 リクエストの 3 つの部分

Claude Code は、リクエストの中身を「変わりにくいものが先」になるよう並べています。公式ドキュメントは 3 つの部分で説明しています。

| 部分 | 中身 | 変わるとき |
|---|---|---|
| system prompt | 中核の指示、ツール定義、出力スタイル | 読み込まれるツール定義の集合が変わったとき、Claude Code を更新したとき |
| project context | CLAUDE.md、auto memory（`MEMORY.md`）、パス指定の無いルール | セッション開始時、`/clear` か `/compact` の後 |
| conversation | あなたのメッセージ、Claude の応答、ツールの結果 | 毎ターン |

```mermaid
flowchart TB
  subgraph R["1 回の API リクエスト（毎ターン、全部を送り直す）"]
    direction TB
    S["system prompt 層<br/>中核の指示 / ツール定義 / 環境情報 / git の状態 / 出力スタイル"]
    P["project context 層（user メッセージ）<br/>CLAUDE.md / MEMORY.md 先頭 200 行 / paths 指定の無い rules"]
    C["conversation 層<br/>あなたの発言 / Claude の応答 / tool_use と tool_result / hook の出力 / スキル本文"]
    S --> P --> C
  end
  R --> M["モデル"]
  M --> O["応答 = テキスト か tool_use"]
  O -.->|"tool_result を末尾に足して、次のリクエスト"| R
```

順序に理由があります。API は**リクエストの先頭からの一致（prefix）**でキャッシュを引きます。一致は完全一致で、前のほうが 1 文字でも変わると、それより後ろは全部作り直しになります。会話層が伸びるだけなら、前の 2 つはキャッシュから読まれます。system prompt が変わると、全部が無効になります。

この設計が、本編で書いた挙動のいくつかを決めています。**指示ファイルをセッションの途中で直しても反映されない**のは、CLAUDE.md が起動時に 1 度読まれてメモリに保持され、次の `/clear`・`/compact`・再起動まで読み直されないからです。スキルや plan mode の指示は会話層のメッセージとして足されるので、キャッシュを壊しません。hook の出力も同じで、会話層の末尾に足されます。

## A.2 1 ターンの流れと、hook が割り込む位置

本編の hook は「入口」「直後」「終わり際」に置かれていました。1 ターンの流れの上で、それぞれがどこに立っているかを図にします。

```mermaid
sequenceDiagram
  participant U as あなた
  participant H as hook（あなたのスクリプト）
  participant CC as Claude Code（ハーネス）
  participant M as モデル
  participant T as ツール（Bash など）

  U->>CC: プロンプト
  CC->>H: UserPromptSubmit（stdin に JSON）
  H-->>CC: exit 0 + stdout → 会話層に足される / exit 2 → プロンプトを止める
  CC->>M: リクエスト = system prompt + project context + 会話（+ hook の stdout）
  M-->>CC: tool_use（例: Bash "rails test"）
  CC->>H: PreToolUse（tool_input を含む JSON）
  H-->>CC: exit 0 → 実行 / exit 2 → 実行せず、stderr をモデルに返す
  CC->>T: 実行
  T-->>CC: 出力（30,000 字までが inline）
  CC->>H: PostToolUse（tool_input + tool_response）
  H-->>CC: additionalContext / decision: block + reason → モデルに返す
  CC->>M: 次のリクエスト = 前回の全部 + tool_result（prefix はキャッシュ）
  M-->>CC: テキスト（応答の終わり）
  CC->>H: Stop
  H-->>CC: exit 2 / block → 止めずに続けさせる（stop_hook_active で 2 度目を区別）
  CC-->>U: 表示
```

図の要点は 3 つです。

- **hook はモデルの外で動き、結果は会話層に足される。** モデルが hook を「呼ぶ」のではなく、ハーネスがイベントのたびに走らせます。だから読まれなくても走ります（第 1 部 第 6 回）
- **止める hook は、モデルの応答を「その場で」返す。** exit 2 の stderr は、次のリクエストの末尾に tool_result 相当として載ります。人間が会話に割り込むのと違って、モデルが今やった tool_use と地続きに届きます（第 1 部 第 11 回）
- **PostToolUse は「ツールは済んだ後」に届く。** 保存を止める hook ではなく、保存した差分を読ませる hook になるのは、この位置の性質です（第 1 部 第 7 回）

## A.3 system prompt に何が入っているか

system prompt の全文は公開されていません。公式ドキュメントが書いている範囲で、中身はこうです。

- **中核の指示** —— 挙動・ツールの使い方・応答の形式。公式のシミュレーションでは約 4,200 トークン。「あなたが見ることはない」と書かれています
- **ツール定義** —— 組み込みツールの定義（JSON スキーマ）。MCP のツールは既定では名前だけが載り、スキーマは必要になったときに tool search で読み込まれます
- **環境情報** —— 作業ディレクトリ、プラットフォーム、シェル、OS のバージョン、git リポジトリかどうか。約 280 トークン
- **git の状態** —— ブランチ、status、直近のコミット。system prompt の末尾に別ブロックとして載ります
- **出力スタイル** —— `/config` で選んだもの。起動時に 1 度だけ読まれます

Agent SDK のドキュメントは、CLI と同じ system prompt を `claude_code` プリセットと呼び、「ツールの使い方の指示、セキュリティと安全の指示、作業ディレクトリと環境の文脈」を含むと書いています。中身を知る公式の手段はこのプリセットの説明と、`--append-system-prompt` で**足す**ことだけです。

ツール定義がこの部分にあることは、本編の 2 箇所に効いています。第 2 部 第 4 回が引いた Anthropic の指針（ツールの説明は極めて詳細に）は、**この部分に載るテキスト**の話です。毎ターン送られ、キャッシュされ、モデルが tool_use を決めるときに読みます。一方、本編の用途カタログはツール定義ではなく、hook が読むファイルです。モデルには「止まったときの案内」としてしか届きません。同じ「説明を厚く」でも、載る部分が違います。

環境情報が system prompt に埋まっていることには、副作用があります。**キャッシュは、実質的に 1 台のマシンの 1 つのディレクトリに閉じます。** 同じリポジトリでも、worktree が違えば作業ディレクトリが違い、prefix が違うので、キャッシュを共有しません。同じディレクトリで並列実行する 2 つのセッションは、prefix が一致するので互いのキャッシュを読みます。

## A.4 user メッセージとして届くもの

本編の主戦場はここです。**指示ファイルは system prompt ではありません。** 公式ドキュメントは、はっきり書いています。

> CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt itself.

Agent SDK のドキュメントも同じことを別の角度から書いています。環境情報を system prompt から user メッセージへ動かす `excludeDynamicSections` というオプションの注意書きに、「user メッセージの中の指示は、system prompt の同じ文より**わずかに重みが弱い**」とあります。指示ファイルは、最初からその弱いほうの部分にいます。

user メッセージとして届くものを、届く時点で並べます。

| 届くもの | いつ | 量の目安・上限 |
|---|---|---|
| CLAUDE.md（管理ポリシー → ユーザー → プロジェクト → ローカルの順に連結） | セッション開始時 | 1 ファイル 4 MiB まで読む。200 行未満が目標。HTML コメントは除かれる |
| パス指定の無い `.claude/rules/*.md` | セッション開始時 | CLAUDE.md と同じ優先度 |
| `MEMORY.md`（auto memory の索引） | セッション開始時 | **先頭 200 行か 25KB のどちらか早いほう**。それより後ろは載らない |
| スキルの description | セッション開始時 | description と `when_to_use` を合わせて 1,536 文字で切られる。`disable-model-invocation: true` のスキルは載らない |
| hook の stdout | `UserPromptSubmit`・`SessionStart` などの限られたイベントだけ | exit 0 の平文 stdout が「Claude が見て動ける文脈」として足される。**他のイベントの stdout はデバッグログ行き** |
| hook の `additionalContext` / `decision: block` の理由 | `PostToolUse` などで JSON を返したとき | そのフィールドだけが会話に入る |
| 読んだファイル、コマンドの出力 | ツールを使うたび | `tool_result` として会話層に積まれる。あなたの端末には 1 行しか出ないが、Claude には全文が届く（上限は A.5） |
| パス指定のあるルール | 一致するファイルを読んだとき | 読んだ時点で会話層に足される |
| スキルの本文 | 呼ばれたとき | user メッセージとして会話層に足される |
| ファイル変更の通知 | 読んだファイルが後で変わったとき | `<system-reminder>` として会話層に足される |

表の最後の行にある `<system-reminder>` は、Claude Code が会話の中に足す system 由来の文脈の入れ物です。私の手元では、CLAUDE.md の中身もこの入れ物に包まれて、最初の user ターンに同梱されていました。

一つ、私が手元で確かめて分かったことを書いておきます。**セッションの記録（transcript の JSONL）には、この同梱分は残りません。** 記録に残る最初の user メッセージは、私が打った 12 文字だけでした。system prompt も、指示ファイルの写しも、記録には無い。あるのは会話層だけです。本編が「読んだかどうかは測れない」と決めた線引きは、記録の側から見ても同じです。AI が指示ファイルを読んだかどうかは、記録のどこにも残っていません。

逆に、記録に残るものもあります。**あなたが打った言葉は、`type: "user"` の行として全部残ります。** 第 3 部 序論は「毎回打っている言葉には行数が無い」と書きましたが、正確には、ファイルには残っていて、数えていなかっただけです。数え方は A.9 の検証手順 5 に置きます。

## A.5 ツールの出力は、どこまで届くか

第 1 部 第 1 回は「AI はツール出力を読み飛ばせない。26,147 行が全部コンテキストに入る」と書きました。この文には、Claude Code の側で 1 つ条件が付きます。**Bash の出力には inline の上限があります。**

公式ドキュメントの「Output limits」は、こう書いています。コマンドの出力は作業ファイルに流され、終わったら読み戻される。読み戻す窓は `BASH_MAX_OUTPUT_LENGTH`（既定 30,000 文字、上限 150,000 文字）。そして Claude に何が届くかは、結果が成功か失敗かで変わります。

| 結果 | Claude に届くもの |
|---|---|
| 成功（exit 0） | inline は約 30,000 文字まで。超えたら、セッションディレクトリに保存したファイルのパス + 先頭の短いプレビュー。残りは Claude が必要なときにそのファイルを読むか検索する |
| 失敗（exit ≠ 0） | inline は約 10,000 文字まで。超えたら、読み戻した窓から切った**先頭と末尾の抜粋**。ファイルのパスは付かない |

つまり、素の `rails test` を打った場合に起きることは、版によって 2 通りあります。上限の無い版なら全文が入り、上限のある版なら「先頭と末尾だけ」が入ります。どちらも本編の主張を弱めません。全文が入れば序論の「薄まる」が起き、抜粋なら**真ん中の失敗が見えない**ままモデルが判断します。テストは失敗すると exit が 0 ではないので、届くのは後者の 10,000 文字の頭と尻です。13,950 件の出力で、失敗が真ん中にあれば、モデルはそれを見ずに「通った」と読みかねません。

第 1 部 第 1 回のラッパーは、この条件の下でも同じ理由で要ります。要約は数行なので上限に掛からず、失敗の抜粋は `grep -A 3` で先頭に寄せられ、全文は自分の決めた場所（`tmp/test_last.log`）に残ります。ハーネスが勝手に保存する場所ではなく、あとから実行せずに読み直せる場所です。

## A.6 数の目安

数字は、公式の「Explore the context window」に載っているシミュレーションの値です。あなたの環境の実測ではありません。組み込みツールの数、有効なプラグイン、MCP サーバーで変わります。手元の値は `/context` で見ます。

| 起動時に載るもの | トークンの例 |
|---|---|
| system prompt（中核の指示） | 4,200 |
| `MEMORY.md`（auto memory の索引） | 680 |
| 環境情報 | 280 |
| MCP ツール（名前だけ。スキーマは遅延） | 120 |
| スキルの description | 450 |
| `~/.claude/CLAUDE.md` | 320 |
| プロジェクトの CLAUDE.md | 1,800 |
| **起動時の合計** | **約 7,850** |

| 作業中に足されるもの | トークンの例 |
|---|---|
| ファイルを 1 つ読む（`Read`） | 1,100〜2,400 |
| `grep` の結果 | 600 |
| パス指定のルールが 1 つ載る | 290〜380 |
| `PostToolUse` hook が `additionalContext` を返す | 100〜120 |
| `npm test` の出力 | 1,200 |
| サブエージェントの結果（最終メッセージ + トレーラー） | 420 |
| スキルを 1 つ呼ぶ（本文） | 620 |

見るべきは合計ではなく比です。起動時の約 7,850 のうち、あなたが書いたもの（CLAUDE.md 2 つ + MEMORY.md）は約 2,800 で、残りはハーネスのものです。作業中に足されるものは、ファイルを 3 つ読めば起動時の合計を超えます。「足すほど薄まる」の分母は、あなたの指示ファイルではなく、会話層のほうで膨らみます。

## A.7 本編との対応

- **第 1 部 序論「足すほど薄まる」** —— 指示ファイルもメモリの索引も、読んだファイルも、同じ 1 つのリクエストの中で注意を奪い合っています。部分が違っても、モデルから見れば 1 本の入力です。「ルールの一覧を hook で毎回注入して約 26KB」は、`UserPromptSubmit` の stdout が毎ターン会話層に足されていた状態で、キャッシュは壊さない代わりに、読む量が毎ターン増えていました
- **第 1 部 第 1 回「テスト結果を読まない」** —— `tool_result` は会話層に積まれます（A.5 の上限つき）。ラッパーは載る量を数行にし、hook の exit 2 は stderr を tool_result 相当として返します。指示ファイルの 1 行より効くのは、届く位置が「今やった tool_use の直後」だからです
- **第 1 部 第 2 回「メモリを読まない」・第 2 部 第 1 回「提案を検討しない」** —— 起動時に載るのは `MEMORY.md` の先頭 200 行か 25KB だけで、本文のファイルは Claude が開くと決めたときにしか会話層へ入りません。第 2 部 第 1 回の「索引に名前があることと、本文が読まれることは違う」は、A.4 の表の 3 行目と 7 行目の差です
- **第 1 部 第 6 回「ルールを読まない」** —— hook は会話層に何も足しません。出力を返したときだけ足されます。指示ファイルの行を hook に移すと、その行のぶんの入力が毎ターン消えます
- **第 1 部 第 4 回「スキルを使わない」** —— スキルは description だけが毎ターン載り、本文は呼ばれたときだけです。`disable-model-invocation: true` にすると description も載りません。84 本のスクリプトに説明文を書かず、止める価値のある入口だけを hook に寄せたのは、毎ターン載る description を増やさない選択でもあります
- **第 1 部 第 11 回「口を挟まない」** —— 途中で打った言葉は、現在のツール呼び出しが終わった後に読まれ、会話層に**残り続けます**（圧縮まで毎ターン送られる）。hook の案内は同じ位置に届いて、次のターンには tool_result の 1 つとして流れていきます
- **第 2 部 第 4 回「入力だけは、確かめろ」** —— Anthropic の「ツールの説明は詳細に」は system prompt 層のツール定義の話で、用途カタログは hook が読むファイルです。カタログの `description` を 1 行にしたのは正しく、厚くした「契約」がモデルに届くのは止まったときの案内経由です
- **第 3 部 序論「打っている言葉は数えられない」** —— transcript JSONL には残っています。A.9 の 5 で数えます
- **第 3 部 第 3 回「不具合詳細を書かない」** —— 貼ったスクリーンショットは画像として会話層に入ります。画像には枚数と総サイズの上限があり、超えると古いものから一括で外されます（A.8）
- **第 3 部 第 5 回「念を押さない」** —— 強調は同じ部分の中の相対順位です。部分の重みは system prompt が上で、指示ファイルは最初からその下にいます

## A.8 本編が言っていない注意

**ツール出力の上限は、ラッパーの exit code で見え方が変わります。** A.5 のとおり、失敗した（exit ≠ 0 の）コマンドの出力は 10,000 文字の頭と尻だけで、ファイルのパスも付きません。ラッパーがテストの exit status をそのまま返す設計（第 1 部 第 1 回）なら、失敗時に届くのはラッパーの要約だけです。要約が 10,000 文字を超える設計にしないでください。要約の末尾に「実行していない領域」の一覧を毎回出す形（手元では 22 行）も、この予算の中です。

**hook の出力が会話層に入るイベントは限られています。** `UserPromptSubmit`、`UserPromptExpansion`、`SessionStart`、`PostModelSwitch` の平文 stdout は文脈として足されます。`PreToolUse` や `PostToolUse` の exit 0 の stdout は、デバッグログに書かれるだけで Claude には届きません。届けたいなら JSON の `additionalContext` を返します。第 1 部 序論で「ルールの一覧を hook で毎回注入していた」と書いた hook は `UserPromptSubmit` に置いたもので、届いていたのはそのイベントだったからです。

**同じ内容でも、毎ターン足せば毎ターン読まれます。** 本編で「約 26KB がコンテキストに入る状態まで行った」と書いたルールの一覧は、prefix cache を壊しません。会話層の末尾に足されるだけだからです。ただし、会話層は毎ターン送られるので、読む量は増え続けます。キャッシュは「計算し直す量」を減らすだけで、「読む量」は減らしません。その 22 行も同じ勘定に乗っています。

**画像は枚数で外れます。** API は 1 リクエストに載せられる画像と PDF の数と総サイズに上限を持ち、Claude Code はそれを超える前に**古いものから一括で**外します。外れた画像は Claude から見えなくなります。第 3 部 第 3 回の「管理画面を丸ごと貼る」は、スクリーンショットを何件も続けて貼ると、最初の件が消えている状態で判断させることになります。1 件ずつ貼って、済んだら次へ進んでください。

**キャッシュの範囲はディレクトリです。** worktree を分けた並列実行（第 1 部 第 7 回）は、キャッシュを共有しません。1 セッション目が温めたキャッシュを 2 セッション目が読めるのは、同じディレクトリで走らせたときだけです。費用を見るなら、並列実行の形で変わります。

**環境情報を user メッセージへ動かせますが、重みが下がります。** Agent SDK の `excludeDynamicSections`（CLI では `--exclude-dynamic-system-prompt-sections`）を使うと、作業ディレクトリなどが最初の user メッセージへ移り、複数のマシンで system prompt を揃えられます。公式の注意書きは、user メッセージの指示は system prompt より「わずかに弱い」と言っています。本編が指示ファイルについて言ってきたことの、公式による裏付けです。

**バージョン依存。** 上の数値と挙動は 2026-09-05 に Claude Code 2.1.260 のドキュメントで確認したものです。inline の上限 30,000 / 10,000 文字、tool search による MCP スキーマの遅延読み込み、スキル description の 1,536 文字、`MEMORY.md` の 200 行 / 25KB は、いずれも版で変わりうる値です。数字を信じる前に A.9 で測り直してください。

## A.9 検証手順

止まるべきものが止まり、通るべきものが通る。本編と同じで、両方向を 1 度ずつ確かめます。

**1. `/context` で、起動時に載っているものを見る。** Memory files に CLAUDE.md と `MEMORY.md` が並ぶこと、各ブロックのトークン数が出ることを見ます。A.6 の表と桁が合っていれば、あなたの版でも同じ層構造です。

**2. hook の stdout が届くイベントと、届かないイベントを対照する。** 同じスクリプトを `UserPromptSubmit` と `PostToolUse` に登録し、どちらの目印を Claude が答えられるかを見ます。

```json
{
  "hooks": {
    "UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "echo MARKER_UPS_7b3f" }] }],
    "PostToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "echo MARKER_PTU_9c1d" }] }]
  }
}
```

設定したら、AI に「`ls` を 1 回実行してから、この会話の中に `MARKER_` で始まる文字列があれば全部書き出して」と頼みます。期待する結果は、`MARKER_UPS_7b3f` は書き出され、`MARKER_PTU_9c1d` は書き出されないことです。前者が出なければ hook が動いていません（設定の置き場所を疑う）。後者が出たら、あなたの版は `PostToolUse` の平文 stdout をモデルへ渡しています（公式の記述と違うので、版を控えて確かめ直す）。

**3. prefix cache を数字で見る。** 同じディレクトリで 2 回続けて走らせ、キャッシュの読み出しが増えることを見ます。

```bash
# 1 回目: キャッシュを書く側が大きい
claude -p "hello" --output-format json | jq '.usage | {cache_creation_input_tokens, cache_read_input_tokens}'
# 2 回目（5 分以内）: 読む側が増える
claude -p "hello" --output-format json | jq '.usage | {cache_creation_input_tokens, cache_read_input_tokens}'
# 陰性対照: 別のディレクトリでは prefix が違うので、読む側は増えない
(cd /tmp && claude -p "hello" --output-format json | jq '.usage.cache_read_input_tokens')
```

2 回目の `cache_read_input_tokens` が 1 回目より大きく、別ディレクトリでは小さいままなら、A.1 の層構造と A.3 のキャッシュの範囲はあなたの版でも同じです。

**4. `InstructionsLoaded` hook で、指示ファイルが読まれる時点を記録する。** 起動時に読まれるものと、ファイルを読んだときに読まれるものが分かれることを見ます。

```json
{
  "hooks": {
    "InstructionsLoaded": [{ "hooks": [{ "type": "command",
      "command": "jq -r '[.hook_event_name, .load_reason // \"\", .file_path // \"\"] | @tsv' >> tmp/instructions_loaded.tsv" }] }]
  }
}
```

セッションを開始し、`paths:` 指定のあるルールに一致するファイルを 1 つ読ませてから、`tmp/instructions_loaded.tsv` を見ます。期待するのは、CLAUDE.md の行が `session_start` で先に出て、ルールの行が `path_glob_match` で後から出ることです。ルールの行が起動時に出ていたら、その `paths:` は効いていません。

**5. 記録に残るものと残らないものを、transcript で数える。** 第 3 部 序論の「打った言葉を数える」を、手で数える代わりにスクリプトで数えます。同時に、system prompt と CLAUDE.md の写しが記録に無いことも見ます。

```python
#!/usr/bin/env python3
# count_user_turns.py — transcript JSONL から「あなたが打った言葉」だけを数える
# 使い方: python3 count_user_turns.py ~/.claude/projects/<project>/<session>.jsonl
import json, sys

typed, tool_results, has_claude_md = [], 0, False
for line in open(sys.argv[1], encoding="utf-8"):
    try:
        entry = json.loads(line)
    except json.JSONDecodeError:
        continue
    if entry.get("type") != "user":
        continue
    content = entry.get("message", {}).get("content")
    blocks = [{"type": "text", "text": content}] if isinstance(content, str) else content or []
    for block in blocks:
        if block.get("type") == "tool_result":
            tool_results += 1            # ツールの結果も user ロールで届く（モデルから見れば同じ部分）
        elif block.get("type") == "text":
            text = block.get("text", "")
            has_claude_md |= "# claudeMd" in text
            typed.append(text)

print(f"user text blocks: {len(typed)}  tool_result blocks: {tool_results}")
print(f"chars typed (incl. hook/system-reminder text if any): {sum(map(len, typed))}")
print(f"CLAUDE.md copy present in transcript: {has_claude_md}")
for text in typed[:5]:
    print("  >", text[:60].replace("\n", " "))
```

期待するのは 3 つです。`user text blocks` があなたが打った回数と一致すること。`tool_result blocks` がそれより桁で多いこと（会話層の大半はツールの結果です）。そして `CLAUDE.md copy present` が `False` であること。`True` なら、あなたの版は同梱分を記録に残しています。その場合、A.4 の「記録には残らない」はあなたの版には当てはまりません。

**6. ツール出力の上限を、成功と失敗の両方で踏む。** 40,000 文字の出力を成功と失敗の両方で出させ、届き方が変わることを見ます。

```bash
# AI に、この 2 つを順に実行させ、それぞれ「出力の何が見えたか」を報告させる
python3 -c 'print("x" * 40000)'                 # 成功: ファイルのパス + プレビュー が届くはず
python3 -c 'print("x" * 40000); exit(1)'        # 失敗: 頭と尻の抜粋だけ。パスは付かないはず
```

成功側で「保存先のファイルのパス」が報告され、失敗側で「先頭と末尾だけ見えた」と報告されれば、A.5 の表のとおりです。失敗側でも全文が見えたと報告されたら、あなたの版には失敗時の上限がありません。第 1 部 第 1 回の「全部入る」が、そのまま当てはまる版です。

## A.10 出典（2026-09-05 確認）

- [How Claude Code uses prompt caching](https://code.claude.com/docs/en/prompt-caching) —— 3 つの部分の表、キャッシュを無効にする操作、TTL、キャッシュの範囲、画像の一括除去
- [Explore the context window](https://code.claude.com/docs/en/context-window) —— 起動時に載るものとトークン数のシミュレーション
- [Tools available to Claude](https://code.claude.com/docs/en/tools-reference) —— Bash の Output limits（成功 30,000 / 失敗 10,000 文字、ファイルへの退避）
- [Environment variables](https://code.claude.com/docs/en/env-vars) —— `BASH_MAX_OUTPUT_LENGTH`（既定 30,000・上限 150,000）
- [How Claude remembers your project](https://code.claude.com/docs/en/memory) —— CLAUDE.md が user メッセージとして届くこと、読み込み順、200 行の目安、HTML コメントの除去、`MEMORY.md` の上限
- [Hooks reference](https://code.claude.com/docs/en/hooks) —— イベント、exit code と stdout の行き先、`additionalContext`、`stop_hook_active`
- [Extend Claude with skills](https://code.claude.com/docs/en/skills) —— description の上限、`disable-model-invocation`
- [Modifying system prompts（Agent SDK）](https://code.claude.com/docs/en/agent-sdk/modifying-system-prompts) —— `claude_code` プリセットの中身、`excludeDynamicSections` の注意書き
- [Extend Claude Code](https://code.claude.com/docs/en/features-overview) —— 機能ごとのコンテキストのコスト
- [How Claude Code works](https://code.claude.com/docs/en/how-claude-code-works) —— agentic loop、途中のメッセージの届き方、セッションの記録（JSONL）
