Graph-based code intelligence for AI agents
Project description
Gristle
Graph-based code intelligence for AI agents. Gristle parses repositories into a FalkorDB graph database, preserving structural relationships — function calls, imports, inheritance, routes, and data models — so AI agents can query code the way humans think about it.
It traces a request from HTTP route → handler → function → database model end-to-end, scores the blast radius of a change before you make it, and renders any slice of the graph as a diagram — all exposed natively over MCP so an agent can call it mid-task.
Why graphs instead of vectors?
Vector search over chunked code loses structure. "Function A calls function B which inherits from class C" becomes three unrelated text chunks. Gristle keeps these relationships as first-class edges in a graph, enabling queries like:
- Impact analysis — "What breaks if I change this function?"
- Call tracing — "How does a request flow from the API handler toward the database?"
- Convention inference — "What patterns does this project follow?"
- Visualization — render a route's full path to the database, or a function's blast radius, as a node-link diagram (
gristle_subgraphover MCP, or a self-contained HTML file viagristle viz).
Who is Gristle for?
Gristle serves two consumers equally — AI coding agents (via MCP) and the developers driving them. Three primary beneficiaries:
- AI coding agents (and the developer driving them) — the headline audience. An agent can't hold a large repo in context, and vector-chunking destroys the very relationships it needs to reason about a change. Before editing, an agent asks Gristle "what breaks if I change this?" (
gristle_impact_score), "which tests cover it?" (gristle_tests), and "how does this route reach the database?" (gristle_subgraph) — turning a confident guess into a grounded edit. Gristle is the only code graph of its kind that's MCP-native. - Developers onboarding to an unfamiliar codebase. They need a map, not taint analysis.
gristle_conventionsplus arequest_tracesubgraph turn a wall of files into a picture of the request surface — build-free, in seconds. - Security / API auditors doing a first-pass structural review. Which routes have no auth? What's the middleware chain? Any hardcoded secrets or CVE-laden dependencies? — surface enumeration across the whole repo (
gristle_security,gristle_unauthenticated_routes,gristle_dependency_health). A first-pass structural audit, explicitly not a taint/dataflow proof.
In one line: Gristle is the connected route→handler→DB code graph that AI agents query over MCP — so the agent knows the blast radius and the request-to-database path before it writes a diff. Deeper than ctags/tree-sitter-only tools, lighter and broader than type-resolved indexers, and the only one designed to be called by an agent rather than browsed in an IDE.
Probably not for you if you need type-exact resolution (use a SCIP/LSIF indexer such as Sourcegraph), dataflow/taint proofs (CodeQL), a language outside Python/TS/JS (+ Vue/Svelte/Astro), or zero infrastructure (Gristle needs FalkorDB running). Its edges are high-coverage navigation aids, not proofs — see the boundary below.
Scope (and what it isn't)
Gristle is a fast, build-free, framework-aware structural graph built with tree-sitter — multiple languages in one queryable graph, exposed natively over MCP for agents. That's its niche, and it's worth being clear about the boundary:
- Call/import resolution is name- and heuristic-based, not type-resolved. It's high-coverage and great for navigation and architecture, but it can miss or mis-link edges that a type-aware indexer (SCIP/LSIF, Sourcegraph) would get exactly. Edges are best-effort, not proofs.
- It is not a dataflow/taint engine (CodeQL/Glean). It models structural and framework relationships (calls, routes→handlers, code→model, tests→code, deps), not value-level data flow.
- Coverage is strongest on the supported frameworks below; constructs outside them (and languages without a parser) are simply not represented.
Supported languages
| Language | Functions | Classes | Imports | Routes | Components | Tests |
|---|---|---|---|---|---|---|
| Python | Yes | Yes | Yes | FastAPI, Flask, Django | - | pytest |
| TypeScript | Yes | Yes | Yes | Express, Hono, Fastify | React | jest, vitest |
| JavaScript | Yes | Yes | Yes | Express, Hono, Fastify | React | jest, vitest |
| Vue / Svelte / Astro | Yes | Yes | Yes | - | - | - |
Vue/Svelte/Astro single-file components are parsed by extracting the embedded
<script> block (or Astro --- frontmatter) and analyzing it with the TypeScript
parser, so the script's functions, classes, imports, and variables become graph
nodes alongside the rest of the codebase.
Quick start
Prerequisites: Python 3.11+ and Docker (with Docker Compose). FalkorDB runs in Docker; everything else is pip-installed.
1. Install
Once published, the fastest path will be
uvx gristle/pipx install gristle, ordocker run ghcr.io/alchemy-agentic/gristle.
For now (and for development), install from source:
git clone https://github.com/Alchemy-Agentic/gristle
cd gristle
pip install -e .
2. Start FalkorDB and check your setup
docker compose up -d falkordb # start FalkorDB (exposes localhost:6390)
gristle doctor # verify FalkorDB, parsers, and config
3. Index a repo and explore it — from the terminal
gristle ingest examples/sample-app --repo-id demo
gristle overview --repo-id demo
gristle explore register --repo-id demo
gristle query "MATCH (f:Function)-[:CALLS]->(g:Function) RETURN f.name, g.name LIMIT 10" --repo-id demo
gristle viz --repo-id demo --view request_trace --out demo.html # render route→DB as a self-contained HTML diagram
Point gristle ingest at your own project to index it. See examples/ for a guided walkthrough.
4. Wire it into your AI client (MCP)
Run Gristle as a local MCP server (gristle serve, or just gristle) and add it to your client config — e.g. Claude Desktop's claude_desktop_config.json:
{
"mcpServers": {
"gristle": {
"command": "gristle",
"args": ["serve"],
"env": {
"GRISTLE_FALKORDB_HOST": "localhost",
"GRISTLE_FALKORDB_PORT": "6390"
}
}
}
}
FalkorDB must be running (
docker compose up -d falkordb) before the first tool call.
Or with the Claude Code CLI: claude mcp add gristle --env GRISTLE_FALKORDB_PORT=6390 -- gristle serve.
Then ask your agent to ingest a repo (gristle_ingest) and explore the code, trace calls, or run an impact analysis.
Use as a library
Gristle's pipeline and query engine are usable directly from Python:
from gristle.graph.client import GraphClient
from gristle.ingestion.pipeline import IngestionPipeline
from gristle.parsers.registry import ParserRegistry
graph = GraphClient(host="localhost", port=6390, repo_id="myrepo")
IngestionPipeline(graph, ParserRegistry().build_default()).ingest_repo("/path/to/your/repo")
rows = graph.execute("MATCH (f:Function) RETURN count(f) AS functions").records
print(rows) # e.g. [{'functions': 1234}]
Remote (HTTP transport)
Run as an HTTP server for shared or cloud deployments:
GRISTLE_TRANSPORT=streamable-http \
GRISTLE_API_KEY=your-secret-key \
gristle
Connect from your MCP client:
{
"mcpServers": {
"gristle": {
"url": "https://your-gristle-host/mcp",
"headers": {
"Authorization": "Bearer your-secret-key"
}
}
}
}
Railway
Gristle is production-ready on Railway. Deploy it alongside a FalkorDB instance and set these environment variables:
| Variable | Value |
|---|---|
GRISTLE_FALKORDB_HOST |
Internal hostname of your FalkorDB service |
GRISTLE_FALKORDB_PORT |
6390 |
GRISTLE_FALKORDB_PASSWORD |
Your FalkorDB password (if set) |
GRISTLE_API_KEY |
A secret token for auth |
Railway auto-injects PORT which Gristle picks up. The transport defaults to streamable-http in the Docker image.
MCP tools
Gristle exposes 32 tools and 2 resources via MCP. See the Integration Guide for the full reference with examples, workflows, and tips.
Key tools: gristle_ingest, gristle_explore, gristle_impact, gristle_impact_score, gristle_trace, gristle_subgraph, gristle_search, gristle_conventions, gristle_tests, gristle_routes, gristle_models, gristle_config, gristle_dead_exports, gristle_cycles, gristle_data_contract, gristle_type_usage, gristle_security, gristle_unauthenticated_routes, gristle_dependency_health. gristle_subgraph returns a {nodes, edges, meta} subgraph for the call_hierarchy, blast_radius, and request_trace views — the same data gristle viz renders to HTML.
Development
pip install -e ".[dev]"
pytest # run tests
ruff check src/ tests/ # lint
ruff format src/ tests/ # format
mypy src/ # type check
Docker
Run both FalkorDB and Gristle together:
docker compose up -d
This starts FalkorDB on port 6390 and Gristle on port 8080 with streamable-http transport.
Documentation
| Document | Audience | Content |
|---|---|---|
| Integration Guide | AI agents, consuming apps | Graph schema, tool reference, configuration, deployment, workflows |
| Architecture | Contributors | Data models, parsers, ingestion pipeline, call resolution, design decisions |
| Changelog | Everyone | Version history, what's new, breaking changes |
| Audience | Product / positioning | Who Gristle benefits most — personas, use cases, and how that drives the parser roadmap |
| Roadmap | Product planning | Upcoming features, prioritization |
Contributing
Contributions are welcome — see CONTRIBUTING.md for setup, testing, and the pull-request checklist. To report a security issue, see SECURITY.md.
License
Gristle is released under the MIT License.
Gristle connects to — but does not bundle — FalkorDB, which is distributed under its own license.
Project details
Release history Release notifications | RSS feed
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 gristle-0.1.1.tar.gz.
File metadata
- Download URL: gristle-0.1.1.tar.gz
- Upload date:
- Size: 502.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88f80fcd4cf05d7e5cc23765ce8a8e217bbefac4a83527dcf290a96e21be9776
|
|
| MD5 |
5094cac86ea4fbd455c747ecfb9edd85
|
|
| BLAKE2b-256 |
f12417517ef913419424110c8f289c72105f6a55922a6bed10b39742419a5ca4
|
Provenance
The following attestation bundles were made for gristle-0.1.1.tar.gz:
Publisher:
release.yml on Alchemy-Agentic/gristle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gristle-0.1.1.tar.gz -
Subject digest:
88f80fcd4cf05d7e5cc23765ce8a8e217bbefac4a83527dcf290a96e21be9776 - Sigstore transparency entry: 2015341049
- Sigstore integration time:
-
Permalink:
Alchemy-Agentic/gristle@8e61cbe4977d8768b85a44e89700af08f49d467e -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Alchemy-Agentic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8e61cbe4977d8768b85a44e89700af08f49d467e -
Trigger Event:
push
-
Statement type:
File details
Details for the file gristle-0.1.1-py3-none-any.whl.
File metadata
- Download URL: gristle-0.1.1-py3-none-any.whl
- Upload date:
- Size: 352.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cbae0f9f325d5b2bbb3e0bb23a5a2ead5105dc46f474e1dcad6b345023594bf7
|
|
| MD5 |
3c264beb703ec6812076f9933b2d0fd5
|
|
| BLAKE2b-256 |
65e59c7bb326856debac57bd56499e9da8ce9e31ad7536ec2e15647f0731e13c
|
Provenance
The following attestation bundles were made for gristle-0.1.1-py3-none-any.whl:
Publisher:
release.yml on Alchemy-Agentic/gristle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gristle-0.1.1-py3-none-any.whl -
Subject digest:
cbae0f9f325d5b2bbb3e0bb23a5a2ead5105dc46f474e1dcad6b345023594bf7 - Sigstore transparency entry: 2015341415
- Sigstore integration time:
-
Permalink:
Alchemy-Agentic/gristle@8e61cbe4977d8768b85a44e89700af08f49d467e -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Alchemy-Agentic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8e61cbe4977d8768b85a44e89700af08f49d467e -
Trigger Event:
push
-
Statement type: