CLAUDE LABJP
AUTO — Auto mode becomes the default in Claude Code today, August 14, across the Pro, Max, and Team plansPRICE — Sonnet 5 promo pricing of $2/$10 per Mtok is now permanent; the increase to $3/$15 planned for September 1 will not happenFIX — Version 2.1.231, released August 13, fixes MCP OAuth sign-in failing with a redirect URI mismatch on servers that use a pre-registered client, such as SlackSUNSET — The legacy Workbench and the experimental prompt tool APIs retire on August 17, now three days awayMCP — Support for the new MCP 2026-07-28 spec is rolling out, bringing a stateless core, stronger OAuth and OIDC authorization, and versioned extensions for Apps and TasksBOOST — The temporary 50% weekly usage boost for Claude Code subscribers runs through August 19AUTO — Auto mode becomes the default in Claude Code today, August 14, across the Pro, Max, and Team plansPRICE — Sonnet 5 promo pricing of $2/$10 per Mtok is now permanent; the increase to $3/$15 planned for September 1 will not happenFIX — Version 2.1.231, released August 13, fixes MCP OAuth sign-in failing with a redirect URI mismatch on servers that use a pre-registered client, such as SlackSUNSET — The legacy Workbench and the experimental prompt tool APIs retire on August 17, now three days awayMCP — Support for the new MCP 2026-07-28 spec is rolling out, bringing a stateless core, stronger OAuth and OIDC authorization, and versioned extensions for Apps and TasksBOOST — The temporary 50% weekly usage boost for Claude Code subscribers runs through August 19
Articles/Claude Code
Claude Code/2026-08-14Advanced

One generated file outweighed all 70 hand-written source files, so I redrew what Claude Code may read

I profiled a repository I actually run to see which areas consume the most context. Here is what I found, the deny rules I settled on, how search selectivity changes the math, and the options I considered but rejected.

Claude Code217settings.json3context10cost design4repository operations

Premium Article

"Which file decides where the preview gets cut off?" I asked Claude Code that about a site I run.

The answer came back correct — two files, precisely identified. What surprised me was the volume read along the way. It went well past what I had pictured when I said "just go find it."

As an indie developer working alone, there is nobody to point out that kind of friction. So before changing how I explore, I decided to measure the repository itself. You cannot decide what to exclude until you know what weighs what.

The finding that stopped me: a single generated file — one that gets rebuilt on every build — outweighed all seventy hand-written source files combined.

Measure the repository before the session starts

The subject is the claudelab.net repository: a Next.js site holding 806 Japanese and 806 English articles as MDX, with 1,796 files under version control.

I started with a small script that ranks areas by "how heavy is this to read." There is no need to replicate a tokenizer exactly. As long as areas can be compared against each other, the decision is the same. Japanese characters count as roughly one token each; everything else as roughly 3.6 characters per token.

#!/usr/bin/env python3
"""ctxweight.py - rank version-controlled files by how heavy they are to read.
 
Usage:
    python3 ctxweight.py            # whole repository
    python3 ctxweight.py src        # one directory
"""
import collections
import subprocess
import sys
 
PRICE_PER_MTOK = 2.0  # input price in USD per 1M tokens; substitute your own model's
 
 
def estimate_tokens(text: str) -> int:
    """Approximate CJK at ~1 char per token and everything else at ~3.6 chars.
 
    Exact counts depend on the model's tokenizer, so treat this as a relative
    measure -- "area A is N times area B" -- rather than an absolute figure.
    """
    cjk = sum(1 for ch in text if ' ' <= ch <= '鿿' or '＀' <= ch <= '￯')
    return int(cjk + (len(text) - cjk) / 3.6)
 
 
def tracked_files(roots):
    # git ls-files means .gitignore'd paths drop out without a hand-kept list
    out = subprocess.check_output(['git', 'ls-files', '-z'] + list(roots)).decode()
    return [f for f in out.split('\0') if f]
 
 
def group(path: str) -> str:
    parts = path.split('/')
    return '/'.join(parts[:2]) if len(parts) > 1 else '(root)'
 
 
def main():
    agg = collections.defaultdict(lambda: [0, 0])  # [tokens, files]
    per_file = []
 
    for path in tracked_files(sys.argv[1:]):
        try:
            text = open(path, encoding='utf-8').read()
        except (UnicodeDecodeError, OSError):
            continue  # binaries such as images are out of scope; skip quietly
        tokens = estimate_tokens(text)
        agg[group(path)][0] += tokens
        agg[group(path)][1] += 1
        per_file.append((tokens, path))
 
    total = sum(v[0] for v in agg.values()) or 1
    print(f"{'area':<28}{'est. tokens':>12}{'files':>7}{'share':>8}{'$/read':>9}")
    for key, (tokens, files) in sorted(agg.items(), key=lambda x: -x[1][0])[:15]:
        print(f"{key:<28}{tokens:>12,}{files:>7,}"
              f"{tokens / total * 100:>7.1f}%{tokens / 1e6 * PRICE_PER_MTOK:>9.3f}")
    print(f"{'total':<28}{total:>12,}"
          f"{sum(v[1] for v in agg.values()):>7,}{100.0:>7.1f}%"
          f"{total / 1e6 * PRICE_PER_MTOK:>9.3f}")
 
    print("\n-- heaviest individual files --")
    for tokens, path in sorted(per_file, reverse=True)[:5]:
        print(f"{tokens:>12,}  {path}")
 
 
if __name__ == '__main__':
    main()

Using git ls-files matters more than it looks. It drops node_modules and .next for free, and a hand-maintained exclusion list always drifts out of date.

Run against the whole repository:

AreaEst. tokensFilesShare
content/articles7,666,9271,61291.0%
src/generated289,60323.4%
repository root162,418151.9%
content/blog157,421701.9%
src/app80,278361.0%
src/components37,332220.4%
Total8,422,3231,796100%

Article bodies taking 91% is unremarkable for a content site. That line matched my expectations exactly.

The next line did not.

A generated file weighed 2.2 times all the code I wrote by hand

Narrow the scope to src and the distortion becomes obvious.

AreaEst. tokensFilesShare of src
src/generated289,603268.9%
src/app80,2783619.1%
src/components37,332228.9%
src/config8,11521.9%
src/lib and others5,029101.2%

All seventy hand-written source files together come to 130,754 tokens. src/generated reaches 289,603 across two files, with articles.json alone accounting for 284,072. A ratio of 2.21.

That file is metadata assembled mechanically from the MDX sources and rewritten on every build. Reading it adds no information whatsoever. Every fact inside it already lives under content/.

Yet in any exploration scoped to src, it sits right at the front of the queue. The filename says articles.json and the path says src, and both read as important. Files that look central by name and location are sometimes the derived ones.

Converted to input price, those two files cost about USD 0.58 per read. Reading every hand-written file costs USD 0.26. The side carrying zero new information was more than twice as expensive.

Prices move, of course. Sonnet 5's input price became permanent at USD 2 per million tokens on 10 August 2026, and the increase that had been scheduled for 1 September will not happen. Still, replace PRICE_PER_MTOK with a figure you have checked yourself rather than trusting a number in an article.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
You will be able to pinpoint which parts of your own repository eat context, using a single command, and decide what to exclude with evidence behind it
You will be able to avoid the failure where generated artifacts quietly enter exploration, inflating input cost and muddying reasoning at the same time
You will be able to recognise the cases where a poorly scoped search costs more than simply reading the files
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
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 →

Related Articles

Claude Code2026-07-16
The Permission Rules You Added for Safety Are Taxing Every Turn — Auditing the Ruleset Without Loosening It
Version 2.1.209 fixed the per-turn slowdown from large deny/ask rulesets, but the design debt in your rules is still yours. Here are the audit scripts, a shadowing detector, a turn-timing harness, and how to fold enumerated rules into prefix rules safely.
Claude Code2026-07-15
Choosing Dynamic Workflow Size and Effort From a Ledger, Not a Hunch
Dynamic Workflows went generally available, handing you the workflow size and effort dials. After a week of picking large and watching only the bill grow, here is how to turn Claude Code's OpenTelemetry console output into a ledger and assign size and effort per task type.
Claude Code2026-07-10
Carrying Decisions Across Compaction with PreCompact and SessionEnd Hooks
Auto-compaction does not delete your conversation. It deletes the reasons behind it. Here is a working PreCompact / SessionEnd / SessionStart hook pipeline that rescues decisions to disk and hands them to the next session, with real code and measurements.
📚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 →