We're excited to announce the initial launch of Nuanced, an open-source Python library that provides LLMs with precise call graph context. By analyzing function relationships, we generate a structured representation of code dependencies. This is our first step toward building a richer context layer that can help AI coding assistants make more informed decisions about your codebase.
Why AI coding needs relevant context
AI coding assistants are surprisingly primitive when it comes to understanding code structure. The LLMs underlying them The LLMs powering these assistants have no equivalent to the Language Server Protocols (LSPs) that developers take for granted — they can't jump to definitions, find references, or understand type hierarchies.
Instead, they examine source code as chunks of text (tokens) with a limited context window, and use embeddings — vector representations that capture statistical patterns but don't preserve actual program structure.
This lack of "dev tools for AI" creates a significant gap: while they excel at pattern matching and local transformations, they lack the fundamental program analysis capabilities that compilers and developers use. These capabilities include following control flow, understanding data dependencies, and reasoning about runtime behavior.
This means when an LLM suggests changing a function's signature or behavior, it can't reliably identify which other parts of the codebase depend on that function or might break as a result of the change. They struggle with basic questions like "what will break if I change this return type?" or "which components depend on this function?" because they lack real semantic understanding of the codebase.
The solution isn't about overwhelming LLMs with all possible context — it's about identifying and providing the most relevant context for each specific task. We can do this by precisely extracting the function relationships and dependencies that matter for a given modification.
Introducing Nuanced CodeGraph
Nuanced leverages static analysis to extract call graphs from your codebase. Rather than relying on the limited context windows or embeddings used by current AI tools, we parse the AST to build a traversable graph of function relationships. The result is structured, semantic information that captures actual program behavior.
The library provides two main interfaces:
init
for generating the call graphenrich
for querying specific functions.
init
: initializing the call graph
# Create a call graph for your module
$ nuanced init .
The init
command analyzes Python files in the specified directory, creates a .nuanced
directory to store analysis results where the full call graph is written to a file called nuanced-graph.json
, and returns a CodeGraphResult
with either the graph or any errors encountered.
enrich
: querying function relationships
# Find what a specific function calls
$ nuanced enrich app/helpers.py format_data
{
"app.helpers.format_data": {
"filepath": "/app/helpers.py",
"callees": [
"<builtin>.dict",
"app.utils.validate_input",
"<builtin>.str"
]
}
}
The enrich command takes two arguments: (1) the path to the Python file containing your function, and (2) the function name (just the name, not the fully qualified name), and returns an EnrichmentResult
containing the function's call graph when found, and any errors encountered (e.g., ValueError
when multiple matching functions exist). Unlike the result of init
, which is written to a file, the result of enrich
is held in memory.
This gives AI tools access to the same structured program understanding that developers rely on—actual call paths and dependencies rather than probabilistic guesses from embeddings or regex matches.
By extracting function call relationships, Nuanced can help AI coding tools resolve imports, and maintain a structured graph that can be queried efficiently.
What Nuanced provides today
This initial release focuses on:
- Call graph generation: create a queryable JSON representation of function relationships
- Function discovery: find specific functions and their dependencies
- Simple CLI: Easy-to-use commands for exploring code structure
Get started
Nuanced is supported for Python versions >= 3.8.
# Install
$ uv tool install nuanced
# Initialize graph for current directory
$ cd your_project
$ nuanced init .
# Query specific functions
$ nuanced enrich path/to/file.py function_name
Graph updates
Nuanced call graphs can be updated whenever they're most useful to you. You might have them update automatically in your commit hooks, run them manually while debugging, or set them up as part of your CI pipeline. For example, you might update the call graph while investigating a complex dependency chain, when refactoring a module's interface, or during code review to visualize recent changes. The library lets you capture relationships in your code without disrupting your development process.
Running Nuanced
Nuanced runs anywhere you've got Python 3.8+ installed. No special dependencies, no complex setup — it works the same way whether you're coding on your laptop, running it in CI, a sandbox, or deploying it to a cloud environment. The lightweight design means you can drop it into any Python project without worrying about compatibility or environment-specific configurations.
Since Nuanced runs entirely in your environment and never sends data externally, you maintain complete control over your code analysis. Whether you're working with proprietary code or sensitive projects, you can generate call graphs without any data leaving your systems. The library's minimal requirements ensure consistent call graph generation across all these environments with simple setup and installation.
Architecture: Building on JARVIS
When we started building Nuanced, we needed a solid foundation for Python call graph generation. After evaluating several tools (pycg, tree-sitter-stack-graphs, Glean, scip-python, and pytype), we chose JARVIS as our starting point.
Anyone who's tried to build static analysis for Python knows the challenges: dynamic imports, monkey patching, decorators that transform functions, and metaprogramming can all confuse static analyzers. JARVIS handles these Python quirks better than most tools we evaluated:
- It correctly resolves most import patterns (even the weird ones)
- It tracks calls through variables and attributes reasonably well
- It preserves enough context to reconstruct fully qualified names
In our tests with real codebases, pycg would regularly miss important connections or time out on larger projects, while JARVIS maintained good performance. It's not perfect—no static analyzer for Python can be—but it gave us a practical foundation to build upon.
We've extended JARVIS with several practical improvements:
- Better error handling for malformed Python
- Consistent function identification across different parts of the graph
- Path resolution that works with how developers actually navigate projects
- A simpler query interface designed specifically for AI tool integration
Our goal wasn't to create the perfect static analyzer, but to build something that works well enough in practice to give AI tools better context than they have today.
Roadmap
We’re building towards a more comprehensive AI-powered code analysis toolkit. Future work includes:
- Function purity analysis: detecting state modifications.
- Code complexity metrics: highlighting refactoring needs.
- Type inference: extracting parameter and return types.
- Dead code detection: finding unused functions.
- Data flow tracking: mapping variable transformations across function calls.
Help shape the future
We’re focusing on precise function-level analysis and evolving towards runtime insights. We want your feedback—what context do your AI tools need? What problems are you facing when navigating large codebases?
Nuanced is open-source and built for both human developers and AI tools. We welcome you to:
- Star our GitHub repository
- Join our Discord where developers and AI tool creators collaborate
- Read our documentation for integration guides
- Contribute to help shape the future of code understanding
Connect with us on X or email ayman@nuanced.dev.