Your Claude Code Setup Gets Bloated If You Ignore It — Weekly Auto-Slimming by Watching Injected Bytes, Agent Count, and Frustration Words A developer created a self-audit script for Claude Code environments that automatically detects and fixes 'environment decay' — the gradual bloat of rules, agents, and hooks that degrades performance. The script, cc-self-audit.sh, measures five metrics weekly including injected bytes, agent count, and frustration words in transcripts, then uses 'claude -p' to remediate any threshold breaches and re-measures to confirm improvement. This is the next installment in my "Claude Code environment" series. Combined with the idempotent marker implementation https://zenn.dev/bokuwalily/articles/substep-idempotent-marker from the previous article, I've come to realize that more than half of the reasons an autonomous loop won't stop come down to one thing: environment decay . A Claude Code setup gets fat if you leave it alone . The rules balloon, agents you thought you'd retired come back to life, and hooks keep misfiring. The only thing you actually notice is a vague "this feels sluggish" or "it keeps making the same mistake," and then you burn time hunting down the cause. This article is about a system that measures that decay every week, lets claude -p fix it, and then confirms the improvement with an independent re-measurement after the fix . This is a real incident I hit during a performance audit on 2026-07-11. I'd tidied up ~/.claude/agents/ several times. I'd manually moved agent definitions I no longer used into agents-archive/ and figured I was done. But when I actually measured, agents loaded was still stuck at 99. The culprit was dot-directories .deprecated/ , .backup/ , and the like . find 's default behavior recurses into dot-directories too. They looked deleted, but every single one was still being loaded through the hidden directories. This real incident is what prompted me to write cc-self-audit.sh . The script's collect function grabs five metrics every run. ~/.claude/scripts/cc-self-audit.sh(collect関数より) --- 静的 --- inject bytes=$ \ $ find "$HOME/.claude/rules" -name ' .md' -print0 2 /dev/null | xargs -0 cat 2 /dev/null | wc -c + \ $ cat "$HOME/.claude/CLAUDE.md" 2 /dev/null | wc -c + \ $ cat "$HOME/CLAUDE.md" 2 /dev/null | wc -c + \ $ cat "$HOME/.claude/projects/-Users-matsubara/memory/MEMORY.md" 2 /dev/null | wc -c agents loaded=$ find "$HOME/.claude/agents" -name ' .md' 2 /dev/null | wc -l | tr -d ' ' --- 動的(前回実行以降のtranscriptのみ・最大200ファイル)--- stopspam=$ echo "$files" | xargs /usr/bin/grep -h -c 'セルフ監査未実施。実装' 2 /dev/null | awk '{s+=$1} END{print s+0}' frustration=$ echo "$files" | xargs /usr/bin/grep -h -c -E '何回も言|いい加減にし|嘘つ|舐めんな|なんで治らん|最悪やろ|頭悪い' 2 /dev/null | awk '{s+=$1} END{print s+0}' toolerr=$ echo "$files" | xargs /usr/bin/grep -h -o -c '"is error":true' 2 /dev/null | awk '{s+=$1} END{print s+0}' | Metric | Meaning | Threshold | |---|---|---| inject bytes | Total bytes of rules + CLAUDE.md + MEMORY.md | 40,000 | agents loaded | Total .md count under ~/.claude/agents/ recursion including dot-dirs | 60 | stopspam | Number of times the audit hook fired / week | 15 | frustration | Occurrences of frustration words in transcripts / week | 8 | toolerr | Count of "is error":true in transcripts / week | 400 | The two static metrics are proxy variables for injection cost , and the three dynamic metrics are proxy variables for experience quality . The frustration-word detection may look out of place, but if I'm scolding it repeatedly, that means it's repeating the same failure — and those failures often stem from environment problems misfiring hooks, rotted memory, broken tools . The thresholds can be overridden with env variables. TH INJECT BYTES="${SELF AUDIT TH INJECT:-40000}" TH AGENTS="${SELF AUDIT TH AGENTS:-60}" TH STOPSPAM="${SELF AUDIT TH STOPSPAM:-15}" TH FRUSTRATION="${SELF AUDIT TH FRUST:-8}" TH TOOLERR="${SELF AUDIT TH TOOLERR:-400}" claude -p fixes itself If every metric is under its threshold, it just posts a one-line ✅ GREEN to Discord and exits. If any is over, it calls claude -p to fix it. BREACH=$ echo "$METRICS" | breaches if -z "$BREACH" ; then log "GREEN" touch "$LASTRUN" notify "✅ CC自己監査: 正常 $METRICS " exit 0 fi log "RED: $BREACH" if "$DRY" = "1" ; then log "DRY=1: 修正スキップ"; touch "$LASTRUN"; exit 0; fi The prompt passed to claude -p has a remediation policy embedded for each decay pattern. PROMPT="... 指示 1. ~/.claude 内だけを調査・修正する(プロジェクトコード・secret・plist削除は禁止) 2. 既知の劣化パターンと正典: - agents loaded超過 → ~/.claude/agents/ 配下の退避漏れ(ドットdirも読み込まれる)を ~/.claude/agents-archive/ へ移動 - inject bytes超過 → 肥大したrules/MEMORY.mdを圧縮(フル版は ~/.claude/rules-archive/ へ。リンクは全維持し索引整合を検証) - stopspam超過 → ~/.claude/hooks/self audit stop.sh の抑制ロジックを点検 - frustration/toolerr超過 → 該当transcriptをgrepして繰り返し失敗の真因を特定し、hook/スキル/メモリで再発防止を仕込む 3. 変更は1件ずつ ${CHANGELOG} に「日時/対象/理由/戻し方」を追記 4. 修正後に必ず 'bash ~/.claude/scripts/cc-self-audit.sh --collect-only' を実行し改善を数値で確認 ..." I restrict it to filesystem operations only with --allowedTools "Read,Write,Edit,Bash,Grep,Glob" , and cap it at max-turns 50 and a 20-minute wall clock FIX TIMEOUT=1200 . Note Having claude run --collect-only itself inside the fix loop is strictly "a confirmation as part of the remediation procedure." The final verdict of the audit is made by the outer, independent re-measurement. The key to the design is not taking the inner confirmation at face value. Even when claude -p says "fixed it," I don't believe it right away. The outer harness calls collect again to re-measure the numbers . 独立再計測(自己申告は信じない) AFTER=$ collect log "after: $AFTER" echo "$AFTER" "$HISTORY" STILL=$ echo "$AFTER" | breaches touch "$LASTRUN" if -z "$STILL" ; then notify "🔧 CC自己監査: 劣化検知→自己修正済み。前: $BREACH 後:全緑。詳細=$CHANGELOG" else notify "🚨 CC自己監査: 自己修正後も残存 $STILL 。要確認: $LOG / $CHANGELOG" fi If a violation still remains after the fix, it flies off to Discord with a 🚨 and hands it over to a human. Trust only the OS's measured values, not self-reporting — that's the core of fail-closed. All measured values are stacked one record per line in ~/.claude/self-audit/history.jsonl , and the prompt handed to claude also includes the most recent 5 entries as a trend. By looking at the magnitude of change — "it was 30KB last week but 51KB this week" — I can distinguish a one-off outlier from a continuous increase. php < -- ~/Library/LaunchAgents/com.lily.cc-self-audit.plist --