From rules-review
Check code changes for .claude/rules/ compliance. Use this skill when you need to verify that code changes follow project coding rules, whether as part of dev-workflow or standalone. Triggers on: rule compliance check, rules review, verify conventions, check coding standards. Best suited for hard rules (naming, imports, placement, explicit prohibitions); intent-style rules are checked on a best-effort basis.
How this skill is triggered — by the user, by Claude, or both
Slash command
/rules-review:rules-reviewThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Check code changes for compliance with `.claude/rules/` rule files.
Check code changes for compliance with .claude/rules/ rule files.
/rules-review --base-commit <sha> # Check diff from specified commit
/rules-review # Check diff from HEAD~1
An optional Model: value — one of the model ids the current Agent tool's model parameter accepts (sonnet / opus / haiku / fable as of this writing; check the tool's live schema loaded in the current session rather than this fixed list, since Anthropic adds new model families over time) — may also be passed as a natural-language argument — an independent optional field (not part of a fixed-arity mode gate). When present and valid it is applied as the model parameter on each reviewer Agent dispatch in §5 (a caller such as dev-workflow uses this to run the review on a cheaper model). When absent or invalid, the reviewer Agent inherits the session model (backward-compatible default). Model: is only effective on the Claude Code Agent-dispatch path; on the inline / Codex fallback path no Agent is spawned, so the value is moot (the executing agent's own model governs).
An optional Files: value — a comma- or newline-separated list of repo-relative file paths — may likewise be passed as a natural-language argument, an independent optional field (not part of a fixed-arity mode gate; same standing as Model:). When present, the changed-file set (§ 1. Prepare) is narrowed to the intersection of the diff's changed files and this list, so the review covers only those files; when absent or invalid, all changed files are reviewed (the backward-compatible default). A caller such as dev-workflow uses this to scope a re-check to just the files a review-finding fix touched, rather than re-scanning the full base-commit diff. When the intersection is empty (none of the listed paths changed since <base-commit>), the § 1. Prepare No changed files early-exit fires (a loud no-issues), so an empty scope never silently passes.
--base-commit <sha> from $ARGUMENTS. If not provided, use git rev-parse HEAD~1. Also parse the optional Model: value from $ARGUMENTS (see § Usage); hold it for §5's reviewer Agent dispatch. Absent or invalid → no model override (inherit). Also parse the optional Files: value from $ARGUMENTS (see § Usage); hold it for step 2's changed-file narrowing. Absent or invalid → no narrowing (review all changed files)git diff --name-only <base-commit>. When Files: was provided (step 1's Files: parse), narrow this set to the intersection of it and the parsed paths (repo-relative match) — a listed path that did not change since <base-commit> simply drops out. When Files: was absent or invalid, keep the full changed-file set (backward-compatible). All downstream steps (rule matching, grouping, per-group diff capture) operate on this possibly-narrowed setNo changed files as the final prose result, then emit the verdict per ## Return contract and end the processing flow (no further processing steps)Glob(".claude/rules/**/*.md")*.examples.md from the check targets (they are reference material, not enforceable rules)No rule files found in .claude/rules/ as the final prose result, then emit the verdict per ## Return contract and end the processing flowFor each rule file:
paths: globspaths: exists: match each glob against the changed file list. If at least one changed file matches, include this rulepaths: does not exist (e.g., project.md): apply to all changed filesGroup matched rules into categories based on their directory path:
.claude/rules/ (e.g., project.md, project.local.md).claude/rules/{subdirectory}/ (e.g., languages, frameworks, integrations, or any custom directory)Within a category, group related rules by filename prefix into families (e.g., rails.md, rails-controllers.md, rails-models.md = one family). Keep related rules together for consistent judgment.
Grouping policy (deterministic):
If no rules matched any changed files, output No applicable rules for changed files as the final prose result, then emit the verdict per ## Return contract and end the processing flow.
Prefer parallel execution: launch one reviewer per group through the current host's reviewer-dispatch mechanism.
Host-aware dispatch:
Agent tool is exposed and nested dispatch is not blocked, launch one reviewer Agent per group — passing the parsed Model: value (§1) as the Agent model parameter when present, omitting it when absent (inherit).Agent tool is absent from the tool surface, or the host indicates before dispatch that reviewer dispatch cannot recurse — execute the same reviewer prompt inline sequentially for each group. Being invoked as a sub-skill (e.g. via Skill() on the main thread) does not by itself trigger this path: decide by whether Agent is exposed and callable, not by invocation lineage — if it is, take the Claude Code path. The current agent acts as the reviewer, reading the embedded rules/examples/diff and producing the reviewer report in the same format.Detect availability by inspecting the current tool surface. Do not attempt speculative tool calls just to probe availability. Do not substitute claude -p, codex, or other external CLIs; the inline path is the defined fallback. Collect results identically in all paths.
No stall after dispatch: once the reviewer Agents are launched (Claude Code path) or the subagent / delegation mechanism is invoked (Codex path), do not end the response with a status-only message such as "dispatched — will report when complete". Continue to § 6. Aggregate Results as soon as the dispatched reviewers' results are available in the same flow; a dispatch is not itself a stopping point.
Scoped re-check note (conditional on Files:): when Files: narrowed the changed-file set (§ 1. Prepare), append this sentence at the end of the reviewer prompt's **Scope** paragraph below — This review is scoped to a caller-specified subset of the changed files. If you suspect a change in these files has a rule-relevant ripple effect on files outside this subset, raise it as a finding. Omit it entirely when Files: was absent (full-scope review — the prompt is unchanged).
Each reviewer (dispatched or inline) receives the following prompt:
You are a rules compliance reviewer. Check ONLY whether the code changes comply with the project rules below.
Do NOT report general code quality, bugs, or design issues — only check what is explicitly stated in the rules.
**Scope**: only the lines added or modified in the diff are in-scope. Pre-existing patterns elsewhere in the file that already match or violate a rule are out-of-scope unless the rule text itself explicitly demands file-wide / project-wide consistency (look for phrases like "across the file", "project-wide", "every occurrence", or equivalent).
**Cross-file scope**: when a rule's text does not restrict its scope to a single file (i.e., contains no "in this file", "within this file", or equivalent limiting phrase), apply it across all changed files in the diff — including cross-file references, imports, and shared contracts between changed files (for skill development: cross-references between SKILL.md files, callee/orchestrator return-contract wording, references/*.md inter-file citations). Apply this cross-file expansion in cycle 1 — deferring cross-file rule application to a later cycle is a defect, not expected behavior.
**Same-rule complete enumeration in cycle 1**: when a rule fires at one location in the diff, actively sweep the **full diff** for additional same-rule violations rather than reporting only the first instance encountered. For rules whose violations cluster around a shared identifier, anchor, naming token, or cross-reference shape (renaming residue, deprecated import names, stale API references, anchor / cross-ref form requirements — for skill development this includes step / heading anchor stability, callee-name references, bundled rule citations), grep the diff for the violation's defining token (the renamed identifier, the rule-mandated anchor form, the deprecated name) and emit a separate report entry for every match — partial enumeration across cycles is a defect of the same shape as deferring cross-file expansion above, and turns what should be one repair pass into multiple round-trips through the caller's iteration budget.
**Existing-baseline judgment**: when the new diff follows the same pattern as a heavily-used existing baseline, judge the new addition against the rule on its own merits — do not let the existing baseline either excuse or condemn the new lines unless the rule's own scope clause says so.
Rules may include hard rules (binary compliance) and intent rules (judgment-based). Evaluate both. For intent-rule cases where your judgment is low-confidence (borderline compliant / unclear intent), report them in the violation list as findings with an explicit "low-confidence" marker rather than silently returning the no-violation string — the exact "No rule violations found" response is reserved for cases where you are confident no violations exist.
For low-confidence intent-rule findings, include a constructive resolution direction in `Suggested fix` — describe the typical relocation pattern rather than a bare flag: preserve the rationale by moving it to a more appropriate surface rather than deleting it outright. For a comment-minimization rule this means moving the "why" explanation into accompanying documentation while keeping the code itself comment-free; for other intent-style rules, identify whether the intent can be satisfied by relocating the flagged content rather than simply removing it.
**Rule-doc drift classification**: if the code is consistent with its behavior across multiple locations in the diff and in the surrounding codebase, while the rule's text describes a *different* behavior — and the code pattern appears to be intentionally established (not an oversight) — classify the finding as **`rule-doc-drift`** rather than a code violation. Indicators (supporting signals — use judgment, not automatic trigger): (i) the same "non-compliant" pattern appears in 3+ call sites in the diff or in the broader file, all following the same shape; (ii) the rule's text cites an **external platform signal** (a documented platform threshold, a version-pinned default, a documented API behavior) and the diff updates the same signal to a different value, with surrounding code or companion docs aligning to the new value; (iii) the rule's text cites a **numeric value / token / literal** that conflicts with the diff's new default for the same concept, and at least one additional signal suggests the referent has intentionally shifted (matching sibling defaults, companion-doc updates, or other changed call sites). When the evidence is limited to a sole new occurrence with no corroborating signal, prefer a code violation or explicitly mark the drift judgment as low-confidence rather than auto-classifying `rule-doc-drift`. For rule-doc-drift findings, set `Classification: rule-doc-drift` in the report entry and recommend routing to rule extraction (`Skill(extract-rules)`) rather than a code fix. Set the Suggested fix to the literal string `Route to extract-rules to update the rule document rather than fixing the code`. The caller decides whether to fix the code or update the rule. Do **not** automatically apply code changes for rule-doc-drift findings.
**Group-exception membership verification**: when a rule includes an exception clause conditioned on the target being a member of a named group — for example, "references to siblings within the same bundle are permitted", "intra-package cross-imports are allowed", or "calls between services in the same module do not require a contract change" — verify actual group membership from the authoritative source (the distribution manifest, package declaration, module registry, or equivalent official membership list) before applying the exception. Apparent co-location in the same repository, directory, or naming domain is insufficient: a component may reside alongside the group without being a declared member. When actual membership cannot be confirmed, treat the exception as inapplicable and report the reference as a violation (for skill development: before applying the "intra-bundle sibling" exception to a cross-skill reference, confirm the referenced skill is listed in the bundle's `skills` array in `.claude-plugin/marketplace.json` — co-location under the same repository does not imply bundle membership).
**Reference/citation matching strictness**: when a rule requires quoting or citing a stable heading, section title, or bold-prose label, apply the same matching criteria on every review cycle for the same diff text — do not accept a documented prefix / pair-form citation (e.g. `§ <Heading>'s "<bold label>" paragraph`) as compliant in one cycle and then flag the identical citation as non-compliant under a stricter verbatim-only reading in a later cycle. Judge compliance against whichever form the citing rule's own text or an established sibling convention documents as canonical; only report a citation as non-compliant when it deviates from that documented form, never merely for using a permitted prefix/pair variant.
## Rules to Check
<Rule file contents with file paths>
## Reference: Code Examples
<Corresponding .examples.md content, if available>
## Diff to Review
<Scoped git diff for the matched files>
## Report Format
For each violation, report:
- **Rule file**: <.claude/rules/... path>
- **Violated rule**: Quote the rule line verbatim from the rule file. If the line bundles multiple sub-rules (e.g., items in parentheses like `型安全性 (any禁止, 明示的型注釈)`), quote the whole line as-is and name the specific sub-rule in Description.
- **Location**: <file:line>
- **Description**: <what violates the rule and why; if quoting a bundled line, name the specific sub-rule here>
- **Suggested fix**: <specific fix to become compliant; for `rule-doc-drift` findings, write "Route to extract-rules to update the rule document rather than fixing the code">
- **Confidence**: `high` for hard-rule violations; `low-confidence` for intent-rule borderline findings (see note above).
- **Classification**: `code-violation` (default, omit for brevity) | `rule-doc-drift` (only when the finding meets the rule-doc-drift criteria above)
When the same rule line is violated at multiple locations or by multiple sub-rules, emit **one entry per (location, sub-rule)** pair — do not collapse them into a single entry. This keeps fixes actionable.
If no violations are found, respond with exactly: "No rule violations found"
Before launching reviewers, prepare the data to embed in each prompt (do NOT rely on reviewers running git commands themselves):
git diff <base-commit> -- <matched-files> using the union of files matched by any rule in that group (so each reviewer sees every file it is responsible for, and the same file may appear in diffs for multiple groups if multiple rules match it)..examples.md exists (same basename, e.g., rails-controllers.md → rails-controllers.examples.md) and read its content..examples.md exists for any rule in the group, omit the ## Reference: Code Examples section entirely from that reviewer prompt (do not write a placeholder line like (no examples file)).@<path> include, or a markdown link to a doc outside .claude/rules/), resolve that reference and Read the target so the embedded ## Rules to Check content is the actual rule text — embedding the bare pointer would make the reviewer judge against empty rules and return No rule violations found even when the referenced rule is violated. If the reference cannot be resolved (target missing, or outside readable scope), do not embed an empty stub: drop the rule from the group and record it as an explicit coverage gap per § 6. Aggregate Results, so an unread rule is never silently reported as compliant.### <.claude/rules/... path> sub-heading inside the ## Rules to Check section.For each reviewer:
No rule violations found and no synthetic non-evaluation entries ((review failed) / (rule not evaluated — ...) coverage gaps) were added in step 4:
No rule violations found as the final prose result, then emit the verdict per ## Return contract and end the processing flow.## Return contract status mapping reads the same consolidated list and stays consistent with it.low-confidence findings in the list with their marker preserved — do not drop them.No rule violations found or the violation format, retry that group once. If it fails again, include a synthetic entry in the final output under the group name with Rule file: (review failed), Description: reviewer returned unparseable output, and continue aggregation for other groups.Rule file: (rule not evaluated — unresolved pointer to <ref>) and Description: rule body deferred to an out-of-tree document that could not be resolved; left unevaluated rather than reported clean. These coverage-gap entries are treated the same as (review failed) synthetic entries for the verdict (see ## Return contract) — they surface loudly instead of letting an unread rule pass silently as No rule violations found.low-confidence findings (no high-confidence violations), still emit the violation list — do not substitute No rule violations found.No rule violations found
Scope note: This check covers only rules documented under
.claude/rules/. Project-specific vocabulary, naming, or style conventions that have not yet been written into a rules file are out of scope — if such an unwritten convention may apply to the changed code, verify manually or runSkill(extract-rules)to capture the pattern as a rule. The prose line stays exactlyNo rule violations foundso callers that substring-match on that string (see§ 6. Aggregate Results) keep working; a single fenced JSON verdict block (see## Return contract) follows it as the additive structured return value.
## Rules Compliance Violations
### .claude/rules/frameworks/rails-controllers.md
- **Violated rule**: <rule text, quoted verbatim>
- **Location**: app/controllers/users_controller.rb:15
- **Description**: <description; if quoting a bundled rule line, name the specific sub-rule>
- **Suggested fix**: <suggestion>
- **Confidence**: high
### .claude/rules/languages/ruby.md
- **Violated rule**: <rule text, quoted verbatim>
- **Location**: app/models/user.rb:42
- **Description**: <description>
- **Suggested fix**: <suggestion>
- **Confidence**: low-confidence
Emit a single fenced JSON block at the end of the response, matching the schema below. The block is additive: the ## Output Format prose above is unchanged, and the verdict block is appended after it. Emit the verdict on every exit path — including the early exits in § 1. Prepare / § 2. Collect Rules / § 4. Group Rules by Category (those end the processing flow, not the response; the verdict block still follows). Only one fenced JSON block — the verdict block — appears in the response, so callers can locate it unambiguously.
{
"status": "no-issues|violations|error",
"violations_count": 0,
"reason": null
}
Status mapping (evaluate in order, first match wins):
no-issues — no changed files (§ 1. Prepare), no rule files (§ 2. Collect Rules), no applicable rules (§ 4. Group Rules by Category), or all groups returned exactly No rule violations found with no synthetic non-evaluation entries present (the all-clean branch of § 6. Aggregate Results — a (review failed) or (rule not evaluated — ...) coverage-gap entry blocks this branch). violations_count: 0, reason: null.error — the review could not be produced: diff collection failed (§ 1. Prepare), matched rule files could not be read (§ 3. Match Rules to Changed Files), or the consolidated violation list in § 6. Aggregate Results is non-empty yet holds no real finding — it is entirely synthetic non-evaluation entries ((review failed) and/or (rule not evaluated — ...) coverage gaps), including the case where some reviewer groups ran clean (contributing no list entry) while the only entries are synthetic. violations_count: 0, reason = the matching closed-enum string below (per the reason-selection order). The § 6. Aggregate Results prose still renders those synthetic entries; the verdict status reflects that no rule was actually evaluated to a finding.violations — the consolidated violation list (§ 6. Aggregate Results) holds at least one real finding (high / low-confidence / rule-doc-drift), possibly mixed with (review failed) and/or (rule not evaluated — ...) coverage-gap synthetic entries. violations_count = total entries in that list. reason: null.Field rules:
violations_count: non-negative integer. Total entries in the consolidated violation list (§ 6. Aggregate Results) for violations; 0 for no-issues and error. (For error the count is 0 even when the list holds synthetic non-evaluation entries — violations_count is a real-finding count, not the list length. The violations-vs-error asymmetry, where violations counts synthetic entries mixed in with real findings while error reports 0, is intentional: an error list by definition evaluated nothing to a finding.)reason: a closed-enum string only when status == "error", otherwise JSON null — keep it to the enum tokens (no free-form text, newlines, or control characters) so the verdict stays mechanically parseable. Reason selection (within status == "error", evaluate in order, first match wins): a diff collection failed / rule loading failed source first (mutually exclusive — they short-circuit before any reviewer is dispatched) → else verdict parse failure if the consolidated list holds ≥ 1 (review failed) entry → else coverage gap only (the synthetic entries are all coverage gaps). Closed enum:
"diff collection failed" — § 1. Prepare produced no usable changed-file list."rule loading failed" — matched rule files could not be read in § 3. Match Rules to Changed Files."verdict parse failure" — the consolidated list holds ≥ 1 (review failed) entry (a reviewer group returned unparseable output even after the retry) and no real finding, so the verdict is error rather than violations (the list may also carry coverage-gap entries and clean groups that contributed no entry). A (review failed) group alongside a real finding from another group stays counted under violations, not error; a clean (no-finding) sibling group does not — then the list has no real finding and the verdict is error."coverage gap only" — the consolidated list's synthetic entries are all (rule not evaluated — ...) coverage gaps from unresolvable pointers (§ 5's Resolve pointer rules before embedding bullet) — no (review failed) entries — and the list holds no real finding (any reviewer groups that ran returned clean and contributed no entry, or no group ran at all). Use this token when the error arises solely from dropped pointer rules rather than from a diff / rule-load failure or unparseable reviewer output.When invoked as a sub-skill (i.e. via Skill(rules-review) from an orchestrator), the fenced JSON verdict block this skill emits is the structured return value of the skill's procedure — it is not a deliverable to the user, and emitting it does not terminate the orchestrator's turn. The same agent that ran this skill must immediately issue the next tool call dictated by the orchestrator's flow (see the orchestrator's § No-Stall Principle; orchestrators that surface a per-callee guidance bullet name the specific next action there). Do not insert a prose summary, an acknowledgment, or a "shall I proceed?" sentence between the JSON verdict and the next tool call. The JSON verdict block and the next tool call MUST be emitted in the same assistant turn. Closing the turn after emitting the JSON block — even with no prose between them — is the same violation as inserting prose. Only one fenced JSON block — the verdict block — appears in the response, so callers can locate it unambiguously. The skill's own procedure is over; the orchestrator's procedure continues without pause.
2plugins reuse this skill
First indexed Jul 18, 2026
npx claudepluginhub hiroro-work/claude-plugins --plugin rules-reviewCheck code changes for .claude/rules/ compliance. Use this skill when you need to verify that code changes follow project coding rules, whether as part of dev-workflow or standalone. Triggers on: rule compliance check, rules review, verify conventions, check coding standards. Best suited for hard rules (naming, imports, placement, explicit prohibitions); intent-style rules are checked on a best-effort basis.
Verifies changed files against project rule checklists before git push, detecting missed cascading changes and proposing rule updates for unmatched patterns.
Reviews code against project rules and reference files, flagging violations in correctness, security, reliability, architecture, dead code, complexity, and conventions.