Skip to main content

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
LayerResponsibility
Language AdapterParses source files, produces a GraphLens
GraphLensTyped nodes + directed relations — the intermediate representation
Graph BackendPersists 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 runtimevisualize emits a static HTML file and mcp exposes 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 (ty for Python, the TypeScript Compiler API, gopls for Go, rust-analyzer for Rust) that emits real CALLS / REFERENCES / HAS_TYPE / INHERITS_FROM edges.
  • Cross-language aware — adapters emit language-agnostic BOUNDARY ports (HTTP, queues, gRPC, Temporal), and graphlens-link connects 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_name is 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.

→ Library API guide

Use it from the CLI

graphlens analyze, query, visualize, neo4j, and mcp cover the common workflows without writing any code.

→ CLI guide

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.

→ CI integration

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.

→ MCP server

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.