Skip to main content

callscape

Point it at a codebase, get a browsable static HTML call-graph map — functions, callers, class/struct definitions, all cross-linked. One output file, no server, no dependencies at view time. Built on tree-sitter, so each new language is one self-contained PR.

callscape browsing its own source

pip install callscape          # or: pip install -e ".[dev]" from a checkout
callscape path/to/repo -o map.html
open map.html
callscape: 12 files · 55 definitions · 174 call edges (163 unresolved)
wrote map.html — open it in a browser

What you get

  • Overview — stats, per-language file counts, most-connected symbols.
  • Symbol pages — signature, source, callers, callees; every name is a link.
  • Call-flow graph — callers → symbol → callees as a clickable SVG.
  • Search — press /, filter by symbol or file path.
  • Single file — the whole map is one self-contained .html. Email it, attach it to a PR, drop it on any static host.

Languages today: Python, JavaScript, Go.

How it works

  1. Walk the repo, parse each supported file with its tree-sitter grammar.
  2. Each language adapter extracts definitions (functions, methods, classes, structs, interfaces) and call sites from the syntax tree.
  3. Calls are attributed to their smallest enclosing definition, then resolved by name across the whole repo.
  4. The index is embedded as JSON into a self-contained HTML viewer (vanilla JS, no CDN, no telemetry).

Honest limitations

Resolution is name-based, not type-based. obj.render() links to every definition named render — dynamic dispatch is approximated, not solved. Names matching more than 12 definitions are treated as too generic and listed as unresolved instead of spraying edges. This is a map for orienting yourself in an unfamiliar codebase, not a precision static analyzer.

Adding a language (the fun part)

One adapter = one PR. An adapter is a single module in callscape/languages/ (~100 lines) exposing four things:

NAME = "ruby"
EXTENSIONS = {".rb"}

def language() -> tree_sitter.Language:
    return Language(tree_sitter_ruby.language())

def extract(root_node, source_bytes) -> tuple[list[RawDef], list[RawCall]]:
    # walk the tree; return definitions (name, kind, byte span, line span,
    # signature, parent) and call sites (bare callee name, byte, line)
    ...

Then:

  1. Add the grammar package (tree-sitter-ruby) to pyproject.toml dependencies.
  2. List the module in _ADAPTER_MODULES in callscape/languages/__init__.py.
  3. Add a test_ruby_defs_and_calls case in tests/test_languages.py (see the existing Python/JS/Go cases — ~30 lines each).

Enclosure attribution, cross-file resolution, and the viewer are all language-agnostic — the adapter never touches them. Use callscape/languages/go.py as the template; it is the smallest.

CLI

callscape PATH [-o OUT.html] [--title TITLE] [--exclude GLOB]...

--exclude globs are relative to the root and repeatable. node_modules, virtualenvs, vendor, build output, and hidden directories are skipped automatically; files over 1.5 MB are ignored.

Development

python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/pytest
.venv/bin/callscape . -o demo/self.html --title "callscape (self)"   # dogfood

MIT license.

Metadata

Release files for callscape 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for callscape 0.3.0
File Size Uploaded Provenance Actions
callscape-0.3.0.tar.gz 20.8 kB With provenance Details for callscape-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for callscape 0.3.0
File Interpreter ABI Platform Actions
callscape-0.3.0-py3-none-any.whl Python 3 none any Details for callscape-0.3.0-py3-none-any.whl

Total release size: 42.6 kB

Release files / callscape-0.3.0.tar.gz

Download URL callscape-0.3.0.tar.gz
Size 20.8 kB
Tags Source
SHA-256 checksum
How to use checksums
f21e93fc31185941c742d6c14705dc083429503156540ed72507631efab3a01a
BLAKE2b-256 checksum
How to use checksums
7bfa59dde6f6ad1ab401a54c02c24a0f698270d11c62e6ddf14319c346a044dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.

Transparency log

Release files / callscape-0.3.0-py3-none-any.whl

Download URL callscape-0.3.0-py3-none-any.whl
Size 21.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f4800e213e80559686a3625b10cea1e5fe2fc335be677354335d3bed8cbcc3ba
BLAKE2b-256 checksum
How to use checksums
a427a9a396b8865ff5bb66f99a3e7a558ef6c810e2870fe1d41079bf6b01179a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.

Transparency log

Security for callscape 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for callscape-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page