-
-
Clean, dark dashboard UI — paste a repo URL, upload a log file, and diagnose.
-
Instant summary: total errors, unique types, files affected, and critical/high count.
-
A second AI pass groups errors that share a root cause, then lists every issue ranked by severity.
-
Tested live on a completely different, unfamiliar repo — not the one RepoDoctor was built to analyze.
-
Correctly parsed a real sqlalchemy.exc.OperationalError and flagged it CRITICAL — on a repo it had never seen before.
-
Full diagnosis grounded in the actual cloned code: root cause, fix, and the real surrounding source — not a guess.
-
How it works: log parsing → repo cloning → code + git history context → LLM diagnosis → correlation → dashboard.
Inspiration
Debugging is slow, and it's slow in a specific way: a stack trace tells you where something broke, but not why. When something fails, the usual move is to copy the error into ChatGPT — but generic AI chatbots can't see your actual codebase, so their answers are educated guesses, not grounded diagnoses.
I wanted to build something that closes that gap: an AI agent that doesn't just read an error message, but actually goes and looks at your real code before saying anything.
What it does
RepoDoctor takes two inputs — a GitHub repository URL and a log/error file — and:
- Parses the log for both full Python tracebacks and single-line
ERROR/CRITICAL/FATALmessages, including fully-qualified error types likesqlalchemy.exc.OperationalError - Clones the actual repository and pulls the exact lines of code around each failing line — not a snippet the AI imagines, the real code
- Checks recent git history on the affected file, so the diagnosis can factor in "this broke right after a recent commit changed X"
- Diagnoses each error with an LLM, grounded in that real code and history, returning a root cause, a suggested fix, a confidence level, and a severity rating (critical/high/medium/low)
- Correlates errors across the whole batch in a second pass, to catch cases where multiple failures share one underlying root cause
- Presents everything in a clean, dark, dashboard-style UI — summary metrics, severity-ranked error cards, before/after diff suggestions, and honest "I couldn't find this file" warnings when confidence is low, instead of guessing silently
How I built it
The whole project runs as a single Streamlit process — no separate backend server. The pipeline logic (log parsing, repo cloning via GitPython, code context extraction, LLM prompting via the OpenAI API) lives in a backend/ module, and the Streamlit frontend calls those functions directly, in-process. This turned out to be the key architectural decision: it made the app trivially deployable on Streamlit Community Cloud with zero extra infrastructure, since there was no second server to stand up or coordinate.
I built it incrementally: get a minimal end-to-end pipeline working first (parse → clone → match → diagnose → display), confirm it with a real API call, then layer in features one at a time — git-history awareness, severity scoring, multi-error correlation, generic log format support, and diff suggestions — testing each addition before moving to the next, since every LLM call costs real API budget.
Challenges I ran into
- Regex fragility on real-world data. My initial error-type regex only matched simple names like
ZeroDivisionError. When I tested RepoDoctor against a completely different, unfamiliar repo of mine (not the one it was built to analyze), it silently failed to detect a realsqlalchemy.exc.OperationalError— because that error type has dots in it, and\w+doesn't match dots. Testing on a stranger's real repo, rather than just my own project, is what caught this. - Streamlit's HTML rendering quirks. Splitting an HTML
<div>open tag and its closing tag across two separatest.markdown()calls doesn't nest the way you'd expect — the browser auto-closes the div immediately, leaving empty boxes in the layout. The fix was switching to Streamlit's nativest.container(border=True)instead of manually building HTML card wrappers. - Architecting for deployment from the start mattered. I originally built this with a separate FastAPI backend that the Streamlit frontend called over HTTP. That worked locally, but Streamlit Community Cloud only runs one process — so before deploying, I refactored the frontend to import and call the backend functions directly, removing the HTTP layer and the FastAPI/uvicorn dependency entirely.
What I learned
- Testing your own tool on your own code only proves it works on code you already wrote in a way it expects. Testing it on a genuinely unfamiliar repo is what actually proves it generalizes — and it's where the real bugs showed up.
- Grounding an LLM's output in real, retrieved context (actual code, actual git history) produces meaningfully more trustworthy answers than just feeding it an error message and hoping.
- Small architectural decisions made early (like whether to keep the backend as a separate service) have outsized effects on how easy deployment ends up being later.
What's next for RepoDoctor
- Support for stack trace formats beyond Python (JavaScript/Node, Java, etc.)
- Support for private repositories via authenticated cloning
- Turning the "before/after" diff suggestion into an actual applied patch or draft pull request, rather than just a suggestion to copy manually
Built With
- community
- css
- git
- gitpython
- gpt-4o-mini
- llm
- machine-learning
- natural-language-processing
- openai-api
- python
- rest-api
- streamlit
Log in or sign up for Devpost to join the conversation.