noodles: turning a repository into a call graph you can actually click through
Your codebase was probably AI-generated. Get a better handle on it. Noodles creates interactive diagrams that visualize how your code actually works, so you can understand what the AI built without reading every line.
At a glance
- What is it?
- A Python tool that parses a codebase with tree-sitter, builds a function call graph, and renders it as interactive mermaid diagrams, with an optional LLM layer that labels nodes and an MCP server so a coding agent can query the graph. Useful, and honest about what it cannot see.
- Who is it for?
- noodles earns its place when you are handed code you did not write and need the shape of it in minutes, especially on a pull request review where the question is what a change actually touches. Its tree-sitter call detection is precise about direct and imported calls and reliably blind to dynamic dispatch, decorators and framework callbacks, which is the boundary to plan around.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 7 months ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 9, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The pitch is aimed squarely at code you did not write
The opening line of the README is blunt: your codebase was probably AI-generated, get a better handle on it. Noodles creates interactive diagrams showing how code actually works, so you can understand what was built without reading every line. That framing sets the bar for everything else. The tool is not a general architecture visualiser; it is aimed at the specific situation where a large body of unfamiliar code has to become legible in under an hour.
What it produces is a function call graph, built with tree-sitter AST parsing, and mermaid diagrams showing code flow, rendered in a viewer you can pan, zoom and drill into. Two analysis targets are offered: an entire repository, and a GitHub pull request to see what changed.
There is a hosted version at unslop.xyz, and the package itself is MIT licensed with version 0.4.2 in `pyproject.toml`, requiring Python 3.10 or newer. The repository tree is small and conventional: `src/`, `tests/`, `assets/`, `pyproject.toml`, `uv.lock`, a `CHANGELOG.md`, a `.env.example` and a `.claude/` directory. The last push was on 2026-03-13.
Installing from git, then deciding whether to hand it a key
There are two install paths, and the dev path is the one to read for a moment because it shows how the package is laid out.
pip install git+https://github.com/unslop-xyz/noodles.gitFor development, clone and install in editable mode:
git clone https://github.com/unslop-xyz/noodles.git
cd noodles
pip install -e .The interesting design decision is that the LLM is optional. An API key enables AI enrichment of node descriptions and edge labels, but without one the call graph is still generated, just without human-readable descriptions on nodes and edges. That separation matters, because it means you can evaluate whether the graph structure itself is useful before spending anything on labels.
Anthropic is the default provider. Setting a key looks like this:
export ANTHROPIC_API_KEY=your-key-here`openai`, `gemini`, `groq` and `huggingface` are also supported, selected through `LLM_PROVIDER` alongside the matching key variable:
export LLM_PROVIDER=openai
export OPENAI_API_KEY=your-key-hereThe `.env.example` goes further than the README and documents `LLM_MODEL` defaults per provider plus `LLM_BASE_URL` for pointing the openai provider at Ollama, vLLM or LMStudio. It also lists a concrete default of `claude-haiku-4-5-20251001` for Anthropic and `gpt-4o-mini` for OpenAI, which tells you what you actually pay for if you leave the model unset. If you cloned the repo, a `.env` file in the working directory is read instead of environment variables.
Three commands and what each one produces
The CLI is three verbs. Analyse a repository by URL, analyse a pull request, or reopen an existing result directory in the viewer:
noodles repo <repo-url>noodles pr <github-pr-url>noodles viewer <result-dir>The `viewer` command is the one to notice, because it means analysis results are persisted rather than streamed to a transient window. You can analyse a repository, close the tool, and open the same result again later. Two options apply across the commands: `--output-dir <dir>` sets where results go, and `--no-view` suppresses the automatic viewer launch, which is what you want in a script or over SSH.
Fetching the repository or pull request is done with the GitHub CLI rather than a bundled client. The README's instruction is to install it and authenticate:
brew install gh
gh auth loginThat is a meaningful dependency choice. It means there is no second set of GitHub credentials to manage, and it means the tool works against whatever repositories your existing `gh` session can already read, including private ones. It also means analysis of a private repository only works on a machine where `gh` is already authenticated.
The viewer itself is a `pywebview` window, which is in the dependency list. Pan by dragging, zoom with the scroll wheel, drill down by clicking nodes marked `[+]`, and go back with Escape.
What the AST parser sees, and the four things it does not
The language support table is short and the limitations section is the most useful part of the README. The call graph is built by detecting function calls in the AST, using tree-sitter for parsing. Supported extensions are `.py` for Python, `.js` and `.jsx` for JavaScript, and `.ts` and `.tsx` for TypeScript and TSX. Anything else requires adding a tree-sitter grammar plus function detection logic, which is a real contribution rather than a configuration change.
One detail deserves credit: React and Next.js JSX component usage is detected as a function call, so `<MyComponent />` appears as a call edge. That is why component hierarchies show up correctly in the graph instead of disappearing, and it is the single feature most likely to matter if your repository is a modern frontend.
Detection works well for direct calls such as `foo()` and `obj.method()`, for imported function calls, and for JSX usage. It explicitly does not detect dynamic calls like `getattr(obj, 'method')()` or `obj[key]()`, and it does not detect callbacks passed to frameworks, route handlers registered via decorators being the example given.
Those four blind spots are not edge cases in a large application. Dependency injection, plugin registries, event emitters, decorator-based routing and most DI containers produce exactly the dynamic dispatch the parser skips. The practical consequence is that a graph can look sparse on a codebase that is heavily decoupled by design, which reads as simplicity but is actually indirection. Treat the diagram as the static skeleton, not the runtime truth.
The MCP server exposes thirteen ways to ask the graph
Noodles can run as an MCP server, which lets Claude Code analyse pull requests and repositories directly instead of a human opening the viewer. The extra is installed separately, and `pyproject.toml` declares the `mcp` dependency as `>=1.0.0,<2`, so the server targets the 1.x line:
pip install "noodles[mcp]"The Claude Code settings file needs one entry:
{
"mcpServers": {
"noodles": {
"command": "noodles-mcp"
}
}
}The README then tells you to restart Claude Code and verify with `/mcp`. Note the small mismatch in the documented path: the primary install is from a git URL, while this extras install is written as a bare package name, so combining them into one command is left to you.
The tool list is where the real argument for this integration sits. Beyond `analyze_pr`, `analyze_repo` and `get_diagram`, the server offers `analyze_local_repo` for working without cloning, `analyze_changes` for uncommitted local edits, `get_call_graph` for the full JSON, `find_path` between two functions, `get_callers` and `get_callees`, `filter_graph` by node type including entry points, endpoints, new, updated and orphans, `get_summary` in plain English, and `get_changes` with detail on modified functions.
`find_path` and `get_callers` are the two that change how an agent works. An agent that can ask which functions reach a given line no longer has to guess from file names, and `analyze_changes` over uncommitted edits gives you review coverage on work that was never pushed.
Why the pull request analyser produces thin results on isolated changes
The PR analyser is the feature with the most caveats, and the README states them plainly. It prunes the call graph down to functions affected by a pull request. That pruning works best when the changed functions either call other functions or are called by them, and when the codebase has interconnected calls. Those are exactly the two conditions that make a dependency graph worth drawing in the first place.
It produces limited results in the other cases, and the README names them: changes to isolated or standalone functions, and codebases using patterns the AST analysis does not detect, such as decorators and dynamic dispatch. A pull request that adds a small self-contained utility, or that wires behaviour through a framework's registration mechanism, is close to a worst case for this approach.
There is a further mismatch worth being honest about. `pyproject.toml` describes the project as AI-powered code visualization and call graph analysis, and the tool description leads with AI. But the README also says an API key is optional and that the graph works without one. Those are both true, and the second is the more interesting claim: the diagram is generated by static parsing, and the model only adds prose. If you go without a key, expect structural accuracy without the descriptions that make a large graph readable at a glance.
Editorial conclusion
noodles earns its place when you are handed code you did not write and need the shape of it in minutes, especially on a pull request review where the question is what a change actually touches. Its tree-sitter call detection is precise about direct and imported calls and reliably blind to dynamic dispatch, decorators and framework callbacks, which is the boundary to plan around. The last push to the repository was on 2026-03-13 and the version in `pyproject.toml` is 0.4.2, with a `CHANGELOG.md` in the tree but no tagged GitHub release, so read the changelog to judge the upgrade path rather than a release page. Install it with `pip install git+https://github.com/unslop-xyz/noodles.git`, leave `ANTHROPIC_API_KEY` unset on a first run to see the raw graph without API cost, and only then decide whether the model-written labels are worth a key.
Frequently asked questions
What programming languages does noodles support?
Five extensions, using tree-sitter for AST parsing: `.py` for Python, `.js` and `.jsx` for JavaScript, and `.ts` and `.tsx` for TypeScript and TSX. JSX component usage is detected as a function call so React component hierarchies appear in the graph. Any other language needs a new tree-sitter grammar plus detection logic.
Does noodles need an LLM API key to work?
No. A key enables AI enrichment of node descriptions and edge labels, but the call graph is generated either way. Anthropic is the default provider, with openai, gemini, groq and huggingface also selectable through `LLM_PROVIDER`.
How do I run noodles as an MCP server for Claude Code?
Install the extra with `pip install "noodles[mcp]"`, then add a `noodles` entry whose command is `noodles-mcp` to your Claude Code `mcpServers` settings. Restart Claude Code and check with `/mcp`, where the noodles server should be listed.
What call patterns can noodles not detect?
Dynamic calls such as `getattr(obj, 'method')()` and `obj[key]()`, and callbacks passed to frameworks including route handlers registered via decorators. Direct calls, imported calls and JSX usage are detected normally.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/unslop-xyz-noodles)