TraceSprout
Understand a codebase you didn't write (or wrote too fast) in minutes. TraceSprout turns Python backends into interactive UML diagrams by reading the code (diagrams never run it): sequence and activity diagrams of each request, a dependency graph of your classes and modules, and an example input and output for every function. For React and Next.js frontends it draws a map of the screens and the backend routes each one calls.
Built for FastAPI and Flask backends, works with any Python code, and needs nothing installed in your project.
Features
Follow a request through your code
Pick a route or function and TraceSprout follows every call it makes, in order, across modules and classes.
- Sequence diagram: lifelines are your modules and classes, arrows are calls (with the real arguments) and returns (with their types).
if, loops, try and asyncio.gather become UML alt, loop, opt and par frames. Third-party libraries (sqlalchemy, anthropic, …) appear as boundaries on the right.
- Activity diagram: the same flow as swimlanes, with decision diamonds for branches, a repeat edge for loops, and fork/join bars for parallel work.
- Semantic zoom: 1 · Overview shows the important calls, 2 · Functions every call into your code, 3 · All calls adds helpers and library calls. Ctrl + scroll switches level; +N opens a single call.
- Details panel: click any call to see its docstring, signature, route, callers and callees. Functions without a docstring get a one-click Explain with AI summary.
- Find: jump to any function in a large trace.
See every entry point
Click the TraceSprout icon at the top right of a Python file to see everything that runs in it. For a FastAPI or Flask app this covers startup and shutdown (lifespan, on_event), middleware, routes (including routers mounted from other files), exception handlers, Depends() providers, __main__ / uvicorn.run, Typer/Click commands and Celery tasks. An app map next to the list shows how the app, routers and routes connect.
Route paths built from constants are understood: @app.get(f"{API_PREFIX}/health"), APIRouter(prefix=settings.api_prefix), imported constants and add_api_route.
The TraceSprout view in the Activity Bar lists every entry point and screen in the workspace.
The Pulse tab shows what goes in and comes out of the selected function. Each value says where it came from:
| Source |
How it works |
| Predicted by AI · not run |
The AI model reads the code and predicts a realistic example. Predict the whole flow fills every call in one request, with values that connect from call to call. |
| Recorded from a real run |
TraceSprout: Record a run… runs your program (a script, uvicorn …, pytest, or inside Docker) and captures real arguments and return values. |
| Run it |
Runs just this function with an input you can edit. This does run your code: importing its module runs the module's top-level code, and your function's logic really runs. Database and network calls it makes are simulated (see Safety). |
Show sample values puts these values on the diagram's arrows.
Dependency graph
TraceSprout: Show dependency graph draws how your code fits together:
- 1 · Modules: which files import which, grouped by package. Import cycles are drawn in red, with the loop spelled out and a hint on how to break it.
- 2 · Classes: a UML class diagram showing inheritance, composition (the class creates the object), aggregation (the object is passed in), typed fields with multiplicity, and "uses". FastAPI routes link to their request and response models and to the services
Depends() provides. Stereotypes mark dataclasses, pydantic models, ORM entities, enums, abstract classes and exceptions.
- 3 · Members: the same, with every field and method.
Double-click a box to focus on it and its neighbours. Filters hide data classes, exceptions, routes or private classes. Right-click a Python file and choose Show this file's dependencies to start from that file.
Screen map for React and Next.js
TraceSprout: Show screen map draws every page of your frontend and the clicks that move between them, each labelled with the button or link text. Modals and drawers are listed on their page rather than drawn as screens. Each screen lists the backend calls it makes, matched to the FastAPI/Flask route, and Show backend flow opens that route's sequence diagram.
It supports the Next.js App and Pages Routers, React Router, and plain React, along with fetch, axios (including instances), ky, useSWR and your own wrapper functions. next.config rewrites and Vite proxies are applied.
Copy as Mermaid
Every diagram (sequence, activity, screen map, app map, dependency graph) can be copied as Mermaid text, ready for a README, pull request, issue or wiki.
Requirements
- VS Code 1.93 or newer.
- Python 3.9 or newer on your machine. TraceSprout uses
tracesprout.pythonPath if you set it, then the interpreter selected in the Python extension, then py -3 / python3 / python on your PATH. It uses only the standard library and installs nothing into your environment.
- Recording real runs needs Python 3.12 or newer in the program being recorded.
- Optional, not required: the Python extension (with Pylance). If it's installed, TraceSprout uses the interpreter you selected there and asks Pylance about calls it can't resolve by itself. Without it, everything still works: TraceSprout uses
tracesprout.pythonPath or the Python on your PATH, and calls it can't resolve are listed under Not traced.
- Optional: an Anthropic API key (or a compatible gateway) for AI summaries and predicted samples. Everything else works without one.
Installation
From the Visual Studio Marketplace: open the Extensions view (Ctrl+Shift+X / Cmd+Shift+X), search for TraceSprout and click Install.
From a .vsix file (for example a build shared by your team):
- Open the Extensions view (Ctrl+Shift+X / Cmd+Shift+X).
- Click ⋯ at the top of the view and choose Install from VSIX….
- Pick
tracesprout-<version>.vsix and reload when asked.
Or from a terminal:
code --install-extension tracesprout-<version>.vsix
Quick start
- Open a folder with a Python backend.
- Open a file with routes (often
main.py) and click the TraceSprout icon at the top right of the editor. Or open the TraceSprout view in the Activity Bar.
- Click an entry point to open its sequence diagram beside your code. You can also click Trace POST /api/… above any route handler, or right-click inside any function and choose TraceSprout: Trace flow from this function.
- Click a call to read what it does, then open Pulse to see an example input and output.
- Switch views: use Activity for the activity diagram, or run TraceSprout: Show dependency graph to see the whole codebase.
For a frontend, run TraceSprout: Show screen map.
Setting up AI features (optional)
Add your key in Settings → Extensions → TraceSprout (on the User tab), or in your user settings.json:
{
"tracesprout.ai.apiKey": "sk-ant-…", // or leave empty to use ANTHROPIC_API_KEY (Anthropic only)
"tracesprout.ai.model": "claude-haiku-4-5" // a fast, low-cost model is plenty
}
Using a company gateway (LiteLLM or any Anthropic-compatible proxy):
{
"tracesprout.ai.baseUrl": "https://llm-gateway.example.com",
"tracesprout.ai.apiKey": "<gateway key>",
"tracesprout.ai.authHeader": "bearer", // if the gateway expects Authorization: Bearer
"tracesprout.ai.model": "<model name on your gateway>",
"tracesprout.ai.fallbackModel": "<optional second model>"
}
AI requests are sent only when you click a button, and only to tracesprout.ai.baseUrl. The AI settings are read from your user settings only; values in a workspace's .vscode/settings.json are ignored, so a repository you open can't redirect your key. The ANTHROPIC_BASE_URL and ANTHROPIC_CUSTOM_HEADERS environment variables are ignored, and ANTHROPIC_API_KEY is only sent to https://api.anthropic.com. Results are cached per workspace and keyed to the exact code, so reopening a trace or re-tracing unchanged code never costs another request.
Commands
| Command |
What it does |
| TraceSprout: Show overview of this file |
Entry points of the current Python file and its app map. In a React/Next.js file, opens the screen map on that screen. Also the icon at the top right of the editor. |
| TraceSprout: Trace flow from this function |
Sequence diagram starting at the function under the cursor. Also in the editor's right-click menu. |
| TraceSprout: Trace an API route or main function… |
Pick any entry point in the workspace. |
| TraceSprout: Show dependency graph |
Modules, classes and how they relate. |
| TraceSprout: Show this file's dependencies |
The dependency graph focused on the current file. Also in the right-click menus. |
| TraceSprout: Show screen map |
Screens of your React/Next.js frontend. |
| TraceSprout: Record a run… / Stop recording |
Run your program with recording on. |
| TraceSprout: Set up recording in Docker |
Shows the environment variables and volume to add to your container. |
| TraceSprout: Show log |
TraceSprout's output channel, for troubleshooting. |
Settings
| Setting |
Default |
What it does |
tracesprout.pythonPath |
(empty) |
Interpreter for TraceSprout. Empty = the Python extension's interpreter, then PATH. |
tracesprout.maxDepth |
8 |
How many calls deep a trace goes. |
tracesprout.maxCalls |
400 |
Maximum calls in one trace; larger flows are cut off and marked. |
tracesprout.exclude |
tests, migrations |
Globs for files that are never entry points, traced into, or drawn in the dependency graph. |
tracesprout.codeLens |
routes |
Show Trace above entry points (routes), every function (all), or nowhere (off). |
tracesprout.useLanguageServer |
true |
Ask the language server about calls TraceSprout can't resolve itself. |
tracesprout.frontend.apiClients |
[] |
Your own API client functions, e.g. [{ "call": "apiClient.post", "baseUrl": "/api" }]. Optional fields: method, urlArg. |
tracesprout.frontend.pathRewrites |
[] |
Extra frontend → backend path rewrites, e.g. [{ "from": "/backend/", "to": "/" }]. |
tracesprout.recording.maxCallsPerFunction |
25 |
Calls of each function kept per recorded run. |
tracesprout.execute.ioModules |
[] |
Extra packages that touch a database, file store or network service; always simulated in Run it. |
tracesprout.execute.paidApiModules |
[] |
Extra packages that call paid APIs; running them for real asks first. |
tracesprout.execute.paidApiHosts |
{} |
Extra hosts a confirmed paid call may reach, per package, e.g. { "anthropic": ["llm-gateway.example.com"] }. Write host:port to allow only that port; a host on this machine (localhost:4000) is reachable only on the port written for it. Subdomains need *.host; shared domains such as amazonaws.com are refused. |
tracesprout.execute.timeoutSeconds |
30 |
Stop a Run it run after this long. |
tracesprout.execute.extraPythonPaths |
[] |
Extra folders (relative to the workspace, and inside it) on the Python path for Run it. |
tracesprout.ai.baseUrl |
https://api.anthropic.com |
Where AI requests go. AI requests go only here. |
tracesprout.ai.apiKey |
(empty) |
API key. Empty = the ANTHROPIC_API_KEY environment variable (only with the default Anthropic base URL). Stored as plain text in your user settings. |
tracesprout.ai.authHeader |
x-api-key |
Send the key as x-api-key or as Authorization: Bearer (bearer). |
tracesprout.ai.model |
claude-haiku-4-5 |
Model for summaries and predicted samples. |
tracesprout.ai.fallbackModel |
(empty) |
Tried when the main model is unavailable, rate limited or declines. |
tracesprout.ai.maxFlowCalls |
60 |
Most calls included in one whole-flow prediction. |
Safety and privacy
- Diagrams never run your code. Tracing, the overview, the dependency graph and the screen map only read source files.
- Workspace Trust: in a folder you haven't trusted (Restricted Mode), diagrams still work, but Run it, recording and Docker setup are turned off, the folder's own interpreter isn't used, and its own values for
pythonPath, exclude, execute.* (extra Python paths, I/O and paid-API package lists, paid-API hosts) and frontend.* (API clients, path rewrites) are ignored (your user settings still apply).
- Run it and Record a run do run your code. Record runs your whole program. Run it imports the function's module (so its top-level code runs) and runs the function, in a separate Python process, with guard rails:
- Database and network calls are always simulated, reads included. Calls into packages such as sqlalchemy, asyncpg, pymongo, redis, boto3, requests and httpx return a recorded or AI-predicted value instead, and each one is listed and tagged Simulated. Every value a simulated call may return is shown in the plan, and the run uses exactly those. AI predictions are only fetched when you click Predict simulated values, and you confirm them before running. Pre-filled inputs (from a recording or an AI prediction) follow the same data-only rule until you edit them; what you type yourself runs as Python. Values can only describe data (literals, lists and dicts, standard types such as dates, Enum members, and your own classes such as
Doc(id='a')): your classes are filled in field by field without running their code (no __init__, validators or metaclasses).
- Paid APIs ask first. If the function would call anthropic, openai, voyageai, cohere or similar, VS Code shows the exact input and the hosts it would reach, and asks whether to run it for real or simulate it. Running it for real opens the network only to that provider's API host, on the port your code asks for (add others, such as a gateway, under
tracesprout.execute.paidApiHosts; write host:port to allow only that port, and a host on this machine is reachable only on the port written for it); other connections the guard sees stay blocked.
- Functions that do I/O themselves aren't run. Their result is tagged Simulated · not run.
- A best-effort guard catches much of the rest. Other network connections, starting processes (
subprocess, os.system, os.spawn*/exec*/startfile, multiprocessing) are blocked; file writes (including os.open and SQLite database files, also through sqlite3.dbapi2, sqlite3.Connection and file: URIs) are redirected to a temp folder, SQLite can only ATTACH (or VACUUM INTO) databases in the temp folder or in memory, and deletions, renames, links and moves that would change your project are skipped. Network connections through asyncio, numeric addresses and DNS lookups are covered too. All of it is reported.
- It is not a sandbox. Code that runs when a module is imported (for example
Base.metadata.create_all(engine) at the top of main.py), native database drivers and C extensions (psycopg2, mysqlclient, grpc, …) can bypass it. Code that deliberately goes around Python's standard library can also bypass it: ctypes, _winapi, the low-level _socket module, or file descriptors passed in place of paths. Only use Run it on code you trust, as you would before running it yourself.
- FastAPI
Depends() parameters you leave empty are filled by calling their provider, as FastAPI would, inside the same guard.
- What the AI sees. Nothing is sent until you click an AI button, and only to
tracesprout.ai.baseUrl:
- Explain with AI and Predict this call: the function's source, its workspace-relative file path, its class header, the source of project types in its signature, the call site (the expression that calls it) and the caller's name, and the signature and first docstring line of each function it calls. For a third-party call, the call site and the package name.
- Predict the whole flow: the same for every call in the trace, up to
tracesprout.ai.maxFlowCalls (60) functions, with their workspace-relative file paths.
- Predict an input and Predict simulated values in Run it: the same as Predict this call, for each function involved.
- Like any Anthropic SDK client, requests include the SDK's standard headers (SDK version, operating system, architecture and Node.js runtime version). Extra headers from the
ANTHROPIC_CUSTOM_HEADERS environment variable are not added.
- Recorded values,
.env files and your settings are never sent.
- No telemetry. TraceSprout collects no usage data and makes no network requests other than the AI requests above.
- Recordings stay on your machine in
.tracesprout/recordings/, which is git-ignored automatically, and only the 20 newest are kept. Values are stored as short text, never pickled. TraceSprout redacts what it can recognise: arguments, dictionary keys and command-line flags that look secret (password, token, api_key, Authorization, …), name=value pairs with such names inside values (Settings(password=...)), common key formats (Anthropic/OpenAI, AWS, GitHub, GitLab, Slack, Google, Stripe, Hugging Face, npm, Azure, PEM private keys, JWTs, bearer and basic auth) and passwords or tokens in URLs. Your home folder is stored as ~. Other personal data in your values (emails, names, request bodies) is recorded as-is, so treat recordings like logs and don't share them.
Known limitations
- Calls made through dependency injection, callbacks,
getattr or plugin registries may not resolve from the code alone. They're listed under Not traced in the details panel, and a recorded run shows what actually happened.
- One trace follows one entry point; background tasks it starts (Celery,
create_task) aren't followed into.
- The dependency graph only draws edges it can work out from the code: annotations, constructor calls and functions with return annotations. Duck typing and metaprogramming don't show up.
- Recording needs Python 3.12+ (
sys.monitoring); on older versions the program runs without recording.
Troubleshooting
| Problem |
What to do |
| "TraceSprout couldn't start Python", or nothing happens |
Run TraceSprout: Show log. Select an interpreter with Python: Select Interpreter, or set tracesprout.pythonPath. |
| No entry points found |
Check that the files aren't matched by tracesprout.exclude. Use Trace flow from this function from inside any function. |
| Run it fails to import your module |
Add the folders your code imports from under tracesprout.execute.extraPythonPaths, or select the project's virtual environment as the interpreter. |
| AI requests fail |
Click Open AI settings in the error message, and check the key, base URL, model name and authHeader for your gateway. |
| A diagram looks out of date |
Press ↻ Refresh in the panel; diagrams are re-read from disk. |
Third-party software
TraceSprout bundles open-source packages (React, React Flow, dagre, Babel's parser, the Anthropic SDK, zod and others). Their licences are listed in ThirdPartyNotices.txt, which ships with the extension.
License
TraceSprout is released under the MIT License; see LICENSE. It's provided as is, without warranty of any kind.
Release notes
See CHANGELOG.md.
Contributing
See CONTRIBUTING.md for building, testing and the project layout.
| |