Every developer has felt it. You join a new project, someone points you at a GitHub repo, and says "just explore the code." Two hours later you're still reading files one by one, trying to figure out which file talks to which, where the actual logic lives, and why there are four different things called "manager."
I got tired of that. So I built something about it.
The idea was simple. The execution wasn't.
Give it a GitHub URL. It clones the repo, figures out the architecture, and hands you an interactive dependency graph with a natural-language summary of how everything fits together.
Simple idea. Except — how do you actually teach a machine to understand a codebase the way a senior engineer would?
You don't write rules. You give it tools and let it explore.
The agent
The core of CodeNarrator is an agentic loop. A locally-hosted LLM — Qwen2.5-Coder 7B running via Ollama — gets five tools:
read_file — open a source file
follow_import — jump to a file this one imports
search_for_pattern — grep across the repo
mark_architecture_insight — record a finding
stop_analysis — finish when done
The model decides what to read, what to follow, and when it has seen enough. No hardcoded traversal logic. No hand-written rules about which files matter. The agent figures it out.
At least, that was the theory.
Problem 1: The agent was lazy
Left to its own devices, the model would find main.py or App.tsx, follow one import chain all the way down, and call it done. It explored ten files in a 44-file repo and declared victory.
The dependency graph looked like a stick figure.
The fix wasn't obvious. The scoring system that ranked candidate files was biased toward depth — files in the current import chain scored higher than files in unexplored directories. The agent was being rewarded for going deep rather than wide.
I rebuilt the scoring: unvisited directories now get a bonus. The nudge logic was rewritten to surface files from folders the agent hadn't touched yet. The system prompt explicitly tells the model "after every 2-3 files in the same directory, go somewhere new."
The graphs started looking like actual architectures.
Problem 2: Python repos had zero edges
I ran CodeNarrator on a FastAPI project and got a beautiful graph — of nothing. Every node was floating, disconnected. Zero internal edges.
The bug was in _detect_python_package_roots. For repos where all packages live inside a backend/ or src/ wrapper, the function was returning "." as the package root instead of "backend". So when the import extractor tried to resolve import db.database, it was looking in the wrong place. Every internal import was silently treated as external.
One wrong assumption, buried three function calls deep, was making the entire graph useless for a huge class of real-world Python projects.
Fixed it. Went from zero edges to 35+ on the next run.
Problem 3: TypeScript components were invisible
The file scanner didn't have .tsx in its extension map. Every React component in every TypeScript project was being silently skipped — scanned past, never explored, appearing only as grey phantom nodes in the graph.
One missing line. Hundreds of files invisible.
The two-layer design
The thing I'm most proud of isn't any single fix. It's the architecture.
CodeNarrator has two completely independent layers. The deterministic layer — file scanning, import extraction, dependency graph computation — runs with pure Python and no LLM. It always produces something. The agentic layer sits on top and adds intelligence: prioritization, architectural reasoning, natural language summaries.
If the LLM times out, crashes, or produces garbage — the report still renders. The deterministic layer already built the graph. The AI is an enhancement, not a dependency.
That design decision saved the project from becoming a "works on my machine" demo.
What's next
The Ollama dependency is the main friction point. Running a 7B model locally requires decent hardware. Pluggable LLM backends — OpenAI, Anthropic, any OpenAI-compatible API — are next. So is a CLI, and full dependency graph support for Java, Go, Rust, and C/C++.
The core is solid. The hard problems are solved. Everything from here is additive.
Try it
pip install codenarrator-ai
PyPI: pypi.org/project/codenarrator-ai
Top comments (0)