Code review is one of the most critical practices in software development. It catches bugs before they reach production, ensures code quality, shares knowledge across teams, and maintains consistent coding standards. Yet, traditional code reviews are time-consuming, inconsistent, and often bottlenecked by senior developer availability. Enter ChatGPT as your always-available code review assistant.
In this comprehensive guide, we'll explore how to leverage ChatGPT for systematic code reviews and refactoring workflows. You'll learn to create custom GPTs tailored to your project's specific standards, develop prompt templates for different review scenarios, and build a feedback loop that continuously improves your code quality.
Why Use ChatGPT for Code Review?
Before diving into techniques, let's understand the unique advantages ChatGPT brings to the code review process:
- 24/7 Availability: Get instant feedback without waiting for team members
- Consistent Standards: Applies the same criteria every time, unlike human reviewers who may vary
- Educational Explanations: Provides detailed reasoning for each suggestion
- Language Agnostic: Reviews code in any programming language with equal proficiency
- Scalability: Reviews unlimited code without fatigue or time constraints
- Pre-filtering: Catches obvious issues before human reviewers spend time on them
Important Caveat
- ChatGPT should augment, not replace, human code review
- AI cannot fully understand business context or architectural decisions
- Always verify AI suggestions, especially for security-critical code
- Use AI as the first pass, humans for final approval
Creating a Custom GPT for Your Project Standards
One of ChatGPT's most powerful features is the ability to create custom GPTs with specialized knowledge and instructions. Here's how to create a code review GPT tailored to your project:
Step 1: Define Your Coding Standards Document
First, create a comprehensive document outlining your project's standards:
# Project Coding Standards for Code Review GPT
## Language: TypeScript/React
## Naming Conventions
- Components: PascalCase (e.g., UserProfile, ShoppingCart)
- Functions: camelCase with verb prefix (e.g., handleSubmit, fetchUserData)
- Constants: SCREAMING_SNAKE_CASE (e.g., MAX_RETRY_COUNT)
- Interfaces: PascalCase with 'I' prefix (e.g., IUserProfile)
- Type aliases: PascalCase without prefix (e.g., UserRole)
## Component Structure
1. Imports (external, then internal, then styles)
2. Type definitions
3. Component function
4. Helper functions (inside component if tightly coupled)
5. Export statement
## Required Patterns
- All async operations must have try-catch with proper error handling
- All API calls must use the centralized apiClient utility
- Forms must use react-hook-form with zod validation
- State management: Zustand for global, useState for local
## Forbidden Patterns
- No inline styles (use Tailwind CSS classes)
- No any type (use unknown if type is truly unknown)
- No console.log in production code (use logger utility)
- No direct DOM manipulation (use refs when necessary)
## Testing Requirements
- All utility functions must have unit tests
- Components must have integration tests for user interactions
- Minimum 80% code coverage for new code
Step 2: Configure the Custom GPT
In ChatGPT's GPT Builder, use these instructions:
# Custom Code Review Assistant Instructions
You are a senior software engineer conducting code reviews for a React/TypeScript
project. Your role is to:
1. ANALYZE code for:
- Security vulnerabilities (XSS, injection, data exposure)
- Performance issues (unnecessary renders, memory leaks, N+1 queries)
- Type safety problems
- Accessibility violations
- Code smell patterns
- Deviation from project standards (see attached document)
2. CATEGORIZE findings by severity:
- CRITICAL: Security vulnerabilities, data loss risks, crashes
- HIGH: Performance issues, type errors, missing error handling
- MEDIUM: Code smells, maintainability concerns, test coverage gaps
- LOW: Style violations, naming issues, documentation gaps
3. FORMAT responses as:
- Issue location (file:line if possible)
- Severity level
- Description of the problem
- Code example showing the fix
- Explanation of why it matters
4. PRAISE good patterns you observe to reinforce positive practices
5. ALWAYS consider the project's specific standards document when reviewing
When reviewing, first acknowledge what the code does well, then provide
constructive feedback organized by severity.
Step 3: Upload Knowledge Files
Upload these documents to your custom GPT:
- Your coding standards document
- Architecture decision records (ADRs)
- API documentation for internal utilities
- Common anti-patterns document with examples
Prompt Templates for Different Review Scenarios
Different review scenarios require different approaches. Here are battle-tested prompt templates:
Template 1: Comprehensive Code Review
Please review the following [LANGUAGE] code for a [PROJECT TYPE] application.
Context:
- Framework: [React/Vue/Angular/etc.]
- This code handles: [brief description of functionality]
- Related to: [feature/module name]
Review criteria (in order of priority):
1. Security vulnerabilities
2. Bug risks and edge cases
3. Performance implications
4. Type safety (if applicable)
5. Error handling completeness
6. Code readability and maintainability
7. Adherence to SOLID principles
8. Test coverage suggestions
For each issue found, please provide:
- Severity: CRITICAL/HIGH/MEDIUM/LOW
- Location: specific line or function
- Problem: clear description
- Solution: code example with fix
- Rationale: why this matters
Code to review:
```[language]
[paste your code here]
```
Template 2: Security-Focused Review
Perform a security-focused code review on the following code.
Application context:
- Type: [web app/API/mobile backend]
- Authentication: [JWT/session/OAuth]
- Data sensitivity: [PII/financial/healthcare/general]
Check specifically for:
1. OWASP Top 10 vulnerabilities
2. Injection risks (SQL, NoSQL, command, XSS)
3. Authentication/authorization flaws
4. Sensitive data exposure
5. Insecure deserialization
6. Security misconfigurations
7. Cryptographic failures
8. Input validation gaps
For each vulnerability found:
- CWE ID if applicable
- Attack vector description
- Proof of concept (safe demonstration)
- Secure code alternative
- Additional hardening recommendations
Code:
```[language]
[paste your code here]
```
Template 3: Performance Review
Review this code specifically for performance issues and optimization opportunities.
Context:
- Expected load: [requests/sec or users]
- Database: [PostgreSQL/MongoDB/etc.]
- Critical path: [yes/no - is this latency-sensitive?]
Analyze for:
1. Time complexity (Big O analysis)
2. Space complexity
3. Database query efficiency (N+1, missing indexes)
4. Memory leaks
5. Unnecessary re-renders (React) or recomputations
6. Caching opportunities
7. Async operation handling
8. Bundle size impact
Provide:
- Current complexity analysis
- Optimized alternatives with complexity
- Benchmarking suggestions
- Trade-offs of each optimization
Code:
```[language]
[paste your code here]
```
Detecting Code Smells with ChatGPT
Code smells are symptoms in code that indicate deeper problems. ChatGPT excels at identifying these patterns:
Common Code Smells ChatGPT Can Detect
// Example: Long Method / God Function
// Before - ChatGPT will flag this
async function processOrder(order: Order) {
// Validate order - 20 lines
if (!order.items || order.items.length === 0) {
throw new Error('Order must have items');
}
if (!order.customer) {
throw new Error('Order must have customer');
}
// ... more validation
// Calculate totals - 30 lines
let subtotal = 0;
for (const item of order.items) {
const price = await getItemPrice(item.id);
subtotal += price * item.quantity;
}
const tax = subtotal * 0.08;
const shipping = calculateShipping(order.address);
const total = subtotal + tax + shipping;
// Process payment - 25 lines
const paymentResult = await chargeCard(order.payment, total);
if (!paymentResult.success) {
throw new Error('Payment failed');
}
// Update inventory - 20 lines
for (const item of order.items) {
await decrementInventory(item.id, item.quantity);
}
// Send notifications - 15 lines
await sendOrderConfirmation(order.customer.email, order);
await notifyWarehouse(order);
return { orderId: order.id, total, paymentId: paymentResult.id };
}
// After refactoring - Clean, single-responsibility functions
async function processOrder(order: Order): Promise<OrderResult> {
validateOrder(order);
const totals = await calculateOrderTotals(order);
const payment = await processPayment(order.payment, totals.total);
await updateInventory(order.items);
await sendNotifications(order, totals);
return {
orderId: order.id,
total: totals.total,
paymentId: payment.id
};
}
Code Smell Detection Prompt
Analyze this code for the following code smells:
1. **Bloaters**: Long methods, large classes, primitive obsession,
long parameter lists, data clumps
2. **Object-Orientation Abusers**: Switch statements, refused bequest,
alternative classes with different interfaces
3. **Change Preventers**: Divergent change, shotgun surgery,
parallel inheritance hierarchies
4. **Dispensables**: Comments (excessive), duplicate code, lazy class,
speculative generality, dead code
5. **Couplers**: Feature envy, inappropriate intimacy, message chains,
middle man, incomplete library class
For each smell found:
- Name the specific smell
- Explain why it's problematic
- Show the offending code section
- Provide refactored alternative
- Estimate effort to fix (quick/medium/significant)
Code:
```[language]
[paste code here]
```
Implementing Systematic Refactoring Workflows
ChatGPT can guide you through structured refactoring processes. Here's a workflow for systematic improvements:
Phase 1: Assessment
// Prompt for initial assessment
I need to refactor this legacy code module. Please help me create a refactoring plan.
Current state:
- Module purpose: [describe what it does]
- Known issues: [list any known problems]
- Constraints: [time, backward compatibility, etc.]
Please analyze and provide:
1. Code quality score (1-10) with justification
2. Top 5 issues to address in priority order
3. Estimated complexity of each refactoring
4. Suggested refactoring sequence
5. Risks and mitigation strategies
6. Test coverage requirements before refactoring
Code:
```[language]
[paste code here]
```
Phase 2: Step-by-Step Refactoring
// Example: Extract Method Refactoring
// Step 1: Identify the code to extract
// Before
function calculateInvoice(customer: Customer, items: Item[]): Invoice {
// Complex discount calculation embedded in the function
let discount = 0;
if (customer.tier === 'gold') {
discount = 0.15;
} else if (customer.tier === 'silver') {
discount = 0.10;
} else if (customer.loyaltyYears > 5) {
discount = 0.05;
}
const subtotal = items.reduce((sum, item) => sum + item.price, 0);
const discountAmount = subtotal * discount;
const tax = (subtotal - discountAmount) * 0.08;
const total = subtotal - discountAmount + tax;
return { customer, items, subtotal, discount: discountAmount, tax, total };
}
// Step 2: Extract with ChatGPT assistance
// Prompt: "Extract the discount calculation into a separate function
// that follows the Strategy pattern for extensibility"
// After
interface DiscountStrategy {
calculate(customer: Customer, subtotal: number): number;
}
class TierBasedDiscount implements DiscountStrategy {
private readonly tierRates: Record<string, number> = {
gold: 0.15,
silver: 0.10,
bronze: 0.05
};
calculate(customer: Customer, subtotal: number): number {
const rate = this.tierRates[customer.tier] || 0;
return subtotal * rate;
}
}
class LoyaltyDiscount implements DiscountStrategy {
calculate(customer: Customer, subtotal: number): number {
if (customer.loyaltyYears > 5) {
return subtotal * 0.05;
}
return 0;
}
}
class DiscountCalculator {
constructor(private strategies: DiscountStrategy[]) {}
calculateBestDiscount(customer: Customer, subtotal: number): number {
return Math.max(
...this.strategies.map(s => s.calculate(customer, subtotal))
);
}
}
function calculateInvoice(
customer: Customer,
items: Item[],
discountCalculator: DiscountCalculator
): Invoice {
const subtotal = items.reduce((sum, item) => sum + item.price, 0);
const discountAmount = discountCalculator.calculateBestDiscount(customer, subtotal);
const tax = (subtotal - discountAmount) * TAX_RATE;
const total = subtotal - discountAmount + tax;
return { customer, items, subtotal, discount: discountAmount, tax, total };
}
Phase 3: Before/After Comparison
// Prompt for generating comparison documentation
Generate a before/after comparison document for this refactoring:
Original code: [paste original]
Refactored code: [paste refactored]
Include:
1. Side-by-side code comparison
2. Metrics comparison:
- Lines of code
- Cyclomatic complexity
- Number of functions/methods
- Coupling metrics
3. Improvements achieved
4. Trade-offs introduced
5. Migration guide for dependent code
6. Test cases that should pass after refactoring
Catching Subtle Bugs with ChatGPT
ChatGPT is particularly effective at finding subtle bugs that escape casual review:
// Example 1: Race Condition Bug
// ChatGPT can identify this subtle issue
async function updateUserBalance(userId: string, amount: number) {
const user = await db.users.findById(userId);
user.balance += amount;
await db.users.save(user);
// BUG: Race condition! Another process could modify balance between
// read and write, causing lost updates
}
// ChatGPT's suggested fix:
async function updateUserBalance(userId: string, amount: number) {
await db.users.updateOne(
{ _id: userId },
{ $inc: { balance: amount } }
);
// Atomic operation prevents race condition
}
// Example 2: Floating Point Precision Bug
function calculateTotal(items: CartItem[]): number {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
// BUG: 0.1 + 0.2 = 0.30000000000000004 in JavaScript
}
// ChatGPT's suggested fix:
function calculateTotal(items: CartItem[]): number {
const cents = items.reduce(
(sum, item) => sum + Math.round(item.price * 100) * item.quantity,
0
);
return cents / 100;
}
// Example 3: Closure Bug in Loop
function createClickHandlers(buttons: HTMLElement[]) {
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
console.log('Button ' + i + ' clicked');
// BUG: All handlers will log the final value of i
};
}
}
// ChatGPT's suggested fix:
function createClickHandlers(buttons: HTMLElement[]) {
buttons.forEach((button, index) => {
button.onclick = () => {
console.log(`Button ${index} clicked`);
};
});
}
Bug Hunting Prompt Template
Analyze this code for subtle bugs that might not cause immediate errors
but could cause issues in production:
Check for:
1. Race conditions and concurrency issues
2. Memory leaks
3. Floating point precision problems
4. Off-by-one errors
5. Null/undefined edge cases
6. Type coercion surprises
7. Closure-related bugs
8. Async/await pitfalls
9. Error handling gaps
10. State mutation side effects
For each bug found:
- Explain why it's a bug
- Describe the failure scenario
- Show a minimal reproduction case
- Provide the corrected code
- Suggest a test case to prevent regression
Code:
```[language]
[paste code here]
```
Architectural Improvement Suggestions
Beyond line-level review, ChatGPT can suggest architectural improvements:
// Prompt for architectural review
Review this module's architecture and suggest improvements:
Module responsibilities:
- [list what this module does]
Current pain points:
- [any known issues]
Questions to answer:
1. Does this module follow the Single Responsibility Principle?
2. Are dependencies properly inverted (Dependency Injection)?
3. Is the module properly encapsulated?
4. Are there opportunities for better abstraction?
5. Should this be split into multiple modules?
6. Are there missing patterns that would improve this? (Repository, Factory, etc.)
Consider our architecture constraints:
- [your constraints]
Code:
```[language]
[paste module code]
```
Example: Service Layer Refactoring
// Before: Tightly coupled service
class OrderService {
async createOrder(data: OrderData) {
// Direct database calls
const order = await prisma.order.create({ data });
// Direct email service call
await sendgrid.send({
to: data.customerEmail,
template: 'order-confirmation',
data: order
});
// Direct payment processing
const charge = await stripe.charges.create({
amount: order.total,
currency: 'usd',
source: data.paymentToken
});
return order;
}
}
// After: ChatGPT-suggested architecture with dependency injection
interface IOrderRepository {
create(data: OrderData): Promise<Order>;
findById(id: string): Promise<Order | null>;
}
interface INotificationService {
sendOrderConfirmation(order: Order): Promise<void>;
}
interface IPaymentGateway {
charge(amount: number, token: string): Promise<PaymentResult>;
}
class OrderService {
constructor(
private readonly orderRepository: IOrderRepository,
private readonly notificationService: INotificationService,
private readonly paymentGateway: IPaymentGateway,
private readonly eventBus: IEventBus
) {}
async createOrder(data: OrderData): Promise<Order> {
// Validate
this.validateOrderData(data);
// Process payment first (fail fast)
const paymentResult = await this.paymentGateway.charge(
data.total,
data.paymentToken
);
// Create order
const order = await this.orderRepository.create({
...data,
paymentId: paymentResult.id,
status: 'confirmed'
});
// Emit event for async processing (notification, inventory, etc.)
await this.eventBus.publish(new OrderCreatedEvent(order));
return order;
}
private validateOrderData(data: OrderData): void {
// Validation logic
}
}
Measuring Code Quality Improvements Over Time
Track the impact of ChatGPT-assisted reviews with these metrics:
// metrics-tracker.ts
interface CodeQualityMetrics {
timestamp: Date;
module: string;
// Complexity metrics
cyclomaticComplexity: number;
cognitiveComplexity: number;
linesOfCode: number;
// Maintainability
duplicateCodePercentage: number;
testCoverage: number;
documentationCoverage: number;
// Issues
criticalIssues: number;
highIssues: number;
mediumIssues: number;
lowIssues: number;
// Technical debt
estimatedDebtHours: number;
}
class QualityMetricsTracker {
async captureMetrics(modulePath: string): Promise<CodeQualityMetrics> {
const [
complexity,
coverage,
duplication,
issues
] = await Promise.all([
this.analyzeComplexity(modulePath),
this.getTestCoverage(modulePath),
this.detectDuplication(modulePath),
this.runStaticAnalysis(modulePath)
]);
return {
timestamp: new Date(),
module: modulePath,
cyclomaticComplexity: complexity.cyclomatic,
cognitiveComplexity: complexity.cognitive,
linesOfCode: complexity.loc,
duplicateCodePercentage: duplication.percentage,
testCoverage: coverage.percentage,
documentationCoverage: coverage.docCoverage,
criticalIssues: issues.critical,
highIssues: issues.high,
mediumIssues: issues.medium,
lowIssues: issues.low,
estimatedDebtHours: this.calculateDebtHours(issues)
};
}
generateTrendReport(history: CodeQualityMetrics[]): TrendReport {
// Analyze improvement trends over time
return {
complexityTrend: this.calculateTrend(history, 'cyclomaticComplexity'),
coverageTrend: this.calculateTrend(history, 'testCoverage'),
issueTrend: this.calculateTrend(history, 'criticalIssues'),
overallHealthScore: this.calculateHealthScore(history[history.length - 1])
};
}
}
Integrating ChatGPT into Your Review Workflow
Here's a practical workflow for incorporating ChatGPT reviews:
Workflow: Pre-PR ChatGPT Review
# .github/workflows/chatgpt-review.yml (conceptual)
# Note: This requires a custom action or integration
name: AI Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
ai-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed files
id: changed
run: |
echo "files=$(git diff --name-only origin/main...HEAD | grep -E '\.(ts|tsx|js|jsx)$' | tr '\n' ' ')" >> $GITHUB_OUTPUT
- name: Run AI Review
uses: your-org/chatgpt-review-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
files: ${{ steps.changed.outputs.files }}
review-prompt: |
Review these changes for:
1. Security vulnerabilities
2. Performance issues
3. Type safety
4. Our coding standards (see .github/CODING_STANDARDS.md)
Post findings as PR comments with severity labels.
- name: Post Review Summary
uses: actions/github-script@v7
with:
script: |
// Post AI review summary as PR comment
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: process.env.AI_REVIEW_SUMMARY
})
Key Takeaways
Remember These Points
- Create custom GPTs with your project's specific coding standards for consistent, context-aware reviews
- Use structured prompt templates for different review scenarios: security, performance, comprehensive
- ChatGPT excels at detecting code smells like long methods, duplicate code, and feature envy
- Systematic refactoring workflows with ChatGPT include assessment, step-by-step changes, and before/after comparisons
- AI catches subtle bugs humans often miss: race conditions, floating-point issues, closure bugs
- Track quality metrics over time to measure the impact of AI-assisted reviews
- Integrate into CI/CD for automated pre-PR reviews, but keep human approval for final merge
Conclusion
ChatGPT transforms code review from a bottleneck into a scalable, consistent process. By creating custom GPTs with your project standards, using structured prompt templates, and implementing systematic refactoring workflows, you can dramatically improve code quality while freeing senior developers for higher-value architectural decisions.
The key is treating ChatGPT as a knowledgeable junior reviewer that never gets tired, never misses obvious issues, and always has time for detailed explanations. Combine this with human oversight for architectural decisions and security-critical code, and you have a powerful code quality system.
Start with a simple prompt template, measure your baseline metrics, and iteratively refine your approach. The improvements compound over time as your custom GPT learns your project's patterns and your team develops effective prompting strategies.
In the next article, we'll explore Claude for Technical Documentation and API Design, diving deep into Anthropic's powerful alternative for different use cases in your development workflow.