Point it at a repo. Get a page showing where the code starts, who calls whom, and what each path touches: AWS, HTTP, environment variables.
pip install code-node-graph # or: uv tool install code-node-graph
cd your/repo && code-nodeNote
Nothing is run. Code is read with ast, AWS operations come from botocore's models on disk. No imports, no requests.
| 🗺️ Graph | What comes in, who calls whom, what each path reaches. AWS calls coloured by kind (read, write, send, run); ↻ marks loops |
| 🔀 Decisions | Each call as a flowchart: every if a question with a yes and a no arrow, loops, try, where it returns or raises |
| 👣 Step by step | Walk the code in run order, like a debugger: Next, Skip call, Finish, arrow keys |
| 🔌 Plugins | boto3, Redis, SQL (sqlite3, psycopg, PyMySQL, asyncpg, SQLAlchemy), MongoDB, OpenAI, Anthropic |
| 📄 Deploy checks | Reads SAM template.yaml / serverless.yml: unset variables, IAM calls the role won't allow, timeouts that don't fit |
| 🚨 Findings | SQL or shell commands built from input, clients with no timeout, queries in loops |
| 🧜 Mermaid | Paste the graph into Markdown, a wiki or a PR |
| 🔁 Live | --serve redraws on every save |
code-node # find entry points and pick one
code-node -i # walk the folder (arrow keys, or type to search) and pick a file
code-node --list # just list them
code-node src/app/main.py:run # start from a function
code-node src/app/store.py:Store.save # ...or a method
code-node -e save # part of a name
code-node --serve # live page on localhost:8765
code-node --mermaid # print the graph as MermaidEntry points it finds
Console scripts in any pyproject.toml (monorepos too), functions named in SAM / Serverless files, Lambda handlers,
FastAPI / Flask routes, Django urls.py files, Typer commands, if __name__ == "__main__": blocks, and functions named
main. Test files are skipped. A web app's routes are read as called with the request, so SQL built from a query
string is flagged.
All options
| Option | What it does |
|---|---|
path |
Folder to read, or a file to start from (main.py, main.py:function) |
-e, --entry |
module.function, module.Class.method, file.py[:function], or part of a name |
-i, --interactive |
Pick the file in the terminal: arrow keys through the folders, or type to search every file |
-l, --list |
List entry points and stop |
--plugins |
List platforms, libraries and deploy files and stop |
--all |
Draw every function (default: 14 functions, 5 calls deep) |
--depth N, --functions N |
Your own limits |
--serve, --port N |
Serve on localhost, redraw on change |
--mermaid |
Print the graph as Mermaid |
-o, --out, --no-open |
Where to save (default ~/.cache/code-node/), and whether to open it |
--platform NAME, --lambda |
Run a platform's checks on any entry point |
--editor vscode|cursor|none |
Editor the line links open (default vscode, WSL-aware) |
--path DIR |
A folder imports start from, as on PYTHONPATH (pyright's extraPaths and pytest's pythonpath are read on their own) |
--no-git |
Leave out what git says about each function (who changed it last, when, in which commit) |
From Python
from code_node import code_graph, map_code, read_project
project = read_project(".")
cmap = map_code(project.files, "pkg.cli.main", libraries=project.libraries())
print([call.label for call in cmap.aws])
print(code_graph(cmap).mermaid())One platform, any number of libraries and deploy files, checked together. On
examples/cart-service:
It can't follow values from outside the code (a client a library hands back, a function picked from a registry at
run time), installed libraries' own code, or getattr with a computed name. A page can miss calls, but everything
it shows is in the code.
make install # .venv with the dev tools (needs uv)
make check # everything CI runs
make shots # remake screenshots (needs Chrome)python makefile.py <task> does the same on any OS.
Extracted from aws-analyzer's how_it_works(). Apache 2.0.