| name | context-audit |
| description | Use when user asks to audit Claude Code context hygiene, optimize token usage, review CLAUDE.md for bloat, check settings.json for context-saving flags, or flag expensive MCP servers and oversized skills. Produces a Context Health Score (1-100), per-turn overhead estimate, and ranked action items. |
Context Audit
Overview
Audits the user's Claude Code environment for token waste and context bloat. Reports a Context Health Score (1-100), a concrete per-turn overhead estimate, and ranked action items. Offers to walk findings one-by-one, applying safe fixes to CLAUDE.md and settings.json.
When to Use
- User says: "audit my context", "optimize tokens", "check my CLAUDE.md", "context hygiene", "/context-audit"
- Conversations hitting auto-compact early
- Slow session startups (heavy CLAUDE.md / too many MCPs)
- Before onboarding a new project
Audit Procedure
Step 0 (MANDATORY): Schema discovery + fail-closed
Schema changes between versions. Never propose a settings key from memory.
cat ~/.claude/settings.json
claude config list 2>/dev/null
Fail-closed rules (#16):
- If schema cannot be obtained this session → abort all settings-change suggestions. Report other sections but mark Settings audit "skipped: schema unavailable".
- If a key is not present in schema
properties → DO NOT propose it. No guesses.
- If
claude CLI is missing → skip MCP-list-dependent checks, fall back to reading settings.json + .mcp.json directly.
Step 0.5: Self-test (#15)
Before running against user, dogfood on skill's own files:
wc -l ~/.claude/skills/context-audit/SKILL.md — if >400, skill is hypocritical.
- Check frontmatter: description ≤ 500 chars, starts with "Use when", no workflow summary (CSO trap).
- If self-test fails → report it first, then proceed to user audit.
Token Measurement Primitives (#2)
Use these for all estimates — never invent numbers.
wc -c <file>
grep -c '^' <file>
Report in both tokens and bytes so the user can verify.
1. CLAUDE.md Audit
Locate all CLAUDE.md files:
~/.claude/CLAUDE.md (global/user)
$CWD/CLAUDE.md (project)
$CWD/**/CLAUDE.md (nested)
- Managed/policy CLAUDE.md if present
Measure actual tokens for each (chars/4). Report real numbers.
Hierarchy dedup (#1): compute overlap between global + project + nested:
- Normalize lines (strip whitespace, lowercase).
- For each line appearing in >1 file → flag as "2× tax" or "3× tax" in per-turn cost.
- Suggest consolidating to the highest-scope file that applies.
Per-file flags:
| Issue | Example | Detection |
|---|
| Default-behavior rules | "Write clean code", "Be concise", "Don't hallucinate" | Pattern list |
| Contradictions | "Always use X" + "Prefer Y over X" | Scan for antonyms |
| Redundancy | Same rule in multiple sections | Line hash |
| Verbose reference blocks | API schemas, long examples | Block >30 lines |
| Stale notes | Dated TODOs, "temporary" rules >30d old | Date regex |
| Narrative | "The reason we do this is..." | Prose paragraphs |
Progressive disclosure: block >30 lines → extract to docs/<topic>.md + 1-line pointer.
2. Settings & Config Audit
Read all three layers:
~/.claude/settings.json (user)
$CWD/.claude/settings.json (project)
$CWD/.claude/settings.local.json (local, git-ignored)
~/.claude/managed-settings.json (policy, read-only)
Effective-merge view (#7): show the user the merged config, not raw files. Merge order (last wins for most): managed < user < project < local < CLI args. For permissions.* arrays, items union. Display:
effective autoCompactWindow = 500000 [from: user]
effective permissions.deny = [...] [from: user ∪ project]
Unused permissions.allow entries (#8): grep transcripts for each allow rule's pattern. If rule never matched a tool call in the last N sessions → flag "unused allow — remove to shrink prompt".
grep -rh 'ffmpeg' ~/.claude/projects/ | wc -l
Known-stable context-hygiene areas (schema-verified only):
permissions.deny — block heavy dirs. Safe.
permissions.allow — trim unused, add frequent safe reads.
- Auto-compact keys — VERSION-DEPENDENT. Past seen:
autoCompactWindow (integer chars). Verify this session before proposing.
cleanupPeriodDays — transcript retention.
skillListingBudgetFraction / skillListingMaxDescChars — tune skill listing cost.
Never propose: autoCompactPercentageOverride, bashMaxOutputLength, any key absent from current schema.
Procedure:
- Read effective settings.
- Confirm each proposed key in schema.
- Show diff. Confirm. Write.
- If useful idea has no schema key → report "no direct setting; consider hook or env var" — never invent.
3. Resources Audit
MCP servers
Run claude mcp list. Classify each:
| Category | Config | Disable | Cost |
|---|
Local plugin MCP (plugin:foo:bar) | settings.json.enabledPlugins | Flip to false | Schema when connected |
| User stdio/http MCP | mcpServers / .mcp.json | claude mcp remove <name> | Schema when connected |
| claude.ai built-in connector | Account-level (web) | claude.ai → Settings → Connectors | Near-zero if unauthed |
Flag:
- Connected heavy MCPs (chrome-devtools, playwright-full, puppeteer, notion, linear, slack, github, gitlab) — 2-10k tok schema each.
- Broken MCPs (
✗ Failed to connect).
- MCPs with zero historical tool calls.
- Duplicates with CLI alternatives.
Usage check:
grep -rh '"name":"mcp__plugin_<server>__' ~/.claude/projects/ | wc -l
Zero hits across many sessions → safe to disable.
Unauthed built-in connectors: near-zero cost. Don't spend user attention on these.
CLI replacements for connected MCPs:
- github →
gh
- gitlab →
glab
- filesystem → built-in Read/Write/Glob
Skills
Scan ~/.claude/skills/ and ~/.claude/plugins/**/skills/SKILL.md.
Measure:
wc -l / wc -w per file.
- Frontmatter description length.
Flag:
- SKILL.md >400 lines or >3000 words (excluding references).
- Description CSO bug (#4): description contains workflow summary ("dispatches X, then Y, then Z"). Causes Claude to skip body. Detect via:
- Keywords: "dispatches", "runs", "executes", "then", "after", "between", "per task"
- Description contains verbs that describe what the skill DOES, not when to USE.
- Description is NOT "Use when..." prefixed.
- Descriptions >500 chars.
- Report top 10 heaviest.
Custom agents (#10)
Scan ~/.claude/agents/*.md and $CWD/.claude/agents/*.md.
- Count lines + tokens per agent file.
- System prompts >2000 tokens = bloat.
- Check for overlap with existing skills (if both exist, prefer skill).
- Flag agents never invoked (grep transcripts for
"subagent_type":"<name>").
4. Hooks, Statusline, Compact Pressure
Hook output size (#6)
For each hook in settings.json.hooks:
- Identify command.
- Dry-run the command (if safe, idempotent):
bash -c "<command>" → wc -c.
- If hook fires on every
UserPromptSubmit → multiply by expected turns/session (default 50).
- Flag hooks outputting >500 tok/fire.
Safety: never dry-run hooks that write, post, or mutate state. Static-analyze the command first (check for git commit, curl POST, rm, >, >>). Skip if ambiguous.
Statusline profiler (#5)
time bash -c "$(jq -r .statusLine.command ~/.claude/settings.json 2>/dev/null)"
Flag if >200ms — causes UI lag. Suggest caching or simplification.
Auto-compact frequency stat (#9)
Grep transcripts for compact events:
grep -rh 'compact' ~/.claude/projects/*/*.jsonl | grep -ic 'auto.*compact\|compact.*event' | head
Report: compacts per session over last 30 days. High rate (>1/session average) = context under pressure → prioritize token-saving findings.
5. Report Format
# Context Health Report
Score: XX/100
Per-turn overhead: ~XXXX tokens [context floor before any work]
Per-session floor: ~XXXXXX tokens [at N turns/session]
Breakdown:
- CLAUDE.md: XX/25 [findings: N, tokens: XXXX]
- Settings: XX/25 [findings: N]
- Resources: XX/25 [findings: N, MCP tokens: XXXX, skill descriptions: XXXX]
- Hooks: XX/25 [findings: N, per-turn hook cost: XXXX]
## Top Findings (ranked by est. tokens saved)
1. [CLAUDE.md] <issue> — saves ~XXX tok/turn
Location: <file>:<line>
Fix: <one-line action>
...
## Walkthrough
(proceeds one-by-one per section 6)
Per-turn overhead calculation (#3)
Sum the concrete costs:
overhead =
tokens(all loaded CLAUDE.md)
+ tokens(skill listing: sum of descriptions + frontmatter)
+ tokens(connected MCP tool schemas)
+ tokens(UserPromptSubmit hook output × 1 per turn)
+ tokens(SessionStart hook output ÷ turns-per-session)
Report actual numbers, not estimates. Use chars/4. This is the context floor the user pays before any prompt/response.
Scoring heuristic
Start 100, subtract:
- CLAUDE.md >500 lines: -5. >1000 lines: -15.
- Each cross-file duplicate line (dedup finding): -1 (cap -10).
- Each default-behavior rule: -1 (cap -10).
- Each contradiction: -5.
autoCompactWindow missing on large ctx: -5.
- Missing deny rules for heavy dirs: -3 each (cap -10).
- Each unused allow entry (>0 allow rules, 0 usage): -1 (cap -5).
- Each connected heavy MCP never used: -5.
- Each MCP with CLI equivalent: -3.
- Broken MCP: -2.
- Each skill >400 lines: -2.
- Each skill with CSO-bug description: -3.
- Each custom agent duplicating a skill: -2.
- Each per-turn hook >500 tok: -5.
- Statusline >200ms: -3.
- Auto-compact rate >1/session: -10.
Clamp [1, 100].
6. Automation (one-by-one walkthrough)
[N/TOTAL] [AUTO|DECIDE|MANUAL] <title>
Problem: <one line>
Cost: ~XXX tok/turn
Options: 1) <action> 2) <action> 3) skip 4) stop
Apply immediately. Never batch. Never hide items. Every finding in report appears in walkthrough.
Tags:
[AUTO] — safe, reversible, one-shot.
[DECIDE] — user picks action.
[MANUAL] — user applies printed diff.
Alt entry:
y → apply all [AUTO] without prompting, still walk [DECIDE]/[MANUAL].
N → stop, print remaining as checklist.
Auto-fixable scope (schema-verified only):
- Add
permissions.deny for heavy dirs.
- Add
permissions.allow for clearly-wanted Bash cmds.
- Remove exact duplicate lines in one CLAUDE.md.
- Flip
enabledPlugins.<id> to false after explicit confirm.
Write procedure:
- Backup:
cp file file.bak.$(date +%s).
- Edit.
- If validation error → restore from backup, drop item, tell user. No retry with guesses.
Never auto: delete/move CLAUDE.md blocks, remove user MCPs, modify skills, touch managed settings.
7. Optional: multi-project aggregate (#11)
Flag in user request: "audit all my projects" / "across all projects".
- Iterate
~/.claude/projects/*/ dirs.
- For each, resolve project path → run sections 1-4.
- Aggregate findings: common CLAUDE.md antipatterns repeated across N projects = suggest moving to global.
- Rank projects by per-turn overhead.
- Single summary report, no per-project walkthrough by default (too long). Offer drill-down.
Quick Reference
| Step | Tool | Target |
|---|
| Find CLAUDE.md | Glob | **/CLAUDE.md |
| Measure file tokens | Bash | wc -c file | awk '{print int($1/4)}' |
| Read settings | Read | ~/.claude/settings.json |
| Probe schema | Edit (bogus key) | error returns schema |
| Effective merge | Bash | jq -s add user.json project.json local.json |
| List MCPs | Bash | claude mcp list |
| Check MCP usage | Bash | grep -rh '"name":"mcp__plugin_<name>__' ~/.claude/projects/ | wc -l |
| Measure skills | Bash | wc -l ~/.claude/skills/*/SKILL.md |
| Detect CSO-bug desc | Grep | description contains "dispatches |
| Custom agents | Glob | ~/.claude/agents/*.md |
| Time statusline | Bash | time bash -c '<cmd>' |
| Compact rate | Bash | grep transcripts for compact events |
| Backup | Bash | cp X X.bak.$(date +%s) |
| Patch JSON | Edit | preserve format, verified keys only |
| Disable plugin | Edit | enabledPlugins.<id>: false |
| Remove local MCP | Bash | claude mcp remove <name> |
Common Mistakes
- Rewriting CLAUDE.md wholesale — do surgical edits, preserve voice.
- Removing rules that look redundant but aren't — ask if unsure.
- Ignoring
settings.local.json — local overrides.
- Measuring skills by lines alone — 600-line reference table is fine, 600-line rule list is not.
- Reporting score without action items.
- Estimating tokens when you can measure them.
- Proposing schema keys from memory.
Red Flags
- User says "just fix it all" → still confirm destructive items.
- CLAUDE.md has legal/compliance text → never auto-remove.
- Score <50 → full review session, not one-shot patch.
- About to propose key from memory → STOP. Probe schema first.
- Edit returns "Unrecognized fields" → restore backup, drop item, tell user honestly.
- Schema unavailable → skip Settings section entirely, never guess.
- Self-test fails → report first; a bloated skill shouldn't lecture the user about bloat.
- Dry-running a hook with side effects → skip, mark as MANUAL measurement.