2014年から個人開発で壁紙アプリや癒し系アプリを運営してきまして、ログ集計や App Store Connect から書き出した CSV を Claude Code に読み込ませる場面が増えました。あるとき10万行を超えるアクセスログを Read ツールで開かせて、続けて「特定のキーワードを含む行だけ抽出して」と頼んだところ、抽出結果が明らかに少ないことに気づきました。原因は単純で、Read がファイルの先頭2000行で静かに止まっていただけでした。エラーは出ません。Claude も切り捨てに気づかないまま作業を続けていました。
このような切り捨てに気づかず、誤った集計や差分検出をしてしまう事故は、ログ・CSV・大きな JSON・minify されたバンドル等を扱う場面で誰もが遭遇します。今回は、私自身がこの落とし穴で何度かハマりながら整理してきた Read ツールの挙動と、offset / limit の使い分け、そして bash で代替すべき判断基準を共有します。
なぜ Read ツールは2000行で切り捨てるのか
Read ツールはデフォルトで先頭から最大2000行を返します。これは Claude のコンテキストウィンドウを保護するための仕様で、エラーを返さず黙って末尾を切るのが特徴です。ファイル末尾に必要な情報があるとき、Claude にはその「不在」が見えないため、嘘ではなく単に部分情報で推論を続けてしまいます。
宮大工だった両祖父の影響もあって、私は「道具の性質を理解してから使う」ことを大事にしているのですが、Read ツールに関しては「黙って切る」性質を最初に理解しておかないと、後で結果のズレを別の原因に押し付けてしまいがちです。
切り捨てを見抜く3つのサイン
切り捨てが起きているかどうかは、以下のいずれかで判別できます。
第一に、返ってきた行数がきっかり2000行であること。3000行以上ありそうな実ファイルに対して、応答末尾の行番号が 2000 で終わっている場合はほぼ確実に切れています。
第二に、ファイルサイズが100KBを超えている場合。1行あたり50バイトと仮定すると2000行で約100KB相当となり、これを超えるサイズのテキストファイルは2000行を超えている可能性が高いです。
第三に、末尾に必要な情報があるのに見つからない現象。「2025年12月のレコードを探して」と頼んだのに「該当なし」と返ってきたときは、まずファイル全体の行数を wc -l で確認してください。
# 切り捨てが起きていそうなときの最初の確認
wc -l /path/to/large.csv
ls -lh /path/to/large.csvoffset と limit の使い分けパターン
Read ツールには offset(読み始める行番号)と limit(読む行数)のパラメータがあります。これは「ファイル全体を読まなくても目的の範囲だけ取れる」ためのもので、使い分けを覚えると切り捨て事故が激減します。
パターン1: 目的の行範囲が分かっているとき
特定のセクションや関数定義、エラー発生時刻周辺のログ等、行番号がおおよそ見えている場合は offset と limit を直接指定します。
Read(file_path="/path/to/server.log", offset=4500, limit=200)
ログファイルなら grep -n "ERROR" server.log | head で該当行を先に確認しておけば、offset をピンポイントで指定できます。
パターン2: 目的の場所が見えないとき
「キーワードを含む行を全部抽出したい」「件数を数えたい」場合は、Read を呼ぶ前に bash で絞り込みをかけるほうが速くて確実です。
# キーワードを含む行のみ抽出してから Read で詳細確認
grep -n "checkout" /path/to/access.log > /tmp/checkout-lines.txt
wc -l /tmp/checkout-lines.txt絞り込んだ結果が2000行以下なら、その出力ファイルを Read で読めばよいですし、まだ大きければ head -100 等で更に絞ります。
パターン3: ファイル全体をスキャンしたいとき
これは原則 Read ではなく bash の出番です。Read は「Claude が文脈として読む」ためのツールであって、データ処理エンジンではありません。集計や全件スキャンは bash・awk・python に任せ、結果サマリーだけ Read で取り込むのが本来の使い方です。
詳しくは Claude Code の Bash ツール実行エラーの原因と対処 で扱った設計の話と地続きで、ツールごとに「何をさせるべきか」を決めると事故が減ります。
CSV を扱うときの落とし穴
私が運営しているアプリの App Store Connect レポートは、月次で数万行の CSV になります。これを Read で素直に開かせると、ヘッダー行と先頭数千行は読めても、12月や3月のデータが末尾にある場合に切られて見つからない、という現象が起きます。
CSV を扱うときの私の手順は次の通りです。
# 1. ヘッダーだけ確認
head -1 /tmp/sales-2025.csv
# 2. 必要な列の値を絞り込み(例: 売上が1000円以上の行)
awk -F',' '$5 >= 1000' /tmp/sales-2025.csv > /tmp/filtered.csv
wc -l /tmp/filtered.csv
# 3. 集計だけ取り出す
awk -F',' '{sum+=$5} END {print sum}' /tmp/sales-2025.csvCSV の場合、生データを Claude に渡すよりも、bash で集計してから「合計はいくらだった、上位5件は何か」というサマリーを Claude に判断してもらうほうが文脈効率も高く、切り捨ても起きません。
ログファイルでよくある事故と回避策
「昨日のエラーを調べて」と頼んだのに Read が古い時間帯で止まっていた、という事故は典型的です。私は次のヘルパーパターンを使うようにしています。
# エラー行とその前後5行をまとめて取得
grep -nB 2 -A 5 "ERROR\|Exception" /var/log/app.log | tail -200-B(前)と -A(後)でコンテキストを取り、tail で最近のものだけに絞ります。これで200行程度に収まるので、Claude に直接渡しても切れません。tail -f のリアルタイム監視は Claude には向かないので、一定時間スナップショットを取って Read させるほうが現実的です。
JSON ファイルは別の罠がある
大きな JSON は CSV やログとは違った形で問題を起こします。5MB の JSON が1行で書かれている場合は「2000行で切られる」のではなく、巨大な1行をそのまま取り込んでコンテキストが急激に減ります。一方で整形済みの JSON だと5万行に及ぶことがあり、こちらは普通に切られます。
私が JSON を扱うときは Read ではなく jq で構造だけ取り出し、Claude には「形」と「サンプル」だけ見せるようにしています。
# トップレベルのキーを確認
jq 'keys' /tmp/big-payload.json
# items 配列の件数
jq '.items | length' /tmp/big-payload.json
# 代表的な3件をサンプリング
jq '.items[0:3]' /tmp/big-payload.json3件のサンプルと件数とキー一覧があれば、Claude は十分に推論を進められます。整形済み5万行を丸ごと渡してもむしろ精度が落ちます。
バイナリ・minify されたファイルは Read しない
これは切り捨て以前の話ですが、Read はテキスト前提のツールです。minify された JS バンドル(数MBで改行が極端に少ない)、画像、PDF、SQLite ファイルを Read で開くと、行が長すぎて token を浪費するだけでなく、Claude の応答品質も落ちます。
私の運用ルールはシンプルで、1行が500文字を超えるか、ファイルが1MB を超えたら Read ではなく bash で要約するです。minify バンドルなら wc -c でサイズだけ見て、構造は package.json や source map から推定するほうが速いです。
長いセッションでコンテキストを節約したい場面については Claude Code の長時間セッションでコンテキストを劣化させない方法 で扱っているので、組み合わせて参考にしてください。
私が普段使っているチェックフロー
最後に、Claude Code に大きなファイルを渡す前に私が踏んでいる確認フローをまとめます。
最初に wc -l と ls -lh でサイズと行数を見ます。次に、行数が2000を超えていたら Read を直接使うのを諦め、grep や awk で必要な部分を抽出してから渡します。集計が必要な場合は bash 側で完結させ、サマリーだけ Claude に渡します。これだけで切り捨て事故はほぼなくなりました。
個人開発を10年以上続けてきた感覚として、こうした「ツールの限界を先に把握する」習慣はそのままバグの予防につながります。Claude Code を本格的に運用に組み込むなら、まず Read の挙動を再現実験で押さえておくのが回り道のようで近道です。
次にやってみてほしいこと
手元にある10万行以上のログまたは CSV を1つ用意して、Read(file_path=..., offset=0, limit=100) で先頭だけを取り、続けて bash で wc -l を実行する流れを Claude Code に頼んでみてください。「全体は何行で、先頭100行に何が含まれていたか」を Claude が言語化できれば、それ以降は offset と limit を意識して使い分けるリズムが自然と身につきます。
お読みいただきありがとうございました。同じ場所で詰まっている方の助けになれば嬉しいです。