DEV Community

Lily
Lily

Posted on • Originally published at dev.to

Making a Bloated Claude Code Fast Again: Auditing Context Injection Down From 228KB to 48KB

Last time, I wrote about teaching Claude Code to write and grow its own skills. Once you start piling on skills and plugins, there's one wall you're guaranteed to hit eventually: sessions get heavy and instructions start slipping through the cracks. This is the record of an audit where I measured the cause and trimmed context injection from 228KB down to 48KB.

The symptom: it drops your most recent instructions

At some point, Claude Code started behaving like this:

  • Sessions were slow to start
  • It would ignore "what I just said" and cross-wire it with an earlier topic

At first I assumed it was "the model having an off day." It wasn't. The real cause was that the context injected at SessionStart had ballooned so much that the user's most recent instructions were getting buried. The bigger the injection, the more the relative presence of the latest part of the conversation gets diluted.

Isolating it: "heavy" and "foggy" have different causes

The important distinction the audit revealed was this.

Symptom The real culprit Fix
Session is just heavy Number of enabled plugins disable unused plugins
Drops recent instructions / conversation cross-wires Total injection volume Measure injection sources and prune them

If you lump "heavy" and "foggy" together, you'll keep cutting plugins with nothing to show for it. The real driver of the "foggy" problem lives somewhere else.

Measurement: get the byte count per injection source

There are multiple injection sources: plugin metadata, rules/, the Obsidian context, auto-memory, and the remember history. I measure each source empirically. You can roughly estimate tokens as "byte count ÷ 4 ≒ English tokens."

# Everything under rules/ is auto-loaded in full as "global instructions" (no cap)
find ~/.claude/rules/ecc -name '*.md' -exec cat {} + | wc -c

# auto-memory (MEMORY.md is injected in full)
wc -c ~/.claude/projects/*/memory/MEMORY.md

# remember history (now/recent/archive are injection targets)
wc -c ~/.remember/now.md ~/.remember/recent.md ~/.remember/archive.md
Enter fullscreen mode Exit fullscreen mode

Once I measured, the culprit was obvious. rules/ecc alone accounted for about 57K tokens (≒228KB) — by far the single largest block of the entire injection.

Why is rules/ so heavy?

This was the biggest trap. Everything under ~/.claude/rules/ is not read on demand via @importClaude Code loads the entire directory in full, every time, as global instructions.

My rules/ecc, inherited from a general-purpose rule pack, contained rules for 10 languages wholesale (angular / golang / swift / php / ruby / arkts / java / kotlin …). The only languages I actually write are Python / TypeScript / Web — three — yet coding conventions for languages I never touch, like Swift and Ruby, were being injected in full every single session.

The fix: keep only the languages I use, and move the rest "outside the tree"

Because rules/ is a directory load rather than @import, you don't need to touch any import lines. Just mv the files outside the tree and the injection stops. And when you want them back, you just mv them back — completely non-destructive.

# Keep only the languages I use (common/python/typescript/web); move the rest out of the tree
A="$HOME/.claude/.rules-archive/ecc"; mkdir -p "$A"
cd ~/.claude/rules/ecc
for d in angular arkts cpp csharp dart fsharp golang java kotlin perl php ruby rust swift zh; do
  [ -d "$d" ] && mv "$d" "$A/"
done
# To restore, bring them back one at a time: mv "$A/rust" ~/.claude/rules/ecc/
Enter fullscreen mode Exit fullscreen mode

Note
Even a hidden directory (.rules-archive) risks being loaded by mistake if you put it inside the rules/ tree. The archive destination must always be outside the tree.

The result

After trimming, I re-measured the current rules/ecc and got this:

$ find ~/.claude/rules/ecc -name '*.md' -exec cat {} + | wc -c
48092
$ ls -d ~/.claude/rules/ecc/*/ | xargs -n1 basename
common
python
typescript
web
Enter fullscreen mode Exit fullscreen mode

228KB (≒57K tokens) → 48KB (≒12K tokens). About a 79% reduction. The directory count dropped from 10 languages to 4. When I open a new session, startup is lighter, and dropped recent instructions have clearly decreased.

Traps I stepped in

Disk cleanup and token reduction are different things

At first, Obsidian's hot.md had grown to 32KB, so I thought "deleting this will make things lighter." I was wrong. The Obsidian context is already capped on the injection-script side at hot.md=9000 chars / index=2500 chars, so no matter how many KB the file balloons to, the injected volume stays constant at about 7K tokens.

Likewise, remember's today-*.done.md isn't an injection target either. Deleting those is disk tidying — it doesn't shave off a single bit of tokens. "Big file = heavy injection" simply doesn't hold, so always measure the injection sources empirically.

There's an upside even on the MAX plan

You might think, "On the MAX plan, $/token is a flat rate, so who cares?" On the cost side, that's true. But the real benefit of the reduction is elsewhere.

  • Saving the context window (matters on long tasks)
  • Stabilizing the cache hit rate
  • Faster session startup
  • And above all, your most recent instructions don't get buried

disable is reversible, uninstall is not

If you're cutting plugins, enabled: true→false in settings.json can be rolled back instantly. claude plugin uninstall reclaims it from disk, so it's irreversible. You should start with disable and see how it goes. That said, disabling a plugin makes its slash commands error out, so keep the rarely-used-but-important commands around.

Summary

  • "Heavy" (= plugin count) and "foggy" (= total injection volume) are separate problems. Don't conflate them.
  • ~/.claude/rules/ is a full-directory load, not @import. It easily becomes your biggest injection source.
  • The fix is just mv-ing files outside the tree. Rollback is mv too — non-destructive.
  • Disk cleanup ≠ token reduction. Always measure injection sources in bytes.
  • Result: 228KB → 48KB (about 79% off), and both startup and responsiveness got lighter.

Next time, I'll write about the launchd setup I built to run all of this automation around the clock — and the macOS-specific traps I hit along the way.


Written by **Lily* — I ship iOS apps and automate my content stack with Claude Code.
Follow along: Portfolio · X · GitHub*

Top comments (0)