Introduction
graphlens is an extensible polyglot code analysis framework. It parses source projects, normalizes their structure into a shared graph IR, and exposes that graph for dependency analysis, navigation, and code-intelligence tooling.
Repository → Language Adapter → GraphLens (IR) → Graph Backend
| Layer | Responsibility |
|---|---|
| Language Adapter | Parses source files, produces a GraphLens |
| GraphLens | Typed nodes + directed relations — the intermediate representation |
| Graph Backend | Persists or queries the graph (Neo4j, in-memory, your own) |
Adapters are pure data producers — they never write to any backend. The graph is the only output, which makes the whole pipeline easy to test, cache, serialize, and reason about.
Scope & Non-goals
graphlens produces a graph IR — and stops there. To keep the boundary explicit, it deliberately does not:
- persist state or own a database — backends (Neo4j, JSON on disk, your own) are a separate layer that consumes the graph; adapters never write to them.
- watch the filesystem or re-index incrementally on its own — a scan is a pure function of the source tree; incremental updates are enabled by deterministic node IDs but driven by the caller.
- compute embeddings, semantic search, or relevance ranking — the graph is structural and type-aware, not a vector index.
- provide a UI or an agent runtime —
visualizeemits a static HTML file andmcpexposes query tools, but graphlens hosts no long-running service or app. - orchestrate a pipeline — the core has no orchestration or I/O; composing adapters, backends, and policies belongs in user code or a separate package (the CLI is the reference example).
These responsibilities belong to tools built on top of graphlens, not to the framework itself.
Why a graph IR?
- Language-agnostic — one shared model for Python, TypeScript, Go, and Rust.
- Plugin-based adapters — each language is a separate package, discovered at runtime through Python entry points. The core never imports an adapter.
- Tree-sitter powered — every adapter uses Tree-sitter for structure and
exact span positions, combined with a type-aware resolver
(
tyfor Python, the TypeScript Compiler API,goplsfor Go,rust-analyzerfor Rust) that emits realCALLS/REFERENCES/HAS_TYPE/INHERITS_FROMedges. - Cross-language aware — adapters emit language-agnostic
BOUNDARYports (HTTP, queues, gRPC, Temporal), andgraphlens-linkconnects a consumer in one language to a provider in another. - Monorepo aware — root discovery handles multi-language repositories correctly.
- Deterministic node IDs — a SHA-256 hash of
project::kind::qualified_nameis stable across re-scans, which makes diffing and incremental updates work.
What can you do with it?
Use it as a library
Call an adapter from Python, get a GraphLens, and query it — find callers and
callees, walk neighborhoods, diff two scans, serialize to JSON, or merge graphs
from several languages.
Use it from the CLI
graphlens analyze, query, visualize, neo4j, and mcp cover the common
workflows without writing any code.
Run it in CI
A --strict mode and a pre-built Docker image with every toolchain make it
easy to index a repository on every push and fail the build on a degraded
graph.
Serve it to agents
The mcp command exposes a saved graph to LLM agents over the Model Context
Protocol as a set of query tools.
A 30-second taste
from pathlib import Path
from graphlens import adapter_registry
adapter = adapter_registry.load("python")()
graph = adapter.analyze(Path("./my-project"))
print(len(graph.nodes), "nodes,", len(graph.relations), "relations")
fn = graph.nodes_by_name("my_function")[0]
print("called by:", [n.name for n in graph.callers(fn.id)])
Requirements
- Python 3.13+
- uv is recommended for installation and development.
- Language resolvers drive external toolchains. The Python (
ty) and TypeScript (Node) toolchains are installed on demand; Go (gopls) and Rust (rust-analyzer) are most easily obtained through the Docker image.
Next steps
- Installation — install the core, an adapter, or the CLI.
- Quick Start — analyze a project in a few lines.
- Core Concepts — adapters, resolvers, nodes, relations, and boundaries.