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
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file entrygraph-0.1.134.tar.gz.
File metadata
- Download URL: entrygraph-0.1.134.tar.gz
- Upload date:
- Size: 757.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ea5fed142eecec86d847b4d871338511772d3b2a795eb898bceb14996398451
|
|
| MD5 |
f6c3e5f67f23918bfaa7b270926e126c
|
|
| BLAKE2b-256 |
7abfcece4d13c47476a59114ef99080fbfa05c4edb295a196836f598cf5ee0a2
|
Provenance
The following attestation bundles were made for entrygraph-0.1.134.tar.gz:
Publisher:
release.yml on brettbergin/entrygraph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
entrygraph-0.1.134.tar.gz -
Subject digest:
1ea5fed142eecec86d847b4d871338511772d3b2a795eb898bceb14996398451 - Sigstore transparency entry: 2222575708
- Sigstore integration time:
-
Permalink:
brettbergin/entrygraph@3e40bedc712cc1266e8abab4cd3dfd786b8a8bc5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/brettbergin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3e40bedc712cc1266e8abab4cd3dfd786b8a8bc5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file entrygraph-0.1.134-py3-none-any.whl.
File metadata
- Download URL: entrygraph-0.1.134-py3-none-any.whl
- Upload date:
- Size: 579.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7022964b7d30093ed8c4fd97e512f20140263ee26705e45a441ee3e2643c9ca
|
|
| MD5 |
308c5d8a339b8eb4f04c621c327447c9
|
|
| BLAKE2b-256 |
e59866ffee64f17d9e6d0527d90319912bf723784b09d53d85885425f8df4fa4
|
Provenance
The following attestation bundles were made for entrygraph-0.1.134-py3-none-any.whl:
Publisher:
release.yml on brettbergin/entrygraph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
entrygraph-0.1.134-py3-none-any.whl -
Subject digest:
a7022964b7d30093ed8c4fd97e512f20140263ee26705e45a441ee3e2643c9ca - Sigstore transparency entry: 2222576252
- Sigstore integration time:
-
Permalink:
brettbergin/entrygraph@3e40bedc712cc1266e8abab4cd3dfd786b8a8bc5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/brettbergin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3e40bedc712cc1266e8abab4cd3dfd786b8a8bc5 -
Trigger Event:
push
-
Statement type: