{"id":51574990,"url":"https://github.com/escoffier-labs/graphtrail","last_synced_at":"2026-07-10T23:30:47.177Z","repository":{"id":366461919,"uuid":"1276078230","full_name":"escoffier-labs/graphtrail","owner":"escoffier-labs","description":"Your agents grep. GraphTrail shows who calls whom. Local SQLite code graph: callers, callees, impact, and context over CLI + read-only MCP. No daemon, no network.","archived":false,"fork":false,"pushed_at":"2026-07-10T13:20:34.000Z","size":1249,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-07-10T15:08:05.858Z","etag":null,"topics":["ai-agents","call-graph","code-graph","code-navigation","mcp","mcp-server","rust","static-analysis","tree-sitter"],"latest_commit_sha":null,"homepage":"https://brigade.tools/graphtrail","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/escoffier-labs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-21T14:13:05.000Z","updated_at":"2026-07-10T13:19:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/escoffier-labs/graphtrail","commit_stats":null,"previous_names":["escoffier-labs/graphtrail"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/escoffier-labs/graphtrail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escoffier-labs%2Fgraphtrail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escoffier-labs%2Fgraphtrail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escoffier-labs%2Fgraphtrail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escoffier-labs%2Fgraphtrail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/escoffier-labs","download_url":"https://codeload.github.com/escoffier-labs/graphtrail/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escoffier-labs%2Fgraphtrail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35346644,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-10T02:00:06.465Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","call-graph","code-graph","code-navigation","mcp","mcp-server","rust","static-analysis","tree-sitter"],"created_at":"2026-07-10T23:30:44.945Z","updated_at":"2026-07-10T23:30:47.170Z","avatar_url":"https://github.com/escoffier-labs.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/graphtrail-social-preview.jpg\" alt=\"GraphTrail banner\" width=\"900\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eGraphTrail\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/marks/graphtrail-circle.svg\" alt=\"\" width=\"40\" height=\"40\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eYour agents grep. GraphTrail shows who calls whom.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  Local code graph in SQLite: symbols, imports, and real tree-sitter call edges. Ask \u003ccode\u003ecallers\u003c/code\u003e, \u003ccode\u003ecallees\u003c/code\u003e, \u003ccode\u003eimpact\u003c/code\u003e, and \u003ccode\u003econtext\u003c/code\u003e over a CLI or MCP server, so an edit starts from the call graph instead of a guess. No daemon, no network in the default build.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://brigade.tools/graphtrail\"\u003eWebsite\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#install\"\u003eInstall\u003c/a\u003e \u0026middot;\n  \u003ca href=\"https://brigade.tools\"\u003eBrigade hub\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://shieldcn.dev/github/ci/escoffier-labs/graphtrail.svg?branch=master\u0026workflow=ci.yml\" alt=\"CI status\"\u003e\n  \u003cimg src=\"https://shieldcn.dev/badge/crate-v0.3.0-orange.svg?logo=rust\u0026logoColor=white\" alt=\"Crate version 0.3.0\"\u003e\n  \u003cimg src=\"https://shieldcn.dev/badge/license-MIT-green.svg\" alt=\"MIT license\"\u003e\n  \u003cimg src=\"https://shieldcn.dev/badge/MCP-server-8A2BE2.svg\" alt=\"MCP server\"\u003e\n\u003c/p\u003e\n\n## Install\n\nGraphTrail requires Rust 1.85 or newer. It installs two binaries: `graphtrail` for CLI use and `graphtrail-mcp` for MCP clients. From [crates.io](https://crates.io/crates/graphtrail):\n\n```bash\ncargo install graphtrail\n```\n\nFrom git or a clone:\n\n```bash\ncargo install --git https://github.com/escoffier-labs/graphtrail\n# or\ngit clone https://github.com/escoffier-labs/graphtrail.git\ncd graphtrail \u0026\u0026 cargo build --release\n```\n\n## Quickstart\n\n```bash\ngraphtrail init .\ngraphtrail sync .                    # incremental after the first pass\nDB=.graphtrail/graphtrail.db\n\ngraphtrail --db \"$DB\" callers serve\ngraphtrail --db \"$DB\" callees serve\ngraphtrail --db \"$DB\" impact serve --depth 2\ngraphtrail --db \"$DB\" context \"handoff lint\" --json\ngraphtrail --db \"$DB\" doctor . --json\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/graphtrail-context.svg\" alt=\"Recording: graphtrail init and sync, then callers and context\" width=\"760\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\u003cem\u003e\u003ccode\u003einit\u003c/code\u003e + \u003ccode\u003esync\u003c/code\u003e build the graph. \u003ccode\u003ecallers\u003c/code\u003e / \u003ccode\u003econtext\u003c/code\u003e answer from it.\u003c/em\u003e\u003c/p\u003e\n\nReal output against GraphTrail's own source:\n\n```text\n$ graphtrail --db .graphtrail/graphtrail.db callers serve\nmain --calls@19 hops=1--\u003e serve  (src/bin/graphtrail-mcp.rs -\u003e src/mcp.rs)\n```\n\n## What it does\n\n| | Job | What you get |\n|---|---|---|\n| **Index** | Parse the repo with tree-sitter | Symbols, imports, and call edges in `.graphtrail/graphtrail.db` |\n| **Ask** | Query structure, not text | `search`, `callers`, `callees`, `impact`, `file_neighbors`, `dead_code`, `cycles`, `affected`, `diff` |\n| **Brief** | Pack neighborhood for agents | `context` over CLI or MCP. Brigade can attach it to runs |\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/graph-relationships.svg\" alt=\"Call graph around serve: callers on the left, focus symbol in the center, callees on the right, impact as blast radius, context pack for agents\" width=\"880\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\u003cem\u003eGrep finds strings. Embeddings find vibes. The graph finds who calls whom, and what breaks if you change it.\u003c/em\u003e\u003c/p\u003e\n\nPython, TypeScript/JavaScript, Rust, and Go. One SQLite file per repo. CLI for humans and scripts. `graphtrail-mcp` serves agents, opens query connections with `SQLITE_OPEN_READ_ONLY`, and supports multiple repositories through `repo` and `db` arguments. No hooks, no daemon, no network in the default build.\n\nWhen the sync root is inside a git repository, `sync` follows `.gitignore` and `.git/info/exclude`, while still indexing hidden paths such as `.github` if they are not ignored. `doctor` exits 0 for `FRESH`, 1 for `STALE`, or 2 for `NEEDS-MIGRATION` or a missing database.\n\n## MCP server\n\n`graphtrail-mcp` speaks newline-delimited JSON-RPC 2.0 over stdio. It has no async runtime and no extra dependencies, so the sidecar stays small. `refresh: true` starts an incremental graph-index write and waits up to 10 seconds before opening the query read-only. If the refresh fails or times out, the query proceeds and appends a `refresh_error` note to its text result. A timed-out worker may finish concurrently with that read-only query. Without `refresh`, query tools do not write the graph.\n\nThe default database comes from `--db \u003cpath\u003e`, `--db=\u003cpath\u003e`, the `GRAPHTRAIL_DB` env var, or `.graphtrail/graphtrail.db` in the working directory. Every tool also accepts an optional `repo` (uses `\u003crepo\u003e/.graphtrail/graphtrail.db`) or `db` (explicit path) argument, so a single running server can answer for any indexed repository. The database is opened lazily per call, so the server starts even before the default db exists.\n\nRegister it with an MCP client. For Claude Code, add to `.mcp.json` (project scope) or `~/.claude.json` (user scope):\n\n```json\n{\n  \"mcpServers\": {\n    \"graphtrail\": {\n      \"command\": \"/abs/path/to/graphtrail-mcp\",\n      \"args\": [\"--db\", \"/abs/path/to/repo/.graphtrail/graphtrail.db\"]\n    }\n  }\n}\n```\n\n### Tools\n\nThe server exposes thirteen tools. This list is verified against the live `tools/list` response from `graphtrail-mcp`:\n\n| Tool | Required args | What it returns |\n|---|---|---|\n| `search` | `query` (`limit` optional, default 20, `path` optional) | Full-text search of code symbols (functions, classes, methods) by name, optionally filtered by indexed file path. |\n| `callers` | `symbol` (`depth` optional, default 1, clamped to 1..5) | Symbols that call the given symbol (incoming call edges), with `hops` on each edge. |\n| `callees` | `symbol` (`depth` optional, default 1, clamped to 1..5) | Symbols called by the given symbol (outgoing call edges), with `hops` on each edge. |\n| `impact` | `symbol` (`depth` optional, default 1, clamped to 1..5) | Combined callers and callees of a symbol (the blast radius of a change), with `hops` on each edge. |\n| `context` | `task` (`limit` optional, default 12) | A context pack: matching entry points plus their caller/callee neighborhood and related files. |\n| `stats` | none | Counts of files, symbols, edges, imports, schema version, sync metadata, and per-language file counts. |\n| `doctor` | none | Freshness contract for the graph: schema status, last sync age, branch drift, pending file changes, ignored entries, and `FRESH`/`STALE`/`NEEDS-MIGRATION` verdict. |\n| `file_neighbors` | `path` | Files connected to an indexed file by incoming or outgoing call edges. |\n| `dead_code` | none (`limit` optional, default 100) | Callables with no incoming call edges. A candidate list, not proof: dynamic dispatch, exports, and entry points are invisible to call edges. |\n| `cycles` | none | File-level dependency cycles from cross-file call edges, grouped into strongly connected components. |\n| `affected` | `files` (`depth` optional, default 3, clamped to 1..5) | Tests statically attributed to the changed files via incoming call edges, plus impacted source files. A lower bound on what to run, not coverage. |\n| `repos` | none (`roots` optional) | Default database metadata plus optional one-level scans for `.graphtrail/graphtrail.db` under root directories. |\n| `diff` | `before`, `after` | Structural diff of two indexed graph DBs: added, removed, and changed symbols plus added and removed call edges. |\n\nEvery tool additionally accepts an optional `repo` or `db` selector for multi-repo use.\n`doctor`, `repos`, and `diff` do not accept `refresh`; `doctor` reports staleness and leaves refresh to the query tools that opt into it.\nCall-edge tools cap each direction at 500 real edges. When a traversal is capped, the JSON array includes a final row with `kind: \"truncated\"`.\n\nBuilds compiled with `--features codesearch` also expose the Code Search integration over MCP:\n\n| Tool | Required args | What it returns |\n|---|---|---|\n| `semantic_search` | `query` (`limit` optional, default 10, clamped to 1..50, `blend` optional, default true) | Code Search semantic hits. With `blend: true`, returns symbols ranked by embedding score plus graph centrality; with `blend: false`, returns raw per-file hits. |\n\nWith the same feature, `context` also accepts `blend_code_search: true` plus optional `embed_weight` and `graph_weight`, mirroring the CLI `--blend-code-search` flag. The default build remains network-free, and a `codesearch` build makes no Code Search request unless `semantic_search` is called or `context` is called with `blend_code_search: true`.\n\nA live self-index reports counts for the checked-out revision. Run this after `graphtrail sync .` instead of relying on counts copied from an older release:\n\n```bash\ngraphtrail --db .graphtrail/graphtrail.db stats --json\n```\n\nThe response includes `files`, `symbols`, `edges`, `imports`, `language_files`, `schema_version`, `synced_at`, and `tool_version`.\n\n## Optional integrations\n\nGraphTrail's Brigade adapter is built in: `graphtrail context \"\u003ctask\u003e\" --markdown` renders a context pack as a Brigade-friendly markdown document you can drop into a handoff's evidence section.\n\nTwo more adapters are gated behind optional cargo features, so the default binary stays free of network and cross-tool dependencies:\n\n```bash\n# Build one context brief from graph context, Code Search semantic hits, and MiseLedger evidence.\ncargo run --features codesearch,miseledger -- \\\n  --db \u003cdb\u003e context \"rate limiting\" --markdown --blend-code-search --evidence\n\n# Blend Code Search embedding hits with graph centrality.\n# Honors CODE_SEARCH_URL, CODE_SEARCH_API_KEY, and the shared code-index manifest.\ncargo run --features codesearch -- --db \u003cdb\u003e blend \"rate limiting\" --json\n\n# Expose Code Search over MCP too.\ncargo build --features codesearch --bin graphtrail-mcp\n\n# Surface MiseLedger evidence items (read-only FTS) mentioning a symbol or term.\n# Honors MISELEDGER_DB (defaults to ~/.local/share/miseledger/miseledger.db).\ncargo run --features miseledger -- links \"dispatch\" --json\n```\n\nWhen `codesearch` is enabled, GraphTrail also reads the shared Code Search index\nmanifest from `CODE_INDEX_MANIFEST`, `XDG_DATA_HOME/code-index/manifest.json`, or\n`~/.local/share/code-index/manifest.json`. `CODE_SEARCH_URL` still wins when it is\nset; otherwise the client falls back to the manifest's `semantic_api_url`, then to\n`http://localhost:5204`. If the manifest has an entry whose canonical `repo_root`\nmatches the GraphTrail repo, requests include that entry's `code_search_project`.\nReturned Code Search paths must start with `code_search_file_prefix`; GraphTrail\nstrips that prefix so blended hits match its repo-relative graph paths and drops\nnonmatching hits.\n\n## How the pieces fit\n\nGraphTrail is one station in a small set of focused tools:\n\n- **Code Search** keeps semantic chunks, summaries, and embeddings.\n- **GraphTrail** owns symbols, imports, call edges, and graph context.\n- **MiseLedger** owns session and evidence archives and JSON receipts.\n- **Brigade** owns operator workflow, handoffs, context packs, and guardrails.\n\nInternally the code is split into focused modules: `model` (shared types), `extractors` (per-language tree-sitter providers plus traversal), `store` (`db`, `schema`, `sync`), `query` (`search`, `graph`, `context`, `stats`), and a thin `cli`.\n\n## Why not just grep or an embedding index?\n\n- **grep / ripgrep** find text, not structure. They will show you every line where a name appears, but they do not know that one function calls another, so they cannot answer \"who calls this\" or \"what breaks if I change it.\" GraphTrail walks real tree-sitter call edges and answers those directly.\n- **An embedding / semantic index** (the kind Code Search keeps) is great for \"find code that looks relevant to this idea,\" but it ranks by similarity, not by reachability. It will not tell you the blast radius of an edit. GraphTrail is the structural layer; the two compose, which is exactly what the optional `blend` feature does.\n- **A language server (LSP)** gives precise per-language navigation inside an editor, but it is a stateful daemon tied to one project and one process, not a queryable database an agent can hit over MCP across many repos at once. GraphTrail persists a small graph to disk, opens queries read-only, runs no daemon, and is multi-repo from a single server.\n- **A full code-intelligence platform** (graph databases, ctags servers, hosted indexers) does far more and costs far more to run. GraphTrail is a sidecar on purpose: one SQLite file per repo, no network, no background process.\n\n## What GraphTrail is not\n\nGraphTrail is a sidecar, not a platform. It does not:\n\n- run a daemon, install hooks, or watch your filesystem\n- make network calls in the default build\n- own memory, receipts, publishing, or scheduling (those stay in Brigade and MiseLedger)\n- keep semantic chunks, summaries, or embeddings (Code Search owns those)\n- mutate your code, or write graph state unless a supported MCP query explicitly sets `refresh: true`\n\nIt indexes source into a graph and answers structural questions. That is the whole job.\n\n## Contributing\n\nIssues and pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for local dev setup and what lands easily, [SECURITY.md](SECURITY.md) for reporting vulnerabilities privately, and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). GraphTrail is MIT licensed; see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fescoffier-labs%2Fgraphtrail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fescoffier-labs%2Fgraphtrail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fescoffier-labs%2Fgraphtrail/lists"}