Nuanced
Nuanced is an open-source library that generates enriched call graphs with static analysis annotations, providing AI coding tools with deeper understanding of code behavior.
Quick Start
Installation
System Requirements:
- Python >=3.8
Usage Modes
Nuanced offers two flexible interfaces to suit different workflows:
Command Line Interface
Python Library Interface
Core API Reference
CodeGraph
provides two methods to analyze and navigate code relationships: init
and enrich
.
init
Initializes a new graph for a repository or directory.
Parameters:
path
: Repository or directory path (e.g.,.
,./src
, absolute path)
Returns:
CodeGraphResult
containing:code_graph
: SuccessfulCodeGraph
instanceerrors
: List of initialization errors (if any)
Path Handling:
- Transforms relative paths to absolute paths
- Analyzes specified directory and subdirectories
- Creates
.nuanced
directory for analysis results
Possible Errors:
FileNotFoundError
: Directory not foundValueError
: No Python files in directoryTimeoutError
: Initialization exceeds 30 seconds
Example Scenarios:
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
Gets a subgraph of the full call graph focused on a specific function.
The enrich
command takes a file path and function 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.
Parameters:
file_path
: Path to the file containing the functionfunction_name
: Fully qualified function name (e.g.,module.submodule.function
)
Returns:
- Dictionary representing a subgraph where:
- Keys are fully qualified function names
- Values are dictionaries containing:
filepath
: Path to the source filecallees
: List of fully qualified function names called by this function
- The subgraph includes the target function and all functions in its call graph (recursive traversal of outgoing edges)
Possible Errors:
ValueError
: Multiple function definitions found
Usage:
Notes:
- The returned subgraph follows the complete call chain, not just direct function calls
- Functions not connected to the call graph of the target function are excluded
- Built-in Python functions in
callees
are prefixed with<builtin>.
- The subgraph preserves the structure and connections of the original graph
- Nuanced takes the file path and the function name (not the fully qualified name), the tool then resolves the fully qualified name (
app.helpers.format_data
) based on the file’s location and module structure.
CLI Usage:
Coming soon:
callers
: List of functions that call this functiondocstring
: Function documentation if availabletype_annotations
: Parameter and return type informationlines_of_code
: Total lines of code in the functionnumber_of_parameters
: Number of parameters the function acceptscyclomatic_complexity
: Measure of function complexitylogical_lines_of_code
: Number of executable statementsstart_line
: Function starting line numberend_line
: Function ending line number
Architecture
Nuanced builds upon JARVIS’ core call graph generation, extending it with a specialized focus on AI tooling integration. We chose Jarvis (JARVIS: Scalable and Precise Application-Centered Call Graph Construction for Python) because of its:
- Precise function resolution that handles Python’s dynamic features
- Scalable analysis that works well with large codebases
- Accurate handling of Python’s import system
- Application-centered approach that prioritizes relevant code paths
We’ve developed a layer on top that standardizes function identification, provides a consistent API for AI consumption, and handles path resolution in a way that makes sense for large codebases. Our wrapper adds structured error handling, clear type interfaces, and simplified querying capabilities that make it practical for real-world AI tooling scenarios.
Future Roadmap
In addition to our upcoming features, we’re researching more advanced static analysis capabilities that will further enhance code understanding:
Our long-term research focuses on:
- Function purity analysis: Identifying which functions modify state versus pure functions that don’t cause side effects.
- Control flow complexity: Providing detailed cyclomatic complexity metrics to highlight areas that need refactoring.
- Type information: Extracting and inferring parameter and return types, even in dynamically-typed code.
- Dead code detection: Finding unused functions to help maintain cleaner codebases.
- Mutation analysis: Tracking how functions modify their inputs for better reasoning about data flow.
- Scope analysis: Mapping variable access and modifications to improve understanding of code behavior.
These advanced capabilities require deeper analysis techniques and will be introduced incrementally as we refine our approach to each problem space.
For information about our versioning policy and release process, please see the Versioning and Release Guide.
Graph Updates
Graph updates Nuanced call graphs can be updated whenever they’re most useful to you. Results are stored in a local .nuanced
directory that you can safely check into version control. This makes it easy to share insights with your team and track how your codebase evolves over time. This approach allows developers to:
- Regenerate call graphs as code evolves
- Integrate graph analysis into continuous integration pipelines
- Perform on-demand code introspection during development
- Share analysis results within team environments
Example:
Running Nuanced
Nuanced is a lightweight tool that runs anywhere Python 3.8+ is installed, supporting:
- Local development environments
- Continuous Integration (CI) systems
- Cloud platforms
- Virtual machines
- Sandboxed environments
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.