Fast CLI for tracing symbol relationships in a codebase.
Helps developers quickly understand where a symbol is defined, who calls it, what it calls, how local call flow branches, and what may be affected if it changes.
Calltrace is a fast CLI tool for tracing symbol relationships in a codebase.
It helps developers quickly answer:
- where a symbol is defined
- who calls it
- what it calls
- how local call flow branches
- what depends on it if it changes
Calltrace works directly on a repository with zero configuration and gives fast, practical answers for everyday code exploration.
It is especially useful for:
- exploring an unfamiliar codebase
- debugging code paths
- checking what may be affected before changing a function
- automation tools or AI agents that need quick symbol relationship lookup
- editor, CLI, or internal workflows that benefit from JSON output
Install from GitHub Releases on macOS or Linux:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/sajidurdev/calltrace/releases/latest/download/calltrace-installer.sh | shInstall from GitHub Releases on Windows PowerShell:
powershell -ExecutionPolicy Bypass -c "irm https://github.com/sajidurdev/calltrace/releases/latest/download/calltrace-installer.ps1 | iex"Run a normal trace:
calltrace loginUserRun reverse impact:
calltrace --impact createSessionRun on another repo:
calltrace --root ./services/auth loginUser
calltrace --root ./services/auth --impact createSessionUse calltrace when you want to quickly understand code without manually jumping across many files.
calltrace loginUserThis shows:
- where it is defined
- who calls it
- what it calls
calltrace --impact createSessionThis helps you see:
- direct callers
- transitive callers
- affected files
calltrace --tree loginUserThis prints a bounded call tree for quick flow inspection.
calltrace --json loginUser
calltrace --impact --json createSessionJSON output makes it easier to use Calltrace inside:
- automation scripts
- editor integrations
- internal developer tools
- AI agent workflows that need fast repository lookup
calltrace scans a repository, builds a lightweight symbol index, and answers practical code-tracing questions without configuration.
Current capabilities:
- find symbol definitions
- find symbol callers and usages
- find local calls made by a symbol
- print a bounded local call tree
- trace reverse impact through callers
- emit machine-readable JSON
- respect
.gitignore - skip common heavy or generated directories
Initial language support is heuristic and pattern-based for:
- JavaScript
- TypeScript
- Python
- Rust
- Go
Current parser coverage:
- JS / TS: named functions, variable-assigned arrow/functions, object-property arrow/functions, member-assigned arrow/functions, and concise methods
- Python:
def,async def, nested functions, decorators, and class methods/static methods as method definitions - Rust: free functions and
implmethods, with method/function classification - Go: free functions and receiver methods
Install the latest prebuilt binary with the generated installer scripts.
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/sajidurdev/calltrace/releases/latest/download/calltrace-installer.sh | shpowershell -ExecutionPolicy Bypass -c "irm https://github.com/sajidurdev/calltrace/releases/latest/download/calltrace-installer.ps1 | iex"You can also download archives directly from the GitHub Releases page:
calltrace-x86_64-unknown-linux-gnu.tar.gzcalltrace-x86_64-apple-darwin.tar.gzcalltrace-aarch64-apple-darwin.tar.gzcalltrace-x86_64-pc-windows-msvc.zip
Checksums and installer scripts are attached to each release as well.
Build from source:
cargo install --path .Development run without installing:
cargo run -- loginUserBasic lookup:
calltrace loginUserShow only callers:
calltrace --callers createSessionShow only local calls:
calltrace --calls loginUserPrint a local call tree:
calltrace --tree loginUserShow reverse impact:
calltrace --impact createSessionPrint JSON:
calltrace --json loginUser
calltrace --impact --json createSessionScan a different root and increase traversal depth:
calltrace --root ./services/auth --max-depth 5 --tree loginUser
calltrace --root ./services/auth --max-depth 4 --impact createSessionShort aliases:
-cfor--callers-Cfor--calls-tfor--tree
Default trace:
Symbol: loginUser
Defined in:
src/auth/login.ts:42
Called by:
src/api/authController.ts:18
src/services/sessionService.ts:33
Calls:
auditLogger
createSession
validatePassword
Tree view:
loginUser
|- validatePassword
|- createSession
| `- insertSession
`- auditLogger
Impact view:
Impact analysis for: createSession
Direct callers:
loginUser
src/auth/login.ts:42
refreshSession
src/auth/refresh.ts:18
Transitive callers:
authController
src/api/authController.ts:10
mobileLoginRoute
src/mobile/loginRoute.ts:7
Affected files:
src/api/authController.ts
src/auth/login.ts
src/auth/refresh.ts
src/mobile/loginRoute.ts
JSON:
{
"symbol": "loginUser",
"definitions": [
{
"symbol": "loginUser",
"location": {
"path": "src/auth/login.ts",
"line": 42,
"column": 16
},
"language": "type_script",
"kind": "function"
}
],
"callers": [
{
"symbol": "handleLogin",
"location": {
"path": "src/api/authController.ts",
"line": 18,
"column": 10
},
"context": null
}
],
"calls": [
"auditLogger",
"createSession",
"validatePassword"
],
"tree": null
}Calltrace is designed for speed and practical usefulness.
It works best on explicit function and method definitions.
Duplicate same-named definitions are handled heuristically.
calltrace uses a practical layered approach:
- scan supported source files while respecting ignore rules
- detect candidate definitions with compiled regex patterns
- extract an approximate function body using brace matching or Python indentation
- detect call expressions inside that body
- reverse-link calls into caller data and build simple forward and reverse traversal views
This keeps the tool fast and useful on large repositories.
Observed on local Windows release builds with:
target/release/calltrace.exe- a missing-symbol query to force a full scan/index pass
- one cold-ish run and a 3-run warm average
- observed working-set sampling while the process ran
Local benchmark data:
| Repo | Supported files | Approx. LOC | Cold run | Warm avg | Observed peak memory |
|---|---|---|---|---|---|
Repo #1 |
1,784 | 932,676 | 34.0 ms | 25.1 ms | 9.1 MB |
Repo #2 |
4,461 | 2,097,106 | 22.8 ms | 24.2 ms | 5.2 MB |
Repo #3 |
5,413 | 2,772,666 | 22.5 ms | 22.0 ms | 10.2 MB |
These numbers are environment-specific and benefit from OS file cache behavior, so treat them as rough field data.
Known limits in the current release:
- dynamic dispatch and runtime-generated calls are not resolved
- imports, aliases, package boundaries, and passed-around function identities are not fully interpreted
- duplicate-definition routing is heuristic
- overloaded names and shadowed locals can still produce ambiguity
- nested definitions and complex metaprogramming can introduce false positives or misses
- block extraction is approximate for unusual formatting or syntax edge cases
Run formatting and tests:
cargo fmt
cargo testBuild release artifacts locally with cargo-dist:
dist build --artifacts=local
dist build --artifacts=globalCreate a tagged GitHub release:
git tag vX.X.X
git push --tags