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

uv tool install nuanced

System Requirements:

  • Python >=3.8

Usage Modes

Nuanced offers two flexible interfaces to suit different workflows:

  1. Command Line Interface
  2. Python Library Interface

Command Line Interface

# Initialize a graph for a directory
cd my_repo
nuanced init .

# Get enriched context for a specific function
nuanced enrich /path/to/file.py module.submodule.function

Python Library Interface

from nuanced import CodeGraph

# Initialize a graph
graph = CodeGraph.init('.')

# Get enriched context for a specific function
enrichment = graph.enrich('app/models.py', 'authenticate')

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.

init(path: str) -> CodeGraphResult

Parameters:

  • path: Repository or directory path (e.g., ., ./src, absolute path)

Returns:

  • CodeGraphResult containing:
    • code_graph: Successful CodeGraph instance
    • errors: 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 found
  • ValueError: No Python files in directory
  • TimeoutError: Initialization exceeds 30 seconds

Example Scenarios:

# Initialize entire repository
nuanced init .

# Initialize specific directory
nuanced init ./src

# Initialize parent directory
nuanced init ../

# Initialize specific component
nuanced init /path/to/project/components/auth

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.

enrich(file_path: str, function_name: str) -> Dict[str, Any]

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 function
  • function_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 file
      • callees: 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:

# Get enriched information for a specific function
$ nuanced enrich app/models.py authenticate

# Example output
{
  "app.models.User.authenticate": {
    "filepath": "/project/app/models.py",
    "callees": [
      "app.utils.hash_password",
      "<builtin>.dict",
      "app.database.query"
    ]
  }
}

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:

nuanced enrich /path/to/file.py module.submodule.function

Coming soon:

  • callers: List of functions that call this function
  • docstring: Function documentation if available
  • type_annotations: Parameter and return type information
  • lines_of_code: Total lines of code in the function
  • number_of_parameters: Number of parameters the function accepts
  • cyclomatic_complexity: Measure of function complexity
  • logical_lines_of_code: Number of executable statements
  • start_line: Function starting line number
  • end_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:

from nuanced import CodeGraph

# Update graph during development
graph = CodeGraph.init('.')

# Analyze specific functions after modifications
enrichment = graph.enrich('app/models.py', 'authenticate')

# Integrate into your development workflow
def pre_commit_analysis():
    # Generate fresh call graph before committing
    graph = CodeGraph.init('.')
    # Perform additional checks or logging
    return graph

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.