entrygraph
entrygraph builds a queryable graph of your codebase. It indexes a repository
into a local SQLite database, then answers questions about the code: what
symbols and classes exist, what the entrypoints are (HTTP routes, GraphQL
resolvers, CLI commands, main, tasks, lambdas), who calls what, and whether
untrusted input can reach a dangerous function.
It works across Python, JavaScript/TypeScript, Go, Java, Ruby, C#, PHP, and Rust, using tree-sitter to parse and per-language rules to detect frameworks and entrypoints.
Install
pip install entrygraph # or: uv pip install entrygraph
Requires Python 3.13+. This installs the entrygraph command.
Quick start
Index a repo, then query it:
cd ~/code/my-app
entrygraph index .
entrygraph entrypoints
entrygraph callers my_app.services.charge
The index lives in ~/.entrygraph/.entrygraph.db and holds every repo you
index, keyed by path. Query commands automatically use the repo you're standing
in; to query another repo, add --repo <name> (run entrygraph repos to see
what's indexed). Add --json to any command for machine-readable output.
Commands
| Command | What it does |
|---|---|
index <path|url> |
Build or update the graph. Incremental by default; --full rebuilds. A git URL is cloned first. |
detect |
Languages (by byte share) and detected frameworks. |
symbols |
Search symbols by name, qualified name, kind, or file. |
entrypoints |
Every route, GraphQL resolver, command, main, task, and handler, with its framework and location. |
callers / callees |
Who calls a symbol / what it calls (--depth N). |
references |
Every call site targeting a symbol, with file:line. |
paths |
Source → sink reachability (see below). |
stats |
Counts for the current repo. |
repos |
List the repositories in the database, with each one's refresh status. |
reindex --stale |
Refresh repos whose data predates the current analyzer (see Upgrading). |
serve |
Web UI over the index. |
Run entrygraph <command> --help for the flags on each.
Upgrading
The index is a cache, but upgrading entrygraph does not make you rebuild it.
A structural schema change is migrated in place, preserving your data. When a
release improves the analyzer itself — teaching it a new framework, say — every
repo you've already indexed keeps serving its existing results and is simply
marked refreshing until re-scanned; nothing goes offline and no repo is wiped.
Refresh them on your own schedule with entrygraph reindex --stale, or let
entrygraph serve do it automatically in the background (EG_HEAL_INTERVAL_S:
0 sweeps once at startup, the default; >0 also re-sweeps on that interval;
-1 disables).
Reachability (paths)
paths answers "can untrusted input reach a dangerous function?" — for example,
can an HTTP request reach subprocess.run. It traces call paths from a
source (where input enters) to a sink (a risky API), using a built-in
catalog of both.
entrygraph paths --source-category http_input --sink-category command_exec
1 path http_input → command_exec
[1] confirmed data flow → high-severity command_exec sink
entrypoint POST /reports flask http_route
source create_report app/routes.py:12 query "cmd"
cmd = request.args.get("cmd")
↓ run_report app/routes.py:20
sink subprocess.run app/services.py:22
subprocess.run(cmd, shell=True)
confidence resolved — every call is exact/import
Read each finding top-down:
- The headline tells you whether to act:
confirmed data flowmeans input actually reaches the sink;reachable, but no data flow observedmeans the call path exists but the input doesn't provably flow through it. It's paired with the sink's severity and category. - entrypoint — the route or command the path is reachable through, when the source is one. This is the surface an attacker would actually hit.
- source → sink — the call chain, each with its
file:lineand the literal line of code. Uncertain links are flagged (~ fuzzy (guess)); the rest are solidly resolved. - confidence — how much to trust the weakest link in the chain.
Paths are ordered best first (confirmed flows, then by severity and confidence). A finding is a lead to review, not proof of a bug.
Useful options:
--source/--sinkname an exact symbol instead of a category (the language prefix is optional:--sink subprocess.run).--list-categoriesprints the valid source and sink categories.--confirmed-onlykeeps only paths with a confirmed flow.--strictreports only high-confidence paths; otherwise the search widens automatically when it finds nothing.
Web UI
entrygraph serve
Browse symbols, entrypoints, the call graph, and reachability in the browser, and
index repos from the UI. Runs locally with no auth by default; supports OIDC SSO
for shared deployments. Everything is bundled — uvx entrygraph serve just works.
(When developing from a source checkout, build the UI once with
cd webapp && npm run build.)
Python API
Every CLI command is a thin wrapper over the CodeGraph class:
from entrygraph import CodeGraph
graph = CodeGraph.index("/path/to/repo") # or CodeGraph.open("index.db")
graph.entrypoints(framework="flask")
graph.callers("app.services.charge")
graph.paths(source_category="http_input", sink_category="sql")
graph.reachable(source="app.routes.upload", sink="py:subprocess.run") # -> bool
Results are plain frozen dataclasses, safe to hold and easy to serialize.
How it works
entrygraph walks the tree (skipping vendored and generated files), parses each file with tree-sitter, resolves references to their definitions with a confidence level, detects frameworks and entrypoints, and stores everything in SQLite. Re-indexing only reparses changed files. Reachability is a graph traversal over the stored call edges; the analyzed code is never executed.
Extending
Add custom sinks and sources with an entrygraph.toml in the repo root (same
format as the built-in catalogs under data/sinks/). New frameworks and
languages are added with small rule and tree-sitter query modules.
License
MIT
Metadata
Release files for entrygraph 0.1.134
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| entrygraph-0.1.134.tar.gz | 757.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| entrygraph-0.1.134-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.3 MB
Release files / entrygraph-0.1.134.tar.gz
| Download URL | entrygraph-0.1.134.tar.gz |
|---|---|
| Size | 757.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1ea5fed142eecec86d847b4d871338511772d3b2a795eb898bceb14996398451
|
|
BLAKE2b-256 checksum How to use checksums |
7abfcece4d13c47476a59114ef99080fbfa05c4edb295a196836f598cf5ee0a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / entrygraph-0.1.134-py3-none-any.whl
| Download URL | entrygraph-0.1.134-py3-none-any.whl |
|---|---|
| Size | 579.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a7022964b7d30093ed8c4fd97e512f20140263ee26705e45a441ee3e2643c9ca
|
|
BLAKE2b-256 checksum How to use checksums |
e59866ffee64f17d9e6d0527d90319912bf723784b09d53d85885425f8df4fa4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency log