Claude Media
Claude CodeでCLAUDE.mdが途中までしか読まれない上限と確認法

Claude CodeでCLAUDE.mdが途中までしか読まれない上限と確認法

サブディレクトリのCLAUDE.mdやrulesファイルは、文字数の上限を超えると先頭だけがClaudeに渡されます。200Kと1Mの上限値、wc -mでの数え方、超えたときの分割先をまとめます。

サブディレクトリに置いたCLAUDE.mdの後半に書いた指示だけが効かないときは、ファイルが文字数の上限を超えている可能性があります。上限を超えたファイルは、先頭の部分だけがClaudeのコンテキストに入ります。末尾には「残りはReadツールで読むこと」という注記が付きますが、Claudeが実際に読みに行くまで、後ろの指示は存在しないのと同じです。

上限はコンテキストウィンドウで決まります。200Kなら40,000文字、1Mなら150,000文字です。Opus 4.6とSonnet 4.6の1Mだけは200,000文字になります。数えるコマンドはwc -mで、ロケールによっては文字数でなくバイト数が出る点に注意が要ります。

上限の対象になるファイルは「あとから読み込まれるもの」だけ

この上限は、起動時に読み込まれるファイルには掛かりません。対象は、必要になったときにあとから読み込まれる次のファイルです。

  • 起動したディレクトリの下にあるサブディレクトリのCLAUDE.mdとCLAUDE.local.md。これらが@pathでimportしているファイルも含む
  • サブディレクトリの.claude/rules/にあるrulesファイル
  • プロジェクトの.claude/rules/か~/.claude/rules/にある、pathsのfrontmatterを持つrulesファイル

サブディレクトリのCLAUDE.mdは、Claudeがそのディレクトリのファイルを読む、書く、編集するまで読み込まれません。単一ファイルへのcatやheadも読む操作に数えられます。起動直後に/contextの「Memory files」を見ても、このファイルは並びません。

つまり「手元のapi/CLAUDE.mdが長いのに、起動時の警告は出ない」という状況が普通に起こります。起動時の警告は別の仕組みで、そちらはCLAUDE.md is too long警告の意味と直し方で扱っています。

くらべる

起動時に読む指示ファイルと、あとから読む指示ファイル

上限の対象外

起動時に読み込まれる

作業ディレクトリと、その上の階層のCLAUDE.md。pathsのないrulesファイル。長すぎると起動時の警告が出ます。

文字数の上限あり

あとから読み込まれる

サブディレクトリのCLAUDE.mdとrulesファイル。paths付きのrulesファイル。上限を超えると先頭だけが入ります。

上限の値は、セッションのコンテキストウィンドウで変わる

セッションのコンテキストウィンドウ1ファイルあたりの上限
200K1ファイルあたりの上限40,000文字
1M(Opus 4.6、Sonnet 4.6)1ファイルあたりの上限200,000文字
1M(それ以降のモデル)1ファイルあたりの上限150,000文字

ここで引っかかりやすいのは、どの行に自分が当たるかです。Fable 5.1、Sonnet 5以降、Haiku 5.5、Opus 4.7以降は、[1m]の接尾辞を付けなくても1Mのウィンドウで動きます。Bedrock、Google CloudのAgent Platform、Microsoft Foundryのセッションも同じです。

一方、環境変数CLAUDE_CODE_DISABLE_1M_CONTEXTを1にすると、本来1Mで動くモデルが200Kのウィンドウに固定されます。企業の環境でこの変数が設定されていると、同じモデルでも上限が40,000文字に下がります。「同僚の環境では読まれるのに自分の環境では途中で切れる」という差は、ここが原因かもしれません。

数字

覚えておく3つの値

  • 200Kのウィンドウ

    40,000文字

    1M無効の環境もここ

  • 1M(新しいモデル)

    150,000文字

    Opus 4.7以降など

  • 1M(4.6世代)

    200,000文字

    Opus 4.6とSonnet 4.6のみ

1ファイルあたりの文字数

上限は1ファイルごとの値です。後で触れるように、rulesファイルに分ければ、それぞれが別々に数えられます。

自分のファイルが超えているかを数える

数え方はwc -mです。行数ではなく文字数で比べます。

wc -m api/CLAUDE.md

日本語のファイルでは、ここに落とし穴があります。手元の環境(macOS、LANG=C.UTF-8)で、日本語の2行だけのCLAUDE.mdを作って数えると、次の結果になりました。

$ wc -m CLAUDE.md
      26 CLAUDE.md
$ wc -c CLAUDE.md
      48 CLAUDE.md
$ LC_ALL=C wc -m CLAUDE.md
      48 CLAUDE.md

wc -cはバイト数なので、日本語1文字が3バイトになり48が出ます。wc -mは文字数で26です。ところが、ロケールをLC_ALL=Cにしてwc -mを実行すると、バイト数と同じ48が出ました。ロケールがUTF-8でない環境では、wc -mでも日本語の分量が3倍近くに見えます。

この結果は、上限を超えているかを調べるときの判断に直結します。日本語主体のCLAUDE.mdで、判定が実際より重く出ることはあっても、軽く出ることはありません。バイト数が40,000未満なら確実に上限以内です。超えて見えるときは、localeでLANGやLC_ALLを確認してから数え直してください。

プロジェクト内のすべてのCLAUDE.mdとrulesファイルを、大きい順に並べる例です。

find . \( -name CLAUDE.md -o -name CLAUDE.local.md \
  -o -path '*/.claude/rules/*.md' \) \
  -not -path '*/node_modules/*' -exec wc -m {} + | sort -rn | head

ファイルが複数あるときは、出力の先頭が合計行になります。合計行を除いて、各ファイルの文字数を上限と見比べます。

超えていたら、削るか、rulesファイルに分ける

ファイルが上限を超えていたときの対処は2つです。

  1. ファイルを削る
  2. 一部をrulesファイルに移す

rulesファイルは、それぞれが単独で上限に対して数えられます。合計では上限を超えていても、1ファイルずつが上限以内なら、全文が渡されます。

分け方の例です。api/CLAUDE.mdが長くなっていたら、エンドポイントの規約とテストの規約を別々のファイルに切り出します。

api/
├── CLAUDE.md                  # 共通の方針だけを残す
└── .claude/rules/
    ├── endpoints.md           # エンドポイントの規約
    └── testing.md             # テストの規約

サブディレクトリの.claude/rules/にあるファイルも「あとから読み込まれる」側に入ります。pathsのfrontmatterを付ければ、対象のファイルを開いたときだけ読み込まれます。

---
paths:
  - "api/**/*.ts"
---
- エラーは共通のレスポンス形式で返す
- 新しいエンドポイントにはOpenAPIのコメントを付ける

ここで注意が要るのは、プロジェクトの.claude/rules/にあるpathsなしのファイルです。これは起動時に読み込まれ、.claude/CLAUDE.mdと同じ優先度になります。サブディレクトリのCLAUDE.mdを分割して起動時のrulesに移すと、上限は避けられても、毎セッションのコンテキストを使い始めます。サブディレクトリ向けの指示は、サブディレクトリ側の.claude/rules/か、paths付きに置くのが筋です。

@pathで分けるのは、この問題の解決になりません。importされたファイルは、importしているCLAUDE.mdと一緒に読み込まれ、しかも上限の対象です。整理には役立ちますが、文字数は減りません。

症状から原因を切り分ける

「後半の指示だけ守られない」ときは、上限以外の原因も候補です。確認の順番を図にします。

切り分け

後半の指示が効かないときの切り分け

  1. QそのCLAUDE.mdは、起動したディレクトリの下にあるサブディレクトリのものか?
    答えがいいえのとき

    起動時に読み込まれるファイルなので、この上限の話ではありません。/contextの「Memory files」に載っているかを見ます。

    答えがはい
  2. Q`wc -m`の値は、自分のセッションの上限を超えているか?
    答えが超えていない

    上限以内なら、文字数が原因ではありません。指示の書き方が曖昧か、別のファイルの指示と矛盾していないかを確かめます。

    答えがはい

先頭だけが渡されている可能性が高い

削るか、rulesファイルに分けます。分けたあとは、対象ディレクトリのファイルをClaudeに読ませたうえで、InstructionsLoadedフックの記録で読み込まれたかを確かめます。

上限以内なのに読み込まれないときは、Instruction file not loadedが出る3つの理由や、rulesのシンボリックリンクが読み込まれない原因が次の候補です。

新しく作ったファイルを試すときは、Claudeに書かせず、シェルから作ります。そのうえで、同じサブディレクトリのファイルをClaudeに読ませます。読み込まれたかどうかは、次のInstructionsLoadedフックの記録で確かめられます。

どのファイルが、いつ、なぜ読み込まれたかは、InstructionsLoadedフックで記録できます。読み込みの理由には、サブディレクトリをたどって読んだ場合のnested_traversalや、pathsに一致した場合のpath_glob_matchなどがあります。

v2.1.309より前は上限がなかった

この上限は、v2.1.309で入りました。それ以前は、あとから読み込まれるファイルに上限がなく、巨大なファイルも全文が入ります。v2.1.309の変更点には、巨大なネスト済みCLAUDE.mdを読んだあとにセッションが繰り返しcompactされる不具合の修正が含まれていました。上限を超えたネスト済みCLAUDE.mdは、先頭だけが読み込まれる動作になっています。

バージョンの違いは、読み込みの失敗の見え方も変えます。

  • v2.1.309より前: 大きなファイルでも全文が入るが、compactが繰り返される恐れがある
  • v2.1.309以降: 上限で切られるので、compactは落ち着くが、後半の指示が渡らない

「更新したら、後半の指示が急に効かなくなった」ときは、このバージョン差を疑えます。claude --versionで確かめ、超えているファイルを分割します。このバージョンの変更点はClaude Code v2.1.309のリリースノートにまとめています。

4MiBの制限と、compact後の挙動は別の話

似た名前の制限がいくつかあり、混ざりやすいので分けておきます。

制限対象超えたときの動作
200行の目安対象各指示ファイル超えたときの動作起動時と/statusで警告が出る
4MiB対象CLAUDE.md全般超えたときの動作ファイルごとスキップされる
文字数の上限(この記事)対象あとから読み込まれるファイル超えたときの動作先頭だけが渡される

4MiBは「ファイルを丸ごと読まない」制限で、先頭だけを渡すこの上限とは動作が違います。MEMORY.mdには、また別の読み込み上限があります。そちらはMemory index read limitの対処で扱っています。

compactとの関係も押さえておきます。プロジェクトルートのCLAUDE.mdは、/compactのあとにディスクから再び読み込まれます。サブディレクトリのCLAUDE.mdは、あとから読み込まれる側なので、compact後はClaudeが対象のファイルを再び読むまで入りません。「compactしたら指示が消えた」場合も、この性質が関係します。

まとめ

サブディレクトリのCLAUDE.mdが途中までしか効かないときは、wc -mで文字数を数えて、自分のコンテキストウィンドウの上限(40,000文字か、150,000文字か、200,000文字)と比べます。日本語のファイルは、ロケールによって数が3倍近く膨らむので、UTF-8のロケールで数えます。超えていたら、サブディレクトリの.claude/rules/へ分けます。@pathのimportは、文字数を減らす手段になりません。

上限の値より先に確認したいのは、自分のセッションのウィンドウです。CLAUDE_CODE_DISABLE_1M_CONTEXTが設定されていると、新しいモデルでも40,000文字の側に落ちます。三層の記憶の使い分けはClaude Code memoryの三層構造にあります。

この記事を共有:XはてブLinkedIn