Automated code review for security, performance, and maintainability. Use when asked for code review, security audit, quality check, PR review, or to find issues in code.
Before generating any output, read config/defaults.md and adapt all patterns, imports, and code examples to the user's configured stack.
// BAD: SQL injection
const query = `SELECT * FROM users WHERE id = ${userId}`;
// GOOD: Parameterized query
const user = await prisma.user.findUnique({ where: { id: userId } });
// BAD: Rendering unsanitized HTML
<div dangerouslySetInnerHTML={{ __html: userContent }} />
// GOOD: Sanitize or use text content
<div>{sanitizeHtml(userContent)}</div>
// Or just render as text
<div>{userContent}</div>
// BAD: Exposing sensitive data
return NextResponse.json({ user: { ...user, password: user.password } });
// GOOD: Exclude sensitive fields
const { password, ...safeUser } = user;
return NextResponse.json({ user: safeUser });
// BAD
const API_KEY = 'sk-1234567890abcdef';
// GOOD
const API_KEY = process.env.API_KEY;
// BAD: User-controlled file path
const filePath = `./uploads/${req.query.filename}`;
// GOOD: Validate and sanitize
const filename = path.basename(req.query.filename);
const filePath = path.join('./uploads', filename);
See prisma-query-optimizer skill for detection patterns.
// BAD: Event listener not cleaned up
useEffect(() => {
window.addEventListener('resize', handleResize);
}, []);
// GOOD: Cleanup on unmount
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
// BAD: Loading all records
const allUsers = await prisma.user.findMany();
// GOOD: Paginate
const users = await prisma.user.findMany({ take: 50, skip: offset });
// BAD: Blocks event loop
const data = fs.readFileSync('large-file.json');
// GOOD: Async I/O
const data = await fs.promises.readFile('large-file.json');
// BAD
if (status === 3) { ... }
// GOOD
const STATUS_COMPLETED = 3;
if (status === STATUS_COMPLETED) { ... }
// BETTER: Use enum or const object
const Status = { COMPLETED: 3 } as const;
// BAD: Arrow code
if (user) {
if (user.isActive) {
if (user.hasPermission('write')) {
// ...
}
}
}
// GOOD: Early returns
if (!user) return;
if (!user.isActive) return;
if (!user.hasPermission('write')) return;
// ...
Functions over 50 lines or with more than 5 parameters should be broken down.
Unused imports, unreachable code after return/throw, commented-out code blocks.
// BAD: Mixed styles
const user_name = '...';
const userEmail = '...';
const UserAge = 25;
// GOOD: Consistent camelCase for variables
const userName = '...';
const userEmail = '...';
const userAge = 25;
// BAD
const d = new Date();
const arr = users.filter(u => u.a);
// GOOD
const createdAt = new Date();
const activeUsers = users.filter(user => user.isActive);
// BAD: Silent failure
try {
await saveData();
} catch (e) {
// Nothing
}
// GOOD: Log or handle
try {
await saveData();
} catch (error) {
console.error('Failed to save:', error);
throw error; // Or handle appropriately
}
// BAD: Catches everything including programming errors
try {
doSomething();
} catch (e) {
return defaultValue;
}
// GOOD: Catch specific errors
try {
doSomething();
} catch (error) {
if (error instanceof NetworkError) {
return defaultValue;
}
throw error;
}
Flag functions that handle:
API routes and database operations should have integration tests.
## Code Review Report
### Critical (must fix before merge)
| Severity | File | Line | Issue | Category |
|----------|------|------|-------|----------|
| CRITICAL | src/api/users.ts | 45 | SQL injection vulnerability | Security |
**Details:**
- Issue: User input directly interpolated into query string
- Fix: Use parameterized queries via Prisma
```typescript
// Before
const query = `SELECT * FROM users WHERE email = '${email}'`;
// After
const user = await prisma.user.findUnique({ where: { email } });
| Severity | File | Line | Issue | Category | |----------|------|------|-------|----------| | WARNING | src/hooks/useData.ts | 23 | Missing cleanup in useEffect | Performance |
| Severity | File | Line | Issue | Category | |----------|------|------|-------|----------| | INFO | src/utils/format.ts | 12 | Magic number should be named constant | Maintainability |
## Severity-Based Prioritization
After completing the review, sort all findings by severity. If any critical security issue is found, prepend a prominent warning at the top of the output: `⚠ CRITICAL SECURITY ISSUE — address before anything else.` Do not bury critical findings in a long list of minor style suggestions. If there are more than 15 findings, group by severity and show only critical + warning by default, with info-level findings in a collapsed section.
## Reference
See `references/review-checklist.md` for the complete review criteria organized by category.
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer