Liking cljdoc? Tell your friends :D

callgraph

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.

Install

Clojars Project

Quick Start

(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

API

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))

Development

Run tests:

lein test

Notes

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.

License

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

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close