16
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code の仕組み — ハーネスの動作と Claude API

16
Last updated at Posted at 2026-07-30

本記事は Claude Code が動作する仕組みについてまとめたものです。

過去に調査を断片的に行い、記事にしてきました。

今回はそれらを一つにまとめて、なるべく体系的に書いています。長い文章になりますが、よければお付き合いください。

検証環境: macOS (Darwin 24.3.0) / Claude Code v2.1.220 / 2026年7月28日時点。セッションログのフォーマットは公式に「内部仕様でありバージョン間で変わり得る」と明言されている 1 ため、本記事の実測値・構造はバージョン依存であることにご注意ください。


1. 全体アーキテクチャ — 3層構造

本章では、本記事全体の土台になる Claude Code の3層構造(ハーネス・Claude API・セッションログ)を説明します。

実体 役割
ハーネス ローカルで動く Claude Code 本体 ツールの実行、コンテキストの組み立て、権限管理、セッションの永続化。すべての状態管理を担う
Claude API Anthropic のサーバー モデルによる推論(思考・応答生成・ツール使用の判断)だけを行う。状態は一切持たない
セッションログ JSONL ファイル 会話の永続化層。ハーネスが API リクエストを組み立てるとき、会話履歴をここから毎回読み出す

「ハーネス」は公式の呼び名です。ドキュメントは Claude Code を "agentic harness"(エージェント用の馬具・骨組み)と呼んでいます 2

Claude Code serves as the agentic harness around Claude: it provides the tools, context management, and execution environment that turn a language model into a capable coding agent.

Claude API (Messages API) はステートレス

この3層構造を理解する上で最も重要な原則が、Claude API(Messages API)はステートレスであるという事実です 3

  • API サーバーは会話履歴を一切保持しません
  • ハーネスは API を呼ぶたびに、システムプロンプト・過去の全メッセージ・今回の入力をすべて含めて送信します
  • 「コンテキスト」とは、この毎回送信される payload 全体のことです

リクエスト payload は次の形式です 3。ポイントは messages 配列で、2ターン目のリクエストには1ターン目の user / assistant メッセージがまるごと含まれます。

POST /v1/messages
{
  "model": "claude-...",
  "system": [ /* システムプロンプト */ ],
  "tools": [ /* ツール定義 */ ],
  "messages": [
    {"role": "user", "content": "..."},          // 1ターン目の発言
    {"role": "assistant", "content": [ ... ]},   // 1ターン目の応答
    {"role": "user", "content": "..."}           // 今回 (2ターン目) の発言
  ]
}

この会話履歴の復元元が、3章で説明するセッションログ(JSONL)です。再構築時にハーネスが何を足すかは、4章で説明します。

プロンプトキャッシュ — ステートレスの代償を消す仕組み

「毎回全量送信」には計算コストの問題があります。モデルは応答を作る前に payload 全体を処理する必要があるため、会話が伸びるほど毎回の処理量が増え続けます。これを解決するのがサーバーサイドのプロンプトキャッシュです 4

  1. 前回のリクエストで: モデルは payload 全体を処理して、応答を生成する
  2. 前回のリクエストの後: サーバーは、payload を処理した結果を捨てずに保存しておく
  3. 今回のリクエストで: payload の先頭部分が前回と同じなら、サーバーはそこの処理を省略して保存済みの結果を使い回す。実際に処理するのは、前回から増えた末尾の部分だけ

ただし「前回と同じ」の判定は、先頭からの完全一致です。payload の途中が1バイトでも前回と変わると、そこから後ろのキャッシュはすべて使えなくなります。

キャッシュを使うかどうかは、ハーネスが payload 内で指示します。キャッシュしたい範囲の末尾のブロックに、cache_control という目印を付けます。

{
  "tools": [ /* ツール定義 */ ],
  "system": [
    {"type": "text", "text": "(システムプロンプト)",
     "cache_control": {"type": "ephemeral", "ttl": "1h"}}
  ],
  "messages": [
    {"role": "user", "content": "..."},
    {"role": "assistant", "content": [ ... ]},
    {"role": "user", "content": [
      {"type": "text", "text": "(今回の発言)",
       "cache_control": {"type": "ephemeral", "ttl": "1h"}}
    ]}
  ]
}
  • payload は toolssystemmessages の順に連結され、目印を付けたブロックまでの範囲がキャッシュされます
  • 目印は1リクエストに最大4個まで。リクエストのたびに、伸びた会話の新しい末尾へ付け直します(過去の位置のキャッシュも有効に残ります)
  • キャッシュの保持期間(TTL)は5分か1時間で、Claude Code は1時間を指定しています(実測)。キャッシュから読んだ分のコストは、通常入力の約0.1倍です

会話が進むたびに payload の末尾へメッセージが積み上がり、「キャッシュヒット / 新規」の境界と目印の位置が下へ移動していきます。


2. ローカルの Agentic Loop とサーバーサイドの thinking

Claude Code は自律的にツールを使いながらタスクを進めます。この自律性は、性質の異なる2つの階層でできています。行動を繰り返すループ(ハーネス側)と、1回の応答の内側での推論(サーバー側)です。

この全体像を、外側(2.1)→ 内側(2.2)の順に詳述します。

2.1 ハーネス側のループ(外側のループ)

ユーザーが1回発言(= 1ターン)すると、裏側では複数回 — 複雑なタスクでは数十回 — の API 呼び出しが走ります。

ポイントは3つです。

  • ループを回すのはハーネスです
    モデルは次の行動を tool_use ブロックで要求するだけで、実際にツールを実行するのはハーネスです
  • ツールの実行結果は user ロールのメッセージとして返送されます
    ハーネスが tool_result ブロックを含む user メッセージを作り、messages の末尾に追加します
  • ループを続けるかはモデルが決めます
    応答の stop_reason(生成を止めた理由)が tool_use の間、ハーネスはツール実行と再呼び出しを繰り返します。end_turn が返るとターンが終わります

図の①〜③に対応する実物を、本記事の執筆セッションのログから抜粋します(内容は一部省略)。tool_usetool_resultid で対応づけられています。

① モデル → ハーネス: API 応答。Bash ツールの実行を要求し、stop_reason: "tool_use" で生成を止める

{
  "role": "assistant",
  "content": [{
    "type": "tool_use",
    "id": "toolu_01Rfm7vm2AAe8YpTdN3t1cvU",
    "name": "Bash",
    "input": {"command": "ls -la /Users/yuusuke-kawatsu/Desktop/tmp/qiita_0728/", ...}
  }],
  "stop_reason": "tool_use"
}

② ハーネス → モデル: ハーネスがローカルで ls を実行し、その結果を user メッセージとして messages 末尾に追加して再呼び出し

{
  "role": "user",
  "content": [{
    "type": "tool_result",
    "tool_use_id": "toolu_01Rfm7vm2AAe8YpTdN3t1cvU",
    "content": "total 0\ndrwxr-xr-x@  2 yuusuke-kawatsu ..."
  }]
}

③ モデル → ハーネス: ツール結果を踏まえた応答。text で完結し、stop_reason: "end_turn" でターンが終わる

{
  "role": "assistant",
  "content": [{
    "type": "text",
    "text": "(ls の結果を踏まえた応答テキスト)"
  }],
  "stop_reason": "end_turn"
}

公式はこのループを「gather context(情報収集)→ take action(行動)→ verify results(検証)の3フェーズの繰り返し」と説明しています 2

2.2 サーバーサイドの thinking(内側の推論)

一方、1回の API 呼び出しの内側でも、モデルは推論を行っています。これが thinking です。Claude Code のターミナルに灰色で流れる思考テキストの実体は、API 応答に含まれる thinking ブロックです。

図のとおり、thinking は1回の連続したテキスト生成の前半部分です。モデルは thinking トークンを書き終えると、そのまま続けて出力トークンを生成します。thinking で応答が遅くなるのは、回答の前に数百〜数万トークンの推論テキストを生成するためで、この分も output トークンとして課金されます。

有効化 — thinking を有効にするのはハーネスで、リクエスト payload の thinking パラメータで指定します 5

extended thinking(Claude 4.5 世代以前)— 思考トークンの予算をハーネスが明示する

{
  "model": "claude-sonnet-4-5",
  "thinking": {"type": "enabled", "budget_tokens": 10000},
  "messages": [ ... ]
}

adaptive thinking(Claude 4.6 世代以降)— 考えるかどうかはモデルが判断し、深さは effort で制御する

{
  "model": "claude-opus-4-6",
  "thinking": {"type": "adaptive"},
  "output_config": {"effort": "high"},
  "messages": [ ... ]
}

応答での現れ方 — content の先頭に thinking ブロックが挿入されます。thinking 無効時との違いは、このブロックの有無だけです(本文はイメージ例)。

{
  "role": "assistant",
  "content": [
    {
      "type": "thinking",
      "thinking": "ユーザーはビルドエラーの原因を尋ねている。エラーメッセージは型の不一致を示していて、直前の diff を見ると引数の順序が入れ替わっている。これが原因だ。結論から伝えよう。",
      "signature": "CAIS..."
    },
    {
      "type": "text",
      "text": "エラーの原因は、`login()` に渡す引数の順序です。..."
    }
  ]
}

3. セッションの仕組み(JSONL)

1章で「ハーネスは API を呼ぶたびに、会話履歴をセッションログから読み出して payload を再構築する」と述べました。本章では、この「JSONL ⇄ payload」の対応関係を説明します。

  • セッションログのエントリには会話系メタデータ系があり、payload の messages に再構築されるのは会話系だけです
  • systemtools、および messages への注入は、ログからではなくハーネスが毎回生成します(4章)

この対応関係が分かると、5章で扱う /clear/compact などのコマンドが何をしているのかを統一的に説明できます。

3.1 ファイルとエントリの構造

セッションログは 1行 = 1エントリの JSONL ファイルとして、次の場所に保存されています 1(デフォルト30日で自動削除)。

~/.claude/projects/<プロジェクトパスのスラッグ>/<セッションID>.jsonl

<プロジェクトパスのスラッグ> は、作業ディレクトリのパスの非英数字を - に置換したものです(例: /Users/foo/myapp-Users-foo-myapp)。

ファイルは末尾に行を追記して伸びていきます。各行(= エントリ)は parentUuid フィールドで1つ前のエントリを指しており、セッションログの実体は、追記で伸びていく連結リスト(linked list)です

{"type": "user",       "uuid": "e1", "parentUuid": "...", "message": { ... }}
{"type": "attachment", "uuid": "e2", "parentUuid": "e1", ... }
{"type": "assistant",  "uuid": "e3", "parentUuid": "e2", "message": { ... }}

1エントリを展開した構造です(実物から抜粋、一部省略)。

{
  "type": "assistant",              // エントリの種類(user / assistant / system ほか)
  "uuid": "0794013f-...",           // このエントリの ID
  "parentUuid": "05c0ddff-...",     // 直前のエントリの ID
  "sessionId": "a726f404-...",
  "timestamp": "2026-07-28T06:41:07.481Z",
  "message": {                        // API とやりとりしたメッセージ本体
    "id": "msg_011CdTzL...",          // API 応答の ID
    "role": "assistant",
    "content": [                      // content は「配列」
      {                               //   要素は「ブロック」オブジェクト
        "type": "text",               //   ブロックの種類(thinking / text / tool_use ...)
        "text": "..."
      }
    ],
    "usage": { ... }
  }
}

会話系のエントリは、API とやりとりしたメッセージを message フィールドにほぼそのまま保持します。content は配列で、その要素が content ブロック(オブジェクト)です。2章に登場した tool_usethinking、通常の応答テキストの text は、すべてこのブロックの type の種類です。

エントリの type は会話系だけではありません。v2.1.220 の実セッションで観測されたタイプを分類すると:

分類 type 内容
会話系(API に送信される) user ユーザー発言、または tool_result
assistant モデルの API 応答(content ブロック1個につき1エントリ)
メタデータ系(API に送信されない) system compact 境界、ターン所要時間などのイベント記録
attachment hook の実行結果、スキル一覧の差分など
file-history-snapshot チェックポイント(→ 5.3 /rewind
ai-title, last-prompt, mode, permission-mode ほか セッション名、入力履歴、モード状態など

3.2 2章の「1ターン」は、ログにどう積み上がるのか

第2章のループは、セッションログにそのまま痕跡として残ります。あるターン(ユーザー発言 → ツール実行1回 → 応答)がログにどう積み上がるかを示します。エントリの構造・並び・チェーンは実測どおりで、中身は説明用の例です。

# API type ブロック 中身(例)
1 入力1 user 「ビルドが失敗する原因を調べて」
2 attachment task_reminder
3 応答1 assistant thinking 「まずビルドを実行してエラーを確認しよう。」
4 応答1 assistant text 「ビルドを実行して原因を確認します。」
5 応答1 assistant tool_use Bash {"command": "npm run build"}
6 入力2 user tool_result Error TS2345: ...
7 attachment hook_success
8 応答2 assistant text 「原因は login() に渡す引数の型不一致です。…」

attachment は、ハーネスが管理情報を記録するメタデータ系エントリです(種類は 3.1 の表)。parentUuid のチェーンは、会話系エントリだけでなくメタデータ系エントリも経由して1本につながっています。

読み取るべき仕様は2つです。

① ツール実行結果は user エントリとして記録される

エントリ6は user タイプですが、ユーザーの発言ではなく、ハーネスがツール実行結果(tool_result)を user ロールとして API に返送した記録です(2.1 で述べた返送の仕組み)。

② 1回の API 応答は content ブロックごとに複数エントリへ分割される

エントリ3〜5は3行に分かれていますが、実は同一の API 応答です。JSONL には API 呼び出しを表す階層構造はなく、すべてのエントリが同じ階層に並びます。どのエントリが同じ応答由来かは、message.id の一致で表現されています。

エントリ ブロック message.id
3 thinking msg_abc123
4 text msg_abc123(= 同じ API 応答)
5 tool_use msg_abc123(= 同じ API 応答)

4. ハーネスによる思考制御(コンテキスト注入)

3章冒頭の図で「ハーネスが毎回生成・注入」と書いた部分を掘り下げます。

ハーネスは JSONL の会話を素朴に messages 配列へ変換するだけではなく、モデルの思考を制御するための情報をあちこちに注入しています。注入まで含めたコンテキスト(= payload 全体)の内訳が次の図です。1章で見た system / tools / messages の3区画に、それぞれ注入された要素が配置されています 6

色付きの5つがハーネスによる注入で、灰色の会話履歴だけが JSONL 由来です。

このうち会話が進むにつれて単調増加するのは messages 配列(会話本体)だけで、これがコンテキスト膨張の主原因です。自分のセッションの内訳は /context コマンドでいつでも確認でき、カテゴリ別のトークン消費が表示されます。

システムプロンプトや CLAUDE.md は、セッションログには保存されません。これらは API を呼ぶたびにハーネスが disk から読み直して生成します。だからこそ、セッションを翌日再開しても最新の CLAUDE.md が反映されるわけです。

4.1 注入の場所と手段

注入先 注入するもの 説明
system システムプロンプト 固定の指示テンプレート + 環境情報。まるごとハーネスが生成する
tools ツール定義 モデルに何のツールを使わせるかをハーネスが決める(組み込み + MCP)
messages <system-reminder> タグ user メッセージ内に差し込まれる万能注入タグ。CLAUDE.md、スキル一覧、モード状態などを運ぶ
messages 合成履歴 「モデルがツールを呼んだことにした」偽の tool_use / tool_result ペア
messages ツール結果のラップ 実在する tool_result の整形・退避

システムプロンプトの実例(実測。抜粋)— ハーネスは、バージョンに焼き込まれた指示テンプレートに、起動時に収集した環境情報(作業ディレクトリ、git の有無、OS など)を埋め込んでシステムプロンプトを生成します。この執筆セッションに実際に送られていたものの抜粋です。

"system": [
  {"type": "text",
   "text": "You are Claude Code, Anthropic's official CLI for Claude.\n
You are an interactive agent that helps users with software engineering tasks.
(中略: トーン、ツール使用の原則、応答形式などの指示が続く)

# Environment
- Primary working directory: /Users/.../qiita_0728
- Is a git repository: false
- Platform: darwin
- OS Version: Darwin 24.3.0",
   "cache_control": {"type": "ephemeral", "ttl": "1h"}}
]

ツール定義の実例(実測。抜粋)— この執筆セッションの tools に含まれていた Bash ツールの定義です。どのツールをどんな説明・引数仕様で使わせるかを、ハーネスが決めてモデルに渡しています。

"tools": [
  {
    "name": "Bash",
    "description": "Executes a bash command and returns its output. ...",
    "input_schema": {"type": "object", "properties": {"command": { ... }, ...}}
  },
  ...
]

<system-reminder> の実例(実測)— 会話に読み込み済みのファイルを、モデルがもう一度 Read しようとしたときのツール結果です。ハーネスはファイルを読ませる代わりにこの注釈を注入し、「既にコンテキストにある内容を使え」とモデルの行動を修正しています。

{
  "type": "tool_result",
  "tool_use_id": "toolu_01Cvcf...",
  "content": "<system-reminder>This file is already in your context (see \"Contents of /Users/.../CLAUDE.md\" above) and has not changed on disk. Use that content instead of re-reading.</system-reminder>"
}

合成履歴の実例(構造は実測どおり、内容は例)— ユーザーが @README.md とメンションすると、モデルが Read ツールを呼んだかのような tool_use / tool_result のペアが payload に合成されます。

{"role": "assistant", "content": [
  {"type": "tool_use", "id": "toolu_x1", "name": "Read", "input": {"file_path": "README.md"}}
]},
{"role": "user", "content": [
  {"type": "tool_result", "tool_use_id": "toolu_x1", "content": "(README.md の内容)"}
]}

ツール結果のラップの実例(実測)— WebFetch の出力が大きすぎたとき、tool_result の中身が退避ファイルへの参照と冒頭プレビューに置き換えられていました。

<persisted-output>
Output too large (71.1KB). Full output saved to:
~/.claude/projects/<プロジェクト>/<セッションID>/tool-results/toolu_01NC....txt

Preview (first 2KB): ...
</persisted-output>

4.2 pull 型の設計

ハーネスは「モデルが必要としそうな情報」をすべて注入(push)するわけではありません。TodoList の状態や Plan ファイルの本体は messages に全文を載せず、モデルが必要になったときにツール呼び出しで取得させる(pull)設計です。

TodoList を例にすると(内容は例):

push 型なら — 毎リクエストの payload にリスト全文が入り続ける

<system-reminder>現在のタスク: 1. ビルド修正(進行中) 2. テスト追加 3. ...(全文)</system-reminder>

pull 型(実際の設計) — 小さな通知だけを注入し、中身はモデルが取りに行く

<system-reminder>タスクリストが更新されています。TaskList ツールで確認できます。</system-reminder>

モデルが必要と判断したときだけ、TaskList の tool_use で全文を取得します。


5. セッション操作コマンドの内部動作

本章では、/clear/compact などのセッション操作コマンドの内部動作を説明します。各コマンドが変更するのは JSONL(記録)で、次の payload(モデルが見る会話)はその結果として決まります。この2軸をコマンドごとに埋めたのが次の表です。

コマンド JSONL への操作 次のコンテキスト ID
/clear 新ファイルを作成 空から再開 新規
/compact 境界と要約を追記 要約 + 以後の会話 同じ
/rewind 新しい枝を追記 選択時点まで巻き戻る 同じ
/btw 何も書かない 現在の会話 + 質問(使い捨て) 同じ
--continue / --resume 追記を再開 履歴から再構築 同じ
/branch / --fork-session 新ファイルへコピー コピーを引き継ぐ 新規

5.1 /clear — 新しいセッションを切る

/clear は「今のセッションログを消す」コマンドではありません。実際には:

  • 新しいセッション ID を発行し、新しい JSONL ファイルへの記録を開始します
  • 旧セッションのファイルは無傷で残り、/resume でいつでも復帰できます 7
  • payload 的には messages 配列が空になるので、コンテキストは初期状態(システムプロンプト + CLAUDE.md 等)に戻ります

5.2 /compact — 履歴を要約に置き換える

/compact(およびコンテキスト逼迫時の自動 compaction)は /clear と対照的に、同じセッション・同じファイルの中で messages だけを圧縮します。実際の JSONL には次の2エントリが追記されます。

compact_boundary(system エントリ) — 実物から抜粋:

{
  "type": "system",
  "subtype": "compact_boundary",
  "parentUuid": null,
  "logicalParentUuid": "e58c52b2-...",
  "compactMetadata": {
    "trigger": "auto",
    "preTokens": 984519,
    "postTokens": 6384
  }
}

このエントリから読み取れる仕様は3つです。

  • parentUuid: null — ここで parentUuid のチェーンが物理的に切断されます。payload を再構築するとき、これより前のエントリは辿られません
  • logicalParentUuid — ただし「論理的には旧チェーンの続き」という接続情報は別フィールドで保持されます(表示や /rewind のため)
  • preTokens: 984519 → postTokens: 6384 — この例では約98万トークン分の履歴が約6千トークンの要約に圧縮されたことが記録されています

② 要約本体(user エントリ、isCompactSummary: true:

{
  "type": "user",
  "isCompactSummary": true,
  "message": {
    "role": "user",
    "content": "This session is being continued from a previous conversation that ran out of context. The summary below covers the earlier portion of the conversation. Summary: 1. Primary Request and Intent: ..."
  }
}

チェーン上ではこうなります。

つまり compact 後の payload は「要約という名の user メッセージ1個 + それ以降の会話」として再構築されます。

なお、compact で失われるのは messages 内の情報だけです。何が生き残るかは公式に整理されています 8

要素 compaction 後
システムプロンプト 影響なし(messages ではないため)
プロジェクトルートの CLAUDE.md / Auto memory disk から再注入される
paths: 付きの rules / サブディレクトリの CLAUDE.md 一旦失われる(該当ファイルを再度読むまで)
発動済みスキルの本文 再注入される(1スキル5,000トークン・合計25,000トークンの上限付き)

5.3 /rewind — チェックポイントへの巻き戻し

/rewind(または空のプロンプトで Esc 2回)は、会話とコードを過去の時点に戻すコマンドです。これを支えるのがチェックポイント機構で、実は2つの独立した仕組みの組み合わせです 9

① 会話の巻き戻し = parentUuid ツリーの枝分かれ

3.1 で見た連結リストは、正確には分岐可能なツリーです。会話を巻き戻して新しい指示を出すと、選択した時点のエントリを親とする新しい枝が生えます。

payload に再構築されるのは、最新エントリから parentUuid を遡って辿れる1本のパスだけです。旧い枝(図の点線側)は削除されず、この再構築対象から外れるだけです 9

② コードの巻き戻し = ファイルスナップショット

ユーザーがプロンプトを送るたびに、ハーネスは編集対象ファイルのスナップショットを取ります。JSONL には file-history-snapshot エントリが記録され(どの user メッセージ時点か messageId で紐づく)、ファイル実体は別ディレクトリに退避されます。

{
  "type": "file-history-snapshot",
  "messageId": "71cf4a77-...",
  "snapshot": {
    "trackedFileBackups": {
      "storyline.md": { "backupFileName": "ecc7d8cb5d6d337a@v2", "version": 2 }
    }
  }
}
~/.claude/file-history/<セッションID>/
├── 6334ef34043b337c@v1   ← コンテンツハッシュ@バージョン
└── ecc7d8cb5d6d337a@v2

/rewind メニューで「Restore code and conversation」「Restore conversation」「Restore code」の3つが選べるのは、この2つの機構が独立しているからです。

制限も、この2機構の構造で決まっています 9

  • Bash コマンドによるファイル変更は巻き戻せない(スナップショットは編集ツール経由の変更だけを追跡するため)
  • サブエージェントの編集は原則対象外(別コンテキストで動くため)
  • チェックポイントは直近100個まで。git の代替ではなく「セッション内 undo」という位置づけ

5.4 --continue / --resume — 保存済みログからの再開

セッションは常時 JSONL に保存されているので、「再開」とは既存ファイルを読み込んで payload を再構築し、同じファイルへの追記を再開することです 1。セッション ID は変わりません。

  • claude --continue: カレントディレクトリの最新セッションを再開
  • claude --resume: セッションピッカーを開く(名前・ID 指定も可)

なお、同じセッションを2つのターミナルで同時に再開すると、両方のメッセージが1つの JSONL に混ざって記録されます(公式も明言 1)。チェーンが交錯して片方から見えなくなる危険があるため、並行作業なら次の /branch を使うべきです。

5.5 /branch / --fork-session — 履歴のコピーで分岐

/branch(CLI では --continue --fork-session 等)は、会話履歴を新しいセッション ID のファイルにコピーし、以後はそちらに追記する操作です 1

  • 元のセッションは無傷で残る(/resume で戻れる)
  • payload 的にはコピー時点までの履歴をそのまま引き継ぐ
  • /rewind の会話復元が「同一ファイル内の枝分かれ」なのに対し、/branch は「ファイルごと分岐」

5.6 /btw — どこにも残らないサイドクエスチョン

最後に、最も特殊な /btw です。これは「今の作業について、会話を汚さずに質問したい」ためのコマンドで、公式ドキュメントの説明が仕組みをよく表しています 10

Side questions have full visibility into the current conversation, so you can ask about code Claude has already read, decisions it made earlier, or anything else from the session. The question and answer are ephemeral: they appear in a dismissible overlay and never enter the conversation history.

  • payload: 現在のコンテキスト全体 + 質問、で API を1回だけ呼ぶ。親会話と先頭部分が一致するので、プロンプトキャッシュ(1章)がそのまま効き、追加コストは小さい
  • JSONL: 質問も回答も一切記録されない。完全に揮発性
  • ツール: 使えない(コンテキスト内の知識だけで回答する)

公式はこれを「サブエージェントの逆」と表現しています。

/btw is the inverse of a subagent: it sees your full conversation but has no tools, while a subagent has full tools but starts with an empty context.

/btw(サイドクエスチョン) サブエージェント
コンテキスト 親会話の全部が見える から開始
ツール 使えない フルに使える
会話履歴への記録 残らない(揮発性) 結果の要約だけが本会話に戻る
用途 「今の会話について」聞く 「新しく調べてきて」と頼む

なお、/btw の回答から f キーで fork すると、その問答を本物の履歴として含む新セッションが作られます。揮発性の問答を後から永続化する唯一の経路です。


おわりに

この様な長文記事を最後まで読んでいただき、ありがとうございました。

  1. Manage sessions — "The entry format is internal to Claude Code and changes between versions" 2 3 4 5

  2. How Claude Code works 2

  3. Messages API — "The Messages API can be used for either single queries or stateless multi-turn conversations." 2

  4. Prompt caching

  5. Thinking(総説)および Extended thinking(旧方式のリファレンス)

  6. Explore the context window — 何がいつロードされるかを対話的に確認できる公式ページ

  7. Commands/clear: "Start a new conversation with empty context. ... Resume the previous conversation with /resume"

  8. Explore the context window — "What survives compaction" の節

  9. Checkpointing 2 3

  10. Interactive mode — "Side questions with /btw" の節

16
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?