Cc config optimize
Skill clever-cc-plugins/cc-config/plugins/cc-config/skills/cc-config-optimize
Two Claude Code skills for setting up and maintaining a best-practice Claude Code configuration, distributed as a Claude Code plugin.
npx -y skills add clever-cc-plugins/cc-config --skill cc-config-optimizeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Audit and optimize an existing Claude Code configuration against current best practices. Use this skill when a user asks to review, improve, clean up, or optimize their Claude Code setup, CLAUDE.md, settings, hooks, MCP servers, or skills. Also use when the user says things like "check my config", "is my CLAUDE.md too long", "reduce token costs", "tighten permissions", or "my Claude Code setup feels bloated". This skill assumes the project has code, and possibly documentation or OpenSpec specs, that inform the optimization.
SKILL.md
43.8 KB, as published. Nobody here has run it
Optimize Claude Code Configuration
You are auditing and improving an existing Claude Code setup. The project has code, possibly documentation, and possibly OpenSpec specifications. Your job is to identify what's good (preserve it), what's missing, what's bloated, and what violates current best practices — then fix it with the user's approval.
Philosophy
Configuration is a multiplier, but only if it's lean. A 60-line CLAUDE.md with progressive disclosure outperforms a 300-line monolith. Three well-chosen MCP servers beat twenty poorly managed ones. A PostToolUse hook that runs the formatter on every edit eliminates an entire class of manual intervention forever.
The guiding question for every instruction in CLAUDE.md: "Would removing this line cause Claude to make a concrete mistake?" If no — remove it.
Step 0: Recall learnings
If .claude/learnings.md exists, read all entries and apply them silently to inform this run. The [skill-name] tag on each entry is provenance only — all entries apply regardless of which skill wrote them. Do not announce that learnings were loaded.
If the file does not exist, proceed without mention.
Step 1: Full inventory
Read and catalog everything that exists. Do this thoroughly before suggesting any changes.
Configuration files
CLAUDE.md(project root and any subdirectories)AGENTS.md.claude/settings.jsonand.claude/settings.local.json.claude/local.md.claude/rules/*.md.claude/skills/*/SKILL.md.claude/commands/*.md(legacy format).claude/agents/*.md.claude/learnings.md.headroom/(machine-local Headroom data — check for presence:ls .headroom 2>/dev/null && echo headroom-present || echo headroom-absent)context/(domain context files at project root by convention — company profile, brand voice, architecture decisions, etc.; if CLAUDE.md's## Context filestable registers a different location, use that instead)context/design/(Claude Design handoff artifacts — PROMPT.md, design-notes.md, screenshots/ — under the registered context location)DESIGN.md(root-level design system spec — YAML tokens + Markdown rationale; auto-read by Claude Code and other agents).mcp.json(project root)~/.claude/CLAUDE.md(user level — read but don't modify without asking)~/.claude.json(user-level MCP — read but don't modify without asking)
Project context
- Package manager and dependencies (package.json, composer.json, Cargo.toml, etc.)
- Build/test/lint commands (scripts in package.json, Makefile targets, etc.)
- Formatter and linter configs (.prettierrc, .eslintrc, phpcs.xml, rustfmt.toml, etc.)
- CI/CD configuration
- Content-project artifacts: static-site configs (
hugo.toml,_config.yml,astro.config.*,mkdocs.yml), prose tooling (.vale.ini,.markdownlint.*), shared knowledge bases or style guides referenced from CLAUDE.md - OpenSpec artifacts (
openspec/directory,openspec/project.md, change specs) - Documentation (
docs/,README.md, architecture docs) - Directory structure and apparent architecture patterns
- Hook managers and their hook files (
.husky/,lefthook.yml,.pre-commit-config.yaml) - Project-local git hooks directory (
.githooks/) and sync scripts (scripts/sync-config-table.{sh,js}) - Design system artifacts:
DESIGN.mdat the project root (persistent design system spec);context/design/(or the registered context location'sdesign/subfolder) for Claude Design handoff artifacts (PROMPT.md, design-notes.md, screenshots/)
Current state metrics
Count and report:
- CLAUDE.md word count via
wc -w(a token-density proxy; line count alone doesn't reflect token load since line length varies) — target ~300–600 words for a lean project-root file, higher only if@-imports carry the bulk of the detail out of the main file - Number of
@-imports in CLAUDE.md - Number of active MCP servers
- Number of skills
- Number of hooks
- Permissions: what's allowed, what's denied
- Environment variables set in settings.json
- Number of entries in
.claude/learnings.md(if it exists)
Step 2: Analyze against best practices
Work through each area systematically. If $ARGUMENTS specified a focus area, prioritize that but still scan everything.
2a: CLAUDE.md audit
Check for these anti-patterns:
Bloat indicators (things to remove or move):
- Standard language conventions Claude already knows → remove
- Rules that the configured linter/formatter already enforces → remove ("never send an LLM to do a linter's job")
- Personality instructions ("be a senior engineer", "think carefully") → remove
- File-by-file codebase descriptions → remove (Claude can read files itself)
- Domain knowledge that's rarely needed → move to a skill
- Long inline documentation → extract to a reference file and use
@-import with a trigger condition - Duplicated information that also exists in AGENTS.md or OpenSpec → remove from CLAUDE.md, reference instead
Missing essentials (things to add if absent):
- Exact build/test/lint/dev commands (not vague — actual command strings)
- Key directory structure (only non-obvious parts)
- Conventions that deviate from standard or that Claude commonly gets wrong
- Explicit "Don't" section for known failure modes
- Compact instructions (what to preserve when compacting)
- Progressive disclosure pointers for reference docs (
@path **Read when:** <trigger>) - Learnings section (instructs Claude to log corrections to
.claude/learnings.mdinstead of modifying CLAUDE.md directly)
Structural checks:
- Is the file using
@-imports for large reference material? (imports reduce token waste by up to 59%) - If AGENTS.md exists, does CLAUDE.md import it via
@AGENTS.mdinstead of duplicating content? - If OpenSpec is used, does CLAUDE.md reference
@openspec/project.mdfor project context? - If
DESIGN.mdexists at the project root, does CLAUDE.md reference it via@DESIGN.md **Read when:** building or editing any UI component? Without this pointer Claude won't consult the design system when making UI decisions. - If the registered context location (
context/by convention, or wherever CLAUDE.md's## Context filestable points) contains files, does CLAUDE.md have a## Context filestable registering them? Without this table, skills can't discover which context files exist or judge their relevance — they only find files they're explicitly pointed to. Note: this is a plain Markdown table, not an@-import — the table itself loads every message, but each underlying file loads only when a skill judges it relevant to the current task from its Summary. - Are there too many
IMPORTANT:orYOU MUSTmarkers? (if everything is marked important, nothing is)
Correctness checks (verify against reality, not just structure):
- For each command referenced in CLAUDE.md (build/test/lint/dev/deploy), verify it exists in the actual manifest (package.json scripts, Makefile targets, Cargo.toml, composer.json, etc.). Flag any command that would fail — renamed script, deleted target, wrong path.
- For each file path referenced (via
@-import, the## Context filestable, or inline mention outside those two), verify withtest -fthat it resolves. Flag broken references. - Flag stack/version claims that contradict the actual dependency manifest (e.g., CLAUDE.md says "Node 16" but
package.jsonenginessays>=20).
2a-bis: Key Config Files table hygiene
sync-config-table.sh (v5+) can only judge whether a file is config-shaped (it matched a
scanned directory/extension) — never whether it's important enough for a lean CLAUDE.md to
carry a row for. That importance call is this skill's job, not the script's. Two things to
check every audit:
Stale placeholder rows. Grep the table for TODO: add description. For each match, decide:
-
The file is genuinely worth a row → write the real one-line purpose.
-
The file isn't worth tracking in this table at all (e.g. it's already documented elsewhere in CLAUDE.md, or it's boilerplate nobody needs to orient on) → don't just delete the row. The script rebuilds the table from the filesystem on every commit, so a bare deletion gets the row silently re-added with the same placeholder next time the file is touched. Instead, add it to the
key-config-excludedblock (create the block if absent, anywhere in CLAUDE.md):<!-- cc-config: key-config-excluded path/to/file.ext — one-line reason — YYYY-MM-DD -->The path must match exactly what the table used (repo-relative, matching the script's own path construction). The reason and date are for human/agent context only — the script only reads the path before the first em-dash.
Excluded-list review. If a key-config-excluded block exists, re-examine every entry:
- If the referenced path no longer exists on disk, remove that entry — it's dead weight.
- If the file has grown in scope or importance since it was excluded (check
git logfor significant recent activity, or judge from its current content) such that a row would now earn its keep, remove the entry. The next sync run will pick the file back up automatically and add it with a placeholder purpose — treat that placeholder the same way as any other stale-TODO finding above (write the real description, don't leave it). - Otherwise leave the entry as-is; don't re-litigate a still-valid exclusion every audit.
2b: AGENTS.md audit
- Does it exist? Should it? (yes if multiple AI tools are used in the project)
- Is it genuinely tool-agnostic? (no Claude-specific features like
@-imports inside AGENTS.md) - Does it cover: setup commands, architecture boundaries, code style, testing, safety?
- Is there unnecessary duplication between AGENTS.md and CLAUDE.md?
2c: Settings audit
Permissions:
- Are sensitive files protected by
permissions.deny? At minimum the real secret-bearing env files (.env,.env.local,.env.*.local,.env.development,.env.production,.env.staging,.env.test) andsecrets/**. - Flag a broad
Read(.env.*)orRead(./.env.*)deny rule as a misconfiguration. That glob also blocks example/template files (.env.example,.env.sample,.env.template,.env.dist,example.env), which hold no secrets and must stay readable for documentation. Because Claude Code evaluatesdenybeforeallowwith no negation inRead()rules, a denied path cannot be re-allowed — anallow(.env.example)does not override it. Recommend migrating to the enumerated deny list above (leaving example files unmatched), and pairing it with the PreToolUse secret-file guard hook for full.env.*coverage with the example carve-out. - Is
permissions.denyused instead of the deprecatedignorePatterns? - Are destructive commands blocked? (
rm -rf, and considercurl/wgetunless specifically needed) - Are safe, frequently-used commands in
permissions.allow? (reduces approval fatigue)
Hooks (Claude Code):
- Is there a PostToolUse formatter hook? If a formatter exists in the project but no hook runs it, this is a high-impact gap. Valid formatter targets include code formatters (prettier, ruff, rustfmt, gofmt, php-cs-fixer) and Markdown formatters (prettier on
.md,markdownlint --fix) — don't skip the audit just because the project produces content rather than code. - Is there a PreToolUse hook protecting sensitive files? (defense in depth beyond
permissions.deny) ARead|Editguard that blocks.env/.env.*basenames while carving out*.example/*.sample/*.template/*.dist/example.envgives broad coverage that the enumerated deny list cannot, since deny rules must leave example files unmatched. See the secret-file guard hook in/cc-config-init. - Do all hooks use
|| truefor graceful degradation? Exception: security hooks must fail closed. A secret-file guard must exit non-zero (block) on the bad path and must not be softened with|| true, or it will pass silently when its dependency (e.g.jq) is missing. Only formatter/lint hooks should carry|| true. - Are hooks doing "block at submit" rather than "block at write"? (fewer interrupts, smoother flow)
Git hooks and hook-manager drift:
/cc-config-init creates a project-local .githooks/pre-commit that runs scripts/sync-config-table.sh and activates it via git config core.hooksPath .githooks. If a hook manager like Husky is added later, it takes over core.hooksPath — the .githooks/pre-commit is still present in the repo but silently stops running. This is a silent drift scenario. Check for it:
- Detect hook managers:
- Husky:
huskyinpackage.jsondevDependencies, or.husky/directory present - Lefthook:
lefthook.ymlorlefthookin devDependencies - pre-commit:
.pre-commit-config.yaml
- Husky:
- Detect cc-init hook infrastructure:
.githooks/pre-commitexists and referencessync-config-table - If both are present, flag as conflict and propose one of these migrations:
- Migrate to the hook manager (recommended if the hook manager is the project standard): move the
sync-config-tableinvocation into the hook manager's pre-commit config (e.g., append it to.husky/pre-commit), then delete.githooks/pre-commitand — if empty — the.githooks/directory. Optionally rungit config --unset core.hooksPathso the setting doesn't confuse future contributors. - Keep the project-local hook (only if the hook manager was added by mistake or is being removed): leave
.githooks/in place and note that the user needs to resolve which hook system ownscore.hooksPath.
- Migrate to the hook manager (recommended if the hook manager is the project standard): move the
- Also check if
scripts/sync-config-table.*exists but.githooks/pre-commitis missing entirely — the script is orphaned and never runs. Same proposal: wire it into the active hook manager or recreate the.githooks/setup. - If the sync script exists in a variant that doesn't match the filesystem conventions of the project (e.g., a
.shscript in a Node-only project where the team prefers.js), note it as a nice-to-have for harmonization but don't force the change.
Sync script version drift:
scripts/sync-config-table.sh is copied into a project once, at init time, and nothing updates it afterwards — a plugin update does not reach into repos that were already initialized. Bug fixes to the script therefore only land when this skill runs. Check for it on every audit:
- Read the version marker from the project's copy:
grep -m1 'sync-config-table-version:' scripts/sync-config-table.sh. A copy predating the versioning scheme has no marker — treat that as version 0. - Read the marker from the plugin's canonical copy. It lives in the sibling
cc-config-initskill directory, i.e.../cc-config-init/scripts/sync-config-table.shrelative to this skill's own directory. If you cannot locate it, say so and skip this check — do not fall back to guessing a version or reconstructing the script from memory. - If the project's version is lower or absent, the copy is stale. Show the user a diff of the two files and ask before overwriting. Never overwrite silently: the marker only tells you the copy is old, not whether the user hand-edited it, and an unattended clobber would discard their changes without a trace.
- On confirmation, copy the plugin's file over the project's and re-apply
chmod +x. Report which version replaced which. - If the versions match, say nothing — this is a no-op on an up-to-date repo, and a clean audit shouldn't spend the user's attention on it.
If the diff shows the project's copy was customized (scan rules added or removed rather than just older core logic), point out that the canonical script guards every scan with a directory check and self-adapts, so the customization is probably unnecessary — but let the user decide. Preserving a deliberate local fork is better than a refresh they didn't expect.
Secret scanning in pre-commit hooks:
Check if the project's active pre-commit hook (whether in .githooks/, .husky/, lefthook, or pre-commit framework) includes a secret scanner like gitleaks. If the project has sensitive files (.env, API keys, credentials) or permissions.deny entries for secrets, but no pre-commit secret scanning, recommend adding gitleaks to the active pre-commit hook:
gitleaks git --pre-commit --staged || exit 1
This catches secrets committed by both Claude Code and the user. Unlike permissions.deny (which only prevents Claude from reading existing secrets), gitleaks prevents anyone from committing new ones. Note: gitleaks must be installed separately (brew install gitleaks, apt install gitleaks, or via the project's CI toolchain). Only recommend — never install tools on the user's machine without explicit permission.
Environment variables:
- Is
CLAUDE_AUTOCOMPACT_PCT_OVERRIDEset? This only affects proactive compaction, which itself only triggers under specific conditions (cloud sessions,CLAUDE_CODE_AUTO_COMPACT_WINDOWbeing set, or specific model versions without extended context). On a typical local session on the current default model, proactive compaction already applies at the model's own default threshold, so this override is very likely a no-op there. If you find it set on a plain local setup, flag it as probably-ineffective and not worth keeping. Only treat it as a legitimate, deliberate tuning if the project actually runs cloud sessions or an older model configuration where the override demonstrably applies. - Is
MAX_THINKING_TOKENSset? Consider10000(down from the model's default cap of 31999) to lower the thinking-token cap. This reduces the ceiling, not necessarily actual usage — don't cite a specific savings percentage. - Is
CLAUDE_CODE_MAX_OUTPUT_TOKENSset? Consider16000to prevent unnecessarily verbose responses. - Is
CLAUDE_CODE_SUBAGENT_MODELset?haikumeaningfully lowers cost for exploration subagents (Haiku pricing is a fraction of Sonnet/Opus) — avoid citing a specific percentage, it varies by workload. - Are
alwaysThinkingEnabledandeffortLevel(insettings.json, notenv) set sensibly? These control thinking budget more directly thanMAX_THINKING_TOKENSand independently of any autocompact override.alwaysThinkingEnabled: trueateffortLevel: highpushes token usage per turn up substantially and can make context fill (and any compaction) happen far sooner than expected — flag this combination unless the user has a specific reason for always-on deep reasoning. Default recommendation: leavealwaysThinkingEnabledunset/falseandeffortLevelatmedium.
.claudeignore:
Check whether a .claudeignore file exists. This file (.gitignore syntax) tells Claude Code which paths to skip entirely when indexing the project, reducing invisible startup token overhead.
Flag as a "should fix" if:
- The repo has
node_modules/,vendor/,.venv/, or other dependency trees present and no.claudeignoreexcludes them. - Build output directories exist (
dist/,build/,.next/,target/,_site/,coverage/) and are not excluded. - Large binary or media asset folders are present that Claude would never usefully read.
Flag as "nice to have" if the repo is small and tidy but could benefit from exclusions as it grows.
Run /context in a fresh session to get the current startup token count — if it exceeds ~10,000 tokens before any user message, a missing .claudeignore is a likely contributor.
2d: MCP audit
- How many servers are active? (5–10 is the sweet spot for most projects)
- Are all servers actually used? Check if they match the project's real needs.
- Are secrets hardcoded or using
${VAR}expansion? - Is the project using
.mcp.json(project-scope, recommended) or~/.claude.json(user-scope)? - Could any MCP server be replaced by a simpler CLI tool? (e.g.,
ghCLI instead of GitHub MCP for basic operations — no permanent context overhead) - Is Tool Search / deferred tool loading active? Current Claude Code models can defer MCP tool schemas and fetch them on demand once tool descriptions get large — the exact model gating and threshold aren't reliably documented, so don't cite specific numbers; just note whether the project's tool count is small enough that this isn't a concern, or large enough to be worth checking.
2e: Skills audit
- Are there skills that duplicate CLAUDE.md content? → Deduplicate.
- Are skills with side effects (deploy, commit, publish) using
disable-model-invocation: true? - Are read-only analysis skills using
allowed-toolsrestrictions? - Are there
.claude/commands/files that should be migrated to the skills format? - Is skill content concise? (target <50 lines per SKILL.md, split if longer)
- If OpenSpec is used: are OpenSpec skills duplicated across multiple tool directories (
.claude/,.codex/,.gemini/,.github/)? If so, flag this as a maintenance risk and suggest consolidation. - Do skills that produce domain-specific output correctly separate context by scope? Check for three types of violations:
- Company-level knowledge inlined or duplicated per-skill: brand voice, company profile, buyer personas, architecture decisions belong in the registered context location (
context/by convention, project root). Consolidate and register in the## Context filestable in CLAUDE.md — update once, every skill reflects the change. - Format-level knowledge in the shared context location: a whitepaper structure guide or blog length rules belong inside the skill's own folder, not the shared context folder.
- Campaign/feature briefings in the shared context location: initiative-specific briefings belong in the relevant project subfolder, not the company-scoped shared folder.
- Company-level knowledge inlined or duplicated per-skill: brand voice, company profile, buyer personas, architecture decisions belong in the registered context location (
- If a
## Context filestable exists, validate its rows:- Malformed rows: don't follow
Label | File | Summary(missing or extra cells). - Orphaned paths: the
Filevalue doesn't resolve to an existing file. Check withtest -f, resolving the path relative to the CLAUDE.md file that contains the table — not the repository root (paths follow the same resolution rule as@-imports, so a nested CLAUDE.md's table is relative to its own directory). - Duplicates: two rows share the same Label or the same File path.
- Vague summaries (soft check — human judgment): a summary too generic to act as a relevance signal, e.g. "Writing style guidelines for the company" instead of "Formal German, em-dash preferred, no exclamation marks — all corporate copy." Flag as a suggestion, not a hard rule.
- Malformed rows: don't follow
- Does each skill end with a feedback step? A skill that closes by asking "Did this output meet your expectations? If not, I'll log a correction to
.claude/learnings.md" makes the learnings loop active rather than passive — corrections are solicited at the point of delivery, not just accumulated from future mishaps. Flag absent feedback steps as "nice to have."
2f: Multi-tool consistency check
If the project uses multiple AI tool directories:
- Is there a single source of truth (ideally AGENTS.md) that all tools reference?
- Are there contradictions between tool-specific configs?
- Is duplicated content maintained in sync, or is it drifting?
2g: Learnings review
If .claude/learnings.md exists:
- Read all entries.
- Group similar entries to identify recurring patterns (3+ similar corrections suggest a real gap in the config).
- For each recurring pattern, propose one of:
- Adding a concrete rule to CLAUDE.md (if it's a universal project convention).
- Adding it to an existing or new skill (if it's domain-specific or rarely needed).
- Adding it as a hook (if it's something that should happen deterministically, not by instruction).
- For one-off entries that don't recur, propose deleting them.
- Present the full list to the user grouped as "promote to config" vs "delete as one-off", with rationale for each. Wait for approval before changing anything.
If .claude/learnings.md does not exist but CLAUDE.md also has no Learnings section, suggest adding the Learnings section to CLAUDE.md:
## Learnings
When the user corrects a mistake or points out a recurring issue, append a one-line
summary to .claude/learnings.md. Don't modify CLAUDE.md directly.
2h: Headroom audit
Headroom is an optional in-flight compression layer that reduces context window usage by compressing tool outputs, Bash results, logs, and code before they reach the model — a different optimization level from env vars and .claudeignore, which operate at startup and configuration time.
Run:
which headroom 2>/dev/null && headroom --version 2>/dev/null | head -1 || echo "headroom-not-installed"
python3 -c "import sys; print('python-ok' if sys.version_info >= (3, 10) else 'python-too-old')" 2>/dev/null || echo "python-unavailable"
ls .headroom 2>/dev/null && echo "headroom-dir-present" || echo "headroom-dir-absent"
If Headroom is installed:
.gitignorecheck: Headroom stores machine-local data in.headroom/— session caches and.headroom/CLAUDE.local.md(machine-local learnings). These must not be committed: they are per-machine, ephemeral, and will conflict across clones. If.headroom/is not in.gitignore, flag as "should fix."- Integration mode: Detect which mode is in use:
- MCP mode: look for a Headroom entry in
.mcp.json. Verify it is still in the active server list; stale entries add tool-count overhead for nothing. - Proxy/wrap mode:
headroom wrap claudeorheadroom proxy --port 8787 --code-awaremust be run before each session. If this is not documented in CLAUDE.md (or a project README), note it — teammates will not know to start it.
- MCP mode: look for a Headroom entry in
- Code-aware flag: For code compression to activate, the proxy must be started with
--code-aware. Without it, code files producetokens_saved: 0. Flag as a note if the user is on proxy mode and this flag is not documented. - Learnings coexistence: Headroom's
.headroom/CLAUDE.local.mdand cc-config's.claude/learnings.mdserve different purposes and should both be kept. Headroom's file captures machine-local session patterns; cc-config's file captures explicit user corrections and is team-shared (committed to git, feeds thecc-config-optimizepromotion cycle). Do not consolidate them.
If Headroom is not installed and Python 3.10+ is available:
Add to "Nice to have." Do not add if Python is unavailable or below 3.10, or if the project is known to run exclusively in sandboxed/remote environments (CI pipelines, Claude Code on the web) — Headroom requires a persistent local process and is incompatible with those contexts.
If Python is unavailable or below 3.10:
Skip. Do not mention Headroom.
2i: Cross-file duplication (hierarchical CLAUDE.md trees)
Relevant when a project uses multiple CLAUDE.md files across folder levels (common with the cc-content context-TOC pattern) — Claude Code auto-loads every CLAUDE.md up the directory chain, so content should live once at the shallowest level it applies to.
- Discover all CLAUDE.md files in the tree:
find . -name CLAUDE.md -not -path '*/node_modules/*' -not -path '*/vendor/*' - Read all discovered files.
- Compare content across levels — not just identical strings, but near-duplicate rules, conventions, or command lists restated at multiple levels.
- Distinguish acceptable repetition (a one-line pointer restating scope, e.g. "This file covers the
api/package only") from true duplication (the same rule or command list copy-pasted across levels). - Flag true duplicates: content should move to the shallowest common ancestor; deeper-level files should only add what's specific to that scope.
Step 3: Generate findings report
Organize findings into three categories:
Must fix (security or correctness issues)
- Missing permissions.deny for sensitive files
- Hardcoded secrets in config files
- Deprecated patterns (ignorePatterns, npm-installed Claude Code)
- Contradictory instructions
- Hook-manager conflict:
.githooks/pre-commitpresent alongside an active hook manager (the sync script is not running) - CLAUDE.md documents a command that doesn't exist in the actual manifest (renamed script, deleted target, wrong path) — Claude will confidently run something that fails
- CLAUDE.md references a file path (outside
@-imports and the## Context filestable) that doesn't resolve
Should fix (quality and cost improvements)
- CLAUDE.md bloat (>80 lines without good reason)
- Missing formatter hook
- Missing cost-optimization env vars
- Redundant content between files
- Skills without proper frontmatter guards
- Learnings entries that should be promoted to CLAUDE.md or a skill
- Orphaned
scripts/sync-config-table.*with no active hook wiring scripts/sync-config-table.sholder than the plugin's canonical copy (stale or missing version marker) — the repo is stranded on a version with known bugsDESIGN.mdpresent at project root but not referenced via@DESIGN.mdin CLAUDE.md (Claude won't apply the design system without the pointer)- Context files present in the registered context location but no
## Context filestable in CLAUDE.md — skills cannot discover context files without this table ## Context filestable has malformed rows (notLabel | File | Summary), duplicate Label/File values, or File paths that don't resolve to an existing file## Context filestable exists but is missing the<!-- cc-config: context-toc-registered -->marker comment right after the heading (v4+sync-config-table.shgreps for this exact string, not the heading text, to decide whethercontext/files belong in## Key Config Filestoo — without the marker, the sync script will re-list every context file there with a generic placeholder, duplicating the registered table). Add the marker; don't rename or reword it.## Key Config Filestable lists individualcontext/*.mdfiles with a generic/placeholder Purpose even though a populated## Context filestable already registers them with real summaries — a sign the marker is missing orsync-config-table.shpredates v4## Key Config Filestable has one or moreTODO: add descriptionrows (see 2a-bis) — write the real description, or move the file to thekey-config-excludedblock if it's not worth a row at allkey-config-excludedblock (see 2a-bis) has an entry whose path no longer exists, or whose file has demonstrably grown important enough to reconsider- Headroom installed but
.headroom/not in.gitignore: machine-local Headroom files (session caches,.headroom/CLAUDE.local.md) must not be committed — they are per-machine and will break other clones - True duplicate content across nested CLAUDE.md files in a hierarchical tree (see 2i) — should live once at the shallowest common ancestor
Nice to have (polish)
- Missing progressive disclosure for reference docs
- Missing compact instructions
- Missing Learnings section in CLAUDE.md
- Skills that could be created for recurring workflows
- MCP servers that could be added or removed
- Missing secret scanner (gitleaks) in pre-commit hook
- Sync script format mismatch with project conventions (e.g.,
.shin a Node-only repo) - Skills producing domain-specific output without referencing the registered context location (
context/by convention, project root) — company-level knowledge duplicated or inlined per-skill - Context scope violations: company-level knowledge buried in campaign subfolders, or format-level guidelines in the shared context location instead of the relevant skill's folder
## Context filestable summaries too vague to act as a relevance signal for skills (soft check — human judgment, e.g. "Writing style guidelines" instead of naming the specific tone, audience, or rules)- CLAUDE.md stack/version claims that don't match the actual dependency manifest (e.g., states "Node 16" while
package.jsonenginessays>=20) - Multi-level folder project without hierarchical CLAUDE.md files: if the repo has campaign, feature, or package subfolders where context meaningfully changes, each level should have its own CLAUDE.md that @-imports the relevant context for that scope — this lets Claude inherit all relevant context when started in any subfolder, without skills needing hard-coded paths to shared files. Any
## Context filestable in a nested CLAUDE.md follows the same path convention as the root one:Filevalues are relative to that CLAUDE.md's own location, not the repository root. - Skills missing a terminal feedback step that solicits corrections into the learnings loop
- PDFs, DOCX files, or HTML pages referenced in CLAUDE.md or context files without Markdown equivalents: converting them saves significant tokens (HTML→Markdown ~90% reduction, PDF→Markdown ~65–70%, DOCX→Markdown ~33%). Tools like Pandoc, Docling, or
markitdownconvert in seconds. Flag any such files found in the registered context location or referenced via@-imports - Missing
.claudeignorestartup token check: suggest the user run/contextin a fresh session to measure actual startup overhead — if high, a missing or incomplete.claudeignoreis a likely cause - Headroom not installed but Python 3.10+ is available (and the project is not exclusively run in sandboxed/remote environments): Headroom compresses tool outputs, Bash results, and code in-flight before they reach the model — a different optimization level from env vars and
.claudeignore. Real-workload savings: 73–92% on code-search and log-heavy tasks. Output tokens cost 5× more than input on Opus-class models, so in-flight compression compounds quickly. Install:pip install "headroom-ai[all]". Start withheadroom wrap claude(quickest path) orheadroom proxy --port 8787 --code-aware(proxy mode;--code-awareis required for code compression). Runheadroom perfafter a few sessions to measure savings. Important constraint: requires a persistent local process — not compatible with remote/sandboxed sessions (Claude Code on the web, CI pipelines). If the project is used in both local and remote contexts, Headroom benefits only the local sessions.
Present the findings to the user as a concise list, grouped by category. For each finding, state: what the issue is, why it matters, and what you'd change. Ask for approval before making changes.
Config health score
Compute a single score from the categorized findings above — it reads directly off the counts you already produced, not a separate rubric:
score = max(0, 100 − 10 × must_fix_count − 4 × should_fix_count − 1 × nice_to_have_count)
Report this score once now (the "before" score) and again in Step 5 after approved changes are applied (the "after" score), so the user sees a concrete before/after (e.g. "Config health: 62/100 → 91/100") rather than only a word-count delta.
Step 4: Apply approved changes
Make the approved changes. For each file modified:
- Show a before/after summary (not full diffs for large files — just the key changes).
- Explain briefly what changed and why.
When applying learnings review results:
- For entries promoted to CLAUDE.md or a skill, remove them from
.claude/learnings.md. - For entries marked as one-off, remove them from
.claude/learnings.md. - If all entries are processed, delete
.claude/learnings.mdentirely (it will be recreated naturally when the next correction occurs).
When resolving hook-manager conflicts:
- If migrating to Husky: append the sync-script call to
.husky/pre-commit(create it if missing), delete.githooks/pre-commit, remove the empty.githooks/directory, and suggest the user runsgit config --unset core.hooksPathon each clone. - If migrating to Lefthook or pre-commit: add the appropriate entry to the respective config file instead.
- Never delete
scripts/sync-config-table.*itself — the script is still useful, only the wiring changes.
When resolving the Headroom gitignore gap:
Append .headroom/ to .gitignore. Place it under the existing Claude Code personal-files block if one exists, or at the end of the file with a short comment:
# Headroom — machine-local session cache and learnings
.headroom/
Do not create .headroom/ or any files inside it — Headroom manages that directory itself.
Preserve things that work well. Don't refactor for the sake of refactoring. If an existing config is well-structured and correct, say so and move on.
Step 5: Final summary
After all changes:
-
List every file modified or created, with one-line descriptions of changes.
-
Report the new metrics: CLAUDE.md word count, number of active MCP servers, hooks configured, etc.
-
Compare key metrics to before (e.g., "CLAUDE.md: 1,850 words → 480 words").
-
Recompute the config health score from whatever findings remain unresolved and report the before/after (e.g. "Config health: 62/100 → 91/100").
-
If learnings were reviewed: report how many entries were promoted, how many deleted, and how many remain.
-
Note anything you deliberately left unchanged and why.
-
Update the audit marker in CLAUDE.md so the bundled
SessionStartstaleness hook (see "Audit staleness reminder" below) has a fresh baseline to compare future commits against:date +%Y-%m-%d # today's date git rev-parse HEAD # current commit SHAWrite or replace the line
<!-- cc-config: last-optimize-run: YYYY-MM-DD <sha> -->anywhere in CLAUDE.md (reuse the existing line if one is already present, e.g. right after the## Key Config Filestable, alongsidekey-config-excludedif that block exists — don't scatter multiple copies of this marker across the file). This step runs even if this audit found nothing to fix — a clean audit still resets the baseline. -
Suggest running
/cc-config-optimizeagain periodically (e.g., after major features, after a few weeks of work) to prevent config drift. Mention that the bundledSessionStarthook will also nudge automatically once enough commits accumulate since the marker just written, so this is a backstop, not the primary way it's kept current. -
Remind the user to commit the changes.
Audit staleness reminder
cc-config ships a SessionStart hook (plugins/cc-config/hooks/check-optimize-staleness.sh,
declared in plugins/cc-config/hooks/hooks.json) that fires in every project the plugin is
active in — no per-repo .claude/settings.json wiring needed, since plugin-declared hooks
apply automatically wherever the plugin is installed. On session start it reads the
last-optimize-run marker this step writes, compares it against the repo's current commit
count and date, and — only if the project has drifted noticeably since that baseline (default
thresholds: 20+ commits, or 14+ days with at least one new commit) — emits a short reminder
suggesting /cc-config-optimize. It never blocks anything and stays silent otherwise,
including in repos that don't use cc-config at all (it only speaks up if it also finds
scripts/sync-config-table.sh, i.e. clear evidence the project already opted in).
This step is what keeps that hook's comparison meaningful — without a fresh marker, every
session in an active repo would eventually trip the threshold and nag regardless of how
recently an audit actually ran.
Common optimization patterns
These are recurring improvements you'll often apply:
CLAUDE.md → Skills migration: When CLAUDE.md contains domain knowledge that's only needed for specific tasks, extract it into a skill. The skill loads on demand (~100 tokens metadata at rest), while CLAUDE.md content loads every message.
Monolithic docs → Progressive disclosure:
Replace inline documentation in CLAUDE.md with @-import pointers:
### API Architecture — @docs/api-architecture.md
**Read when:** Adding or modifying API endpoints
AGENTS.md as single source of truth: If the project has both CLAUDE.md and AGENTS.md with overlapping content, consolidate the universal parts into AGENTS.md and reduce CLAUDE.md to a slim adapter:
@AGENTS.md
## Claude-Code-specific
- <only Claude-specific additions here>
OpenSpec integration: If OpenSpec is present, CLAUDE.md should reference it rather than duplicate project context:
@openspec/project.md
Hook-ification of repeated instructions: If CLAUDE.md says "always run prettier after editing" — that's a hook, not an instruction. Replace the instruction with a deterministic PostToolUse hook and remove the line from CLAUDE.md.
Learnings graduation:
When .claude/learnings.md has accumulated entries, recurring patterns graduate into CLAUDE.md rules, skills, or hooks. One-off corrections get deleted. The file stays lean or gets removed entirely until the next correction cycle.
Hook-manager migration for sync-config-table:
When a project gains Husky or another hook manager after /cc-config-init was used, the .githooks/pre-commit goes silent because core.hooksPath is taken over. Migrate the sync script into the active hook manager's pre-commit hook and remove the now-dead .githooks/ directory.
What NOT to do
- Don't refactor things that work well. If a config is correct and clean, say so.
- Don't add MCP servers speculatively. Only suggest servers that address a concrete gap.
- Don't create skills for workflows that haven't been repeated yet.
- Don't modify user-level files (
~/.claude/CLAUDE.md,~/.claude.json) without explicit permission. - Don't remove functionality. If something serves a purpose, keep it — just optimize how it's expressed.
- Don't make the config dependent on tools or servers the user hasn't installed.
Feedback
Auto-store phase. Before asking for feedback, review this run. For each qualifying observation, append one tagged line to .claude/learnings.md (create with standard header if missing). Skip entries promoted or deleted by Step 2g in this run:
[cc-config:cc-config-optimize] <concise fact about this project> — <YYYY-MM-DD>
Qualifies: something about this project that differs from what this skill assumes on a generic project; a suggestion the user explicitly accepted or rejected that deviates from skill defaults; a constraint or fact discovered that would change how this skill behaves next time.
Does not qualify: standard skill behavior applied without deviation; facts already present in CLAUDE.md, AGENTS.md, or other config files; anything a reader could determine from the repo without this skill having run; facts semantically equivalent to any existing .claude/learnings.md entry — when in doubt, skip.
Check for the file before appending:
ls .claude/learnings.md 2>/dev/null && echo "exists" || echo "missing"
Standard header when creating the file:
# Learnings
Corrections and observations collected during configuration sessions.
Entries are tagged by skill and dated.
---
Explicit feedback. After the auto-store phase, ask:
"Did this optimization meet your expectations? If anything needs adjusting, share it here — or press Enter to finish."
- If the user provides a correction: append it as a tagged entry using the same format and qualification criteria above. Confirm total entries written across both phases: "✓ N learning(s) saved to
.claude/learnings.md." - If the user confirms quality or skips: if any entries were auto-stored, confirm "✓ N learning(s) auto-saved to
.claude/learnings.md." Then exit. If nothing was stored, skip the confirmation and exit directly.
Note: Learnings are automatically recalled at the start of the next skill run. Run
/cc-config-optimizeperiodically to promote recurring patterns into the configuration.