callgraph is a small Clojure debugging and teaching library for visualising
function and macro calls directly in the terminal.
Each traced node is labelled like normal Clojure code:
(fn-name arg1 arg2 ...)
The trace itself is plain EDN. You can render it as a call tree, or as a leaf-to-root return flow that shows how recursive results recombine.
(ns demo
(:require
[callgraph.core :as cg]))
(cg/deftraced fib
"Returns the nth Fibonacci number."
[n]
(if (< n 2)
n
(+ (fib (- n 1))
(fib (- n 2)))))
(def captured
(cg/with-trace
(fib 4)))
(:result captured)
;; => 3
(cg/print-trace (:trace captured) {:show-meta? false})
;; └── (fib 4)
;; ├── (fib 3)
;; │ ├── (fib 2)
;; │ │ ├── (fib 1)
;; │ │ └── (fib 0)
;; │ └── (fib 1)
;; └── (fib 2)
;; ├── (fib 1)
;; └── (fib 0)
(cg/print-return-trace (:trace captured))
;; (fib 1) => 1
;; (fib 0) => 0
;; (fib 2) ⇐ [1 0] => 1
;; (fib 1) => 1
;; (fib 3) ⇐ [1 1] => 2
;; (fib 1) => 1
;; (fib 0) => 0
;; (fib 2) ⇐ [1 0] => 1
;; (fib 4) ⇐ [2 1] => 3
with-trace enables tracing for a block and returns:
{:result <body-result>
:trace <plain-edn-trace>}
If the body throws, the original exception is wrapped in ExceptionInfo and the
partial trace is available at:
(-> error ex-data :callgraph/trace)
trace-call traces one function call without redefining the function:
(cg/with-trace
(cg/trace-call map inc [1 2 3]))
deftraced defines a traced fixed-arity function. It supports docstrings,
metadata, pre/post maps, and multiple fixed arities.
deftracedmacro defines a macro whose expanded runtime body appears in the
trace as a :macro node. Macro arguments are displayed as source forms because
macros receive syntax rather than evaluated values.
trace->text renders a trace as a terminal tree string. Unicode tree
connectors are used by default. Pass {:style :ascii} for older terminals.
(cg/trace->text (:trace captured) {:show-meta? false})
print-trace prints the terminal tree directly to the console:
(cg/print-trace (:trace captured))
trace->return-text renders the same trace in leaf-to-root return order:
(cg/trace->return-text (:trace captured))
print-return-trace prints that return-flow view directly:
(cg/print-return-trace (:trace captured))
Run tests:
lein test
Tracing is opt-in and local to with-trace, so normal program execution is not
instrumented globally. This keeps the library predictable for debugging,
classroom demos, recursion visualisation, and dynamic-programming walkthroughs.
Copyright © 2026 Punit Naik
This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at https://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |