- JavaScript 99.6%
- HTML 0.4%
Operator corrected two things about the brief committed in 3086e8b/3252b51.
Provenance: the operator watched the recording and identifies Boris Cherny on
stage, so the attribution is confirmed by direct observation, not a channel's
claim. The verbatim figures (80 %, "more intelligent without the prompts") still
reach us through the summary's editing and stay at that confidence level. §1 now
carries both levels separately, and the register source string reflects the split
instead of flattening to "unverified".
Design: "start with what it must have" is the constraint the whole feature turns
on, so it is a hard constraint (§6.0), not a candidate-shape detail. Model
capability erodes compensatory instructions ("read the whole file first") and
does nothing to load-bearing local facts ("only Forgejo", "bash is 3.2", the test
command) — the model isn't failing at intelligence there, it cannot know. A tool
that treats them alike deletes the Forgejo constraint because Opus 5 "is smart
enough now". Rebuild is therefore three tiers: floor restored immediately, earned
returns on repeated stumbling, dead never comes back. Policy prohibitions stay in
the floor by decision rather than classification — asymmetric cost, cheap to keep.
Consequences threaded through: §5 disqualifies any shape that cannot express the
distinction, §7.2 becomes the core open question (age and class are independent
signals, so age alone can never carry the call), and §8 gains a blocking floor
test with a hand-built fasit and named must-survive items.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JNrtHo9hKSLKNyMS6b4Zuy
|
||
|---|---|---|
| .claude/rules | ||
| .claude-plugin | ||
| agents | ||
| commands | ||
| docs | ||
| examples | ||
| hooks | ||
| knowledge | ||
| scanners | ||
| skills/config-hierarchy | ||
| templates | ||
| tests | ||
| .config-audit-ignore | ||
| .gitignore | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| GOVERNANCE.md | ||
| LICENSE | ||
| README.md | ||
Config-Audit Plugin for Claude Code
Know if your configuration is correct. Find what could improve it. Fix it automatically.
Solo-maintained, fork-and-own. This plugin is a starting point, not a vendor product. Issues are welcome as signals; pull requests are not accepted. See GOVERNANCE.md for the full model and what upstream provides.
AI-generated: all code produced by Claude Code through dialog-driven development. Full disclosure →
A Claude Code plugin that checks configuration health, suggests context-aware improvements, and auto-fixes issues — CLAUDE.md, settings.json, hooks, rules, MCP servers, @imports, and plugins. 16 deterministic scanners across 10 quality areas, context-aware feature recommendations, auto-fix with backup/rollback, a prompt-cache-aware Token Hotspots scanner with optional API-calibrated --accurate-tokens mode, plus cache-prefix stability, dead-tool, cross-plugin collision, output-style, and always-loaded agent-listing-budget detection. Zero external dependencies.
Table of Contents
- What's New in v5.4.0
- What Is This?
- The Configuration Problem
- Quick Start
- Feature Opportunities
- Workflow Examples
- Commands
- Deterministic Scanners
- Agent Architecture
- Hooks & Safety
- Skills
- Suppressions
- Examples & Self-Audit
- Scanner Library
- Knowledge Base
- Testing
- Gotchas
- Data Storage & Safety Guarantees
- What This Plugin Does Not Cover
- Version History
- License
What's New in v5.4.0
Plugin-hygiene & settings-validation hardening. Three additive findings extend the plugin and settings surfaces — no new scanner, so the count stays 13:
- PLH plugin-folder shadowing (
CA-PLH-015) — flags aplugin.jsoncomponent-path key in the replaces set (commands/agents/outputStyles) that points at a custom path while the default folder of that name still exists, so the folder is silently ignored (dead config). Mirrors Claude Code's own warning in/doctor,claude plugin list, and the/plugindetail view.skillsis excluded (it adds to the default scan, never shadows), as arehooks/mcpServers/lspServers(own merge rules); a custom path resolving into the default folder is not flagged. - PLH
skills:-array validation (CA-PLH-016) — validates eachplugin.jsonskillsentry (string or array) resolves to an existing directory inside the plugin root; flagsnon-string,escapes-root,not-found, andnot-a-directoryentries. Mirrorsclaude plugin validate. - SET
autoModestructure + dead-config — checks thatautoModeis an object whose only keys areenvironment/allow/soft_deny/hard_deny, each a string array (the literal"$defaults"is valid); unknown sub-keys and wrong types are flagged (medium). Separately,autoModeplaced in shared project settings (.claude/settings.json) is flagged as dead config (low) — Claude Code's classifier does not read it there.
All three extend existing PLH and SET scanners. --json and --raw output remain byte-stable.
What Is This?
Claude Code reads instructions from at least 7 different file types across multiple scopes: CLAUDE.md, settings.json, .claude/rules/, hooks.json, .mcp.json, .claudeignore, and settings.local.json. Each can exist at project level, user level, or both. Plugins add more. The system is powerful — but nobody tells you what you're using wrong, what you're missing, or what's silently conflicting.
This plugin provides three layers of configuration intelligence:
- Health — 16 deterministic scanners verify correctness across every configuration file, catching broken imports, deprecated settings, conflicting rules, format errors, permission contradictions, prompt-cache token waste, cache-prefix instability, dead tool grants, cross-plugin skill collisions, output styles that silently strip Claude Code's coding instructions, an oversized always-loaded agent listing, and procedures in CLAUDE.md that would fit better as a skill
- Opportunities — context-aware recommendations for Claude Code features that could benefit your specific project, backed by Anthropic's official guidance
- Action — auto-fix with mandatory backups, syntax validation, rollback support, and a human-in-the-loop workflow for anything non-trivial
Tip
Start with
/config-audit posturefor a 30-second scorecard, then/config-auditfor the full picture.
The Configuration Problem
You've been using Claude Code for weeks — maybe months. It works fine. But there's a gap between "works fine" and "configured well," and it's invisible until someone shows you.
These are not hypotheticals. They come from running the posture scanner on real setups:
- Your global
CLAUDE.mdsays "never use mocks" but a project rule says "prefer mocks" — Claude gets confused and you don't know why - You've written dozens of projects but have never set up hooks, rules, or keybindings because you didn't know they existed
- Three plugins define hooks for the same event with conflicting behavior
- Your
settings.jsonhas a deprecated key that silently does nothing - An
@importin your CLAUDE.md points to a file you deleted last week - You're using maybe 30% of what Claude Code can do — and you don't know what the other 70% is
The plugin ships with two example projects. Run them yourself:
examples/minimal-setup/ — just a CLAUDE.md, nothing else
> node scanners/posture.mjs examples/minimal-setup/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Config-Audit Health Score
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Health: A (99/100) 7 areas scanned
Area Scores
───────────
CLAUDE.md ............ A (90)
Settings ............. A (100) Hooks ............... A (100)
Rules ................ A (100) MCP ................. A (100)
Imports .............. A (100) Conflicts ........... A (100)
22 opportunities available — run /config-audit feature-gap for recommendations
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Grade A — nothing is broken. The health grade only reflects real issues, and this setup has none. The 22 opportunities are not failures — they're features you could use. Run /config-audit feature-gap to see which ones are relevant to your project.
examples/optimal-setup/ — full configuration across all 4 tiers
> node scanners/posture.mjs examples/optimal-setup/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Config-Audit Health Score
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Health: A (93/100) 7 areas scanned
Area Scores
───────────
CLAUDE.md ............ A (100) Settings ............ A (90)
Hooks ................ A (100) Rules ............... B (80)
MCP .................. A (90) Imports ............. A (100)
Conflicts ............ A (90)
3 opportunities available — run /config-audit feature-gap for recommendations
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Also Grade A — with only 3 opportunities remaining. This project has CLAUDE.md split via @imports, permissions scoped to specific tools, path-scoped rules (different rules for src/ vs. tests/), hooks covering multiple events, and MCP servers. Both setups are healthy — the difference is how much of Claude Code's surface area you're choosing to use.
Quick Start
Prerequisites
- Claude Code installed
- Node.js 18+ (for standalone CLI tools)
Installation
Add the marketplace and browse plugins with /plugin:
claude plugin marketplace add https://git.fromaitochitta.com/open/ktg-plugin-marketplace.git
Or enable directly in ~/.claude/settings.json:
{
"enabledPlugins": {
"config-audit@ktg-plugin-marketplace": true
}
}
First Scan
# Full audit with auto-scope detection (inside Claude Code)
/config-audit
# 30-second posture check (standalone, no LLM needed)
node scanners/posture.mjs /path/to/project
# Auto-fix issues with backup
node scanners/fix-cli.mjs /path/to/project --apply
The CLI tools work standalone — no Claude Code session needed, just Node.js 18+.
Feature Opportunities — Context-Aware Recommendations
Most configuration tools stop at "is it valid?" Config-audit goes further: what could improve your setup, and is it relevant to your project?
The feature opportunity scanner checks 25 dimensions and groups recommendations by impact:
| Impact Level | Focus | Examples |
|---|---|---|
| High | Correctness & security | permissions.deny for sensitive files, basic hooks for safety automation |
| Worth Considering | Workflow efficiency | Path-scoped rules, modular @imports, custom agents |
| Explore | Nice-to-have | Keybindings, status line, output styles, agent teams |
Each recommendation is context-aware — it considers what your project actually contains. A solo TypeScript project gets different suggestions than a team Python monorepo. Recommendations include why (backed by Anthropic's official guidance) and how (concrete steps).
Run /config-audit feature-gap to see what's relevant to your project.
Workflow Examples
1. First Time — Just Curious
You heard about this plugin and want to know where you stand:
/config-audit # Auto-detects scope, runs full audit
# → See your grade, top issues, and gaps
/config-audit posture # Even faster: 30-second scorecard only
2. Monthly Configuration Checkup
A quick health check — are things still clean?
/config-audit posture # Quick health check (A-F grade, 7 areas)
/config-audit # Full audit if grade dropped
/config-audit fix # Auto-fix deterministic issues
/config-audit posture # Verify improvement
3. Deep Optimization
You want to go from C to A. The full pipeline:
/config-audit # Audit — understand what you have
/config-audit feature-gap # Opportunities — context-aware recommendations
/config-audit plan # Plan — prioritized actions with risk assessment
/config-audit implement # Execute — changes with backup + verification
4. Plugin Author
You maintain Claude Code plugins and want to ensure quality:
/config-audit plugin-health # Audit plugin structure, frontmatter, cross-plugin conflicts
# → Checks naming, frontmatter completeness, tool grants, duplicates
5. Track Configuration Drift
Your team configuration changes over time. Track it:
/config-audit drift # First run creates baseline, subsequent runs show delta
# → New findings, resolved findings, unchanged, moved
/config-audit drift --save my-baseline # Save a named baseline for comparison
Commands
Core (just run /config-audit to get started)
| Command | Description |
|---|---|
/config-audit |
Full audit with auto-scope detection (no setup needed) |
/config-audit posture |
Quick health scorecard: A-F grades across 10 quality areas (incl. Token Efficiency, Plugin Hygiene) |
/config-audit tokens |
prompt-cache-aware token hotspots — ranked by estimated waste, each tagged with its load pattern (always / on-demand / external); 8 patterns + optional --accurate-tokens API calibration. Cache-aware: stale ~/.claude/plugins/cache versions (superseded installs that load on zero turns) are excluded from the ranking by default — only each plugin's active version is counted; --no-exclude-cache restores the full walk. Stale versions surface as a separate Dead config disk-cleanup finding |
/config-audit manifest |
Ranked table of every token source (CLAUDE.md, rules, agents, skills, output styles, MCP, hooks) sorted by estimated tokens — each tagged with its load pattern (always-loaded / on-demand / external) plus an always-loaded subtotal ("≈X tokens enter context every turn before you type"). Component-level: no coarse plugin roll-up (it would double-count) |
/config-audit feature-gap |
Context-aware feature recommendations grouped by impact |
/config-audit optimize |
Optimization lens (mechanism-fit): config that works but fits a better mechanism — procedure→skill, lifecycle→hook, unscoped path→rule, "never"→permission. Hybrid motor (deterministic pre-filter + opus precision gate), every finding cites a best-practices-register rule |
/config-audit fix |
Auto-fix deterministic issues with backup + verification |
/config-audit rollback |
Restore configuration from a previous backup |
/config-audit plan |
Generate prioritized action plan from audit findings |
/config-audit implement |
Execute plan with automatic backup + verification |
/config-audit help |
Show all commands with usage examples |
Additional
| Command | Description |
|---|---|
/config-audit drift |
Compare current config against a saved baseline |
/config-audit plugin-health |
Audit plugin structure, frontmatter, cross-plugin coherence |
/config-audit whats-active |
Read-only inventory of plugins, skills, MCP, hooks, CLAUDE.md active for a repo (with token estimates) |
/config-audit knowledge-refresh |
Keep the best-practices register fresh — flag stale entries (sources older than ~90d) + poll for new/changed Claude Code practices; human-approved writes only (Verifiseringsplikt). Deterministic stale core + web candidate poll |
/config-audit campaign |
Machine-wide audit campaign — durable ledger above sessions tracking each repo's lifecycle (pending → audited → planned → implemented) + a machine-wide roll-up by severity + a machine-wide always-loaded token bill (refresh-tokens live cross-repo sweep — the shared global layer counted once + per-repo deltas, ranked "most expensive repos") + a single cross-repo prioritized backlog to pick from (severity-weighted) + plan export (drop a planned repo's plan into its own docs/), resumable across sessions; human-approved writes only (read-only report + deterministic write/export CLIs). Execution reuses the existing /config-audit implement + rollback |
/config-audit discover |
Run discovery phase only |
/config-audit analyze |
Run analysis phase only |
/config-audit interview |
Set preferences for action plan (optional) |
/config-audit status |
Show current session state and available actions |
/config-audit cleanup |
Remove old session directories |
Scope
By default, /config-audit auto-detects scope from your git context. Override with: /config-audit current, /config-audit repo, /config-audit home, /config-audit full. Use --delta for incremental scanning (only new/changed findings).
Deterministic Scanners
15 Node.js scanners that perform structural analysis an LLM cannot reliably do: schema validation, circular reference detection, import resolution, conflict detection across scopes, prompt-cache-aware token-cost analysis, cache-prefix stability, dead-tool detection, cross-plugin skill collisions, output-style validation, and a best-practice optimization lens (mechanism-fit). Plus a standalone plugin-health scanner. Zero external dependencies.
Why deterministic? LLMs are powerful at understanding intent and context. But they cannot reliably validate JSON schemas, detect circular @import chains, or catch that your global settings.json contradicts your project-level one. These scanners fill that gap — fast, repeatable, and zero false positives on structural issues.
| Scanner | Prefix | What It Catches |
|---|---|---|
claude-md-linter.mjs |
CML | Oversized files (line count plus a context-window-scaled char budget mirroring Claude Code's ~40.0k-char startup warning), missing sections, broken @imports, duplicates, stale TODOs |
settings-validator.mjs |
SET | Schema violations, unknown/deprecated keys, type mismatches, permission issues |
hook-validator.mjs |
HKV | Invalid format, missing scripts, wrong event names, timeout risks, verbose-stdout scripts, and a low-precision advisory (info) when a hook injects un-grepped command output into hookSpecificOutput.additionalContext — that payload enters context on every fire (plain stdout does not) |
rules-validator.mjs |
RUL | Bad glob patterns, orphaned rules, deprecated fields, unscoped rules |
mcp-config-validator.mjs |
MCP | Invalid server types, exposed env vars, unknown fields |
import-resolver.mjs |
IMP | Broken @imports, circular references, deep chains, tilde path issues |
conflict-detector.mjs |
CNF | Settings contradictions across scopes, permission conflicts, hook duplicates |
feature-gap-scanner.mjs |
GAP | 25 feature checks shown as opportunities, not grades — plus a conditional disableBundledSkills recommendation when the active skill listing is over budget, and a conditional filter-before-Claude-reads lever when a hook injects unfiltered output into additionalContext (companion to the HKV advisory; cites the documented filter-test-output.sh pattern) |
token-hotspots.mjs |
TOK | Cache-breaking volatile content, redundant tool permissions, deep import chains, oversized cascades, bloated skill descriptions, MCP tool-schema budget, and stale ~/.claude/plugins/cache versions (disk-cleanup, zero live-context impact) — cache-aware ranking excludes superseded plugin versions by default (--no-exclude-cache to include) |
cache-prefix-scanner.mjs |
CPS | Volatile content in lines 31–150 of the CLAUDE.md cascade — beyond Pattern A's top-30 window but still re-loaded every turn — plus volatile content inside @import-ed files (inlined into the cached prefix, one hop, otherwise invisible to per-file scans) |
disabled-in-schema-scanner.mjs |
DIS | Dead/ineffective permission entries: (1) tools in BOTH permissions.deny and permissions.allow — deny wins (incl. the Tool(*) deny-all glob, equivalent to a bare deny); (2) unanchored allow wildcards (*, B*, mcp__*) that Claude Code silently skips — valid only as mcp__<server>__*; (3) Tool(param:value) rules whose key is the tool's own canonicalizing field (command/file_path/path/notebook_path/url) — CC ignores these and emits a startup warning |
collision-scanner.mjs |
COL | Cross-plugin skill name collisions; user-vs-plugin overlaps |
skill-listing-scanner.mjs |
SKL | Skill-listing token budget: a single skill description over the ~1,536-char listing cap Claude Code truncates (CA-SKL-001), the summed active-skill descriptions exceeding the ~2%-of-context listing budget (CA-SKL-002), and an oversized SKILL.md body over ~5,000 tokens (CA-SKL-003, low — on-demand cost: the body loads only when the skill runs, not every turn; recommends supporting-file split + context: fork). The CA-SKL-002 (and CML char-budget) findings accept --context-window <n> to calibrate to your real window instead of the conservative 200k anchor (--context-window auto keeps the anchor but downgrades to advisory) |
output-style-scanner.mjs |
OST | Output-style validation: a custom (user/project) style missing keep-coding-instructions: true that silently strips built-in software-engineering instructions (CA-OST-001), a plugin style with force-for-plugin: true overriding the user's selected outputStyle (CA-OST-002), and a settings outputStyle resolving to no built-in or custom style — dead config (CA-OST-003) |
optimization-lens-scanner.mjs |
OPT | Optimization lens (mechanism-fit): a multi-step procedure in CLAUDE.md that would fit better as a skill (CA-OPT-001) — reads the machine-readable best-practices register, framed as an opportunity, not a failure. The deterministic half of the lens; prose-judgment cases (lifecycle→hook, unscoped path→rule, "never"→permission) are judged by the opus optimization-lens-agent via /config-audit optimize |
agent-listing-scanner.mjs |
AGT | Always-loaded agent-listing budget: a per-agent description over the soft bloat cap (CA-AGT-001, advisory) and the summed active-agent name+description listing — re-sent every turn — exceeding the listing budget (CA-AGT-002). Both LOW and explicitly inferred / upper-bound: the agent-listing mechanism is undocumented, so the evidence discloses the estimate and heuristic budget rather than overstating certainty |
Cross-scanner remediation — diagnosis meets the fix. SKL diagnoses an over-budget skill listing (
CA-SKL-002); GAP prescribes the remedy. When the active skill listing exceeds its ~2%-of-context budget anddisableBundledSkillsis not already set (in the env var or the settings cascade), the feature-gap scanner recommends that lever — hiding Claude Code's bundled skills (/code-review,/batch,/debug,/loop,/claude-api, …) from the model to reclaim listing budget without touching your own skills (CC 2.1.169+). It fires only under measured pressure, so it stays an opportunity rather than noise. Both scanners share one budget definition (scanners/lib/skill-listing-budget.mjs).
CLAUDE.md size — two complementary signals. CML checks line count (200/500, for readability) and a character budget that mirrors Claude Code's own startup warning — "Large CLAUDE.md will impact performance (X chars > 40.0k)." CC 2.1.169 scales that threshold with the model's context window, so the char finding anchors on a conservative 200k window and discloses the relaxed ~200,000-char figure at 1M context. A file can be long by lines yet under the char budget (short lines), or short by lines yet over it — so both signals earn their place. The 200k/1M window constants live in the shared
scanners/lib/context-window.mjs(single source of truth with the skill-listing budget).
Permission rules CC silently ignores — severity follows intent.
Tool(param:value)matching is real (CC 2.1.178), but the tool's own canonicalizing fields are off-limits:command(Bash/PowerShell),file_path(Read/Edit/Write),path(Grep/Glob),notebook_path(NotebookEdit),url(WebFetch). CC ignores a rule keyed on its tool's field and emits a startup warning, becauseBash(command:rm *)is bypassable by a compound command. DIS splits severity by where the rule lives: in deny/ask it is false security (medium — the block you intended never applies), in allow it is dead config (low —param:valuematching is deny/ask-only, so the entry grants nothing). The predicate lives inscanners/lib/permission-rules.mjs; valid forms likeBash(npm:*),WebFetch(domain:host), andAgent(model:opus)are never flagged.
Plugin namespace collisions — the one shadow that actually loses components. Claude Code namespaces every plugin component by the plugin's declared
name(/name:command,name:skill, agentname), so a plugin component can never shadow a user- or project-level one — they live in separate namespaces. The real hazard is two plugins that declare the samenameinplugin.json: their namespaces collapse into one, and because the resolution between two installed same-name plugins is undocumented, one plugin's commands, skills, and agents are silently shadowed and become unreachable. The standalone plugin-health scanner (PLH) flags this at medium severity, keying on the declarednamefield rather than the folder name (the folder name is irrelevant to the namespace). A command name shared by two differently-named plugins is a milder case — namespacing keeps both reachable as/a:cmdand/b:cmd, so it is only ambiguity in error messages, search results, and the command listing. PLH reports that at low severity (group-first, one finding per command name), mirroring the COL scanner, which owns the analogous skill-name overlaps across different namespaces.
Plugin-folder shadowing — when a manifest path silently buries a default folder. A plugin's
plugin.jsoncan point a component type at a custom path —commands,agents, andoutputStylesall replace their default folder when set. So if a plugin declares"commands": "./custom/"while acommands/folder still exists, Claude Code stops scanningcommands/entirely and everything in it silently disappears (dead config). PLH flags this at medium severity (CA-PLH-015), mirroring Claude Code's own warning in/doctorandclaude plugin list(v2.1.140+). It does not flagskills— that key adds to the defaultskills/scan rather than replacing it, so both load — nor does it flag a custom path that points back into the default folder (e.g."commands": ["./commands/x.md"]), because the folder is then addressed explicitly.
skills:-array validation — every listed path must be a real skill folder. A plugin'splugin.jsonmay list custom skill directories in askillsarray (each entry a path to a folder containingSKILL.md). PLH validates each entry (CA-PLH-016, medium) and flags four ways an entry can be broken: it isn't a string, it points at a path that doesn't exist, it points at a file instead of a directory, or it escapes the plugin root (../…— installed plugins can't reference files outside their own directory, so the skill never loads). A valid existing directory is never flagged. This mirrorsclaude plugin validate. Noteskillsadds to the defaultskills/scan, so a custom path here is never a shadow — it just has to resolve to a real folder.
autoModevalidation — structure and the shared-settings blind spot. The SET scanner checks the auto-mode classifier config two ways. Structure:autoModemust be an object whose only keys areenvironment,allow,soft_deny, andhard_deny, each a list of plain-text rule strings (the literal"$defaults"is allowed). An unknown sub-key (e.g. a typo'dhard_denies), a non-object value, or a sub-key that isn't a string array is flagged medium — a typo'd key silently drops those rules. Scope: Claude Code does not readautoModefrom shared project settings (.claude/settings.json) — "a checked-in repo cannot inject its own allow rules" — so anautoModeblock committed there is dead config (low); it only takes effect in user (~/.claude/settings.json), local (.claude/settings.local.json), or managed settings.
CLI Tools
All tools work standalone — no Claude Code session needed:
| Tool | Usage |
|---|---|
| Posture | node scanners/posture.mjs <path> [--json] [--global] [--full-machine] [--output-file path] |
| Fix | node scanners/fix-cli.mjs <path> [--apply] [--json] [--global] |
| Drift | node scanners/drift-cli.mjs <path> [--save] [--baseline name] [--json] |
| Tokens | node scanners/token-hotspots-cli.mjs <path> [--json] [--global] [--no-exclude-cache] [--output-file path] [--accurate-tokens] [--with-telemetry-recipe] |
| Manifest | node scanners/manifest.mjs <path> [--json] — ranked component-level source table with per-source load pattern + always-loaded subtotal |
| What's active | node scanners/whats-active.mjs <path> [--json] [--verbose] [--suggest-disables] |
| Self-audit | node scanners/self-audit.mjs [--json] [--fix] [--check-readme] |
| Full scan | node scanners/scan-orchestrator.mjs <path> [--global] [--full-machine] [--no-suppress] |
Agent Architecture
Six specialized agents collaborate through the audit workflow, each matched to an appropriate model for cost and quality:
| Agent | Model | Role | Tools |
|---|---|---|---|
| scanner-agent | Sonnet | Fast filesystem scanning, file discovery | Read, Glob, Grep, Write |
| analyzer-agent | Sonnet | Deep analysis, hierarchy mapping, conflict detection | Read, Glob, Grep, Write |
| planner-agent | Opus | Action plan generation with risk assessment | Read, Glob, Write |
| implementer-agent | Sonnet | Change execution with mandatory backups | Read, Write, Edit, Bash, Glob |
| verifier-agent | Sonnet | Post-implementation verification | Read, Glob, Grep |
| feature-gap-agent | Opus | Context-aware feature recommendations | Read, Glob, Grep, Write |
| optimization-lens-agent | Opus | Mechanism-fit precision gate — judges prose-judgment lens candidates (lifecycle→hook, path→rule, never→permission), cites the best-practices register | Read, Glob, Grep, Write |
Orchestration Flow
+-----------+
| Interview | (optional)
+-----+-----+
|
+-----------+ +---------+ +-------v---+ +-----------+
| Discover | --> | Analyze | --> | Plan | --> | Implement |
| (sonnet) | | (sonnet)| | (opus) | | (sonnet) |
+-----------+ +---------+ +-----------+ +-----+-----+
|
+-----v-----+
| Verify |
| (sonnet) |
+-----------+
Hooks & Safety
Four hooks provide automatic safety and session continuity — they activate the moment the plugin is installed:
| Event | Script | What It Does |
|---|---|---|
| PreToolUse | auto-backup-config.mjs |
Backs up any config file before Edit/Write touches it |
| PostToolUse | post-edit-verify.mjs |
Re-scans after edits — blocks if new critical/high findings introduced |
| SessionStart | session-start.mjs |
Checks for incomplete audit sessions so you can resume |
| Stop | stop-session-reminder.mjs |
Shows current phase so your next session picks up where you left off |
All hooks are Node.js (.mjs) for cross-platform compatibility (macOS, Linux, Windows).
Important
The PreToolUse and PostToolUse hooks only activate when config-audit is modifying configuration files. They don't interfere with your normal development workflow.
Skills
| Skill | Trigger | Description |
|---|---|---|
config-hierarchy |
"CLAUDE.md hierarchy", "config file locations", "settings.json structure" | Comprehensive reference for Claude Code's configuration hierarchy — CLAUDE.md, settings.json, managed config, @imports, path-scoped rules |
Skills activate automatically when your question matches their trigger patterns.
Suppressions
Finding ID Format
Every finding has a unique ID: CA-{SCANNER}-{NNN} — where {SCANNER} is the scanner prefix (see table above) and {NNN} is a sequential number. Examples: CA-CML-001, CA-SET-003, CA-HKV-002, CA-RUL-005.
Suppression
Some findings are expected — maybe you intentionally have a large CLAUDE.md, or a feature gap doesn't apply to your workflow. Create a .config-audit-ignore file to suppress them:
# Suppress by exact finding ID
CA-SET-003
# Suppress by scanner prefix (glob pattern)
CA-GAP-*
# Suppress all plugin health findings
CA-PLH-*
Suppressed findings are tracked in the scan envelope's suppressed_findings array for audit trail — nothing is silently hidden. Use --no-suppress to see everything.
Examples & Self-Audit
Example Projects
The examples/ directory contains two projects shown in the before/after demo above:
| Example | Description | Grade | Opportunities |
|---|---|---|---|
minimal-setup/ |
Single CLAUDE.md, nothing else | A | 22 |
optimal-setup/ |
Full configuration across all 4 tiers | A | 3 |
# Run them yourself
node scanners/posture.mjs examples/minimal-setup/
node scanners/posture.mjs examples/optimal-setup/
Self-Audit: Scanning the Scanner
The plugin runs all 16 scanners + the standalone plugin-health scanner on itself via self-audit.mjs. Test fixtures and example files are automatically excluded from scoring — a configuration plugin that ships deliberately broken examples shouldn't fail its own audit. Use --check-readme to verify badge counts are in sync with the filesystem.
node scanners/self-audit.mjs
Scanner Library (scanners/lib/)
Shared modules used by all scanners — useful if you're reading the source or extending the plugin:
| Module | Purpose |
|---|---|
severity.mjs |
Severity constants, risk scoring, verdict logic, WEIGHTS export (v5 F3) |
output.mjs |
Finding objects (CA-XXX-NNN format), scanner results, envelope, details field |
file-discovery.mjs |
Config file discovery: single-path, multi-path, full-machine |
yaml-parser.mjs |
Frontmatter parsing, JSON parsing, @import/section extraction |
string-utils.mjs |
Line counting, truncation, similarity, key extraction |
scoring.mjs |
Area scoring (v5 severity-weighted), health scorecard, scoringVersion: 'v5' |
backup.mjs |
Backup creation, manifest parsing, checksum verification |
diff-engine.mjs |
Drift diffing: diffEnvelopes(), formatDiffReport() |
baseline.mjs |
Baseline save/load/list/delete for drift detection |
report-generator.mjs |
Unified markdown reports: posture, drift, plugin health |
suppression.mjs |
.config-audit-ignore parsing, finding suppression, audit trail |
active-config-reader.mjs |
Read-only inventory of plugins/skills/MCP/hooks/CLAUDE.md cascade with token estimates |
tokenizer-api.mjs |
Anthropic count_tokens wrapper for --accurate-tokens (v5 N5); 5s timeout, 429 backoff, key masking |
Action Engines
| Module | Purpose |
|---|---|
fix-engine.mjs |
planFixes(), applyFixes(), verifyFixes() — 9 fix types |
rollback-engine.mjs |
listBackups(), restoreBackup(), deleteBackup() |
fix-cli.mjs |
CLI entry point for auto-fix |
drift-cli.mjs |
CLI entry point for drift detection |
manifest.mjs |
CLI: ranked component-level source table w/ load-pattern accounting (v5 N2; v5.6 B) |
whats-active.mjs |
CLI: read-only active-config inventory (v3.1.0+) |
token-hotspots-cli.mjs |
CLI: token hotspots ranking with optional --accurate-tokens |
Knowledge Base (knowledge/)
Reference documents that inform the feature-gap agent and context-aware recommendations:
| File | Content |
|---|---|
claude-code-capabilities.md |
Feature register: 18 config surfaces, Anthropic guidance, relevance table |
configuration-best-practices.md |
Per-layer best practices (cache-stability guidance) |
anti-patterns.md |
Common mistakes mapped to scanner IDs |
hook-events-reference.md |
All 28 hook events with details |
feature-evolution.md |
Feature timeline for staleness detection |
gap-closure-templates.md |
Config-specific templates for closing gaps |
prompt-cache-patterns.md |
Token-cost dynamics (prompt-cache patterns) — patterns powering the TOK scanner |
cache-telemetry-recipe.md |
jq recipe for verifying prompt-cache hit rate from session transcripts |
Machine-readable register (best-practices.json). Alongside the human-readable documents
above, knowledge/best-practices.json is a provenance-stamped, schema-validated register of
best-practice claims and mechanism-fit rules — each entry carries source.url, a verified
date, and a confidence. It is the source of truth for the optimization lens (OPT scanner +
/config-audit optimize); the Markdown files remain the human-readable mirror. Loaded and validated by
scanners/lib/best-practices-register.mjs (zero-dependency, native JSON). See
docs/v5.7-optimization-lens-plan.md.
Testing
node --test 'tests/**/*.test.mjs'
1168 tests across 67 test files (22 lib + 35 scanner + 1 hook + 1 agent + 3 commands + 1 knowledge + 4 top-level). Test fixtures in tests/fixtures/. Requires Node.js 18+ (node:test).
Gotchas
- Session accumulation — session directories at
~/.claude/config-audit/sessions/grow over time. Use/config-audit cleanupto manage - Node.js version — scanners require Node.js 18+ (uses
node:test,node:fs/promises) - Plugin CLAUDE.md in node_modules — these should be excluded via scope to avoid false positives
Data Storage & Safety Guarantees
Where Data Lives
All data stays local at ~/.claude/config-audit/sessions/:
~/.claude/config-audit/sessions/{session-id}/
scope.yaml # Scan boundaries
discovery.json # File manifest
findings/ # Individual issues (YAML)
analysis-report.md # Full report
action-plan.md # Prioritized actions
backups/ # Pre-modification copies
implementation-log.md # Change log
state.yaml # Phase tracking
Safety Guarantees
This plugin is cautious by design — configuration files are important, and a bad edit can break your entire Claude Code setup:
| Guarantee | How |
|---|---|
| Backups mandatory | Every file is copied before modification — no exceptions |
| Read-only audit | /config-audit and /config-audit posture analyze without changing anything |
| Rollback support | /config-audit rollback restores from any backup |
| Syntax validation | Every change is validated before finalization |
| Verification pass | A separate agent confirms changes actually work |
| Human-in-the-loop | You approve the plan before anything is implemented |
| Post-edit guard | Hook blocks the session if a new critical/high finding is introduced |
What This Plugin Does Not Cover
- Runtime behavior — this plugin audits configuration files, not what Claude actually does at runtime. For runtime defense, see claude-code-llm-security
- Secret scanning — config-audit checks for structural issues, not leaked credentials. Use llm-security for secret detection
- Custom scanner rules — scanners check against known Claude Code configuration schemas. Custom rule definitions are not supported
- Remote/team configuration — managed settings, SSO-provisioned config, and organization-level policies are detected as gaps but not managed
Version History
| Version | Date | Highlights |
|---|---|---|
| 5.12.5 | 2026-06-26 | "Dogfood denoise" — a samle-release of the Fase-3 scanner false-positive batch (M-BUG-2/6/7/8/10, all dogfooding finds on the maintainer's real machine). Five scanners stop counting non-user / non-live config as the user's: CNF (M-BUG-2) excludes files under .claude/plugins/ from conflict analysis (isPluginBundled) — installed plugins' bundled settings/hooks/fixtures are not a user-resolvable cascade (dogfood 339→0, Conflicts was an F on pure plugin noise). file-discovery (M-BUG-8) adds backups to SKIP_DIRS — a backups/ tree holds frozen copies, never live config (dogfood files-under-/backups/ 36→0, 717 live retained). token estimator (M-BUG-6) strips block-level <!-- --> HTML comments from CLAUDE.md sizing — CC strips them before injection, so they were never always-loaded tokens (dogfood ~3386→3301, ~85 tok). CPS (M-BUG-7) skips fenced/inline code and whitelists CC-stable path vars (${CLAUDE_PLUGIN_ROOT}/${CLAUDE_PROJECT_DIR}) before cache-buster matching (dogfood 5→2). SET (M-BUG-10) typo-gates the unknown-settings-key finding — the CC schema is passthrough (verified against the 2.1.193 binary), so an unknown key is forward-compatible, not an error; it now flags only a near-miss of a known key (levenshtein ≤2), severity medium→low, +6 binary-verified KNOWN_KEYS (dogfood 6→0). No count change (scanners 16, agents 7, commands 21, hooks 4); all five are byte-stable — frozen v5.0.0 + SC-5 + default-output snapshots untouched, no re-seed (each fixture's findings are genuinely unchanged). 1344 tests (+37). |
| 5.12.4 | 2026-06-26 | "Rooted rules" — fixes M-BUG-9 (dogfooding find) in scanners/rules-validator.mjs: the RUL "Rule path pattern matches no files" check now resolves a rule's paths:/globs: pattern against the rule's own project root (the dir containing its .claude/), not the outer scan root. Previously countGlobMatches globbed against the scan target and collectProjectFiles' depth>4 cutoff never reached deep matching files, so a live rule in a nested repo (e.g. a marketplace checkout under ~/.claude) was wrongly flagged "never activates" (high) — a false F-grade for anyone with rules in a nested repo. The fix derives each rule's project root, collects+globs per root (cached), and skips the check for user-global rules (root === $HOME), which scope against the active project at runtime. Same scope-conflation family as M-BUG-1/2. No count change (scanners 16, agents 7, commands 21); the fix is a no-op when projectRoot === targetPath (the common single-repo scan), so frozen v5.0.0 + default-output snapshots stay byte-stable. 1307 tests (+2 TDD: nested-repo false-positive + HOME guard). |
| 5.12.3 | 2026-06-26 | "Phantom agents" — fixes M-BUG-3/4/5 (dogfooding finds) in scanners/lib/active-config-reader.mjs: enumerateAgents now counts only the agents Claude Code actually registers. Per the official subagents doc, an agent needs valid name+description frontmatter, and CC scans recursively and silently skips frontmatter-less files. The reader previously (M-BUG-5) counted every .md regardless of frontmatter, (M-BUG-3) never recursed into agent subdirs, and (M-BUG-4) double-counted when the project dir equals the user dir (scanning $HOME — root cause, also affecting rules/output-styles). Real-machine verify: user-agent count 13→0 (all 12 user agents + REMEMBER.md are frontmatter-less → CC registers none), HOME project-dup 13→0; corrected always-loaded baseline ≈ 53 (was 66). Agent enumeration is machine-dependent and absent from the frozen snapshots, so the v5.0.0 + SC-5 + default-output snapshots stay byte-stable; no count change (scanners 16, agents 7, commands 21). 1305 tests. |
| 5.12.2 | 2026-06-24 | "Honest census" — fixes M-BUG-1 (dogfooding find): enumeratePlugins walked ~/.claude/plugins/marketplaces/<mkt>/plugins/ and ignored both enable-state and the polyrepo cache layout, so it over-counted phantom agents from disabled plugins while missing the entire enabled polyrepo set (whose plugins live under cache/). It now gates on installed_plugins.json + enabledPlugins and enumerates each plugin from its active installPath, with the marketplaces walk as fallback. Fixes manifest/whats-active/AGT/token-hotspots for any user with disabled plugins or a polyrepo marketplace. No count change (scanners 16, agents 7, commands 21); --json/--raw byte-stable, frozen v5.0.0 + SC-5 + default-output snapshots untouched. Real-machine verify: agent listing 114→104, ghosts gone. 1301 tests. |
| 5.12.1 | 2026-06-24 | "Footgun guard" — Pattern H (stale plugin-cache versions, token-hotspots) recommended deleting stale version dirs with no warning that a currently-running session may still hold one of those versions for its whole lifetime. "Stale" is judged against installed_plugins.json (what NEW sessions load), so the recommendation could reproduce the exact failure that breaks a live session: deleting the dir pulls the files out from under the running session, which then must /exit + restart. The plugin-cache-hygiene recommendation now carries the live-session caveat. Recommendation string only — no new finding ID or scanner (count stays 16, agents 7, commands 21), no token figures changed, so --json/--raw stay byte-stable and the frozen v5.0.0 + SC-5 + default-output snapshots are untouched. 1297 tests. |
| 5.12.0 | 2026-06-23 | "Auto-calibration" — completes the deferred B8 half (B8b): --context-window auto now probes the configured model instead of always falling back to advisory. New pure modelToContextWindow() maps known 1M-tier model IDs (Fable 5, Opus 4.8/4.7/4.6, Sonnet 4.6 — verified June 2026 — plus the explicit [1m] tier tag, dated/provider-prefixed IDs, and the opus/sonnet/fable aliases) to the 1M window; new IO helper lib/active-model.mjs resolveActiveModel() reads the model the way Claude Code resolves it (shell ANTHROPIC_MODEL override, then the settings cascade local > project > user). When auto resolves a recognized model the budget calibrates to its window (auto-probed, not advisory); when no model is pinned or it is unrecognized it keeps the conservative anchor and stays advisory (auto-unresolved) — the honest fallback. No new finding ID or scanner (count stays 16, agents 7, commands 21); the default and explicit --context-window paths are unchanged, so --json/--raw stay byte-stable and the frozen v5.0.0 + SC-5 snapshots are untouched. 1296 tests. |
| 5.11.0 | 2026-06-23 | "Precision polish" — the two LOW-priority calibration gaps, both additive (scanner count stays 16, agents 7, commands 21; --json/--raw byte-stable, frozen v5.0.0 + SC-5 untouched). B7 — oversized skill body (CA-SKL-003, low): the SKL scanner now measures the SKILL.md body (it already read the file in full) and flags bodies over ~5,000 tokens, recommending a supporting-file split + context: fork. Honestly framed as an on-demand cost — the body loads only when the skill is invoked, not every turn like the always-loaded listing — hence low severity. B8 — context-window calibration (--context-window): CA-SKL-002 (skill-listing budget) and the CML char-budget now calibrate to a real context window via --context-window <n> (e.g. 1000000 stops the 200k anchor crying wolf on a 1M host) instead of always anchoring at 200k; --context-window auto keeps the conservative anchor but downgrades budget findings to info/advisory rather than firing a breach (model→window auto-probing deferred to a later B8b). No flag → byte-identical to the pre-B8 200k default. CPS is intentionally excluded (no window-anchored budget to calibrate). 1279 tests |
| 5.10.0 | 2026-06-23 | "Deferral & injection hygiene" — three additive hardening levers that extend existing scanners toward a tighter always-loaded prefix (scanner count stays 16, agents 7, commands 21; --json/--raw byte-stable, frozen v5.0.0 + SC-5 untouched). B4 — MCP tool-schema deferral (CA-TOK-006; tokens patterns 7→8): Claude Code defers MCP tool schemas (names-only, ~120 tok; full schemas load on demand) by default, so CA-TOK-006 detects config-file signals that force the FULL schemas into the always-loaded prefix every turn — env.ENABLE_TOOL_SEARCH="false" (high), a "ToolSearch" deny (high), a configured Haiku model (medium), or per-server alwaysLoad:true (CC v2.1.121+, high); severity scales with the aggregate forced-upfront tokens. New pure engine lib/mcp-deferral.mjs shared by TOK + GAP, plus a feature-gap CLI-over-MCP companion lever (prefer gh/aws/gcloud). Triggers on config files ONLY — Vertex / custom ANTHROPIC_BASE_URL / a runtime /model switch are launch state and are disclosed, never triggered; the prefix-cache-invalidation claim was NOT-CONFIRMED in docs and is not asserted. B5 — hook additionalContext advisory + filter-before lever: HKV emits an info advisory when a hook injects unfiltered output into additionalContext, with a feature-gap filter-before-Claude-reads companion citing the documented filter-test-output.sh pattern. B6 — CPS @import volatile scan: the cache-prefix scanner now follows @imports (one hop) and flags volatile content in the imported file that breaks the cached prefix — a new medium finding, keyed on the resolved file. 1257 tests |
| 5.9.0 | 2026-06-23 | "Machine-wide token lens" — the three highest-impact hardening gaps toward whole-machine token tuning. B1 — agent-listing budget (new orchestrated scanner AGT, count 15→16): the always-loaded agent listing (name+description re-sent every turn) is now measured — CA-AGT-001 per-agent description bloat (advisory), CA-AGT-002 aggregate listing over budget; both LOW and explicitly inferred / upper-bound (the mechanism is undocumented — the evidence discloses it rather than overstating). B2 — machine-wide always-loaded token roll-up: the campaign ledger now carries a token bill — campaign refresh-tokens does a live cross-repo sweep that counts the shared global always-loaded layer once + per-repo deltas, with a ranked "most expensive repos" table (the whats-active double-count, avoided by construction). B3 — cache-aware filtering (folds in B0): ~/.claude/plugins/cache holds both active and stale plugin versions (installPaths point INTO it), so token-hotspots + CNF are now version-aware — --exclude-cache (default ON) keeps each plugin's active version and drops only stale ones (installed_plugins.json-driven), so stale versions stop polluting the hotspot ranking and inflating duplicate-hook conflicts; stale versions surface as a separate Dead config disk-cleanup finding (zero live-context impact). --json/--raw byte-stable; frozen v5.0.0 + SC-5 snapshots untouched. 1215 tests |
| 5.8.0 | 2026-06-23 | "Campaign motor" — a durable, machine-wide audit campaign that sits ABOVE individual sessions (one repo = one session; a fleet of repos = a campaign). Ledger: ~/.claude/config-audit/campaign-ledger.json (outside the plugin dir → survives uninstall/upgrade) tracks a repo list + per-repo lifecycle (pending→audited→planned→implemented) + a machine-wide roll-up by status & severity; pure transforms with injected now. /config-audit campaign (commands 20→21): read-only report (campaign-cli) + human-approved writes (campaign-write-cli: init / add / set-status) — reports first, mutates only on explicit approval, never hand-edits the ledger. Cross-repo backlog: one severity-weighted prioritized pick-list (buildBacklog, critical:1000/high:100/medium:10/low:1). Plan export + execution-by-reuse: campaign-export-cli --write drops a planned repo's plan verbatim into its own docs/; execution reuses the existing /config-audit implement + rollback (no new execution machinery). All campaign code is -cli/lib → scanner count stays 15, agents 7, byte-stable. Plus pre-release cleanup: knowledge-refresh wired into the router + help; CLAUDE.md trimmed 540→134 lines (impl notes → docs/scanner-internals.md, config grade B→A). 1168 tests |
| 5.7.0 | 2026-06-21 | "Optimization lens" — first detector of the «optimally shaped?» axis (vs «correct?»), plus a living knowledge layer. Register: knowledge/best-practices.json, a provenance-stamped, schema-validated best-practices register (first runtime-consumed knowledge/ file). OPT scanner (count 14→15): CA-OPT-001 (LOW) a ≥6-step CLAUDE.md procedure that would fit better as a skill, citing register entry BP-MECH-003. /config-audit optimize + optimization-lens-agent (opus, agents 6→7): prose-judgment lens for lifecycle→hook (BP-MECH-001), unscoped path→rule (BP-MECH-002), "never"→permission (BP-MECH-004); pre-filter recall + opus precision gate. /config-audit knowledge-refresh (commands 19→20): deterministic stale-check (injected reference date, 90-day cadence) + web re-verify/poll, human-approved writes only. Last two are agent/web-driven (not byte-stable). 1091 tests |
| 5.6.0 | 2026-06-20 | "Steering-model II" — the load-pattern / compaction-survival model lands end-to-end. Foundation: active-config-reader now enumerates rules, agents, and output styles (alongside CLAUDE.md/plugins/skills/hooks/MCP), each tagged loadPattern (always / on-demand / external) + survivesCompaction from the published loading model; the frontmatter parser also reads YAML block sequences (paths: lists). B (load-pattern accounting): manifest reports component-level sources (the double-counting plugin roll-up is gone), tags every source with the load-pattern triple, and leads with an always-loaded subtotal ("tokens that enter context every turn"); token-hotspots annotates each ranked hotspot with its load pattern. C (output styles): new orchestrated OST scanner (count 13→14) — CA-OST-001 a custom style stripping built-in coding instructions (missing keep-coding-instructions: true, V10), CA-OST-002 a plugin style with force-for-plugin: true overriding the user's outputStyle (V11), CA-OST-003 a settings outputStyle resolving to no known style (dead config). Doc-verified; frozen v5.0.0 snapshots preserved via strip-helpers, SC-5 regenerated. 1023 tests |
| 5.5.0 | 2026-06-20 | "Steering-model I" — two additive compaction-durability / dead-config findings (count stays 13, --json/--raw byte-stable). Per the official "what survives compaction" model: RUL flags a large (>50-line) path-scoped rule not re-injected after compaction (LOW); CML flags a nested (subdir) CLAUDE.md not re-injected after compaction (LOW). PLH flags a plugin agent setting hooks/mcpServers/permissionMode — Claude Code ignores these for plugin subagents, so it's dead config (permissionMode = MEDIUM false-security, hooks/mcpServers = LOW). Known limitation: the frontmatter parser reads inline paths: but not YAML block sequences (deferred to v5.6 Foundation). 961 tests |
| 5.4.1 | 2026-06-20 | Scanner-correctness patch (count stays 13, --json/--raw byte-stable). HKV: added Setup/UserPromptExpansion/PostToolBatch to the valid-event set (a valid hook using one was wrongly flagged "will never fire"), and removed post-session (the 2.1.169 post-session is a self-hosted-runner workspace-lifecycle hook, not a settings.json event — absent from hooks.md; verified 2026-06-20). RUL: globs-rule wording corrected — only paths: is documented, so the finding drops the unverified "deprecated/legacy" claim and steers to the documented field. PLH: optional model/tools/name/allowed-tools frontmatter no longer required; CLAUDE.md component-section required only for components the plugin actually ships. 954 tests |
| 5.4.0 | 2026-06-19 | Plugin-hygiene & settings-validation hardening. Three additive findings extend existing PLH and SET scanners (count stays 13): PLH plugin-folder shadowing (CA-PLH-015 — a plugin.json component-path key in the replaces set commands/agents/outputStyles pointing at a custom path while the default folder still exists) mirroring CC's /doctor & claude plugin list warning; PLH skills:-array validation (CA-PLH-016 — each entry must resolve to a directory in the plugin root; flags non-string/escapes-root/not-found/not-a-directory) mirroring claude plugin validate; SET autoMode structure (only environment/allow/soft_deny/hard_deny string arrays) + dead-config (autoMode in shared .claude/settings.json is not read by CC). --json/--raw byte-stable. 949 tests |
| 5.3.0 | 2026-06-19 | Permission-rule & plugin-hygiene hardening. Five additive scanner findings extend existing scanners (count stays 13): DIS forbidden-param rules (Tool(param:value) on a canonicalizing field — deny/ask = false security, allow = dead config) and ineffective allow-wildcards + Tool(*) deny-all; CML context-window-scaled 40.0k-char CLAUDE.md budget mirroring CC's startup warning; PLH plugin namespace collision (two plugins declaring the same name); feature-gap disableBundledSkills lever under skill-listing pressure. PLH cross-plugin command-name overlap reframed HIGH → LOW (namespacing keeps both reachable). --json/--raw byte-stable. 936 tests |
| 5.2.0 | 2026-06-18 | CC 2.1.114→181 compatibility + skill-listing budget. New orchestrated scanner SKL (CA-SKL-001 1,536-char listing cap, CA-SKL-002 listing-budget sum) → 13 orchestrated scanners. Five validators refreshed for CC 2.1.114–181 settings/hook surface (xhigh effort, MessageDisplay + post-session events, 28 hook events). False positives eliminated in MCP (auto-injected/POSIX env vars, invented trust field) and permissions (param-aware DIS/CNF). Hermetic HOME isolation across all CLI-spawning tests. 875 tests |
| 5.1.0 | 2026-05-01 | Plain-language UX humanizer. Default output of all 18 commands now leads with prose; findings grouped by user-impact category (Configuration mistake, Conflict, Wasted tokens, Missed opportunity, Dead config) and led by urgency phrase (Fix this now → FYI). New --raw flag preserves v5.0.0 verbatim output for tooling that scrapes stderr; --json is unchanged and byte-stable. New scanner-lib modules: humanizer.mjs, humanizer-data.mjs with TRANSLATIONS for 13 scanner prefixes. Self-audit terminal output also humanized. 792 tests (+157 humanizer-tester) |
| 5.0.0 | 2026-05-01 | Reality-based token-optimization. 3 new scanners (CPS cache-prefix, DIS dead tools, COL plugin collisions) → 12 deterministic scanners. New /config-audit manifest and --accurate-tokens API calibration. Severity-weighted scoring (scoringVersion: 'v5'). MCP token estimates 15 → 500+. Plugin Hygiene as 10th quality area. Knowledge: cache-stability replaces 200-line rule, cache-telemetry recipe. Breaking: F2 token magnitude jump, F3 severity weighting, F5 Pattern D removed, N1 CA-TOK-* glob now matches CA-TOK-005. 635 tests |
| 4.0.0 | 2026-04-19 | Opus 4.7 era: new TOK scanner (cache-breaking volatile content, redundant tool permissions, deep import chains, sonnet-era setups), /config-audit tokens command, Token Efficiency 8th quality area, scanner-agent + verifier-agent migrated haiku → sonnet. 543 tests |
| 3.1.0 | 2026-04-14 | New /config-audit whats-active — read-only inventory of active plugins, skills, MCP, hooks, CLAUDE.md for a repo, with token estimates. 522 tests |
| 3.0.1 | 2026-04-04 | Cross-platform fix: Windows path separators. 486 tests |
| 3.0.0 | 2026-04-04 | Health redesign: quality-only grades, context-aware opportunities (replaces utilization/maturity/segment), Anthropic guidance. 482 tests |
| 2.2.0 | 2026-04-04 | Fixture filtering (test findings excluded from grades), session path fix, UX polish. 461 tests |
| 2.1.0 | 2026-04-03 | UX redesign: auto-scope, zero questions, simplified commands (15 from 17). 441+ tests |
| 2.0.0 | 2026-04-03 | Complete rewrite: 8 scanners, 25 gap dimensions, auto-fix, drift, suppressions, self-audit. 408+ tests |
| 1.6.0 | 2026-04-03 | Report generator, suppression engine, self-audit CLI, PostToolUse hook |
| 1.5.0 | 2026-04-03 | Diff engine, baseline manager, drift CLI, plugin health scanner |
| 1.4.0 | 2026-04-03 | Fix engine, rollback engine, fix CLI, PreToolUse hook |
| 1.3.0 | 2026-04-03 | Scoring module, posture CLI, feature-gap agent |
| 1.2.0 | 2026-04-03 | 4 advanced scanners (MCP, import, conflict, feature-gap) |
| 1.1.0 | 2026-04-03 | 4 core scanners, scan orchestrator, test infrastructure |
| 1.0.0 | 2026-02-11 | Cross-platform support |
| 0.7.0 | 2026-02-07 | Initial version (version reset from inflated 1.2.0) |
See CHANGELOG.md for full details.
License
MIT License — Copyright (c) 2025-2026 Kjell Tore Guttormsen