Tips & Tricks

Code Review Checklist with Claude Code

A practical code review checklist using Claude Code for improving code quality.

Streamline Code Reviews With Claude Code

Code reviews are an important process for maintaining quality, but they place a heavy burden on reviewers. By leveraging Claude Code, you can run efficient reviews based on a systematic checklist.

Security Checks

> Review the code in this PR from a security angle.
> Check for XSS, SQL injection, and authentication vulnerabilities.
// Security checklist
const securityChecks = {
  // 1. Input validation
  inputValidation: {
    check: 'Is user input sanitized?',
    bad: `element.innerHTML = userInput;`,
    good: `element.textContent = userInput;`,
  },

  // 2. SQL injection
  sqlInjection: {
    check: 'Are parameterized queries used?',
    bad: `db.query(\`SELECT * FROM users WHERE id = \${userId}\`);`,
    good: `db.query('SELECT * FROM users WHERE id = ?', [userId]);`,
  },

  // 3. AuthN/AuthZ
  auth: {
    check: 'Do API endpoints have auth middleware?',
    bad: `app.get('/api/admin/users', handler);`,
    good: `app.get('/api/admin/users', requireAuth, requireAdmin, handler);`,
  },

  // 4. Secret exposure
  secrets: {
    check: 'Are environment variables leaking to the client?',
    bad: `const apiKey = "sk-1234567890abcdef";`,
    good: `const apiKey = process.env.API_KEY;`,
  },
};

Performance Checks

// Performance checklist
const performanceChecks = [
  {
    item: 'Are there any N+1 queries?',
    bad: `
      const users = await db.user.findMany();
      for (const user of users) {
        const posts = await db.post.findMany({ where: { userId: user.id } });
      }`,
    good: `
      const users = await db.user.findMany({
        include: { posts: true },
      });`,
  },
  {
    item: 'Are there unnecessary re-renders?',
    bad: `
      function Component() {
        const handler = () => doSomething();
        return <Child onClick={handler} />;
      }`,
    good: `
      function Component() {
        const handler = useCallback(() => doSomething(), []);
        return <Child onClick={handler} />;
      }`,
  },
  {
    item: 'Is virtualization applied to large lists?',
    check: 'Lists with 1000+ items -> consider react-virtual',
  },
];

Readability and Maintainability Checks

> Suggest improvements for readability in this code.
> Check naming conventions, function length, and the usefulness of comments.
// Readability checklist

// 1. Function length (ideally under 30 lines)
// BAD: a single function that does everything
async function processOrder(order: Order) {
  // 100 lines of logic...
}

// GOOD: split by responsibility
async function processOrder(order: Order) {
  const validated = validateOrder(order);
  const priced = calculateTotal(validated);
  const payment = await processPayment(priced);
  return createConfirmation(payment);
}

// 2. Early return pattern
// BAD: deep nesting
function getDiscount(user: User) {
  if (user) {
    if (user.isPremium) {
      if (user.orders > 10) {
        return 0.2;
      }
      return 0.1;
    }
    return 0.05;
  }
  return 0;
}

// GOOD: early returns
function getDiscount(user: User) {
  if (!user) return 0;
  if (!user.isPremium) return 0.05;
  if (user.orders > 10) return 0.2;
  return 0.1;
}

// 3. Eliminating magic numbers
// BAD
if (status === 3) { /* ... */ }

// GOOD
const ORDER_STATUS = { PENDING: 1, PROCESSING: 2, COMPLETED: 3 } as const;
if (status === ORDER_STATUS.COMPLETED) { /* ... */ }

Error Handling Checks

// Points to check in error handling

// BAD: swallowing errors
try {
  await saveData(data);
} catch (e) {
  // do nothing
}

// GOOD: proper error handling
try {
  await saveData(data);
} catch (error) {
  logger.error('Failed to save data', { error, data: data.id });
  throw new AppError('SAVE_FAILED', 'Failed to save data', { cause: error });
}

Review Automation Script

// scripts/review-check.ts
import { execSync } from 'child_process';

interface ReviewIssue {
  file: string;
  line: number;
  severity: 'error' | 'warning' | 'info';
  message: string;
}

function checkForIssues(): ReviewIssue[] {
  const issues: ReviewIssue[] = [];
  const diff = execSync('git diff --cached --name-only').toString().split('\n');

  for (const file of diff.filter(f => f.endsWith('.ts') || f.endsWith('.tsx'))) {
    const content = execSync(`git show :${file}`).toString();
    const lines = content.split('\n');

    lines.forEach((line, index) => {
      // Check for console.log
      if (line.includes('console.log') && !file.includes('scripts/')) {
        issues.push({
          file, line: index + 1, severity: 'warning',
          message: 'console.log is still present',
        });
      }

      // Check for TODO/FIXME
      if (/\/\/\s*(TODO|FIXME|HACK)/i.test(line)) {
        issues.push({
          file, line: index + 1, severity: 'info',
          message: 'TODO/FIXME comment found',
        });
      }

      // Check for `any`
      if (/:\s*any\b/.test(line)) {
        issues.push({
          file, line: index + 1, severity: 'warning',
          message: '`any` type is being used',
        });
      }
    });
  }

  return issues;
}

const issues = checkForIssues();
issues.forEach(i => console.log(`[${i.severity}] ${i.file}:${i.line} - ${i.message}`));

Summary

Code review is closely tied to your testing strategy. With Claude Code, you can systematically review code from the angles of security, performance, and readability. Combined with AI pair programming techniques, you can improve both review quality and speed simultaneously. For code review best practices, see Google Engineering Practices.

#Claude Code #code review #quality assurance #checklist #automation

Level up your Claude Code workflow

50 battle-tested prompt templates you can copy-paste into Claude Code right now.

Free

Free PDF: Claude Code Cheatsheet in 5 Minutes

Key commands, shortcuts, and prompt examples on a single printable page.

Download PDF
M

About the Author

Masa

Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.