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.
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:
- Takes a path to a C# file as input.
- Reads the code content.
- Sends it to an AI model (hosted on GitHub Models) with a specific system prompt.
- Generates a detailed Markdown report covering Security, Performance, and Best Practices.
- 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.2makes 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.
Related Articles
Mastering ASP.NET Core Middleware: From Basics to Advanced (.NET 10)
A comprehensive deep dive into ASP.NET Core Middleware. Learn how the request pipeline works, how to build high-performance custom middleware, and implement real-world patterns like Multi-Tenancy, Request Logging, and API Key Authentication.
MongoDB Mastery: Advanced Features and Integration - Part 3
Explore MongoDB's advanced features including aggregation pipelines, transactions, change streams, and integration patterns with real-world applications using C# and .NET.
Full Stack Insights
Software Engineer
Passionate about software development, architecture, and sharing knowledge.
Quick Links
Full Stack Insights
Software Engineer
Passionate about software development, architecture, and sharing knowledge with the community.