CallTree
Overview
Multi-language static analysis CLI that extracts caller-callee relationships from a single file or an entire project and renders them as an ASCII call tree, with optional Mermaid and Graphviz DOT exports.
CallTree is a single-file Bash utility built as a "Google Maps for software engineers" - a way to quickly orient oneself in an unfamiliar codebase by visualising which functions exist, where they are defined, who calls whom, and where to look first when trying to find an entry point or trace an execution path.
The tool follows a three-stage pipeline: universal-ctags emits one JSON record per function definition; an embedded Perl backend filters tags by a per-language kind allow-list, builds a global symbol registry, and scans each function body for known callees; a Bash front-end loads the resulting tables into associative arrays and renders the call graph. The whole pipeline runs as a single shell command with no compilation step.
Function identification covers roughly thirty languages out of the box - C, C++, C#, Python, Rust, Go, Java, JavaScript, TypeScript, Ruby, Lua, PHP, Perl, Kotlin, Scala, Swift, Haskell, OCaml, F# - with a permissive fallback for anything else ctags can parse. Return types are extracted from the ctags typeref field, parsed from trailing-return-type signatures (Rust style), or defaulted per language.
Call-edge detection works by lexical scanning of function bodies after comment and string-literal stripping. When multiple files are analysed together, calls are resolved to same-file definitions first, then to the first defining file in input order - a deterministic policy that approximates compiler lookup for non-overloaded names.
Output is configurable: the default is an ASCII tree printed in the terminal alongside a summary table of call frequencies, callees, return types, and source line ranges. The same graph can also be written out as a raw .txt tree, a Mermaid .mmd diagram for inline rendering in Markdown documentation, or a Graphviz .dot file for SVG/PNG export.
The tool is designed as a lexical analyser and explicitly trades semantic precision for portability and speed: overloaded names collapse to the first definition, method calls and macro-defined pseudo-functions are not detected, and template specialisations map to their base name. Within those bounds, it produces an immediate, navigable map of any project ctags can read.