`rtk read --max-lines N` outputs only N/2 lines — `head -N` hook rewrite silently under-delivers half the requested lines
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 81.1k
- Forks
- 5.1k
- Avg merge
- 4d 21h
- Merged PRs (30d)
- 35
Description
Environment
- rtk 0.38.0 and 0.44.2 (both reproduce)
- macOS (Darwin 25.5.0, arm64), Homebrew install
- Claude Code, hook:
PreToolUse→matcher: "Bash"→rtk hook claude
Summary
--max-lines N emits exactly N/2 content lines (plus a [K more lines] marker), not N. Because the Claude Code hook rewrites head -N <file> to rtk read <file> --max-lines N, every agent head -N receives half the lines it asked for.
Repro
$ python3 -c "open('long.txt','w').write(''.join(f'line {i}: some content here\n' for i in range(3000)))"
$ for n in 5 10 20 50 100 200; do
echo "max-lines $n -> $(rtk read long.txt --max-lines $n | grep -c '^line ')"
done
max-lines 5 -> 2
max-lines 10 -> 5
max-lines 20 -> 10
max-lines 50 -> 25
max-lines 100 -> 50
max-lines 200 -> 100
Expected (matching head -50): 50 lines. Actual: 25 lines + [2975 more lines].
Hook path that makes this user-visible:
$ rtk hook check 'head -50 big.log'
rtk read big.log --max-lines 50 # → agent gets 25 lines
--tail-lines N is exact (verified against tail -N, byte-identical); only --max-lines halves.
Impact
- Any agent running
head -N filesilently getsN/2lines. The truncation marker is visible in standalone use, but the count contradicts what was requested. - On 0.38.0 this also poisoned pipelines (
head -200 f | grep X→ grep searched only 100 lines and the marker was consumed by grep → silent false negative). 0.44.2 no longer rewritesheadinside pipelines, which contains that failure mode — but the standalone halving remains.
Additional observation (savings accounting)
rtk read ... --max-lines/--tail-lines invocations are logged to history.db with original_cmd synthesized as plain cat <file> (flags erased), input_tokens = the full file, and the difference booked as savings. Example measured entry: a --max-lines 20 read of a 1.27 MB file logged as cat <file>, input=318,445 tokens, output=119, savings 99.96%. A raw head -20 would have produced the same small output without rtk, so the full-file baseline overstates real savings. In our 3-month ledger, 205 such entries account for 71.5M of 79.4M total rtk read "saved" tokens (~90%). Related in spirit to #3339 (different mechanism). Happy to split this into its own issue if you prefer.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue with the provided Python file-generation command and the rtk read --max-lines loop. Trace the implementation of rtk read and the Claude hook rewrite for head -N; compare --max-lines with the verified --tail-lines behavior. Done means --max-lines N emits N content lines, the hook preserves head semantics, and relevant command behavior is covered by tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 66/100