DEV Community

shashank ms
shashank ms

Posted on

Building a Code Analysis Tool with LLM: A Practical Guide

I shipped a small CLI tool last quarter that runs first-pass code reviews on Python files. It reads a module, sends it to an LLM with a strict system prompt, and returns a structured markdown report covering bugs, style issues, and complexity. If you review a lot of pull requests or inherit legacy code, this cuts the initial triage time significantly.

What you'll need


Step 1: Read the target file


We need a helper that loads the source file into memory. I keep the entire file in one string because Oxlo.ai uses flat per-request pricing (see https://oxlo.ai/pricing), so a 400-line module costs the same as a 10-line script. That removes the need for chunking logic on most files.


import argparse
from pathlib import Path

def load_source(path: str) -> str:
file_path = Path(path).resolve()
if not file_path.exists():
raise FileNotFoundError(f"File not found: {file_path}")
return file_path.read_text(encoding="utf-8")

if name == "main":
parser = argparse.ArgumentParser(description="LLM code review")
parser.add_argument("file", help="Path to the Python file to analyze")
args = parser.parse_args()

code = load_source(args.file)
print(f"Loaded {len(code.splitlines())} lines from {args.file}")
Enter fullscreen mode Exit fullscreen mode

Step 2: Lock down the system prompt


The prompt is the product. I treat it as a config constant that tells the model to act as a senior engineer and to emit only structured markdown.


SYSTEM_PROMPT = """You are a senior software engineer performing a code review.
Analyze the provided Python code for the following:
  • Bugs or logical errors (cite line numbers when possible)
  • Security issues such as unsafe eval or hardcoded secrets
  • Performance or complexity concerns
  • Style and maintainability issues

Output your findings as a structured markdown report with these sections:

Summary

A one-sentence overview of code quality.

Issues

A bullet list. Each bullet must include severity (Critical / Warning / Info), a short description, and a suggested fix.

Complexity Score

Rate complexity from 1 to 10 with a one-line justification.

If the code looks good, state that clearly.
"""

Step 3: Send the code to Oxlo.ai


Oxlo.ai exposes an OpenAI-compatible endpoint, so the standard SDK works with just a base_url swap. I use llama-3.3-70b here because it handles long context well, and the request-based pricing means I do not have to worry about token count when passing in large modules.


from openai import OpenAI

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

def analyze_code(code: str) -> str:
user_message = f"Please review the following Python code:\n\n

{code}

"
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
)
return response.choices[0].message.content

Step 4: Build the CLI wrapper


Now we connect the loader, the analyzer, and a simple argument parser into one script.


import argparse
from pathlib import Path
from openai import OpenAI

SYSTEM_PROMPT = """You are a senior software engineer performing a code review.
Analyze the provided Python code for the following:

  • Bugs or logical errors (cite line numbers when possible)
  • Security issues such as unsafe eval or hardcoded secrets
  • Performance or complexity concerns
  • Style and maintainability issues

Output your findings as a structured markdown report with these sections:

Summary

A one-sentence overview of code quality.

Issues

A bullet list. Each bullet must include severity (Critical / Warning / Info), a short description, and a suggested fix.

Complexity Score

Rate complexity from 1 to 10 with a one-line justification.

If the code looks good, state that clearly.
"""

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

def load_source(path: str) -> str:
file_path = Path(path).resolve()
if not file_path.exists():
raise FileNotFoundError(f"File not found: {file_path}")
return file_path.read_text(encoding="utf-8")

def analyze_code(code: str) -> str:
user_message = f"Please review the following Python code:\n\n

{code}

"
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
)
return response.choices[0].message.content

if name == "main":
parser = argparse.ArgumentParser(description="LLM code review via Oxlo.ai")
parser.add_argument("file", help="Path to the Python file to analyze")
args = parser.parse_args()

code = load_source(args.file)
report = analyze_code(code)
print(report)
Enter fullscreen mode Exit fullscreen mode

Run it


Save the script as review.py, set your key, and point it at any Python file.


$ export OXLO_API_KEY="sk-xxxxxxxx"
$ python review.py app.py

Example output after running against a small Flask-style module:


## Summary
A decent prototype, but it mixes business logic with raw SQL and lacks input validation.

Issues

  • Critical: Line 23 uses string concatenation in a SQL query. This introduces SQL injection. Use parameterized queries instead.
  • Warning: Line 45 calls eval() on user input. Replace with ast.literal_eval or a proper parser.
  • Info: Line 12 function get_data is 80 lines long. Consider breaking it into smaller helpers.

Complexity Score

6/10. The flow is linear, but tight coupling between route handlers and database access increases cognitive load.

Next steps


You can wire this into a pre-commit hook so every modified file gets reviewed before it reaches CI. If you need deeper reasoning on complex algorithms, swap the model to kimi-k2.6 or deepseek-v3.2; Oxlo.ai's request-based pricing stays flat regardless of context length, so the switch does not change your cost structure.

Top comments (0)