HKV now flags hooks that build hookSpecificOutput.additionalContext from un-grepped command output as an INFO advisory (weight 0, never severity-bearing — excluded from the self-audit nonInfo set). That field enters Claude's context every time the hook fires (plain stdout on exit 0 does not), so an unfiltered payload is a recurring per-turn token cost. - New lib scanners/lib/hook-additional-context.mjs: pure assessHookAdditionalContext (unit-tested, no IO) + IO wrapper assessHookContextForRepo (walk hooks->scripts). Heuristic: additionalContext + verbose-prone capture (cat/git log/execSync/…) && no filter (grep/head/jq/.slice). Deliberately low precision -> advisory only. - HKV: emits the advisory inline on scripts it already reads (after the M5 verbose check). Additive, info severity -> frozen v5.0.0 + SC-5 snapshots untouched. - feature-gap: new filterHookLeverFinding companion, fires ONLY when >=1 chatty hook is detected — surfaces the filter-before-Claude-reads lever (CC filter-test-output.sh). Silent otherwise (opportunity, not noise). - docs: README HKV + GAP scanner rows; scanner-internals.md HKV row + full B5 implementation note. CLAUDE.md kept lean ([skip-docs]); B5 fully documented in README + scanner-internals. Mechanism verified 2026-06-23 against code.claude.com/docs context-window.md (additionalContext enters context; plain stdout does not). Suite 1239 -> 1254 green. Version/badges/CHANGELOG wait for the v5.10 release cut. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
698 lines
51 KiB
Markdown
698 lines
51 KiB
Markdown
# 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](GOVERNANCE.md) for the full model and what upstream provides.
|
||
|
||
*AI-generated: all code produced by Claude Code through dialog-driven development. [Full disclosure →](../../README.md#ai-generated-code-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](#whats-new-in-v540)
|
||
- [What Is This?](#what-is-this)
|
||
- [The Configuration Problem](#the-configuration-problem)
|
||
- [Quick Start](#quick-start)
|
||
- [Feature Opportunities](#feature-opportunities--context-aware-recommendations)
|
||
- [Workflow Examples](#workflow-examples)
|
||
- [Commands](#commands)
|
||
- [Deterministic Scanners](#deterministic-scanners)
|
||
- [Agent Architecture](#agent-architecture)
|
||
- [Hooks & Safety](#hooks--safety)
|
||
- [Skills](#skills)
|
||
- [Suppressions](#suppressions)
|
||
- [Examples & Self-Audit](#examples--self-audit)
|
||
- [Scanner Library](#scanner-library-scannerslib)
|
||
- [Knowledge Base](#knowledge-base-knowledge)
|
||
- [Testing](#testing)
|
||
- [Gotchas](#gotchas)
|
||
- [Data Storage & Safety Guarantees](#data-storage--safety-guarantees)
|
||
- [What This Plugin Does Not Cover](#what-this-plugin-does-not-cover)
|
||
- [Version History](#version-history)
|
||
- [License](#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 a `plugin.json` component-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 `/plugin` detail
|
||
view. `skills` is excluded (it *adds to* the default scan, never shadows), as are
|
||
`hooks`/`mcpServers`/`lspServers` (own merge rules); a custom path resolving *into* the default
|
||
folder is not flagged.
|
||
- **PLH `skills:`-array validation** (`CA-PLH-016`) — validates each `plugin.json` `skills` entry
|
||
(string or array) resolves to an existing directory inside the plugin root; flags `non-string`,
|
||
`escapes-root`, `not-found`, and `not-a-directory` entries. Mirrors `claude plugin validate`.
|
||
- **SET `autoMode` structure + dead-config** — checks that `autoMode` is an object whose only keys
|
||
are `environment`/`allow`/`soft_deny`/`hard_deny`, each a string array (the literal `"$defaults"`
|
||
is valid); unknown sub-keys and wrong types are flagged (medium). Separately, `autoMode` placed
|
||
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 posture` for a 30-second scorecard, then `/config-audit` for 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.md` says "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.json` has a deprecated key that silently does nothing
|
||
- An `@import` in 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](https://docs.anthropic.com/en/docs/claude-code) installed
|
||
- Node.js 18+ (for standalone CLI tools)
|
||
|
||
### Installation
|
||
|
||
Add the marketplace and browse plugins with `/plugin`:
|
||
|
||
```bash
|
||
claude plugin marketplace add https://git.fromaitochitta.com/open/ktg-plugin-marketplace.git
|
||
```
|
||
|
||
Or enable directly in `~/.claude/settings.json`:
|
||
|
||
```json
|
||
{
|
||
"enabledPlugins": {
|
||
"config-audit@ktg-plugin-marketplace": true
|
||
}
|
||
}
|
||
```
|
||
|
||
### First Scan
|
||
|
||
```bash
|
||
# 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); 7 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 the cache-prefix window but still re-loaded every turn |
|
||
| `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`), and the summed active-skill descriptions exceeding the ~2%-of-context listing budget (`CA-SKL-002`) |
|
||
| `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 and `disableBundledSkills` is 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, because `Bash(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:value` matching is deny/ask-only, so the entry grants nothing). The
|
||
> predicate lives in `scanners/lib/permission-rules.mjs`; valid forms like `Bash(npm:*)`,
|
||
> `WebFetch(domain:host)`, and `Agent(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`, agent `name`), 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 **same** `name` in `plugin.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
|
||
> declared `name` field 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:cmd` and `/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.json` can point a component type at a custom path — `commands`,
|
||
> `agents`, and `outputStyles` all *replace* their default folder when set. So if a plugin
|
||
> declares `"commands": "./custom/"` while a `commands/` folder still exists, Claude Code
|
||
> stops scanning `commands/` 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
|
||
> `/doctor` and `claude plugin list` (v2.1.140+). It does **not** flag `skills` — that key
|
||
> *adds to* the default `skills/` 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's `plugin.json` may list custom skill directories in a `skills` array (each entry a
|
||
> path to a folder containing `SKILL.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 mirrors
|
||
> `claude plugin validate`. Note `skills` *adds to* the default `skills/` scan, so a custom path
|
||
> here is never a shadow — it just has to resolve to a real folder.
|
||
|
||
> **`autoMode` validation — structure and the shared-settings blind spot.** The SET scanner
|
||
> checks the auto-mode classifier config two ways. **Structure:** `autoMode` must be an object
|
||
> whose only keys are `environment`, `allow`, `soft_deny`, and `hard_deny`, each a list of
|
||
> plain-text rule strings (the literal `"$defaults"` is allowed). An unknown sub-key (e.g. a
|
||
> typo'd `hard_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** read
|
||
> `autoMode` from *shared* project settings (`.claude/settings.json`) — "a checked-in repo cannot
|
||
> inject its own allow rules" — so an `autoMode` block 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](#the-configuration-problem) above:
|
||
|
||
| Example | Description | Grade | Opportunities |
|
||
|---------|-------------|-------|---------------|
|
||
| `minimal-setup/` | Single CLAUDE.md, nothing else | A | 22 |
|
||
| `optimal-setup/` | Full configuration across all 4 tiers | A | 3 |
|
||
|
||
```bash
|
||
# 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.
|
||
|
||
```bash
|
||
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
|
||
|
||
```bash
|
||
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 cleanup` to 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](https://git.fromaitochitta.com/open/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.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](CHANGELOG.md) for full details.
|
||
|
||
---
|
||
|
||
## License
|
||
|
||
[MIT License](LICENSE) — Copyright (c) 2025-2026 Kjell Tore Guttormsen
|