agentleFS
AttemainioAttemainio/dotnet-toolkit/skills/dotnet-consistency/SKILL.md

dotnet-consistency

Skill2 starsChanged 53 days agoMITView on GitHub

Use when auditing this plugin's own docs, skills, agents, rules, hooks, CLAUDE.md and README.md — three axes at once. (1) Do they match the actual MCP tool implementation under src/DotnetToolkit.McpServer? Run after adding, removing, renaming, or changing the signature/return shape/[Description] of a tool, or after adding or editing a hook. (2) Do we still follow official Claude Code and Claude API guidance — "are our tool descriptions findable", "does tool search actually find every tool", "is CLAUDE.md too long", "is anything always-loaded that shouldn't be", "check we follow Claude's guidelines", "refresh the Claude docs links". (3) What has drifted since a baseline — "what has drifted since <commit>", "what did we change and forget to document". Also owns the install-procedure audit — "audit the init skill", "does what we ship actually reach a consuming repo", "would uninstalling leave anything behind". Reports or fixes exact drift, file by file.

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 0 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    All in ${CLAUDE_PLUGIN_ROOT}/skills/dotnet-consistency/, read on demand — a run that only needs drift detection should not pay for the rest.

    line 27
  2. Very specific:

    Not every file under Tools/ is a tool group.

    line 56
  3. Very specific:

    1. Harness compliance: Read harness-compliance.md and run §A–§G.

    line 65
  4. Very specific:

    Before running it, apply the staleness gate: if claude-docs.md's last-verified is older than its refresh-window, or the user asked to …

    line 69
  5. Very specific:

    6. Hooks and launch path: All seven hooks are hook <name> subcommands of the published server binary, in src/DotnetToolkit.McpServer/Hooks/ …

    line 178
  6. Very specific:

    Read those with get_symbol (not grep — a tree grep here would only earn an advisory note from guard-cs-bash-read, not a denial, but …

    line 186
  7. Very specific:

    7. Internal drift: Read drift.md and run it. This is the step that starts from *what changed* rather than from a file list: …

    line 232

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Auditing plugin self-consistency

This plugin teaches Claude to use its own MCP tools through a scattered set of hand-maintained files — skills, agent definitions, rules, hooks, docs/*.md, CLAUDE.md, README.md. None is generated, so any of them can silently drift the moment something changes and the doc edit is skipped. This is the audit pass that catches that, run as its own task rather than trusted to unrelated work.

Three sources of truth, and which one wins

The code is not the only ground truth, and treating it that way is how a defect gets locked in: the doc gets rewritten to match code that was itself wrong.

  • Code is ground truth for facts. Tool names, signatures, arguments, defaults, return shapes, error codes, what a hook actually dispatches. A doc that disagrees here always loses.
  • Official Claude documentation is ground truth for design. How a tool gets found, what is always loaded and what is not, what a skill / agent / rule may contain, the harness's own limits. Code that disagrees here loses — and the result is a CODE FINDING, not a doc edit.
  • Internal documents are ground truth for nothing. They are claims, checked against both.

The three reference files

All in ${CLAUDE_PLUGIN_ROOT}/skills/dotnet-consistency/, read on demand — a run that only needs drift detection should not pay for the rest.

FileOwnsRead by
claude-docs.mdthe official Claude doc URLs, their must-remember shortlists, and the staleness gateStep 1
harness-compliance.mdthe by-section checklist §A–§G with every threshold and its citationStep 1
drift.mdthe baseline, the evidence order, and the drift-sensitivity rankingStep 7

Step 0 — enumerate the actual tool surface

Get the current, complete list from the source — don't trust any doc's tool list, including this skill's own examples; that is exactly the kind of claim being audited. Not grep: the guard-cs-bash-read hook flags a shell read of a solution .cs file as advisory (allowed, not blocked, since 2026-08-21) rather than denying it, but get_symbol is still the right call regardless of what the hook does — this is a symbol query, not a text search.

get_symbol(symbols: ["ContextTools", "FlowTools", "GraphTools", "HistoryTools",
                     "RenameTools", "MetricsTools", "ServerTools", "GuardTools"], include: "members")

Each [McpServerToolType] class's public methods are its tools, one per method, with every parameter and default. Confirm the class list itself first with search_index(query: "Tools", pathPrefix: "src/DotnetToolkit.McpServer/Tools"), so a new tool group is caught rather than assumed away — a new Tools/*.cs file is itself a finding (Step 7). That search is also what keeps the list above honest: it is an example, and an example of the thing being audited goes stale exactly like any other doc claim.

Not every file under Tools/ is a tool group. ToolTelemetry.cs, ResponseGuard.cs and VocabularyHint.cs carry no [McpServerToolType] and are shared internal helpers; they belong in docs/design/architecture.md's Tools/ table, not in any tool list. Check the attribute, not the folder. A search hit's modifiers column separates them at a glance without a second call: a tool group renders ps and an A1 in shape (the [McpServerToolType] attribute), a helper renders is with no A.

The audit, step by step

1. Harness compliance. Read harness-compliance.md and run §A–§G. First, because it is the only axis that can produce code findings, and because a guidance change invalidates a previously-clean result on every other axis.

Before running it, apply the staleness gate: if claude-docs.md's last-verified is older than its refresh-window, or the user asked to refresh the links, run that file's refresh procedure and update the shortlists before checking anything against them.

2. Implementation. For each tool from Step 0, read its method body (not just the [Description]) — get_symbol for its declarationSites, then a ranged Read of that span — and confirm what it actually accepts, returns, and errors on. Docs get audited against this, not against their own prior text.

3. [Description] attributes vs. documented behavior and return shape. Compare each tool's [Description] (on the method and on each parameter) against:

  • docs/tools/<tool>.md — its "When to reach for it" guidance, arguments, defaults, the example call/response, and its Next steps footer. If you can, call the tool with the documented example arguments and confirm the response still matches what's printed; an example that no longer matches the current return shape is worse than no example.
  • Any wording that has drifted from what the code now does — e.g. a default named in the attribute that the method body no longer honors.
  • Whether it works as a search target — that criterion, its thresholds and the live probe are harness-compliance.md §B and §C, already run in Step 1. Don't re-derive them here.

4. Skills vs. tool set. For skills/dotnet-read/SKILL.md, skills/dotnet-write/SKILL.md, skills/dotnet-explore/SKILL.md, skills/dotnet-review/SKILL.md and skills/dotnet-architecture/SKILL.md, confirm every tool they describe still exists (Step 0) with the arguments they claim, and that every tool relevant to that skill's subject actually appears in it — a tool added to Tools/*.cs that fits an existing skill's scope but isn't mentioned there is a finding, not just a missing doc row.

Every one of the 17 tools must be named by some skill, because .claude/rules/dotnet-index.md names none. A tool named by no skill is unreachable: nothing always-loaded points at it, and free-text ToolSearch does not reliably find it (§C). Split by side — retrieval and the server/meta tools in dotnet-read, rename_symbol in dotnet-write — with workspace_status and reload_workspace legitimately in both, since each skill's step 0 depends on them, and set_hook_guards in dotnet-performance alone, its only sanctioned caller.

set_hook_guards is the one deliberate exception, owned by dotnet-performance alone. It is not missing from dotnet-read; it is kept out. The tool suspends the guards that make the rest of the plugin load-bearing, so naming it in the skill every read task loads would advertise the off-switch to every session — including the ones the guards exist for. Reachability is satisfied because dotnet-performance names it (for its strict variant only — the default procedure calls it nowhere, because Claude Code's auto-mode classifier denies the call as self-modification and the meter's wholeFileCsReads count answers the same question without it), and that skill is the only sanctioned reason to call it. If a future audit finds it added to dotnet-read or to the always-loaded rule, or back in dotnet-performance's default steps, that is the finding — not its absence there.

5. Every instruction/guideline file that tells a caller to use the MCP tools. Check each still lists every tool from Step 0, with nothing stale (a tool it describes that no longer exists) and nothing missing (a tool that exists but appears nowhere in it):

FileWhat it must carry
docs/tools/<tool>.md (one per tool, plus server.md)when to reach for it, arguments, one real example call/response, and a Next steps footer naming what to call with what it just returned. Every tool from Step 0 has a file, and no file names a tool that no longer exists — the filename is the reachability contract now that dotnet-index.md derives it (<tool>.md, the five server/meta tools sharing server.md) rather than tabulating it, so a manual named anything else is unreachable no matter how good it is. Each tool's [Description] should also name its own file. These carry the per-tool mechanics that must not move into the always-loaded router
CLAUDE.md's "Non-negotiable workflow" and "Where to read what"that they still route to .claude/rules/dotnet-index.md and the maintainer-facing files rather than carrying a copy of any table. A per-tool table, architecture rundown, skill catalog, or size policy reappearing here is drift — each was moved out deliberately (harness-compliance.md §A)
docs/design/architecture.md's Tools/ tableevery Tools/*.cs file and the tool names it groups — a new file (Step 0) needs a new row. Also its Id-namespace table, subsystem list, and "Changing the tool surface" consequences (positional test callers, Contracts/Contract.cs bump)
.claude/rules/dotnet-index.mdthe only always-loaded rule — here and copied verbatim into consuming repos by init, so drift ships and is paid by every session and every subagent. What it may and may not contain is harness-compliance.md §E, and §D owns its size. It is a pure skill router: check that it names no MCP tool at all (one appearing is the finding), that its rows still match the skills that exist (one per agent-launching or always-needed skill: read, write, explore, review, architecture), and that the "agents are launched by skills" mandate survives. A tool table, a standards table, a limitedBy section or a pluginRoot join reappearing here is drift — each was moved out deliberately
standards/index.mdthe shared standards routing table. It lists exactly the files present in standards/; its stated dotnet-code-review core matches agents/dotnet-code-review.md's six exactly; every "When" cell states an observable property of the code rather than a topic; and the pluginRoot join matches what workspace_status actually returns, naming exactly one location per file — a per-repo override tier reappearing is the drift to flag
skills/dotnet-read/SKILL.md(a) it names every retrieval tool from Step 0, each with a Manual: pointer whose filename is derived (<tool>.md, the five server/meta tools sharing server.md); (b) its per-tool "Answers to" lists stay questions, never argument grammar — that is the manual's job; (c) it owns the cheap-route table and the limitedBy/TOON response conventions, which must not drift back into the always-loaded rule; (d) its step 0 mandates workspace_status before any read, and the ${CLAUDE_PLUGIN_ROOT}-is-not-expanded warning is intact
skills/dotnet-write/SKILL.md(a) its pre-edit standards step defers to standards/index.md rather than re-listing the files; (b) it resolves standards as <pluginRoot>/standards/<name>.md via workspace_status, with no override tier; (c) it owns the write-decisions — when to dry-run, when to amend versus rebuild, the definition of done, raising .editorconfig severity with the user rather than unasked — which were moved out of the always-loaded layer and must not drift back; (d) its step 0 mandates workspace_status before an edit, and its "How the index follows your edits" section matches what refresh-cs-files actually does (silent on success, a note only for a new/deleted file, a queued refresh, or an unreachable server); (e) it states Edit/Write as the write path and rename_symbol as the one tool-made edit, with dotnet build as the gate — a validating or compiling tool reappearing in its text is the drift to flag. Its two known duplication risks (standards list, write-time checklist) are harness-compliance.md §A
skills/dotnet-explore/SKILL.mdit is the only sanctioned launcher of the dotnet-explore agent. It must check workspace readiness before spawning, must state that the agent reads no .cs text (it reports locations; the caller reads), and must not restate the agent's own router — agents/dotnet-explore.md is self-contained and authoritative
skills/dotnet-review/SKILL.mdit does not claim to inject a Standards root: into the spawn — the agent resolves its own pluginRoot from its own workspace_status call (§below), so the skill's job is only to state each instance's scope/mode/focus, never a path. It must also check workspace readiness before spawning: launching parallel instances against a degraded workspace is a parallel waste, and it points at standards/index.md rather than restating the table
every file in standards/every MCP tool named in them (e.g. get_references in testing.md's calibration, get_symbol in xml-documentation.md's) still exists with the described behavior; cross-file pointers still resolve; none offers a per-repo override path — that tier was removed, and a reintroduced sentence would promise a mechanism nothing implements. The no-frontmatter invariant is harness-compliance.md §G
skills/dotnet-init/SKILL.mdthat it still copies .claude/rules/dotnet-index.md verbatim rather than embedding its own tool table or standards list. Also the "what is deliberately not written" table and the uninstall list: every asset the plugin ships is in exactly one of write / not-written / uninstall, and the write and uninstall lists name the same files
docs/install/audit.mdthe install-procedure audit this skill runs in Step 5b (maintainer-facing; the consumer never reads it). Its four-mechanism inventory must cover every top-level directory the plugin actually ships (skills/, agents/, hooks/, docs/, docs/tools/, .claude/rules/, scripts/, .mcp.json), and its reachability scenarios must resolve to files that exist
docs/install/{install,verify,uninstall}.mdthe three paths dotnet-init routes to. They name the files init actually writes (the settings allowlist, install.json, and .claude/dotnet-toolkit/.gitignore) and no file it doesn't, and the skill's router table points at all three. The three must agree on the count: a file added to install.md's table and not to verify.md's presence check is installed but never verified
.claude/dotnet-toolkit/.gitignorecopied verbatim into consuming repos by init, so it is a mechanism-2 file like the rule. Check it still covers every directory the skills write reports into — a new report directory added to a skill without a line here is committed by the next git add -A in every consuming repo — and that it still leaves install.json, config.json and cache/ alone
skills/dotnet-selfeval/SKILL.md + analyses.mdthe efficiency probe matrix. Its Step 2 families still cover every tool from Step 0; the tools it lists as recording no telemetry (ping, workspace_status, set_output_format, reload_workspace, get_retrieval_metrics, set_hook_guards) are still exactly the ones with no ToolTelemetry.Record call, and it still tells the run not to probe set_hook_guards by calling it — a suspension mid-evaluation would let the rest of the run bypass the very tools being measured; its taskId/taskIds/groupBy:"task" recipe still matches MetricsTools/MetricsReader. A tool newly instrumented but still listed as unmeasurable understates what the evaluation can see
agents/dotnet-code-review.mdthe agent's complete, self-contained instructions. tools: frontmatter matches Step 0's read-side subset (nothing stale, still excluding get_project_graph/detect_circular_dependencies, withheld as out of a scope slice's reach); every tool it names in Process, evidence bars and Boundaries is granted there and behaves as described; its standards core and per-aspect fold-ins resolve to real standards/ filenames, reached through the pluginRoot it resolves itself from its own workspace_status call and never by constructing a ${CLAUDE_PLUGIN_ROOT} path itself; the no-root fallback still reports standards-derived aspects as not-assessed rather than reviewing from memory; it still requires the Standards: line; and it has not re-acquired a skills: grant or a directive to read docs/design/agents.md — both removed to hold the per-instance token baseline down
agents/dotnet-explore.mdthe navigator's complete, self-contained instructions. Its router must name no write tool as callable, and three properties are load-bearing (rationale in docs/design/agents.md, not here): no writer and no memory: key in tools:, Read whitelisted to docs/tools/<tool>.md only, and no .cs reads at all
skills/dotnet-architecture/SKILL.mdthe only sanctioned launcher of dotnet-architecture-review. It points at skills/dotnet-review/SKILL.md's Step 0 for workspace readiness rather than restating it, briefs each instance with scope, pluginRoot, mode, the consumer assumption and recorded decisions, and sorts findings by action class (auto / approve / ask) without ever applying a removal itself
agents/dotnet-architecture-review.mdthe system-level reviewer's complete, self-contained instructions. tools: is the read-side set plus get_project_graph/detect_circular_dependencies (solution shape is its subject, unlike dotnet-code-review's slice) and ToolSearch; every tool it names is granted and behaves as described; its standards come from standards/index.md via the pluginRoot it resolves itself, never a restated trigger table; the capability rule (unreferenced public members classified, never condemned by a zero count) and the framework-invocation check before any zero-caller claim are intact
docs/design/agents.mdcovers every agent; human-facing only — no agent is told to read it. It must not contradict the agent file (authoritative); its tool-grant and token-budget sections match the agents' actual frontmatter and loading rule; every tool it names still exists
docs/design/hooks.mdmaintainer-facing design notes; nothing routes to it. Describes exactly the hooks hooks/hooks.json registers and the behavior they implement — matchers, allow/deny cases, fallback chain
README.md's Features tableevery tool from Step 0 appears in some row; no row names a tool that no longer exists

5b. Consumer reachability — does the plugin work out of the box? Steps 2–5 check that the files describing the tools are accurate. This checks they are reachable from a consuming repo, where this repo's CLAUDE.md does not exist. Every operational instruction must live in something that ships: the one rule init copies (.claude/rules/dotnet-index.md), a skill, an agent file, or a docs//standards/ file reachable by ${CLAUDE_PLUGIN_ROOT} path from a skill — rules and agent files must not depend on that variable expanding, which is why agents/dotnet-code-review.md resolves its own pluginRoot from its own workspace_status call instead of expecting a path handed to it.

The install procedure is half of this step. dotnet-init is prose, hand-maintained, and describes a file set that grows every time this plugin gains a tool, doc, skill, or standard. When it falls behind, the failure is silent in both directions: an asset ships but never reaches the consumer, or the uninstall instructions leave files behind that keep steering a repo that no longer has the plugin. Read docs/install/audit.md and run it. Two of its findings are hard errors worth naming here because both have shipped: a ${CLAUDE_PLUGIN_ROOT} path in a copied rule, and any claim that mechanism-1 assets need a repo-local install or cleanup step.

Then two sweeps, both cheap:

  • This repo's CLAUDE.md, paragraph by paragraph. For each instruction, decide: is this about maintaining the plugin (correct — it belongs only here), or about using the tools? Anything in the second category must also exist in a shipped file, with CLAUDE.md carrying a pointer rather than a second copy. The write-path discipline is the canonical example — the "Edit/Write are the write path, the hook re-indexes, dotnet build is the gate" argument lives in the rule and dotnet-write, never in CLAUDE.md, because a consumer never sees CLAUDE.md.
  • The maintainer's memory directory (~/.claude/projects/<repo-slug>/memory/, indexed by its MEMORY.md). Read the index, then each entry, and sort every one into: (a) operational for consumers → must be embedded in a shipped file; (b) operational for this repo only → belongs in CLAUDE.md or .claude/rules/; (c) personal or environment-specific → belongs in neither, and is correctly only in memory. Memory is user-local and does not travel with the plugin, so anything in (a) or (b) that exists only there is a finding — silently absent for every other user, and for this repo after a memory reset.

Report each finding as: the memory or CLAUDE.md paragraph, its category, and the shipped file that should carry it. Do not copy a category-(c) fact into a shipped file to close a finding — categorising it correctly is closing it.

6. Hooks and launch path. All seven hooks are hook <name> subcommands of the published server binary, in src/DotnetToolkit.McpServer/Hooks/ — HookCli.cs dispatches, the GuardCsRead/GuardCsBashRead/CsFileRefresh/CsWriteChecklistHint/ToolCallMeter files carry the behaviour, and four more have no hooks.json entry of their own: CsFileMembership.cs/ BashCommandScanner.cs (shared guard logic, including the ranged-read recogniser), GuardSuspension.cs (the off-switch HookCli reads before dispatching the two read guards, written by set_hook_guards) and ControlClient.cs (how refresh-cs-files and meter-tool-call both reach the running server, with the command words in Control/ControlCommands.cs). Read those with get_symbol (not grep — a tree grep here would only earn an advisory note from guard-cs-bash-read, not a denial, but get_symbol is still the right call), plus hooks/hooks.json and .mcp.json:

  • Does each guard's advisory text still name the correct tool(s) and procedure (get_symbol plus a ranged Read for the read guards, reload_workspace(scope: "all") for the refresh hook's unreachable-server note)? It is read at the exact moment a caller is nudged — a stale one teaches the wrong fix at the worst moment. And do both read guards still pass a ranged read silently in every mode (Read with offset/limit; sed -n 'a,bp', head -n, tail -n +N)? A guard that notes a ranged read is arguing against the route the skills recommend.
  • hint-cs-write-checklist owns the write-time checklist, matching Edit/Write/ NotebookEdit. Its text must still match the standards it summarizes (security.md, testing.md), and it must stay once-per-session and fail-quiet — a version that fires on every edit, or that denies, is a finding.
  • refresh-cs-files is the PostToolUse hook that makes the index follow edits. It must stay silent on success, send every written .cs path (from Edit/Write/NotebookEdit/apply_patch input and from Bash write shapes) to the server's refresh command, ask for a rescan on a git verb, and answer with a note only when a file was added/deleted (reload started), a refresh is queued, or the server was unreachable.
  • meter-tool-call is the one hook matching every tool ("*"), and the one exempt from GuardSuspension on purpose. It observes rather than withholds, and a guard suspension is asked for precisely in order to measure the unguarded route — a version that honours suspension silently produces a benchmark with half its data missing, which is the finding. It is also the hook that records wholeFileCsRead on every call, the count dotnet-performance reads per probe instead of switching guard state; the predicate is WholeFileCsRead.Matches, shared with the two read guards so the count and the advisory agree on what a whole-file read is — a version where they diverge is the finding. It must also stay fail-open-and-silent and keep reporting over the control channel rather than opening the store itself: a hook process has its own ambient session id, so a row it wrote directly would be invisible to every read.
  • Does hooks/hooks.json name subcommands HookCli actually dispatches, with matchers (Edit/Write/NotebookEdit/apply_patch/Read/Bash) matching docs/design/hooks.md and docs/design/architecture.md's "Packaging" section? The shell-free and output-cap invariants are harness-compliance.md §G. scripts/ holds developer conveniences only; anything new there or in Hooks/ unmentioned by docs/design/hooks.md or "Packaging" is a Step 7 finding.
  • Matchers key on tool name, not on which agent calls, so they fire for subagents too. For dotnet-code-review: (a) its tools: list never grants Edit/Write/NotebookEdit — memory: project makes the harness grant them anyway, which is why Boundaries carries the weight; (b) its Process step 2 still locates with search_index/get_symbol and reads with a ranged Read over declarationSites, treating a whole-file Read as the scope-mode exception rather than the default — its own text (checked in Step 5's table) must say that a ranged read draws no note and a whole-file one only advises. For dotnet-explore, whose own file bans Read on .cs outright with no hook backstop behind that ban, a Read of a .cs file appearing in its transcript is itself the drift to report — the file's own instruction, not any hook, is what should have stopped it.

7. Internal drift. Read drift.md and run it. This is the step that starts from what changed rather than from a file list: get_semantic_diff against a baseline, then git log for the recorded intent and for everything the semantic diff cannot see, checked against the drift-sensitivity ranking. It is how a shipped-but-undocumented tool gets found — nothing in a per-file check ever will, because the files that should mention it are internally consistent.

8. The skills' own instructions. Once Steps 1–7 have surfaced concrete drift, the fix usually touches a skill body, not just a table row — e.g. a new tool needs a section in dotnet-read or dotnet-write (whichever side it belongs to), a row in that skill's cheap-route table if it displaces an existing route, and its own docs/tools/<tool>.md. It needs nothing in .claude/rules/dotnet-index.md, which names no tools: a new row there is only warranted by a new skill. Update the skill body, not only its tool list, so a caller reading the skill gets the same guidance a caller reading the code would.

9. CLAUDE.md and README.md last. The two files a fresh session or a new user reads first, so they should reflect the already-corrected state of everything above rather than being patched independently of it. Update CLAUDE.md per Step 5's table, then README.md's Features table and prose.

Output format

Report drift the same way dotnet-code-review reports findings — concrete and file-anchored, not a narrative:

  • File:line of the stale claim.
  • What it claims vs. what is actually true, naming which source of truth decided it — the code (Steps 0/2) or the official guidance (claude-docs.md, via Step 1).
  • Exact fix — the replacement text or the specific file to add a row to. Point at the file; don't describe the fix in the abstract.

A finding driven by guidance rather than by code, where the code is what must change, uses a distinct form so it is never mistaken for something this skill already fixed:

CODE FINDING — src/…/Tools/X.cs:NN · guideline: harness-compliance.md §B · current: <measurement or text> · required: <threshold> · proposed replacement: <exact text> · apply via: dotnet-write → Edit, then dotnet build.

Group findings by file, in Step 5's table order, then hooks, then CLAUDE.md/README.md last, with CODE FINDINGs collected together at the end. State the baseline Step 7 used. If a section is in sync, say so in one line — don't manufacture findings to justify the run.

Fixing vs. reporting

  • Doc findings: fix them yourself, in Step 1→9 order. Every such fix is to a non-.cs file, so no hook fires and no build is needed.
  • CODE FINDINGs: report only, never apply. This skill does not edit .cs, even when the fix is a one-line attribute change with no behavior impact — an audit that can change the tool contract can no longer be run freely. Hand it off with the exact replacement text; the user or a follow-up dotnet-write task applies it.
  • Never silently skip a step because "nothing looks wrong there" — state it was checked and came back clean. A skipped step and a clean step read identically in a report, and only one of them is true.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.