Code Review
Find real problems and write the fix. Vague feedback ("consider extracting this", "could be cleaner") wastes the author's time. Every finding gets a line number, an observed behavior, an impact, and a concrete code change.
Reason internally in English. Code references and quoted snippets stay in their original form. Final review prose goes in the user's detected language.
Detect target language and project conventions
- From file extension, pasted snippet syntax, or explicit user instruction, identify the language.
- From project files (
pyproject.toml, package.json, go.mod, Cargo.toml, .editorconfig), identify the existing toolchain. Defer to the project's existing config — if they use biome not prettier, review against biome. If they have a custom eslint config, check against that.
- Run the language's standard checks first and treat their output as the starting list of findings.
| Language |
Formatter |
Linter |
Type checker |
| Python |
ruff format --check |
ruff check --select ALL |
ty check |
| TypeScript |
prettier --check |
eslint |
tsc --noEmit |
| Go |
gofmt -l |
golangci-lint run |
(built-in) |
| Rust |
rustfmt --check |
clippy |
(built-in) |
| Java |
google-java-format --dry-run |
checkstyle |
(built-in) |
| C# |
dotnet format --verify-no-changes |
dotnet analyzers |
(built-in) |
| Shell |
shfmt -d |
shellcheck |
N/A |
Severity rubric
| Severity |
Trigger |
| 🔴 High |
Security risk, data loss, crash, undefined behavior, broken contract |
| 🟡 Medium |
Type gaps, missing error handling, performance issues on hot paths |
| 🔵 Low |
Style, naming, doc gaps, organizational suggestions |
When at least one 🔴 High exists, collapse all 🔵 Low findings into a single summary row — the author needs to focus.
Review criteria
1. Type safety (often the highest-leverage finding). Flag every untyped escape hatch (Any, any, object, interface{}) and propose a specific replacement type — TypedDict, Protocol, generics, discriminated union. Flag missing return types and missing parameter types on public functions. At public API boundaries and deserialization points, suggest runtime validation (Pydantic, isinstance, schema validators).
2. Style and readability. Enforce the language's official style guide and naming conventions (Python: snake_case; TypeScript / Java / C# / Go: camelCase / PascalCase per language). Flag missing docs on public APIs. Flag comments that restate the code, decorative separators, or non-English comments. Flag chained ternaries (≥ 2), nested comprehensions, single-letter names outside conventional cases, functions > 50 lines of executable code, nesting ≥ 4 levels, cyclomatic complexity ≥ 10. Identify dead code (unused imports, unreachable branches).
3. Architecture. Flag classes with > 5 public methods or > 200 lines (likely SRP violation). Flag direct instantiation of external dependencies in business logic (DI violation). Prefer immutable data structures where the language supports them cheaply. Catch the narrowest exception / error type — no catch-all outside top-level boundaries.
4. Performance and security. O(n²) or worse in loops on user-sized data. Synchronous I/O in async contexts. Resources not closed (no context manager, defer, using, or RAII). SQL injection (string-interpolated queries), hardcoded secrets, eval / exec / Function(), unsafe deserialization (pickle, yaml.load), path traversal. N+1 query patterns when an ORM is in use.
Anti-pattern checklist
These are the recurring offenders. Look for each on every review:
- Untyped escape hatch —
Any, any, object, interface{} to bypass the type checker.
- Unsafe defaults — Python mutable default args (
def f(items=[])); JS/TS mutating default object params; Go nil slice/map assumptions.
- God function/class — > 5 public methods or > 200 lines on a class; > 50 lines on a function.
- Catch-all error handling — bare
except:, except Exception:, catch(e) without narrowing, ignored Go error, .unwrap() in library code, catch (Exception e) in Java.
- Hardcoded config — paths, secrets, URLs, timeouts inline.
- N+1 query — sequential queries in loops when an ORM supports batching or eager loading.
For each, the fix is specific, not generic. Don't write "use proper error handling" — write "catch ValueError here; promote to a ParseError so the caller can distinguish parse failures from missing data".
Workflow
- Run the tools. Format check, lint, type check. Capture findings.
- Type-safety pass. Walk every parameter and return. Flag escape hatches with specific replacements.
- Architecture pass. Look for SRP, DI, error-handling shape, immutability opportunities.
- Security and performance pass. Walk anti-pattern checklist. Verify resource lifecycles.
- Style pass. Naming, doc presence, comment quality, dead code.
- Severity assignment. Map each finding to 🔴 / 🟡 / 🔵 using the rubric. If no findings, say "No critical findings" and list residual risks instead of inventing nits.
- Compose review. Sort by severity. Each finding: location, observed behavior, impact, concrete fix. For files > 200 lines, do passes in order: safety → correctness → maintainability → style.
For 🔴 findings involving SQL injection, credential exposure, data deletion, or unsafe deserialization, double-check the suggested fix internally before publishing — these are the cases where a wrong recommendation does real damage.
Python specifics
When reviewing Python, also enforce:
- Google Python Style Guide + PEP 8 / 257 / 484. Variable naming (snake_case), class naming (PascalCase), line length per project config.
- Modern syntax for the project's Python version. Check
python_requires or [tool.ruff] target-version. Suggest list[int] over typing.List (3.9+), X | Y over Union (3.10+), type statement (3.12+) when applicable.
- Google-style docstrings. One-line summary in imperative mood.
Args format name: Description. (no types in docstring — they're in annotations). __init__ args go in the class docstring. Flag missing docstrings on public functions, classes, modules.
- Async hygiene. Flag
open(), requests.get(), time.sleep() inside async def. Suggest aiofiles, httpx.AsyncClient, asyncio.sleep().
- Pythonic patterns. Suggest comprehensions over manual loops, context managers over manual close,
pathlib over os.path, enumerate over manual indices, EAFP over LBYL where appropriate.
Output format
## 📊 Review Summary
- **Quality Score:** [1-10]/10 — (10: no findings; 8-9: 🔵 only; 6-7: ≤ 3 🟡; 4-5: any 🔴; 1-3: multiple 🔴 or security breach)
- **Status:** [Approved | Changes Requested | Critical Issues]
- **Key Strengths:** <bullets>
- **Critical Issues:** <bullets>
## 🔍 Detailed Analysis
| Severity | Location | Issue | Recommendation |
|:--------:|:---------:|:-------------------------------|:--------------------------------|
| 🔴 High | file.ts:12 | <observed behavior> | <concrete fix> |
| 🟡 Med | file.ts:45 | <observed behavior> | <concrete fix> |
| 🔵 Low | file.ts:88 | <observed behavior> | <concrete fix> |
## 💡 Refactoring Suggestions
### 1. <Issue Title>
**Current:**
```<lang>
<before>
```
**Recommended:**
```<lang>
<after>
```
**Reasoning:** <why — reference the rule, PEP, RFC, or design principle>
## 🛡️ Security & Performance Notes
- <specific finding or "no concerns">
If no critical findings, replace the table with **No critical findings.** Residual risks: <list> rather than fabricating issues.
Don't
- Flag style nits when there are unaddressed 🔴 findings — collapse them into a summary row.
- Recommend deprecated syntax (
typing.List on 3.9+, var over let in TS, interface{} over generics in modern Go).
- Write "consider X" without committing to whether X is recommended. The author wants a verdict.
- Flag a violation that would require restructuring > 20 lines of unrelated code as a required change — flag it as a suggestion instead.
- Cite a "violation" without a specific line number and concrete failure mode.
- Recommend insecure shortcuts (disabling type checks, broadening exception handlers) to make a finding "pass".
Example
Input:
function processData(data: any[]) {
let results: any[] = [];
for (let i = 0; i < data.length; i++) {
if (data[i].active) {
results.push(data[i].value * 2);
}
}
return results;
}
Review:
📊 Review Summary
- Quality Score: 5/10
- Status: Changes Requested
- Critical Issues: Untyped
any parameter and return; missing return type; non-idiomatic loop.
🔍 Detailed Analysis
| Severity |
Location |
Issue |
Recommendation |
| 🔴 High |
file.ts:1 |
data: any[] bypasses type safety |
Define DataItem interface, use readonly DataItem[] |
| 🔴 High |
file.ts:2 |
results: any[] loses type information |
Use number[] |
| 🟡 Med |
file.ts:1 |
Missing return type annotation |
Add : number[] |
| 🔵 Low |
file.ts:3 |
C-style for loop is non-idiomatic |
Use .filter().map() chain |
💡 Refactoring Suggestions
1. Type safety + idiomatic style
Current:
function processData(data: any[]) { /* ... */ }
Recommended:
interface DataItem {
active: boolean;
value: number;
}
/** Filter active items, double their values. */
function processData(data: readonly DataItem[]): number[] {
return data.filter((item) => item.active).map((item) => item.value * 2);
}
Reasoning: DataItem replaces any — gains compile-time checking and IDE autocompletion. readonly prevents accidental mutation of the input. .filter().map() removes a class of off-by-one risks the C-style loop carries.
Source: NekoBend/dotfiles — distributed by TomeVault.
1---2name: code-review-923description: Review code for type safety, idiomatic style, architecture, security, and performance, with concrete fixes (not vague nits). Trigger this whenever the user asks to "review", "check", "look over", "audit", "find issues in", or "PR review" some code, or pastes a diff and asks what's wrong. Works on any language with deeper Python checks (Google style, ruff, ty, PEP compliance) when the target is Python. Outputs severity-ranked findings with line numbers and before/after code. Use when this capability is needed.4---56# Code Review78Find real problems and write the fix. Vague feedback ("consider extracting this", "could be cleaner") wastes the author's time. Every finding gets a line number, an observed behavior, an impact, and a concrete code change.910Reason internally in English. Code references and quoted snippets stay in their original form. Final review prose goes in the user's detected language.1112## Detect target language and project conventions13141. From file extension, pasted snippet syntax, or explicit user instruction, identify the language.152. From project files (`pyproject.toml`, `package.json`, `go.mod`, `Cargo.toml`, `.editorconfig`), identify the existing toolchain. **Defer to the project's existing config** — if they use `biome` not `prettier`, review against `biome`. If they have a custom `eslint` config, check against that.163. Run the language's standard checks first and treat their output as the starting list of findings.1718| Language | Formatter | Linter | Type checker |19|------------|----------------------|----------------------------|---------------|20| Python | `ruff format --check` | `ruff check --select ALL` | `ty check` |21| TypeScript | `prettier --check` | `eslint` | `tsc --noEmit` |22| Go | `gofmt -l` | `golangci-lint run` | (built-in) |23| Rust | `rustfmt --check` | `clippy` | (built-in) |24| Java | `google-java-format --dry-run` | `checkstyle` | (built-in) |25| C# | `dotnet format --verify-no-changes` | `dotnet analyzers` | (built-in) |26| Shell | `shfmt -d` | `shellcheck` | N/A |2728## Severity rubric2930| Severity | Trigger |31|------------|----------------------------------------------------------------|32| 🔴 High | Security risk, data loss, crash, undefined behavior, broken contract |33| 🟡 Medium | Type gaps, missing error handling, performance issues on hot paths |34| 🔵 Low | Style, naming, doc gaps, organizational suggestions |3536When at least one 🔴 High exists, collapse all 🔵 Low findings into a single summary row — the author needs to focus.3738## Review criteria3940**1. Type safety (often the highest-leverage finding).** Flag every untyped escape hatch (`Any`, `any`, `object`, `interface{}`) and propose a specific replacement type — `TypedDict`, `Protocol`, generics, discriminated union. Flag missing return types and missing parameter types on public functions. At public API boundaries and deserialization points, suggest runtime validation (Pydantic, `isinstance`, schema validators).4142**2. Style and readability.** Enforce the language's official style guide and naming conventions (Python: snake_case; TypeScript / Java / C# / Go: camelCase / PascalCase per language). Flag missing docs on public APIs. Flag comments that restate the code, decorative separators, or non-English comments. Flag chained ternaries (≥ 2), nested comprehensions, single-letter names outside conventional cases, functions > 50 lines of executable code, nesting ≥ 4 levels, cyclomatic complexity ≥ 10. Identify dead code (unused imports, unreachable branches).4344**3. Architecture.** Flag classes with > 5 public methods or > 200 lines (likely SRP violation). Flag direct instantiation of external dependencies in business logic (DI violation). Prefer immutable data structures where the language supports them cheaply. Catch the narrowest exception / error type — no catch-all outside top-level boundaries.4546**4. Performance and security.** O(n²) or worse in loops on user-sized data. Synchronous I/O in async contexts. Resources not closed (no context manager, `defer`, `using`, or RAII). SQL injection (string-interpolated queries), hardcoded secrets, `eval` / `exec` / `Function()`, unsafe deserialization (`pickle`, `yaml.load`), path traversal. N+1 query patterns when an ORM is in use.4748## Anti-pattern checklist4950These are the recurring offenders. Look for each on every review:51521. **Untyped escape hatch** — `Any`, `any`, `object`, `interface{}` to bypass the type checker.532. **Unsafe defaults** — Python mutable default args (`def f(items=[])`); JS/TS mutating default object params; Go nil slice/map assumptions.543. **God function/class** — > 5 public methods or > 200 lines on a class; > 50 lines on a function.554. **Catch-all error handling** — bare `except:`, `except Exception:`, `catch(e)` without narrowing, ignored Go `error`, `.unwrap()` in library code, `catch (Exception e)` in Java.565. **Hardcoded config** — paths, secrets, URLs, timeouts inline.576. **N+1 query** — sequential queries in loops when an ORM supports batching or eager loading.5859For each, the fix is specific, not generic. Don't write "use proper error handling" — write "catch `ValueError` here; promote to a `ParseError` so the caller can distinguish parse failures from missing data".6061## Workflow62631. **Run the tools.** Format check, lint, type check. Capture findings.642. **Type-safety pass.** Walk every parameter and return. Flag escape hatches with specific replacements.653. **Architecture pass.** Look for SRP, DI, error-handling shape, immutability opportunities.664. **Security and performance pass.** Walk anti-pattern checklist. Verify resource lifecycles.675. **Style pass.** Naming, doc presence, comment quality, dead code.686. **Severity assignment.** Map each finding to 🔴 / 🟡 / 🔵 using the rubric. If no findings, say "No critical findings" and list residual risks instead of inventing nits.697. **Compose review.** Sort by severity. Each finding: location, observed behavior, impact, concrete fix. For files > 200 lines, do passes in order: safety → correctness → maintainability → style.7071For 🔴 findings involving SQL injection, credential exposure, data deletion, or unsafe deserialization, double-check the suggested fix internally before publishing — these are the cases where a wrong recommendation does real damage.7273## Python specifics7475When reviewing Python, also enforce:7677- **Google Python Style Guide + PEP 8 / 257 / 484.** Variable naming (snake_case), class naming (PascalCase), line length per project config.78- **Modern syntax for the project's Python version.** Check `python_requires` or `[tool.ruff] target-version`. Suggest `list[int]` over `typing.List` (3.9+), `X | Y` over `Union` (3.10+), `type` statement (3.12+) when applicable.79- **Google-style docstrings.** One-line summary in imperative mood. `Args` format `name: Description.` (no types in docstring — they're in annotations). `__init__` args go in the class docstring. Flag missing docstrings on public functions, classes, modules.80- **Async hygiene.** Flag `open()`, `requests.get()`, `time.sleep()` inside `async def`. Suggest `aiofiles`, `httpx.AsyncClient`, `asyncio.sleep()`.81- **Pythonic patterns.** Suggest comprehensions over manual loops, context managers over manual close, `pathlib` over `os.path`, `enumerate` over manual indices, EAFP over LBYL where appropriate.8283## Output format8485````markdown86## 📊 Review Summary87- **Quality Score:** [1-10]/10 — (10: no findings; 8-9: 🔵 only; 6-7: ≤ 3 🟡; 4-5: any 🔴; 1-3: multiple 🔴 or security breach)88- **Status:** [Approved | Changes Requested | Critical Issues]89- **Key Strengths:** <bullets>90- **Critical Issues:** <bullets>9192## 🔍 Detailed Analysis9394| Severity | Location | Issue | Recommendation |95|:--------:|:---------:|:-------------------------------|:--------------------------------|96| 🔴 High | file.ts:12 | <observed behavior> | <concrete fix> |97| 🟡 Med | file.ts:45 | <observed behavior> | <concrete fix> |98| 🔵 Low | file.ts:88 | <observed behavior> | <concrete fix> |99100## 💡 Refactoring Suggestions101102### 1. <Issue Title>103**Current:**104```<lang>105<before>106```107**Recommended:**108```<lang>109<after>110```111**Reasoning:** <why — reference the rule, PEP, RFC, or design principle>112113## 🛡️ Security & Performance Notes114- <specific finding or "no concerns">115````116117If no critical findings, replace the table with `**No critical findings.** Residual risks: <list>` rather than fabricating issues.118119## Don't120121- Flag style nits when there are unaddressed 🔴 findings — collapse them into a summary row.122- Recommend deprecated syntax (`typing.List` on 3.9+, `var` over `let` in TS, `interface{}` over generics in modern Go).123- Write "consider X" without committing to whether X is recommended. The author wants a verdict.124- Flag a violation that would require restructuring > 20 lines of unrelated code as a required change — flag it as a suggestion instead.125- Cite a "violation" without a specific line number and concrete failure mode.126- Recommend insecure shortcuts (disabling type checks, broadening exception handlers) to make a finding "pass".127128## Example129130**Input:**131```typescript132function processData(data: any[]) {133 let results: any[] = [];134 for (let i = 0; i < data.length; i++) {135 if (data[i].active) {136 results.push(data[i].value * 2);137 }138 }139 return results;140}141```142143**Review:**144145## 📊 Review Summary146- **Quality Score:** 5/10147- **Status:** Changes Requested148- **Critical Issues:** Untyped `any` parameter and return; missing return type; non-idiomatic loop.149150## 🔍 Detailed Analysis151152| Severity | Location | Issue | Recommendation |153|:--------:|:--------:|:-------------------------------------------|:----------------------------------------|154| 🔴 High | file.ts:1 | `data: any[]` bypasses type safety | Define `DataItem` interface, use `readonly DataItem[]` |155| 🔴 High | file.ts:2 | `results: any[]` loses type information | Use `number[]` |156| 🟡 Med | file.ts:1 | Missing return type annotation | Add `: number[]` |157| 🔵 Low | file.ts:3 | C-style `for` loop is non-idiomatic | Use `.filter().map()` chain |158159## 💡 Refactoring Suggestions160161### 1. Type safety + idiomatic style162**Current:**163```typescript164function processData(data: any[]) { /* ... */ }165```166**Recommended:**167```typescript168interface DataItem {169 active: boolean;170 value: number;171}172173/** Filter active items, double their values. */174function processData(data: readonly DataItem[]): number[] {175 return data.filter((item) => item.active).map((item) => item.value * 2);176}177```178**Reasoning:** `DataItem` replaces `any` — gains compile-time checking and IDE autocompletion. `readonly` prevents accidental mutation of the input. `.filter().map()` removes a class of off-by-one risks the C-style loop carries.179180---181> Source: [NekoBend/dotfiles](https://github.com/NekoBend/dotfiles) — distributed by [TomeVault](https://tomevault.io).182<!-- tomevault:4.0:skill_md:2026-05-22 -->