My CLAUDE.md was 48,000 tokens. I cut it to 4,400 — and then measured whether that broke anything. A developer restructured a 194,492-character CLAUDE.md memory file down to 17,283 characters — a 91% reduction — by splitting content into a resident core plus 12 skills and 28 reference files loaded on demand, then built a measurement harness that runs real headless Claude Code sessions to verify the restructure did not break behavior. All 26 security rules and 21 architectural invariants stayed resident, while topic-specific guidance moved to skills and path-globbed rules. The developer reports only four words lost, all from headings deleted intentionally. Every session in my repo started by loading a 194,492-character CLAUDE.md . That is roughly 48,600 tokens, on every single message , and about 4.9× the size at which Claude Code starts warning you about a memory file. Disclaimer: This guide and the accompanying scripts were generated with the assistance of AI. The workflow was tested end-to-end on one real repository and the numbers quoted throughout are from that run, but every codebase differs — please read and double-check all terminal commands and scripts before running them on your own system. Two things worth knowing before you start. The restructure rewrites CLAUDE.md in place and creates files under .claude/ — commit or back up first so you can git checkout your way out. The measurement harness launches real headless Claude Code sessions , one per prompt, which consume API quota and can take several minutes each; start with two or three prompts before running twenty. None of it was junk. It was two years of hard-won operational memory: the migration command that silently deletes an index, the seat index that retries the same seat forever, the colour function that serialises to a syntax both our contrast checkers were blind to. Deleting it was not an option. I got it to 17,283 characters — a 91% reduction — with four words lost, all of them from headings I deleted on purpose. Then I measured whether the restructure actually worked, which turned out to be the most useful part and the part nobody writes about. Here is the whole method, including the mistake I made halfway through. "Just delete the stale bits." You cannot know which bits are stale without re-reading the code each one describes. "This trap looks obsolete" is a guess, and a wrong guess deletes the one note that would have saved the next debugging session. "Summarise it." This is the dangerous one, and I will come back to it. "Use @import to split it up." Imports expand inline. You get a tidier file and identical context cost. The actual problem is not that the file is big. It is that all of it loads for all of it , including the 90% irrelevant to whatever you are doing right now. A CSS bug does not need the Stripe webhook ordering rules. | Layer | Holds | Loads | |---|---|---| | CLAUDE.md | Commands, and rules true in every session | Always | | .claude/skills/