Call tracing
Transitive callers, callees, and shortest paths — with call-site lines and resolution confidence on every edge.
Code-Crawler turns a project into a queryable property graph of modules, types, methods, annotations, calls, virtual dispatch, and the wiring frameworks add — routes, injected dependencies, and reflective lookups — then exposes it to Claude, Cursor, Copilot, and any MCP client through 22 tools with typed arguments.
// routes found across two languages, one index
GET /orders/:id OrderController#read nestjs · controller.ts:7
GET /orders/{id} read_order fastapi · api.py:13
// trace_execution · OrderService#place
OrderService#place
CALLS OrderRepository#create repository.py:19
CALLS OrderService#audit service.py:20
INJECTS OrderRepository fastapi · Depends()
2 languages · 2 routes · 1 injection graph · 1 SQLite file
“Who transitively calls this method?” “What breaks if I change this interface?” “What does the framework invoke that no source line calls?” Those are traversals, not searches. Code-Crawler builds the graph once and answers them with bounded recursive SQL.
Transitive callers, callees, and shortest paths — with call-site lines and resolution confidence on every edge.
Interface and base-class calls fan out to every real override in the project, so traces follow runtime targets, not just source text.
Routes, injected dependencies, and reflective lookups become first-class
edges — including AspectJ and Spring AOP pointcuts woven into traces as
INTERCEPT hops.
Annotations are first-class nodes. Query @Transactional,
@Cacheable, @Async, or your own custom decorator
across types, methods, and fields.
Rank hotspots by fan-in, fan-out, and advice count. Surface dead-code candidates that no call, dispatch, or advice edge reaches, with entry points, tests, and constructors excluded.
Persistent, idempotent, file-scoped indexing. No server, no docker, no
external database — just index.db.
A crawl walks the project, parses each file, resolves call targets against a global type index, writes nodes and edges in a single transaction, then rebuilds the derived dynamic edges.
Tree-sitter WASM grammars for Java, Python, TypeScript and JavaScript extract modules, types, methods, constructors, fields, imports, modifiers, annotations and decorators.
A global TypeIndex plus scope heuristics infer receiver types
from locals, parameters, fields, new T(), this,
and super.
Nodes and edges land in SQLite (WAL). Ids are stable FQNs; reparsing a file replaces only that file's slice.
Every overridable call target gains DYNAMIC_DISPATCH edges to
each override found in the hierarchy index.
Aspect advice is matched against all methods with an AspectJ pointcut
matcher, producing ADVISES edges.
Recursive CTEs power callers, callees, paths, execution traces, subgraphs, hotspots, and dead-code detection.
Install, point it at a project, and register the server with your MCP client. The database is created automatically on first crawl.
Requires Node.js 20 or newer.
npm install
npm run build
Re-run any time; the crawl is idempotent and refreshes changed files.
node dist/index.js crawl /absolute/path/to/your-project
node dist/index.js status
Add it to your MCP client configuration and restart the client.
{
"mcpServers": {
"code-crawler": {
"command": "node",
"args": ["/absolute/path/to/code-crawler/dist/index.js"]
}
}
}
The assistant can now call any of the 22 tools.
Trace every runtime path from Checkout#checkout.
Who transitively calls OrderRepository#create?
List the aspects that intercept Payment#pay.
Every tool returns structured JSON. Unknown symbols return fuzzy suggestions instead of a bare error.
| Group | Tools | Answers |
|---|---|---|
| Index |
crawl_project index_status clear_index
get_schema
|
What is indexed, and what is the graph model? |
| Search | search_symbols get_node |
Where is this symbol and what is its id? |
| Static tracing |
get_callers get_callees
trace_path get_subgraph
|
What calls what, and how is it connected? |
| Dynamic tracing |
trace_execution find_implementations
find_aspects get_decorators
find_annotated
|
What actually executes, and what intercepts it? |
| Run-time wiring |
find_entry_points find_routes
find_injections find_reflections
find_external_dependencies
|
What does a framework invoke, inject, or reflect on? |
| Analytics | find_hotspots find_dead_code |
Where is the risk and the unused code? |
Build the graph once, then let your assistant trace callers, runtime dispatch, routes, injections, and reflective lookups with exact file and line references.
Read the quickstart →