Building a Smart Code Reviewer with .NET and GitHub Models

Learn how to build a CLI tool that uses GitHub Models and Azure AI Inference SDK to automatically review C# code for security, performance, and best practices.

FSI
Full Stack Insights
••5 min read•...

Building a Smart Code Reviewer with .NET and GitHub Models

In the era of AI, automating mundane tasks is a superpower for developers. One such task is code review. While human review is irreplaceable for context and logic, AI can be an excellent first line of defense for catching security issues, performance bottlenecks, and style violations.

In this article, we'll build a Smart Code Reviewer CLI tool using .NET 8 and GitHub Models. We'll leverage the Azure.AI.Inference SDK to interact with powerful models like gpt-4o directly from our C# application.

What We're Building

We will create a console application that:

  1. Takes a path to a C# file as input.
  2. Reads the code content.
  3. Sends it to an AI model (hosted on GitHub Models) with a specific system prompt.
  4. Generates a detailed Markdown report covering Security, Performance, and Best Practices.
  5. Provides a refactored version of the code.

Prerequisites

  • .NET 8 SDK installed.
  • A GitHub Account to generate a Personal Access Token (PAT).
  • Access to GitHub Models Marketplace (currently in public beta).

Step 1: Project Setup

First, let's create a new console application and add the necessary NuGet packages.

dotnet new console -n SmartCodeReviewer
cd SmartCodeReviewer

# Add Azure AI Inference SDK
dotnet add package Azure.AI.Inference --prerelease

# Add Configuration packages
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables

Step 2: Configuration

We need a place to store our API configuration. Create an appsettings.json file:

{
  "GitHubModels": {
    "Endpoint": "https://models.inference.ai.azure.com",
    "ModelName": "gpt-4o",
    "Token": "YOUR_GITHUB_PAT_HERE"
  }
}

Security Note: Never commit your secrets to source control! We'll use .NET User Secrets for the actual token during development.

dotnet user-secrets init
dotnet user-secrets set "GitHubModels:Token" "ghp_YourActualGitHubPAT"

Let's define a settings class to map this configuration:

public class GitHubModelsSettings
{
    public string Endpoint { get; set; }
    public string ModelName { get; set; }
    public string Token { get; set; }
}

Step 3: The Code Review Service

This is the core of our application. The CodeReviewService handles the communication with the AI model. We use the ChatCompletionsClient from the Azure.AI.Inference library.

Create a Services folder and add CodeReviewService.cs:

using Azure;
using Azure.AI.Inference;
using System.Text;

namespace SmartCodeReviewer.Services;

public class CodeReviewService
{
    private readonly ChatCompletionsClient _client;
    private readonly string _modelName;

    public CodeReviewService(GitHubModelsSettings settings)
    {
        _client = new ChatCompletionsClient(
            new Uri(settings.Endpoint),
            new AzureKeyCredential(settings.Token));
        _modelName = settings.ModelName;
    }

    public async Task<string> ReviewCodeAsync(string codeContent)
    {
        var systemPrompt = @"You are a Senior C# Architect and Security Expert. 
Your goal is to review the provided C# code.

Please provide your output in the following Markdown format:

# Code Review Report

## 1. Security Analysis
(List any security vulnerabilities found, or state 'No critical vulnerabilities found'.)

## 2. Performance Analysis
(Identify potential performance bottlenecks.)

## 3. Code Style & Best Practices
(Critique the code style, naming conventions, and adherence to SOLID principles.)

## 4. Refactored Code
(Provide the complete, refactored version of the code in a C# code block. Ensure it compiles and fixes the issues mentioned above.)
";

        var response = await _client.CompleteAsync(
            new ChatCompletionsOptions()
            {
                Messages =
                {
                    new ChatRequestSystemMessage(systemPrompt),
                    new ChatRequestUserMessage($"Please review this code:\n\n{codeContent}")
                },
                Model = _modelName,
                Temperature = 0.2f // Low temperature for more deterministic results
            });

        return response.Value.Content;
    }
}

Key Takeaways:

  • System Prompt: We define a persona ("Senior C# Architect") and a strict output format. This ensures the AI returns structured data we can save directly as a Markdown file.
  • Temperature: Setting it to 0.2 makes the model less creative and more analytical, which is perfect for code reviews.

Step 4: The Main Program

Now, let's wire everything together in Program.cs. We'll set up configuration, initialize the service, and handle user input.

using Microsoft.Extensions.Configuration;
using SmartCodeReviewer;
using SmartCodeReviewer.Services;

// 1. Setup Configuration
var config = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddUserSecrets(System.Reflection.Assembly.GetExecutingAssembly())
    .AddEnvironmentVariables()
    .Build();

var settings = new GitHubModelsSettings();
config.GetSection("GitHubModels").Bind(settings);

// Validate Config
if (string.IsNullOrWhiteSpace(settings.Token) || settings.Token == "YOUR_GITHUB_PAT_HERE")
{
    Console.ForegroundColor = ConsoleColor.Red;
    Console.WriteLine("Error: Please configure your GitHub PAT.");
    return;
}

// 2. Initialize Service
var reviewer = new CodeReviewService(settings);

// 3. Get Input File
Console.WriteLine("Smart Code Reviewer CLI");
Console.WriteLine("-----------------------");
Console.Write("Enter the path to the C# file to review: ");
var filePath = Console.ReadLine()?.Trim('"');

if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath))
{
    Console.ForegroundColor = ConsoleColor.Red;
    Console.WriteLine("Error: File not found.");
    return;
}

// 4. Read File
string codeContent = await File.ReadAllTextAsync(filePath);

Console.WriteLine("\nšŸ” Analyzing Code... (This may take a moment)");

// 5. Execute AI Review
try
{
    var reviewReport = await reviewer.ReviewCodeAsync(codeContent);

    // 6. Save Report
    var reportPath = Path.Combine(
        Path.GetDirectoryName(filePath) ?? Directory.GetCurrentDirectory(),
        $"Review_{Path.GetFileNameWithoutExtension(filePath)}.md");

    await File.WriteAllTextAsync(reportPath, reviewReport);

    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine($"\nāœ… Review Complete! Report saved to:");
    Console.WriteLine(reportPath);
    Console.ResetColor();
}
catch (Exception ex)
{
    Console.ForegroundColor = ConsoleColor.Red;
    Console.WriteLine($"\nāŒ Critical Failure: {ex.Message}");
}

Step 5: Running the Tool

Now you can run your tool and point it at any C# file on your disk.

dotnet run

When prompted, paste the path to a C# file (e.g., C:\Projects\LegacyApp\UserService.cs). The tool will generate a Review_UserService.md file in the same directory, containing the AI's analysis and a refactored version of your code.

Conclusion

By combining the .NET ecosystem with GitHub Models, we've built a powerful productivity tool in under 100 lines of code. This pattern can be extended to:

  • Generate unit tests automatically.
  • Translate code between languages.
  • Write documentation for legacy codebases.

The Azure.AI.Inference SDK provides a unified way to access various models, making it easy to swap gpt-4o for other models like Phi-3 or Llama-3 depending on your needs.

Share this article:

Related Articles

FSI

Full Stack Insights

Software Engineer

Passionate about software development, architecture, and sharing knowledge with the community.