code-reviewer について
プロジェクトファイルをセキュリティ、性能、保守性、命名、エラー処理、テストの観点から確認するスキルです。最初に config/defaults.md を読み、重要度順の指摘と具体的な修正案を出力します。
主な機能
- 01セキュリティとインジェクションのリスクを確認
- 02性能と保守性の問題を確認
- 03命名、エラー処理、テスト網羅率を評価
- 04重要度順に指摘を整理
- 05実行可能な修正案を提示
活用シーン
- 01プルリクエストの差分をレビュー
- 02プロジェクトファイルのセキュリティ欠陥を検出
- 03テストやエラー処理の不足を特定
- 04マージ前に修正項目を優先順位付け
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ nembie/ claude-code-skills --skill code-reviewerインストール後、Claude Code で/code-reviewerを入力して読み込まれたか確認します。
同梱ファイルreferences/review-checklist.md
詳細
コードレビュー担当
出力を生成する前に、config/defaults.md を読み、すべてのパターン、インポート、コード例をユーザーが設定したスタックに合わせてください。
レビュープロセス
- 対象範囲のすべてのファイルを読みます(指定されたファイル、PR の差分、またはプロジェクト全体)
- 以下のレビューカテゴリに照らして、各ファイルを分析します
- 重要度を付けて、構造化された指摘を出力します
- 実行可能な修正案を提示します
レビューカテゴリ
セキュリティ
インジェクションの脆弱性
// BAD: SQL injection
const query = `SELECT * FROM users WHERE id = ${userId}`;
// GOOD: Parameterized query
const user = await prisma.user.findUnique({ where: { id: userId } });
XSS(クロスサイトスクリプティング)
// 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);
パフォーマンス
N+1 クエリ
検出パターンについては、prisma-query-optimizer スキルを参照してください。
メモリーリーク
// 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 });
同期的なファイル I/O
// 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;
// ...
巨大な関数
50 行を超える関数、または引数が 5 個を超える関数は、分割してください。
デッドコード
未使用のインポート、return/throw の後に実行されないコード、コメントアウトされたコードブロック。
命名規則
一貫性のない命名
// 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
}
汎用的な catch
// 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;
}
テストカバレッジの不足
未テストのエッジケース
以下を処理する関数にフラグを付けます。
- テストがない null/undefined の入力
- テストがない空の配列/オブジェクト
- テストがないエラー条件
- テストがない境界値
統合テストの不足
API ルートとデータベース操作には統合テストが必要です。
出力形式
## 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 } });
警告(修正が必要)
| 重要度 | ファイル | 行 | 問題 | カテゴリ |
|---|---|---|---|---|
| WARNING | src/hooks/useData.ts | 23 | useEffect のクリーンアップがありません | パフォーマンス |
情報(提案)
| 重要度 | ファイル | 行 | 問題 | カテゴリ |
|---|---|---|---|---|
| INFO | src/utils/format.ts | 12 | マジックナンバーは名前付き定数にする必要があります | 保守性 |
概要
- 重大:X 件
- 警告:X 件
- 情報:X 件
- レビューしたファイル:X 件
## 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.
コメント
Markdown 対応