DEV Community

myougaTheAxo
myougaTheAxo

Posted on

How to Automate Code Reviews with Claude Code's /code-review Skill

Code reviews are essential — but they're slow, inconsistent, and depend heavily on who's reviewing that day.

Claude Code's /code-review skill changes this. It evaluates your code across 5 dimensions every time, with zero reviewer fatigue. Here's how to put it to work on real code.


What /code-review Actually Does

Run /code-review inside Claude Code and it analyzes the target code across five axes:

Dimension What It Checks
Design Separation of concerns, SOLID principles, dependency structure
Readability Naming conventions, comments, cyclomatic complexity
Security Input validation, auth flows, OWASP Top 10
Testability Mockability, side effect isolation, dependency injection
Performance N+1 queries, unnecessary computation, memory leaks

Basic usage:

# Review current directory
/code-review

# Review a specific file
/code-review src/auth/login.py

# Review only the diff since last commit
/code-review --diff HEAD~1
Enter fullscreen mode Exit fullscreen mode

Example 1: Catching an Auth Vulnerability in Python

The Code (with bugs)

import sqlite3

def login(username, password):
    conn = sqlite3.connect("app.db")
    cursor = conn.cursor()
    # Direct string interpolation — SQL injection waiting to happen
    query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
    cursor.execute(query)
    user = cursor.fetchone()
    conn.close()
    return user is not None
Enter fullscreen mode Exit fullscreen mode

/code-review Output

[Security] CRITICAL
  - SQL injection: f-string used to build query. Switch to parameterized queries.
  - Plaintext password comparison: use bcrypt.checkpw() or equivalent.
  - Fix: cursor.execute("SELECT...", (username, password_hash))

[Design] MEDIUM
  - DB connection mixed with business logic. Extract to a Repository layer.
  - conn.close() must be guaranteed via try/finally or a context manager.

[Testability] MEDIUM
  - Direct DB dependency makes unit testing impossible.
  - Inject the connection (or a factory) as a parameter.

[Performance] LOW
  - Reconnecting on every call is expensive. Consider a connection pool.

[Readability] LOW
  - Missing return type hint. Add -> bool.
Enter fullscreen mode Exit fullscreen mode

Fixed Version

import sqlite3
import bcrypt
from contextlib import contextmanager

@contextmanager
def get_db(path: str = "app.db"):
    conn = sqlite3.connect(path)
    try:
        yield conn
    finally:
        conn.close()

def login(username: str, password: str, db_path: str = "app.db") -> bool:
    with get_db(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute(
            "SELECT password_hash FROM users WHERE username = ?",
            (username,)
        )
        row = cursor.fetchone()
    if row is None:
        return False
    return bcrypt.checkpw(password.encode(), row[0].encode())
Enter fullscreen mode Exit fullscreen mode

Two critical vulnerabilities caught before the PR was opened.


Example 2: JavaScript async/await Error Handling

The Code (with bugs)

async function fetchUserData(userId) {
  const response = await fetch(`/api/users/${userId}`);
  const data = response.json(); // missing await
  return data.name;
}
Enter fullscreen mode Exit fullscreen mode

/code-review Output

[Design] CRITICAL
  - response.json() is missing await. Returns a Promise, so data.name is always undefined.

[Security] MEDIUM
  - userId interpolated directly into URL. Use encodeURIComponent() on the client side.
  - Server-side validation is also required.

[Error Handling] CRITICAL
  - No try/catch for network failures.
  - No response.ok check — 4xx/5xx responses pass through silently.

[Testability] MEDIUM
  - fetch is referenced globally. Accept fetchFn as a parameter for easy mocking in tests.
Enter fullscreen mode Exit fullscreen mode

Fixed Version

async function fetchUserData(userId, fetchFn = fetch) {
  const safeId = encodeURIComponent(userId);
  let response;
  try {
    response = await fetchFn(`/api/users/${safeId}`);
  } catch (err) {
    throw new Error(`Network error: ${err.message}`);
  }
  if (!response.ok) {
    throw new Error(`API error: ${response.status}`);
  }
  const data = await response.json();
  return data.name;
}
Enter fullscreen mode Exit fullscreen mode

The missing await would have caused a silent runtime bug. The error handling gaps would have made debugging a nightmare in production.


Pairing /code-review with /refactor-suggest

The two commands work well together in a loop:

Step 1: /code-review src/auth/login.py
        → Get the problem list

Step 2: /refactor-suggest src/auth/login.py --focus security
        → Generate a targeted fix for the security issues only

Step 3: Review and apply the generated code

Step 4: /code-review src/auth/login.py
        → Confirm improvement, repeat for next axis
Enter fullscreen mode Exit fullscreen mode

Using --focus keeps each iteration scoped and reviewable. Don't try to fix all five dimensions in one pass.


Automating PR Reviews with GitHub Actions

Combine /code-review with GitHub Actions to post review comments automatically on every pull request:

# .github/workflows/code-review.yml
name: AI Code Review
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Run /code-review on PR diff
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          npx claude-code /code-review --diff origin/main \
            --output-format github-comment \
            --post-to-pr ${{ github.event.pull_request.number }}
Enter fullscreen mode Exit fullscreen mode

With this setup:

  • First-pass review happens instantly, with no reviewer availability dependency
  • The 5-axis evaluation is consistent across every PR, every time
  • Human reviewers can focus on design decisions and business logic

The Real Value

The examples above caught a SQL injection vulnerability and a broken async function — both of which would have shipped to production without this review. The review took seconds.

The consistency is the key differentiator. Human reviewers are good, but their attention varies. /code-review applies the same scrutiny to the 47th PR of the week as it does to the first.


Code Review Pack

If you want a ready-made setup — custom 5-axis review templates, GitHub Actions workflow files, and /refactor-suggest integration patterns — I've packaged everything in the Code Review Pack (¥980).

Get the Code Review Pack → PromptWorks

It's the same workflow I use to maintain review quality without blocking shipping velocity.


What's the worst bug a code review caught for you before it shipped? I'm always curious what slips through without a second pair of eyes.

Top comments (0)