Harness audit
a second-order harness for cooking ai primitives.
npx -y skills add claudialnathan/agent-kitchen --skill harness-auditAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Audits the coding-agent harness a project's sessions run under, end-to-end: what loads every session, what it costs, whether the harness's own claims hold, and whether its parts work when assembled. Inventories the standing surfaces (CLAUDE.md chain, personal/project/plugin skills, MCP instruction blocks, agent rosters, hooks, settings at every scope), quantifies their per-session token cost, runs setup checks (self-consistency, duplication across scopes, enforcement parity, scope discipline, and a provisional routing-effectiveness check for doc-fleet repos), and after substantial harness changes can run a representative composition probe through the complete installed system. The audit itself is read-only: the deliverable is a ranked findings report leading with the highest-value edit, nothing is applied without the owner's explicit go-ahead, and edits stay inside the project directory. Machine scope (anything under ~/.claude, user or enterprise settings, global plugins) is never edited; those findings are reported with a project-scoped counterweight proposed where one exists. Use to review, slim, or sanity-check a project's harness after major harness changes or when sessions feel slow or behave incoherently from turn one; for a single artifact, the relevant forge owns the audit.
SKILL.md
21.5 KB, as published. Nobody here has run it
Do not load shared snapshots for every audit. Read the plugin-root STATE.md when an installed capability, limit, or cross-tool convention is in question; read MODELS.md only when the audit includes model policy, routing economics, or model-release convergence. Resolve both from this skill's source. They orient the check but never replace inspection of the installed harness or live canonical docs.
The attention this skill redirects
From "read the config files and comment" to "measure what every session pays before any work starts, then check the harness's claims against its own behavior."
The default failure is a vibes review: opening CLAUDE.md, calling it well-written, and missing that the setup burns five figures of tokens per session on descriptions, instructions, and rosters nobody chose deliberately. The second failure is trusting the harness's documentation of itself: files that say "this is not loaded" while being loaded, checklists that say "always run X" with nothing enforcing X.
The third failure is this skill's own trap: treating cost as the verdict. Tokens are what's easy to count; what a surface lets the owner produce is what decides, and an audit that only counts always lands on cut, because the cheapest harness is the empty one. A surface the owner reaches for is already earning its cost, and that she uses it is the evidence it clears the bar, not a number to override. Report what each surface costs so the owner spends deliberately; never strip toward zero.
Operating contract
Three rules frame every step, and no finding overrides them:
- The audit is read-only. Steps 1–4 inventory, measure, and check; none of them writes anything, anywhere. The deliverable is the findings report (Step 5). Edits happen only in Step 6, after the owner's explicit go-ahead on named findings — invoking the audit is consent to look, never to change.
- Writes stay inside the project directory, always. Even after a go-ahead, nothing outside this repo is edited: not
~/.claude/, not another repo, not user, enterprise, or managed settings. No approval unlocks machine scope. - The subject is this project's harness, not the machine. Machine-scope surfaces are inventoried because they load into this project's sessions and this project pays their cost — not because the machine is under audit. The only remedy an audit proposes for a machine-level problem is a project-scoped counterweight (a plugin disabled for this repo via
enabledPluginsin.claude/settings.local.json, a project rule that overrides a global instruction for this repo's files); the machine-level fix itself is reported for the owner to make.
Step 1: Inventory the standing surfaces
List everything that enters context at session start, with its scope and owner:
- Instruction files: CLAUDE.md chain (enterprise → user
~/.claude/CLAUDE.md→ project → CLAUDE.local.md), auto-memoryMEMORY.md. - Skills: personal (
~/.claude/skills/), project (.claude/skills/), and plugin-delivered (enabledPluginsacross all settings files). Every visible skill'sdescription+when_to_useloads every turn. - MCP servers:
.mcp.json(minusdisabledMcpjsonServers, plusenabledMcpjsonServersallowlists), plugin-shipped servers, claude.ai connectors. Tool schemas defer behind tool search, but server instruction blocks load in full. - Agent roster: every plugin-shipped subagent type adds its description to the Agent tool's listing.
- Hooks and settings: all levels (managed → user → project → local). Note which hooks exist and what they enforce, and any managed model/version policy (
availableModels+enforceAvailableModels,requiredMinimumVersion).
The session you are in is a specimen: the listings injected into your own context are the ground truth of what loads.
Step 2: Quantify before judging
Numbers first; opinions after. The unit that matters is tokens-per-session-forever, and prefix size also costs prompt-cache build time on every cache miss.
- Skill descriptions: sum frontmatter
description+when_to_usechars across each scope, divide by ~4 for tokens. One pass:
python3 - <<'EOF'
import os, re
root = os.path.expanduser('~/.claude/skills') # repeat for project + plugin cache dirs
total = 0
for name in sorted(os.listdir(root)):
p = os.path.join(root, name, 'SKILL.md')
if not os.path.isfile(p): continue
m = re.match(r'^---\n(.*?)\n---', open(p, encoding='utf-8', errors='replace').read(), re.S)
fm = m.group(1) if m else ''
total += sum(len(v) for _, v in re.findall(r'^(description|when_to_use):(.*?)(?=^\w|\Z)', fm, re.S | re.M))
print(total, 'chars ~', total // 4, 'tokens/session')
EOF
- Instruction files:
wc -lon every always-loaded file. The repo's own cost model applies (shorter is better-read; loaded local files count too). - Ask the user to run
/contextfor the authoritative split. Your estimates bound it; the command confirms it.
Step 3: The setup checks
- Self-consistency. Diff what the harness's documentation claims against what the harness does. Classic finds: a loaded file that says it is not loaded; a dateline pinned to a version several releases back; a "this is enforced" line with no enforcement; a skill or command body that invokes or assumes another skill (
/X) — fragile by construction (the target can be absent, disabled viadisableBundledSkills, or set todisable-model-invocation) and a dead cross-reference that reads as working capability when/Xis not in the inventory at all. This flags the presence of the reference, not the quality of the body — authoring skills to stand alone is the forge's remit. The instruments for this diff are live commands, never the harness's word for itself:/contextis the authoritative record of what loaded and from where;/skills,/hooks,/mcp,/permissions,/status, and/doctoreach resolve one surface; a fault that won't localize bisects withclaude --safe-mode(all customizations off, v2.1.169+) or a cleanCLAUDE_CONFIG_DIR, reintroducing surfaces one at a time. The canonical page for this battery, settings precedence, and the common-misconfiguration table (hook matcher syntax,~/.claude.jsonvs~/.claude/settings.json, skill folder layout,mcpServersin the wrong file) iscode.claude.com/docs/en/debug-your-config— fetch it at audit time rather than trusting this paragraph's snapshot;code.claude.com/docs/llms.txtindexes every other page a claim can be verified against. - Duplication across scopes. The same artifact listed twice pays twice: a project symlink and a user-scope plugin copy of the same skill; two plugins shipping the same command under different names; a personal skill shadowing a project one (personal wins silently).
- Enforcement parity. Every "always", "never", and "run X before Y" sentence in the instruction files should map to a hook, a CI gate, a permission rule (
permissions.deny, now matching tool parameters too, e.g.Agent(model:opus), v2.1.178), a managed setting (a "we standardize on model X" line is enforced only byavailableModels/enforceAvailableModels, not prose), or a conscious decision to stay manual. A promise with no mechanism is a request, not a guarantee. Parity starts one step earlier: a guardrail has to be a fact of the repo before its mechanism matters.git statusandgit diffevery instruction file and hook in the chain, because a guardrail that exists only in the working tree (git log -S"<its key phrase>"returns nothing) is one checkout away from not existing and has reached no teammate, other machine, or plugin install. The classic find: a prior session writes the fix for an incident into CLAUDE.md and never commits it, so the audit reads standing policy where git holds nothing. And tier what stays prose-only: an order the model demonstrably read and still skipped (the owner had to re-issue it in session) has already failed as prose, because prose is re-weighed against everything else in context every session; it leads the hook/gate candidates rather than settling as a conscious stay-manual. - Scope discipline. Each artifact should live at the narrowest scope that serves it. Personal-scope skills used in one domain belong in a toggleable plugin or a project; product plugins needed in some repos should be per-project
enabledPluginsentries, not global; a fleet of client-work skills in~/.claude/skills/taxes every repo on the machine. - Routing effectiveness (provisional — one directional validation 2026-07-27; see CHANGELOG). Applies wherever the repo routes agents to other resources: a doc fleet (subsystem docs routed from an AGENTS.md table or equivalent), or instruction-file rows steering the model among installed skills and MCPs. Skip it for single-doc repos with no fleet routing. The question is whether the routing actually reaches the agent rather than living as good intentions:
- Dead rows. Every routing row points to something that still exists: a doc at that path, a skill or MCP under that exact name. Plugin renames silently orphan
old-prefix:skillreferences, so check the prefix too. A row naming a moved, renamed, or deleted target routes nowhere, and is worse than an absent row because it reads as coverage. - Invocation-style fit. Skill-routing rows assume the model picks among collisions autonomously. Where the owner invokes those skills manually, picker rows are dead weight; what earns its place there is the misfire guard — the row, or better the path-scoped rule, stopping an autonomously-triggered skill from acting on the wrong slice.
- Two-level routing. Each system doc opens with a greppable header (
Purpose / Read when / Key constraints / Relevant paths / Last verified) so an agent can confirm the doc applies before paying to read it. A fleet routed only by a top-level table forces whole-doc reads just to check relevance. - Mechanical backing. The highest-value rows are duplicated down into mechanical surfaces (path-scoped rules, skill descriptions, hooks). A routing table whose only enforcement is a prose "read the router first" instruction is a request, not a guarantee — the same failure as enforcement parity one level up, because the model won't reliably run a preflight.
- Staleness. Each doc's
Last verifiedsits within a sane window; a fleet of confidently-worded but months-stale docs is the doc-fleet form of the frozen-fact trap.
- Dead rows. Every routing row points to something that still exists: a doc at that path, a skill or MCP under that exact name. Plugin renames silently orphan
Step 4: Probe the assembled behavior when the harness changed
After a substantial harness change, or when individually sound artifacts produce incoherent sessions, test the system as installed. This is conditional because a fresh live run costs tokens: reuse a recent representative transcript already in the audit's scope when it exercises the changed seams; otherwise state the proposed job, tools, token cost, mutation boundary, and external side effects, then get the owner's approval before launching one or two fresh sessions.
Choose one or two high-traffic jobs that cross more than one surface — for example an instruction file plus a skill plus a tool or hook — and state the expected output and required human boundary before running them. Default to replay, a read-only job, a finished real job, or a disposable copy. A composition probe never mutates active work, another repo, machine scope, or an external system without explicit approval for those exact side effects; when no safe representative probe exists, report composition as unverified. Use the complete installed harness, not an isolated artifact fixture. Inspect the trace and result together:
- Which instructions and context were loaded or supplied, and which artifacts and tools were invoked?
- Did two surfaces compete, duplicate ownership, or issue contradictory guidance?
- Was intent or state lost between a trigger, a tool call, and the next surface?
- Did the system pause, ask, or stop at the intended human decision point?
- Was the final work better against the job's objective, not merely compliant with each component?
Report the observable composition path and the first seam that failed. A transcript cannot prove which loaded instruction causally changed hidden reasoning; leave that unknown unless a controlled comparison establishes it. An artifact passing alone does not clear this check; the unit of quality is the installed system's behavior. Keep this at the interaction boundary: reviewing the expertise inside one skill body still belongs to that artifact's forge.
The CLAUDE.md chain, read as intent
CLAUDE.md is the always-on spine, the most-paid surface and the one that rots fastest, because it sits next to the code it describes. Give each file in the chain a closer read than the cost pass, against the job it alone can do: transmit what the code can't tell you. Flag, in the file:
- No code-authority clause. The file should state that when it and the code disagree, the code wins, and that a contradiction means this file is stale, flag it, not that the agent should obey the doc. This is the single highest-leverage line a CLAUDE.md can carry: without it, every sentence that has quietly gone stale is still read as current instruction. Two scopings keep the clause from overreaching. Code is authoritative about what is, never about what's good — read unscoped, "code wins" licenses conforming to entrenched drift instead of flagging it, on top of a harness already instructing the model to match surrounding code. And normative documents run the other way: when the contradicting file is an ADR or spec recording decided intent, the drift may indict the code, so the finding is investigate and ask, never a silent rewrite of the requirement to match the implementation.
- Restated current state. Any line restating stack, dependencies, scripts, file layout, or "we use X" where X already lives in a manifest or the source pays tokens to go stale on the next commit. What survives a refactor is intent, spirit, durable traps, and pointers. Grep the file's version numbers and dependency names against the actual manifests; each match is a line the code already owns and the doc should drop.
/doctorautomates part of this find from v2.1.206: it flags checked-in CLAUDE.md content Claude can derive from the codebase and proposes the trim. - Frozen facts that should be discovered. A value that lives at runtime (a token file, a config, a schema, a vendored doc set) belongs behind a read-first instruction ("read
globals.cssfor the theme before writing classNames"; "read the docs innode_modules/…before coding"), not pasted as today's snapshot. The discovery survives every project the snapshot dies in. - Bare directives. A rule the model can't generalize from ("Y before Z", no reason, no condition) underperforms a condition-shaped, reasoned one ("when X genuinely needs Y, do Z, because …"). The model generalizes from a why where it can't from a bare MUST.
- Unverified mechanisms. An intent voice does not protect a wrong mechanism inside it: check each concrete claim (a path, a script name, a flag) against the filesystem it names.
- Bloat. Compliance dilutes as rules and examples accumulate. Count them and report the counts; size is judgment for the owner, not a threshold to enforce.
Finding and quantifying these gaps is this skill's job; authoring the fixes (voice, the Why pattern, the goes-elsewhere table) is the forge's CLAUDE.md and rules remit.
Step 5: The findings report
The report is the audit's deliverable, and nothing in it is applied yet. Everything at machine scope is inventory-and-report only: anything under ~/.claude/ (personal skills, user CLAUDE.md/settings.json, skillOverrides, user-scope hooks), enterprise or managed settings, global enabledPlugins, and anything that changes another repo. Never edit it, never stage an edit, never ask "shall I apply this?"; the audit's job at machine scope ends at the observation the owner acts on herself, plus any project-scoped counterweight the contract allows. This holds even when the finding is obviously correct and the fix is one line, because the owner owns her machine. It is a hard boundary, not a default to weigh.
A cost is not yet a verdict. Before any finding recommends removing or disabling a capability (a skill, plugin, MCP server, or hook), weigh whether the owner uses it; a used surface is reported at its cost, never cut, and a disable becomes a recommendation only where she confirms she does not reach for it. An unrequested disable is the harm the audit exists to prevent, not a saving it delivers.
Every finding is quantified and lands in one bucket:
- Proposed is for current-repo edits: content moves (splitting a loaded file), this repo's
.claude/settings and hooks, project-scope plugin toggles — including the project-scoped counterweight to a machine-level problem (the global plugin is the owner's to remove; disabling it for this repo in.claude/settings.local.jsonis a project edit and belongs here). Carry the exact change (file, edit, token saving) so a go-ahead is all that's needed. - Reported is for every machine-scope and cross-repo finding. State the exact edit the owner can make herself (file, change, token saving) and stop. No staged file, no apply prompt, no question that reads as an offer to apply — and no go-ahead changes this.
- Held is for what fails the bar: would not change what the user or agent actually does.
Shape the report so the owner can act on it, not just read it:
- The first line is the single highest-value item and what it buys — an approvable action, not a summary of the audit.
- Findings are numbered and ranked by impact. Each is one bounded item: what, where, the number that proves it, the exact remedy, the bucket.
- Cap the ranked list at five; everything else goes under a separate "later" heading. Five ranked beats fifteen unranked.
- End with exactly one question: which Proposed items get the go-ahead.
- On any later turn, restate where things stand (applied, pending, reported) rather than assuming the report is remembered.
Step 6: Apply on the go-ahead
Apply only what the owner approved, only inside the project directory, exactly as proposed — a go-ahead on the report is not consent to improvise adjacent fixes, and a partial go-ahead ("just 1 and 3") leaves the rest untouched. Note the reversal where each change lives ("flip this back by..."). The auto-mode classifier gates harness self-modification (this repo's hooks, settings.local.json) even after a yes; surface the change and let the prompt through, never route around a denial. Close by restating what applied and what remains.
Anti-patterns
- Vibes without counts. "Your CLAUDE.md looks clean" is not an audit.
- Editing during the audit. The tell is a "quick fix while I'm here" mid-inventory. Invocation is consent to look, never to change; every edit waits for the report and the go-ahead, however small and however obviously right.
- Recommending a cut you never use-tested. Flagging a skill, plugin, or server for removal on token cost alone, without weighing whether the owner reaches for it. The description budget is real and the unchosen marginal artifact taxes every turn, but a used one out-earns its cost by being used; report its cost, do not charge it as waste.
- Bulk-disabling without a reversal note. Every disable gets a one-line "flip this back by..." where the change lives.
- Auditing only the visible skill list. MCP instruction blocks and agent rosters are quieter and often bigger.
- Declaring composition from isolated passes. Individually valid skills, hooks, and rules can still compete or lose context when assembled. Trace at least one representative cross-surface job after a substantial change before calling the system coherent.
- Drifting into skill-body content review. Whether a skill's guidance is expert-grade is the forge's job; this skill audits the setup (including the always-on CLAUDE.md chain that frames it), not the quality of individual artifact bodies.
- Offering to apply machine-scope fixes. The tell is a question like "which of these should I prepare exact changes for?" aimed at
~/.claude/, user settings, or global plugins. Report them; do not stage or offer them. The only edit an audit may propose against a machine-scope problem is the project-scoped counterweight in this repo's.claude/.