CLAUDE LABJP
FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as OctoberFORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Articles/Claude Code
Claude Code/2026-05-10Intermediate

When Claude Code's Read Tool Silently Truncates Large Files — offset/limit Patterns and When to Reach for Bash

Lessons from running an indie app business since 2014: how Claude Code's Read tool quietly cuts off after 2000 lines, the three signs of truncation, and when to use offset/limit versus bash.

claude-code129troubleshooting87read-toolfilesbash4

I have been shipping wallpaper and meditation apps as an indie developer since 2014, and as that business grew I started feeding App Store Connect CSVs and access logs into Claude Code for analysis. One day I asked Claude Code to read a 100,000-line access log and extract every line containing a particular checkout keyword. The result came back suspiciously short. After a few minutes of confusion I realized what had happened: the Read tool had quietly stopped at the first 2000 lines. No error. No warning. Claude was reasoning over a fraction of the file without knowing the rest existed.

Silent truncation like this is a class of bug that hits anyone working with logs, CSVs, large JSON, or minified bundles in Claude Code. After getting bitten by it a few times I built a mental model for when Read is the right tool, when offset and limit come in, and when the answer is "do not use Read at all, drop into bash." Here is what I have settled on.

Why Read Caps at 2000 Lines

Read returns at most the first 2000 lines by default. The cap exists to protect Claude's context window, and the failure mode is to return a partial file without raising an error. When the information you need lives below line 2000, Claude has no signal that anything is missing — it confidently reasons over the head of the file as if it were the whole thing.

My grandfathers were both temple carpenters in Japan, and one principle I inherited from watching them work is "understand the tool's grain before you use it." Once you accept that Read quietly cuts and never warns, you stop blaming the wrong things when results look off.

Three Signs You Got Truncated

A few signals tell you truncation is in play.

The first is the response ending exactly at line 2000. If you suspect the file is larger and Claude's last line number is 2000, assume it was cut.

The second is file size above roughly 100 KB. At an average of 50 bytes per line, 2000 lines is about 100 KB. Anything heavier is almost certainly past the cap.

The third is the answer "not found" when you know the data is in there. When Claude reports that a December record does not exist in a file that obviously contains a full year, run wc -l first.

# First sanity check whenever truncation feels possible
wc -l /path/to/large.csv
ls -lh /path/to/large.csv

How I Use offset and limit

Read accepts two arguments that most people skip past in the docs: offset (the line number to start from) and limit (how many lines to read). Using these well is the difference between "Read keeps cutting things" and "Read does exactly what I want."

Pattern 1: You Know Roughly Where to Look

When you have a sense of the line range — a function definition, a section heading, the timestamp of an error — pass offset and limit directly.

Read(file_path="/path/to/server.log", offset=4500, limit=200)

For logs, run grep -n "ERROR" server.log | head first to surface the line numbers of interest, then point offset at one of them.

Pattern 2: You Cannot See the Target

If you are looking for "every line containing X" or "how many rows match Y", filter in bash before calling Read.

# Narrow the file first, then read what is left
grep -n "checkout" /path/to/access.log > /tmp/checkout-lines.txt
wc -l /tmp/checkout-lines.txt

If the filtered output is under 2000 lines, Read it. If not, narrow further with head -100 or another grep.

Pattern 3: You Want a Whole-File Scan

This is bash territory, not Read territory. Read is built to give Claude context, not to be a data-processing engine. Aggregations and full scans belong in bash, awk, or Python — feed Claude only the summary.

The same separation-of-duties idea runs through Claude Code Bash Tool Execution Errors and How to Fix Them, and once you start dividing work by tool the failure modes shrink dramatically.

CSVs Are Where This Bites Hardest

The App Store Connect reports for my apps run to tens of thousands of rows per month. Letting Claude Code Read one of them directly works fine for the headers and the first few thousand lines, but a query like "what was December's total" can come back wrong because December lives at the bottom of the file, past the cap.

My standard CSV workflow now looks like this:

# 1. Inspect the header
head -1 /tmp/sales-2025.csv
 
# 2. Filter on the column you care about (rows where revenue >= 1000)
awk -F',' '$5 >= 1000' /tmp/sales-2025.csv > /tmp/filtered.csv
wc -l /tmp/filtered.csv
 
# 3. Compute the aggregate in bash, hand only the answer to Claude
awk -F',' '{sum+=$5} END {print sum}' /tmp/sales-2025.csv

For CSVs, asking Claude to reason over raw rows is almost always worse than asking Claude to interpret a small numeric summary.

Logs and the "Yesterday's Errors" Trap

A common version of this bug is asking Claude to investigate "yesterday's errors" while Read quietly returns a window of yesterday morning's traffic and stops. The pattern I keep on hand for log triage is:

# Pull error lines plus surrounding context, then take only the recent ones
grep -nB 2 -A 5 "ERROR\|Exception" /var/log/app.log | tail -200

-B and -A give you context, tail keeps it recent. The result fits comfortably in the cap. Real-time tailing (tail -f) does not work well as a Claude input — take a fixed snapshot instead, hand it over, and ask for analysis.

JSON Files Need Their Own Approach

Large JSON files are a separate trap. A 5 MB JSON file might be a single line, in which case Read will not "truncate at line 2000" — it will pull the whole thing and burn enormous context. A formatted JSON file, on the other hand, can run to 50,000 lines and get cut.

For JSON I almost never let Claude Read directly. The pattern is to extract just the keys or just the relevant subtree with jq, then feed Claude the shape.

# What is the top-level shape?
jq 'keys' /tmp/big-payload.json
 
# How many entries are in the items array?
jq '.items | length' /tmp/big-payload.json
 
# Pull a representative sample of three records
jq '.items[0:3]' /tmp/big-payload.json

Claude can do excellent reasoning over a three-record sample plus a count and a key list. It struggles when handed 50,000 lines of nested objects.

Do Not Read Binary or Minified Files

Truncation is one issue. Wasting tokens is another. Read assumes text. Pointing it at minified JS bundles (megabytes with almost no line breaks), images, PDFs, or SQLite files burns context and degrades Claude's reasoning.

My personal rule: if a single line is over 500 characters, or the file is larger than 1 MB, do not Read it — summarize from bash instead. For a minified bundle, wc -c plus inspection of package.json or the source map tells you more than dumping the file.

If you are juggling many of these concerns inside one long session, How to Keep Claude Code's Context Healthy Across Long Sessions covers the broader budgeting question and pairs well with this article.

My Pre-Read Checklist

This is the routine I run before handing any sizeable file to Claude Code.

I start with wc -l and ls -lh to see how big the thing actually is. If the line count is over 2000, I stop reaching for Read directly and pre-filter with grep or awk. Anything that looks like aggregation gets done in bash, with only the summary handed to Claude. Since adopting this flow, silent-truncation incidents have basically disappeared.

Ten years of indie development has taught me that learning a tool's limits before relying on it is the same skill as preventing bugs. Bringing Claude Code into a serious workflow is no different — get the Read behavior into your fingers through small experiments first, and the rest gets easier.

What to Try Next

Grab a real log or CSV with at least 100,000 lines. Ask Claude Code to call Read(file_path=..., offset=0, limit=100) and then run wc -l in bash. Once Claude can articulate "the file has N lines and the first 100 contain X," using offset and limit deliberately becomes second nature.

Thanks for reading. I hope this saves someone the afternoon I lost to a silently truncated log file.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Claude Code2026-05-13
Claude Code Bash Tool Hangs on `npm run dev` and `docker run` — How to Handle Long-Running Processes
Claude Code's Bash tool freezes when running npm run dev, docker run, or other long-running processes. Learn background execution patterns, timeout strategies, and process management best practices.
Claude Code2026-04-08
Fix Claude Code Bash Tool Execution Errors — Timeouts, Permission Denied, and Truncated Output
Learn how to troubleshoot and fix Claude Code Bash tool errors including timeouts, Permission Denied, ENOENT, truncated output, and environment variable issues with step-by-step solutions.
Claude Code2026-06-18
When a Broken settings.json Stops Claude Code From Starting — Safe Mode and How to Split Your Config
How to find which config layer is broken when a settings.json syntax error stops Claude Code from starting, recover in minutes, and structure your settings so an automated pipeline can't quietly break itself.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →