Skip to main content

graphlint

PyPI Python License

English | 简体中文

Dead code detection for AI-generated codebases.

AI agents generate code rapidly, leaving behind dead and redundant code that pollutes the LLM's context window and dilutes attention. Graphlint analyzes your codebase's dependency graph to identify entry points and detect dead code — components unreachable from any entry point — so agents can self-clean and keep the codebase lean.

Supported Languages

Language Status Parser Features
Python (.py) Built-in ast (stdlib) Decorators, type annotations, dynamic imports, framework-aware entry detection
Rust (.rs) Built-in (opt-in deps) tree-sitter Attribute macros, traits, pub visibility, macro_rules!

Install with Rust support: pip install graphlint[rust] (adds tree-sitter and tree-sitter-rust).

Features

  • Dead code detection — finds components unreachable from any entry point via graph traversal
  • Multi-language support — Python and Rust backends via a language adapter abstraction; Python uses stdlib ast, Rust uses tree-sitter
  • Language-specific awareness — Python decorators, Rust attribute macros (#[tokio::main], #[test]), trait implementations, pub visibility, and more
  • AST/CST parsing — extracts functions, methods, structs, enums, traits, impls, macros, variables, and fields; aware of type annotations and unpacked variables
  • Dependency graph — builds directed edges: read, write, call, inherit, decorate
  • Entry point detection — 17 built-in rules covering Python frameworks (FastAPI, Flask, Django, Click, Typer, Celery, pytest) and Rust conventions (main, async runtimes, WASM, proc macros, FFI, tests, pub API) plus custom rules
  • Configurable entry templates — add custom entry rules via ast_pattern prefixes including function_call:, function_def:, decorator:, file_match:, visibility:pub (Rust), trait_impl: (Rust), macro_def: (Rust), and more
  • --public-as-entry flag — treat all public items (Rust pub) as entry points for library-crate analysis
  • Warning detection — 11 warning types including circular references, unused imports, write-only variables, and more
  • Incremental updates — after initial full scan, only changed files are re-indexed; delta-aware reachability analysis avoids full-graph recomputation.
  • Python API + CLI — integrate into any Tool, CI pipeline, or let agents self-analyze and self-clean

Installation

pip install graphlint

Requirements: Python >= 3.9

For Rust support (.rs files), install the optional tree-sitter dependencies:

pip install graphlint[rust]

Quick Start

Agent Integration

Graphlint provides a command to inject its usage prompt into your AI coding tools at the global level, so every project automatically has graphlint's guidance:

# Install graphlint prompt into agent tools (opencode, cursor, codex, cc)
graphlint install

# Copy the prompt to clipboard for manual paste into your agent
graphlint prompt

# Remove graphlint prompt from agent tools
graphlint uninstall

Run graphlint install and select the tools you use — the prompt (usage scenarios, essential commands, and parameters) will be added to their global configuration. For details, see Agent Integration.

If your agent tool is not listed in install, run graphlint prompt to copy the prompt to your clipboard and provide it to your agent manually. For tools you'd like native support for, feel free to submit an issue — these requests are typically handled quickly.

CLI

# Find dead code in current directory
graphlint query --warn-types "dead_code"

# Full analysis with JSON output
graphlint query --json

# View a specific graph detail
graphlint query -g 1 --detail full

# Exit non-zero when dead code or circular refs found (for CI)
graphlint query --json --fail-on dead_code,circular_ref

# Treat all public items as entry points (library-crate mode)
graphlint query --public-as-entry

# Rebuild index
graphlint build --force

# Configure
graphlint config show
graphlint config set --key lang --value en

Exit Codes

Code Meaning
0 Success — no warnings matched --fail-on
1 Error — invalid parameters, exception, or config error
2 Warnings found — --fail-on matched specified warning types

Use --fail-on with a comma-separated list of warning types to make graphlint query return exit code 2 when matching warnings are found. This enables CI pipeline integration without blocking on non-critical warnings.

Graphlint is static-analysis based and cannot recognize certain Python dynamic references (e.g., getattr, importlib), which may produce unexpected exit codes. Only use --fail-on for CI blocking behavior when you're confident in your configuration. Agents are better suited for logic that requires contextual judgment. See Limitations for details.

Python API

from graphlint.api import query

# Find dead code components
result = query(warn_types="dead_code", json_output=True)

# Full dependency graph analysis
result = query(include_tests=True, json_output=True)

Warning Types

Warning Description
unused_import Imported module or name is never used
dynamic_import Dynamic import via importlib or __import__
circular_ref Circular dependency between functions/classes
syntax_error File contains a syntax error
write_only Variable is written but never read
deprecated_usage Usage of a deprecated function/class
dead_code Component unreachable from any entry point
type_mismatch Suspicious type annotations
unresolved_ref Reference to an undefined name
unused_variable Variable is defined but never used
file_too_large File exceeds the configured size limit

Development

# Clone the repository
git clone https://github.com/AngelosZou/graphlint.git
cd graphlint

# Create a virtual environment
python -m venv env
env/Scripts/activate  # Windows
source env/bin/activate  # Unix

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run with coverage
pytest --cov=graphlint

# Run type checking
mypy graphlint/

# Run linting
ruff check graphlint/ tests/

Configuration

Graphlint stores its configuration in .graphlint/config.json within the analyzed directory. Use graphlint config commands to manage settings, or edit the file directly.

See graphlint config show for the full default configuration.

Documentation

Full documentation is available in the docs/ directory:

Limitations

  • Static analysis only — graphlint performs static analysis and cannot detect runtime linkage such as getattr, importlib, or dynamic dispatch patterns, which may result in false positives. This primarily affects Python; Rust's static dispatch model produces fewer false positives. Mitigation: add custom entry rules matching your codebase's conventions. For example, graphlint's own codebase uses function_def:_detect_* and function_def:visit_* patterns to prevent functions discovered via getattr from being flagged as dead.
  • Python dynamic imports — due to Python's dynamic import mechanisms (importlib, getattr, metaclasses, etc.), the default entry templates may produce false positives in codebases that rely heavily on runtime dispatch. Users should tune the entry_rules configuration to match their project's conventions.
  • Rust macro expansion — tree-sitter parses unexpanded source; procedural macros and macro_rules! bodies appear as opaque token trees. Some macro-generated call paths may be missed. #[derive] attributes are partially recognized via implicit inherit edges.
  • --public-as-entry scope — this flag only applies to languages with public visibility declarations (Rust pub). It has no effect on Python files. Toggling this flag triggers a full re-index. For long-term library-crate analysis, prefer enabling the rust_pub_api entry rule via graphlint config to persist the setting.
  • Large codebase build time — on a large codebase with 700+ .py files, 1,000+ classes, and 14,000+ functions, a full rebuild takes approximately 200 seconds (actual performance depends on hardware). Small projects (~60 files) complete in ~1 second. This cost is one-time, after the initial full scan, subsequent queries use incremental updates.

License

MIT — see LICENSE for details.

Links

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

graphlint-0.3.6.tar.gz (189.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

graphlint-0.3.6-py3-none-any.whl (110.1 kB view details)

Uploaded Python 3

File details

Details for the file graphlint-0.3.6.tar.gz.

File metadata

  • Download URL: graphlint-0.3.6.tar.gz
  • Upload date:
  • Size: 189.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for graphlint-0.3.6.tar.gz
Algorithm Hash digest
SHA256 c0eb6112864ddb1c760529af7d8bec0a30b9d4e2db5b2e5ab51cf33ae6dced88
MD5 f430917abeb31bc69f4aa0a60b29c749
BLAKE2b-256 e7e7a03567915ce5172caabbea0f923305b46329f34a76dadee8e65c2ad6c03e

See more details on using hashes here.

File details

Details for the file graphlint-0.3.6-py3-none-any.whl.

File metadata

  • Download URL: graphlint-0.3.6-py3-none-any.whl
  • Upload date:
  • Size: 110.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for graphlint-0.3.6-py3-none-any.whl
Algorithm Hash digest
SHA256 cf8f72d853d12941edea7ef050f690f4823e200286ff0cdc9714304e1a23e718
MD5 cebe69d384c79ac492de63fc660ebd4b
BLAKE2b-256 51a4fb996e484dd1a2a6137e48152304ffc9e2332ebe6202360fc6eb029fbeed

See more details on using hashes here.

Release history Release notifications | RSS feed

0.7.1

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.1

2 files

0.4.0

2 files

0.3.8

2 files

0.3.7

2 files

This release

0.3.6 This release

2 files

0.3.5

2 files

0.3.4

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.0

2 files

0.1.12

2 files

0.1.11

2 files

0.1.10

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page