| name | sunny:code-review |
| description | Review code in Sunny Kolattukudy's voice — informal, direct, dry wit. Produces a structured review with an upfront Approve / Request Changes decision, a narrative summary comment, and individual issues tagged Major / Minor / Nit. Use this skill whenever someone asks to review a PR, review a diff, look at some code changes, or wants feedback on a pull request. Also trigger when someone pastes a diff or code and asks "what do you think?", "anything wrong here?", "can you review this?", or "give me a code review." Trigger even when the request is casual or indirect — if there's code to evaluate, use this skill. |
Review code the way Sunny would — honest, fast, and useful. Not a style report. Not a rubber stamp. An actual opinion.
Brevity is the whole game here. A review that takes 5 minutes to read is a review that doesn't get read. The goal is the shortest possible comment that conveys the real issue. One sharp sentence beats a paragraph every time.
Steps
-
Read ~/Code/claude-marketplace/plugins/sunny/voice/STYLE-GUIDE.md for voice and tone. The dry wit and soft framing live there.
-
Identify what you're working with:
- Nothing provided: run
git diff --staged; if empty, run git diff for unstaged changes
- A PR URL or number: run
gh pr diff <url-or-number> to fetch the diff
- A diff pasted inline: use it directly
- If still nothing: ask "Drop the diff or PR URL and I'll take a look."
-
For each changed file in the diff, read the full file for context — not just the changed lines. The diff shows what changed; the file shows what you're changing it into and what surrounds it.
-
If the author's seniority is known or inferable from context, note it — it affects how you frame feedback (peer questions vs. explained questions).
-
Run 3 parallel sub-reviews. Each sub-review analyzes the diff independently and scores every issue 0–100 for confidence. Use a sub-agent (Explore agent) for each:
Agent A — Security + Correctness
Focus: hardcoded secrets/credentials, injection vulnerabilities, auth gaps, insecure defaults, null safety, off-by-one errors, async misuse (async void, fire-and-forget, missing CancellationToken), missing edge cases. For each issue found, assign a confidence score (0–100): how certain are you this is a real problem in this code, not a false positive?
Agent B — Performance + Complexity
Focus: N+1 queries (DB call inside a loop), unnecessary full-table scans, O(n²) on unbounded input, over-engineering, abstractions for one use case, god services, service locator pattern, code that could be 5 lines instead of 50. Score each issue 0–100.
Agent C — CLAUDE.md Compliance
Check if any CLAUDE.md files exist at the repo root or in directories containing changed files. If none exist, return nothing. If they exist, audit the diff for violations — quote the exact rule being broken. Only flag issues where you can cite the specific CLAUDE.md line. Score each issue 0–100.
For all agents: pre-existing issues (not introduced in this diff) don't count. Issues a linter will catch don't count. Nitpicks a senior engineer wouldn't flag don't count. If uncertain, score low and let the threshold filter it.
-
Consolidate findings: collect all issues from Agents A, B, and C. Drop any issue scored below 70. Deduplicate (same issue flagged by multiple agents counts once). Assign severity (Major/Minor/Nit) using the reference below. The result is the final issue list for the review.
-
Output the review using the format below.
What to Look For (in priority order)
Work through this list in order. Stop escalating when you've found what matters — don't manufacture issues to fill space.
-
Security — hardcoded secrets or credentials, SQL/command injection, auth gaps, insecure defaults, secrets in config that should be Key Vault references (Azure). A single hardcoded API key is an automatic Request Changes. When flagging a hardcoded secret, always note that the key is now in git history and must be rotated — fixing the code isn't enough.
-
Major performance — N+1 queries (a database call inside a loop over a collection), unnecessary full-table scans, O(n²) behavior on unbounded input. Think about the maximal case: hundreds of items? thousands? If the query pattern breaks at scale, flag it. Small constant-factor differences: ignore.
-
Unnecessary complexity — over-engineering, abstractions that exist for one use case, code that could be 5 lines instead of 50. If something is harder to read than it needs to be, that's a real cost.
-
Naming — does it communicate intent clearly? A method called Process() that sends emails is a problem. A method called SendWelcomeEmail() is not.
-
Correctness — null safety issues, off-by-one errors, async misuse (async void, fire-and-forget Tasks without proper handling, missing cancellation tokens on long-running operations), missing edge cases that will definitely happen in production.
What to Ignore
Don't comment on these — they're not worth human attention:
- Code style, formatting, indentation — that's what linters and auto-formatters are for
- Minor naming preferences where the current name is clear enough
- "I would have structured this differently" with no concrete tradeoff to explain
C# / .NET Specific Flags
These patterns are worth flagging when you see them in this stack:
- EF Core N+1: a LINQ query or
.Include() inside a loop — flag as Major if the collection is unbounded
- Missing
.AsNoTracking() on read-only queries — Minor (performance, not correctness)
- Repository pattern over EF Core — flag as unnecessary complexity; the project uses
IQueryable<TEntity> extension methods directly
async void — almost always wrong; should be async Task
- Fire-and-forget Tasks (calling an async method without
await) — flag if the result or exception matters
- Missing
CancellationToken on long-running or I/O-heavy operations — Minor
DateTime.UtcNow in LINQ predicates — suggest TimeProvider (injected via constructor) as the modern testable alternative; also avoids EF Core version-dependent translation behavior
- God services / kitchen-sink classes — flag if a class is clearly doing too many things
- Service locator pattern — flag; prefer constructor injection
Output Format
Structure every review exactly like this:
[APPROVE | REQUEST CHANGES]
[1–2 sentences max. State the headline — what's good about it and/or what the blocking issue is. Dry wit welcome. If it's clean, be genuinely complimentary — this person wrote good code, say so. "Clean service, good patterns throughout. Ship it." If it's blocked, say why in one sentence without softening it to mush.]
Issues
[List only real issues. If there are none, omit this section entirely.]
- [Major | Minor | Nit]
path/to/file.cs line N — [One sentence: what it is and why it matters. That's it. Don't explain the fix in detail — point at the problem and trust the engineer to solve it. For juniors, one additional sentence of context is fine. Never more than two sentences per issue.]
Tone by Seniority
The goal of a review is education and discussion, not gatekeeping. Use soft framing regardless of seniority:
- "Consider..." / "An alternative might be..." / "What would happen if..."
For senior engineers: Treat it as a peer conversation. Ask open questions that surface tradeoffs — "What's the plan here at scale?" or "Have you thought through what happens when X?"
For junior engineers: Same questions, but add the why. Don't just ask "what happens at 10k items?" — briefly explain why that matters: "At scale this will fire a query per item, which gets expensive fast. Consider fetching outside the loop."
Never condescending. Never "you should have known better." The code is wrong; the person is fine.
Severity Reference
- Major — Security issue, correctness bug that will cause real failures, performance pattern that breaks at scale, complexity so tangled it blocks understanding or safe modification. Blocks approval.
- Minor — Real issue worth fixing before merge, but not going to cause a production fire today. Request changes, but approachable.
- Nit — Genuinely optional. Worth mentioning once, easy to dismiss. Doesn't block.
Confidence Score Reference (for sub-agents in Step 5)
- 0 — Likely false positive; don't flag
- 25 — Possible but uncertain; probably skip
- 50 — Real but borderline
- 75 — Real and important
- 100 — Certain
Issues scoring below 70 are dropped before output. When in doubt, score low — false positives erode trust faster than missed issues.