Build an AI Code Explainer: Understand Any Code Instantly
·
3 min read
·
AI Learning Hub
Project Overview
A CLI tool that takes any code snippet or file and explains it in plain English, identifies potential bugs, suggests improvements, and optionally generates docstrings or comments.
Learning Goals
- Use the OpenAI API for code understanding tasks
- Build a multi-command CLI with Click
- Handle different programming languages in prompts
- Detect language from file extension
Implementation
Step 1: Setup
pip install openai click
Step 2: Code Analysis Functions
# explainer.py
from openai import OpenAI
client = OpenAI()
EXPLAIN_PROMPT = """Explain this {language} code to a developer who hasn't seen it before.
Be clear and concise. Cover: what it does, key logic, and any gotchas.
```{language}
{code}
```"""
BUG_PROMPT = """Review this {language} code for bugs, errors, and potential issues.
List each issue with: (1) description, (2) line/location, (3) how to fix it.
If no bugs found, say so.
```{language}
{code}
```"""
IMPROVE_PROMPT = """Suggest improvements for this {language} code.
Focus on: readability, performance, error handling, best practices.
For each suggestion, show the original and improved version.
```{language}
{code}
```"""
DOCSTRING_PROMPT = """Add docstrings and inline comments to this {language} code.
Return ONLY the commented code, no other text.
```{language}
{code}
```"""
def call_llm(prompt: str) -> str:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
max_tokens=1500,
temperature=0.2,
)
return response.choices[0].message.content
def detect_language(filename: str) -> str:
ext_map = {
".py": "python", ".js": "javascript", ".ts": "typescript",
".go": "go", ".rs": "rust", ".java": "java", ".cpp": "cpp",
".c": "c", ".rb": "ruby", ".sh": "bash", ".sql": "sql",
".html": "html", ".css": "css", ".json": "json",
}
import os
_, ext = os.path.splitext(filename.lower())
return ext_map.get(ext, "code")
def explain_code(code: str, language: str = "python") -> str:
return call_llm(EXPLAIN_PROMPT.format(code=code, language=language))
def find_bugs(code: str, language: str = "python") -> str:
return call_llm(BUG_PROMPT.format(code=code, language=language))
def suggest_improvements(code: str, language: str = "python") -> str:
return call_llm(IMPROVE_PROMPT.format(code=code, language=language))
def add_docstrings(code: str, language: str = "python") -> str:
return call_llm(DOCSTRING_PROMPT.format(code=code, language=language))
Step 3: CLI
# main.py
import click
import sys
from pathlib import Path
from explainer import (
explain_code, find_bugs, suggest_improvements, add_docstrings, detect_language
)
def get_code_and_language(file, code, language):
if file:
path = Path(file)
source_code = path.read_text(encoding="utf-8")
lang = language or detect_language(file)
elif code:
source_code = code
lang = language or "python"
else:
source_code = click.get_text_stream("stdin").read()
lang = language or "python"
return source_code, lang
@click.group()
def cli():
"""AI Code Explainer — understand any code instantly."""
pass
@cli.command()
@click.option("--file", "-f", help="Path to code file")
@click.option("--code", "-c", help="Code snippet as string")
@click.option("--language", "-l", help="Programming language")
def explain(file, code, language):
"""Explain what code does in plain English."""
source_code, lang = get_code_and_language(file, code, language)
click.echo(f"\nExplaining {lang} code...\n")
click.echo(explain_code(source_code, lang))
@cli.command()
@click.option("--file", "-f", help="Path to code file")
@click.option("--code", "-c", help="Code snippet as string")
@click.option("--language", "-l", help="Programming language")
def bugs(file, code, language):
"""Find bugs and potential issues."""
source_code, lang = get_code_and_language(file, code, language)
click.echo(f"\nChecking {lang} code for bugs...\n")
click.echo(find_bugs(source_code, lang))
@cli.command()
@click.option("--file", "-f", help="Path to code file")
@click.option("--code", "-c", help="Code snippet as string")
@click.option("--language", "-l", help="Programming language")
def improve(file, code, language):
"""Suggest code improvements."""
source_code, lang = get_code_and_language(file, code, language)
click.echo(f"\nSuggesting improvements for {lang} code...\n")
click.echo(suggest_improvements(source_code, lang))
@cli.command()
@click.option("--file", "-f", help="Path to code file")
@click.option("--output", "-o", help="Save commented code to file")
@click.option("--language", "-l", help="Programming language")
def document(file, output, language):
"""Add docstrings and comments to code."""
if not file:
click.echo("Error: --file required for document command")
sys.exit(1)
source_code, lang = get_code_and_language(file, None, language)
click.echo(f"\nAdding documentation to {lang} code...\n")
result = add_docstrings(source_code, lang)
if output:
Path(output).write_text(result)
click.echo(f"Documented code saved to {output}")
else:
click.echo(result)
if __name__ == "__main__":
cli()
Step 4: Run
# Explain a file
python main.py explain --file utils.py
# Find bugs in code
python main.py bugs --code "def divide(a, b): return a/b"
# Suggest improvements
python main.py improve --file messy_code.py
# Add documentation
python main.py document --file module.py --output module_documented.py
# Explain from stdin
cat complex_query.sql | python main.py explain --language sql
Extension Ideas
- VS Code extension — right-click any selection → "Explain with AI"
- GitHub Action — run bug checker on every PR automatically
- Complexity scoring — add cyclomatic complexity metrics
- Refactor mode — generate a refactored version of the code
- Multi-file mode — explain an entire Python module/package
What to Learn Next
- AI code review agent → AI Code Review Assistant
- OpenAI API → OpenAI API Complete Guide