From codereview
Automated pre-PR code review. Diffs current branch against main, analyzes all changed files, and produces a structured report with severity-rated findings, test coverage assessment, documentation sync verification, and a final grade. Checks docstring coverage, OpenAPI/README/rules sync, race conditions (TOCTOU), accessibility, data integrity, and code quality. Use this skill whenever the user asks for code review, pre-PR review, code analysis, quality check, documentation check, security review, accessibility audit, or wants to review changes before merging — even if they don't say "codereview" explicitly. Triggers: "code review", "pre-PR review", "review my code", "quality check", "review changes", "codereview", "check my code", "analyze code", "PR review", "check docs", "documentation review", "security review", "accessibility check", "race condition", "toctou"
How this skill is triggered — by the user, by Claude, or both
Slash command
/codereview:codereviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
```text
$ARGUMENTS
You MUST consider the user input before proceeding (if not empty). Valid inputs:
security, performance, types, bugs, tests, docssrc/components/Quote*)baseDir=app/ fileExtensions=ts,js uiLibReducedRigor=true (see references/configuration.md)Read references/configuration.md for default values and override syntax.
Perform a comprehensive, automated code review of all changes in the current branch compared to the base branch. Produce a structured Markdown report with severity-rated findings, test coverage assessment, and a final grade. This replaces manual pre-PR review.
This skill is stack-agnostic. Defaults target TypeScript/React but all values are configurable. Set frameworkPatterns=dotnet for C#/.NET projects (WPF, WinForms, ASP.NET, Console) — this activates .NET-specific checks and deactivates web-frontend rules. The universal checks (readability, complexity, error handling, secrets) apply to every stack.
STRICTLY READ-ONLY: Do not modify, create, or delete any files. Do not run destructive commands. Do not run formatters, linters, or fixers. Output ONLY a structured analysis report in the conversation.
No Code Rewrites: This skill identifies issues and suggests fixes in the report — it does NOT apply them.
Could not analyze: {filename} ({reason}) in the final report.unanalyzable and continue with the remaining files.Analysis incomplete due to context limits. {n} files not analyzed. and proceed to the final report.unanalyzable and continue.Regardless of which failures occur, always produce a final report that lists:
Run these git commands to understand the branch state:
# Abort early if not inside a git repository
git rev-parse --is-inside-work-tree 2>/dev/null || { echo "Error: not a git repository."; exit 1; }
# Determine base branch: prefer BASE_BRANCH env var, then origin HEAD, then try main/master
BASE_BRANCH="${BASE_BRANCH:-$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')}"
if [ -z "$BASE_BRANCH" ]; then
if git show-ref --verify --quiet refs/heads/main 2>/dev/null; then
BASE_BRANCH="main"
elif git show-ref --verify --quiet refs/heads/master 2>/dev/null; then
BASE_BRANCH="master"
else
echo "Error: could not detect base branch (no main or master found)."; exit 1
fi
fi
# Current branch name (fail clearly on detached HEAD)
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
if [ -z "$BRANCH_NAME" ] || [ "$BRANCH_NAME" = "HEAD" ]; then
echo "Error: detached HEAD state — cannot determine current branch."; exit 1
fi
# Prevent reviewing a branch against itself
if [ "$BRANCH_NAME" = "$BASE_BRANCH" ]; then
echo "Cannot review base branch ($BASE_BRANCH) against itself."; exit 1
fi
# Common ancestor with base branch
MERGE_BASE=$(git merge-base "$BASE_BRANCH" HEAD 2>/dev/null) || { echo "Error: could not find merge base with $BASE_BRANCH (missing remote?)"; exit 1; }
# Files changed (names only)
git diff "$MERGE_BASE"...HEAD --name-only
# Change statistics
git diff "$MERGE_BASE"...HEAD --stat
# Commit log for this branch
git log "$MERGE_BASE"..HEAD --oneline --no-decorate
Capture and store:
BASE_BRANCH: configured or auto-detected base branchBRANCH_NAME: current branchMERGE_BASE: the ancestor commit hashCHANGED_FILES: list of changed file pathsDIFF_STAT: insertions/deletions summaryCOMMIT_LOG: list of commits on this branchIf CHANGED_FILES is empty, output a short message: "No changes detected between this branch and $BASE_BRANCH." and stop.
Exclude these files from analysis (still list them in the report header as "Excluded"):
**/package-lock.json, **/yarn.lock, **/pnpm-lock.yaml**/node_modules/****/dist/**, **/build/**, **/.next/****/*.min.js, **/*.min.css**/.claude/** (command and skill files themselves)**/.claude/skills/**Additional exclusions by frameworkPatterns:
dotnet: **/bin/**, **/obj/**, **/*.Designer.cs, **/*.g.cs, **/*.g.i.cs, **/AssemblyInfo.cs, **/*.user, **/*.suoClassify remaining files into categories using the Configuration values:
| Category | Pattern (uses config values) | Review Rigor |
|---|---|---|
CODE | {baseDir}/**/*.{fileExtensions} — excluding testFilePatterns and generatedDirs | Full analysis |
UI_LIB | files matching generatedDirs (e.g. src/components/ui/**) | Reduced rigor when uiLibReducedRigor=true — only flag CRITICAL/HIGH issues |
TESTS | files matching testFilePatterns (e.g. src/**/*.test.ts, src/test/**) | Test quality analysis |
CONFIG | files matching configFilePatterns (e.g. *.config.*, tsconfig*, package.json) | Config-specific checks only |
DOCS | *.md, *.txt (excluding .claude/) | Skip analysis, note in header |
STYLES | files matching styleFilePatterns (e.g. **/*.css) | Minimal review |
If more than 15 files are classified as CODE or TESTS, prioritize files with the most changes (by diff stat lines changed). Note any deprioritized files in the report.
For each file, load the appropriate context:
Use the Read tool for file contents and Bash with git diff for diffs.
When a CODE file imports types or functions from other changed files, note these cross-file dependencies for coherence analysis.
Map each CODE file to its corresponding test file(s) using the following priority order. Probe each candidate path in order and stop at the first level that yields at least one existing file:
| Priority | Candidate pattern (given source {dir}/{Base}.{ext}) |
|---|---|
| 1 (highest) | {dir}/{Base}.test.{ext} then {dir}/{Base}.spec.{ext} — same directory, same extension |
| 2 | {dir}/{Base}.test.ts, {dir}/{Base}.test.tsx, {dir}/{Base}.test.js, {dir}/{Base}.test.jsx — same directory, all extensions |
| 3 | {dir}/__tests__/{Base}.test.{ext}, {dir}/__tests__/{Base}.spec.{ext} — __tests__ sibling folder |
| 4 | {testRoot}/{dir}/{Base}.test.{ext}, {testRoot}/{dir}/{Base}.spec.{ext} — project test root |
| 5 (lowest) | Any file in CHANGED_FILES (TESTS category) whose basename matches {Base} (case-insensitive) |
Auto-detect {testRoot}: Check in order:
vitest.config.* or vite.config.* exists, look for test.root or test.include paths in the configjest.config.* or package.json contains jest.roots or jest.testMatch, derive the test rootsrc/test/, tests/, test/, or __tests__/ that exists at repo rootWhen frameworkPatterns=dotnet, use these candidate patterns instead:
| Priority | Candidate pattern (given source {dir}/{Base}.{ext}) |
|---|---|
| 1 (highest) | {ProjectName}.Tests/{Base}Tests.cs — sibling test project |
| 2 | {ProjectName}.Tests/**/{Base}Tests.cs — test project subdirectory |
| 3 | {dir}/{Base}Tests.cs — same directory |
| 4 (lowest) | Any file in CHANGED_FILES (TESTS category) matching {Base} (case-insensitive) |
Auto-detect {testRoot} for dotnet: Look for *.csproj files containing <PackageReference Include="xunit" or Microsoft.NET.Test.Sdk or NUnit or MSTest. The directory of such .csproj is the test root.
Resolution rules:
.test.ts and .test.tsx exist), treat them as a single logical match group — any one of them being in CHANGED_FILES satisfies the WITH_TESTS condition.Classify each CODE file using the matched group:
CHANGED_FILES).Apply these 5 principles as analysis lenses to all CODE files (reduced rigor for UI_LIB):
Universal:
react|vue|angular|node: JSDoc (/** ... */)dotnet: XML documentation comments (/// <summary>)Universal:
When frameworkPatterns is react|vue|angular|node (web frontend):
anyuseEffect with missing or incorrect dependency arraysvalue && <Component /> where value could be 0)When frameworkPatterns=dotnet:
var used where type is genuinely ambiguous (non-obvious inference)dynamic keyword without strong justificationlong to int)Universal:
When frameworkPatterns is react|vue|angular|node:
When frameworkPatterns=dotnet:
Universal:
When frameworkPatterns is react|vue|angular|node:
.then() chains or nested callbacks)When frameworkPatterns=dotnet:
if/else chains that could use pattern matching or guard clausesUniversal:
catch blocks or catch that only logs without re-throwing or returning errorWhen frameworkPatterns is react|vue|angular|node:
When frameworkPatterns=dotnet:
async void methods outside of UI event handlers (unobservable exceptions) — flag as CRITICALcatch (Exception) { } without logging or re-throw — flag as HIGHtry/finally or using for IDisposable resources — flag as HIGHUniversal:
async functions that never await anything (likely missing await or unnecessary async)When frameworkPatterns is react|vue|angular|node:
useEffect dependency array mismatches (missing deps or unnecessary deps)== instead of ===)When frameworkPatterns=dotnet:
async void (except UI event handlers) — unhandled exceptions crash the appIDisposable not disposed (missing using statement)Task.Run and shared mutable stateDateTime.Now instead of DateTime.UtcNow in cross-timezone logic.Result or .Wait() on async code in UI threadUniversal:
eval(), new Function(), or dynamic code executionWhen frameworkPatterns is react|vue|angular|node:
dangerouslySetInnerHTML, unescaped user input in DOMWhen frameworkPatterns=dotnet:
MessageBox.Show() or OpenFileDialog in service/domain classes (UI leak into business layer)System.Windows.Forms using in non-UI classesPath.Combine()Universal:
When frameworkPatterns is react|vue|angular|node:
key props or using array index as key in dynamic listsReact.memo missing — flag as MEDIUM only when the component is rendered inside a list or loop, or when prop identity changes are known to cause unnecessary child re-renders. Otherwise flag as LOW or omit.useCallback missing — flag as MEDIUM only when the callback is passed as a prop to a memoized child or used in a useEffect dependency array and its identity changes provably cause repeated effect execution. Otherwise flag as LOW or omit.useMemo missing — flag as MEDIUM only when the computation is demonstrably expensive (>100ms measured, or explicitly identified by profiling). For cheap computations flag as LOW or omit.When frameworkPatterns=dotnet:
new HttpClient() per-call instead of IHttpClientFactory or injected instanceStringBuilder)Thread.Sleep() in async code or tests.ToList() or .ToArray() when IEnumerable suffices (unnecessary materialization)Universal:
When frameworkPatterns is react|vue|angular|node:
any type (explicit or implicit)as Type) that bypass type checkinga?.b?.c?.d?.e)When frameworkPatterns=dotnet:
public static mutable fields used as service locator pattern(Type)obj instead of pattern matching (is Type t)object or dynamic used where a generic <T> or interface fitsStale documentation is worse than no documentation — it actively misleads. This pass verifies that project documentation stays synchronized with code changes and that new/modified code has proper inline documentation.
Why this matters: When documentation drifts from code, the next developer (or AI assistant) trusts the docs, makes wrong assumptions, and introduces bugs or writes incompatible code. Catching drift at review time prevents compounding errors.
6.5.1 Docstring / Code Comment Coverage
For every new or modified function, method, class, or exported constant in the diff, check whether it has documentation appropriate to its language:
/** ... */) on exported functions, classes, interfaces, and type aliases. At minimum: a one-line description. Parameters and return types documented when not obvious from the signature. If the project's CLAUDE.md or rules specify a documentation language (e.g., "docstrings in Brazilian Portuguese"), flag docstrings written in the wrong language as MEDIUM./// <summary>) on public members.godoc convention..sh, .bash): Header comment block describing script purpose and usage; inline comments on non-obvious logic. No formal docstring standard — flag only when a script has zero header comment.Severity rules for missing docstrings:
describe, it, test) without doc comment → MEDIUM if the project's CLAUDE.md or conventions explicitly require it, LOW otherwise6.5.2 Project Documentation Sync
When the diff introduces new API endpoints, data models, configuration, features, or architectural patterns, verify that the corresponding project documentation was also updated in the same branch. This prevents the common failure mode where code ships but docs stay stale.
Check each applicable item:
| What changed in code | Documentation to verify | Severity if missing |
|---|---|---|
| New/modified API endpoints (routes, controllers) | OpenAPI/Swagger spec (docs/openapi.json, swagger.yaml, or equivalent) | HIGH |
| New/modified API endpoints | README.md API section (if project has one listing routes) | MEDIUM |
| New data model / DB migration / schema change (Prisma, EF Core, Django, etc.) | OpenAPI spec (if model surfaces in API), README data model section | MEDIUM |
| New route patterns, middleware, or architectural conventions | Framework rules file (e.g., .claude/rules/backend-api.md, .claude/rules/frontend-react.md) | MEDIUM |
| New frontend public routes | Framework rules file listing public routes | MEDIUM |
| New features visible to end users | README.md features/roadmap section | LOW |
| Changes to stack, dependencies, or project structure | CLAUDE.md or equivalent project instructions | LOW |
| New patterns, conventions, or corrections to stale info | MEMORY.md or equivalent persistent memory index (if project uses one) | LOW |
How to check:
CHANGED_FILES.Detection heuristics (language-agnostic — apply whichever match the project):
Skip this sub-pass if the project has no documentation files at all (no README, no OpenAPI, no rules files). Don't penalize projects that haven't started documenting — only penalize projects that have documentation but let it drift.
Race conditions occur when code checks a state and then acts on it in separate operations, allowing another process/request to change the state in between. These bugs are hard to reproduce but cause data corruption, duplicate records, and security bypasses.
Read references/toctou-patterns.md for the full pattern catalog with code examples. Apply the following detection heuristics during review:
Universal (all languages/frameworks):
Check-then-act on database records: A read query (find, get, select) whose result gates a write query (create, update, delete) in a separate call — without wrapping both in an atomic operation. The read provides stale data if another request modifies the record between the two calls.
UPDATE ... WHERE status = 'unused' and check affected rows), or wrap in a serializable transactionRead-modify-write on numeric fields: Reading a value (balance, counter, sequence), computing in application code, then writing back. Concurrent requests cause lost updates.
Business rules enforced only in application code: Count checks, uniqueness checks, or limit enforcement done via application query + conditional logic instead of database constraints.
Read outside transaction, write inside: A read performed before a transaction block, with the transaction body relying on that read's result without re-validating.
File system check-then-act: exists() / stat() followed by read() / write() in separate calls.
Cache check-then-compute without coalescing: Simple cache miss → compute → store pattern without mutex, allowing thundering herd under concurrent load.
Shared mutable state without synchronization (Java, C#, Go, Python): Reading a shared variable (if (obj == null), if (queue.size() > 0)) and acting on it (obj = new ..., queue.poll()) outside a synchronized/lock block. Common in lazy initialization and producer-consumer patterns.
lock statement, sync.Mutex, or language-level atomic typesWhen a check-then-act pattern is ambiguous — e.g., single-user CLI tool, idempotent reads, or the code already handles the race gracefully — downgrade to LOW or skip rather than generating a false positive.
Accessibility issues prevent users who rely on assistive technology (screen readers, keyboard navigation) from using the application. These checks apply to any frontend framework that renders HTML.
When frameworkPatterns is react|vue|angular|node (web frontend):
Icon-only buttons without accessible name: A <button> or <Button> component whose only child is an icon (SVG, icon component) without aria-label, aria-labelledby, or visible text. Screen readers announce these as "button" with no description.
Form buttons without explicit type: A <button> inside a <form> without type="button" implicitly has type="submit", which may trigger unintended form submission when the button is meant for a different action (e.g., "Cancel", "Toggle", "Open picker").
Interactive elements without keyboard support: Custom clickable <div> or <span> elements without role="button", tabIndex, and onKeyDown handler.
Images without alt text: <img> tags without alt attribute (or empty alt="" for decorative images).
These checks catch issues in database schemas, ORM configurations, and data validation that can lead to data loss or inconsistency.
Universal:
Cascade delete on user/tenant-facing entities: ON DELETE CASCADE (or ORM equivalent like onDelete: Cascade) on foreign keys where the parent is a user, account, or tenant. Deleting a user could silently wipe related data (invites, history, audit logs).
RESTRICT (prevent deletion) or SET NULL (orphan safely)Missing database indexes on frequently-queried columns: Junction tables or foreign keys without indexes, especially in multi-tenant schemas where queries filter by tenant_id + entity_id.
URL/link fields accepting dangerous protocols: URL validation that accepts javascript:, data:, or vbscript: protocols. When these URLs end up in href attributes, they enable stored XSS.
http:// or https:// onlyInconsistent validation schemas: The same field (e.g., email, artista_id) validated differently across related endpoints — required in one, optional in another, or with different normalization logic.
Test fakes/mocks missing fields from real schema: Fake repositories or mock objects that don't include all fields from the production schema. Tests pass but the feature is broken because the fake doesn't exercise the full data model.
Each finding gets one severity:
| Severity | Criteria | Action |
|---|---|---|
| CRITICAL | Security vulnerabilities, data loss risk, crashes in production, exposed secrets | Must fix before merge |
| HIGH | Bugs likely to manifest, missing error handling on user-facing flows, any on public API | Should fix before merge |
| MEDIUM | Code smell, minor Zen violations, missing tests for new logic, performance concerns | Recommend fixing |
| LOW | Style preferences, minor readability improvements, suggestions for future improvement | Optional improvement |
Read references/report-template.md for the full report structure, grading scale, and examples.
Output the Markdown report directly in the conversation following that template.
security → run only 6.2 Security + 6.6 Race Conditions + 6.8 Data Integrity (URL validation, cascade checks)performance → run only 6.3 Performancetypes → run only 6.4 Type Safetybugs → run only 6.1 Bug Detection + 6.6 Race Conditionstests → run only Step 4 (Test Coverage assessment) and test quality analysis on TESTS filesdocs → run only 6.5 Documentation Sync & Docstring Coveragea11y → run only 6.7 Accessibilityrace-conditions → run only 6.6 Race Conditions & TOCTOU (skip 5.x, 6.1-6.4)npx claudepluginhub j0ruge/skills_commands_manager --plugin codereviewReviews and verifies code before merge via triage-first checks (up to 16 parallel agents). Pipeline mode verifies vs plans; general mode for PRs/branches/staged changes. Flags findings only.
Reviews pull requests, branch diffs, and local working-tree diffs for correctness, security, concurrency, performance, and code quality issues. Returns structured JSON findings.
Systematic code review across security, performance, maintainability, error handling, testing, and accessibility with severity-ranked findings and specific fixes.