One night I opened the instruction file I use for running my websites and stopped at the size of the scrollbar. Rules I had been adding for months had quietly reached about 32KB.
What sent me there was a pattern: rules I knew I had written were being missed more often. I would point at the line, and all I got back was a polite apology. Maybe what was missing wasn't another instruction. Maybe it was room for the reader.
This post covers the lines I used to roughly halve what gets loaded every time. It applies whether you're using Cowork project instructions or a CLAUDE.md in your folder.
Load only what today's work always needs. Everything else can move, and moving it costs nothing.
Three ways to tell an instruction file has grown too long
When a rule isn't followed, I check these first:
- Are the ignored rules clustered in the later part of the file?
- Is the same rule written twice in different words?
- Has the story of a past incident settled in right beside the rule it produced?
All three applied to me. Adding a line takes seconds, so each addition felt like safety. But text loaded every time takes a little of the room in every task, one line at a time.
I should add that how length affects accuracy depends on the environment and the model. This is what happened on my machine, not a threshold above which things always break.
Measure first
If I cut by feeling, I keep the parts I'm used to reading. So I put numbers on it first. This script splits a Markdown file at each ## heading and lists the sizes, largest first. It uses only the standard library.
# measure_sections.py — measure the size of each heading in an instruction file
import re
import sys
from pathlib import Path
text = Path(sys.argv[1]).read_text(encoding="utf-8")
parts = re.split(r"(?m)^(?=## )", text)
rows = []
for part in parts:
title = part.splitlines()[0].strip() if part.strip() else "(top)"
rows.append((len(part.encode("utf-8")), title))
total = sum(size for size, _ in rows)
print(f"total {total:,} bytes")
for size, title in sorted(rows, reverse=True):
print(f"{size:>7,} bytes {size / total:>5.1%} {title}")Run it as python3 measure_sections.py CLAUDE.md. In my file, the largest sections were procedures needed only for certain jobs, and reference tables. Those were the weakest reasons to load anything every time.
Sorting into three drawers
Starting from the largest heading, I asked one question per item:
| Question | If yes |
|---|---|
| Would breaking this hurt no matter what I'm working on today? | Keep (loaded every time) |
| Is it a procedure or list needed only for a specific job? | Move (to another file, leaving a one-line pointer) |
| Is it the story of a past incident, or a fixed problem? | Delete (or archive in a history file) |
What I keep
Prohibitions that are costly to break, style rules that apply to everything, and a map of where things live. One line of map means I don't have to carry the contents.
What I move
Per-site settings, troubleshooting tables, long procedures. In the main file I left this:
## Where the details live
- Troubleshooting table, settings list → REFERENCE.md (read only for that kind of job)
- Full history → archive/ (normally not read)The thing I was most careful about was writing when to read it into the pointer. "See REFERENCE.md for details" alone tends to push the reader to either open it every time or never.
What I delete
An incident's backstory is valuable as the reason a rule exists. But the daily work needs only the conclusion. I moved the story to a history file and left the conclusion and the prohibition in a single line.
Tightening the wording wasn't enough
The first thing I tried was rephrasing: turning "when you do X, always do Y" into "X: always Y". A few lines disappeared, but the total size barely moved.
The reason is simple. What was heavy wasn't the phrasing; it was the number of items. Here is the same rule set, tightened versus relocated:
# Tightened only (all items still there)
- Before publishing, confirm the JA/EN counts match. If not, don't publish.
- After publishing, append to the ledger. Columns: slug / type / source.
- If the ledger breaks, run the recovery script. Steps 1-7 below.
# Relocated (one line stays in the main file)
- What to do before and after publishing lives in PUBLISHING.md, read only for publishing jobs.
One rule stays here as well: if JA/EN counts don't match, don't publish.Keep only the single sentence that hurts when broken, and put the rest where it's read for that kind of job. Splitting did far more than squeezing.
After halving, check three things
I don't cut and walk away. Over a few days of real work, I watch for:
- When a moved procedure becomes necessary, can I follow the pointer to the right file?
- Is any rule that used to hold now slipping?
- Am I repeating the same question more often?
If 2 or 3 happens, that item goes back to the main file. Cutting becomes safe only when you also have a standard for putting things back. A short reason on the restored line saves the next person doing this cleanup, who is probably you, from hesitating.
If you're in the same spot
Here's one thing you can do in the next fifteen minutes. Run measure_sections.py on your instruction file, pick the largest heading, and decide whether its contents are needed "always" or "only for that job". If it's the latter, move it to another file and leave a one-line pointer behind.
I think moving one heading is a good enough first step. It tends to make the rest of the file much easier to see.