Skip to content

Cartographer Integration

Cartographer is a Rust library that CKB embeds via CGo FFI to provide architectural analysis, semantic retrieval, and git history intelligence. It runs in-process — no daemon, no IPC, no subprocess — making calls as fast as a function call into a shared object.


What You Get

Without Cartographer, CKB relies on SCIP index, tree-sitter, and git CLI for everything. Cartographer adds a layer of structural intelligence on top of those:

Architectural Analysis

Feature What it tells you
Dependency graph Every file and its import edges, with cycle detection and god-module identification
Architectural health A 0–100 score built from bridge count, cycle count, god-module count, layer violations, and coupling
Layer enforcement Validates your layers.toml rules and reports which files cross the boundaries
Cycle detection Circular dependencies with severity and pivot-node identification
God modules Overly-connected files (high degree + low cohesion) that become chokepoints

These feed the getArchitecture, getModuleOverview, and reviewPR (arch-health check) tools.

Impact Prediction

SimulateChange predicts — before you touch anything — what happens if a module's signature changes:

  • Which modules are affected
  • Whether the change would create a new cycle
  • Whether it would introduce a layer violation
  • Risk level and health delta

This is what powers analyzeImpact when Cartographer is available.

Skeleton Maps and Retrieval

SkeletonMap and RankedSkeleton give CKB a tree-sitter-powered view of your codebase compressed to a token budget:

  • Every file reduced to its signatures (no bodies)
  • PageRank ranking personalised around focus files
  • BM25 + PageRank combined retrieval pipeline (QueryContext)
  • Context bundle quality scoring (ContextHealth) — composite A–F grade

These make explainFile, getArchitecture, and the retrieval pipeline significantly more accurate because they're graph-aware, not just lexical.

Git History Intelligence

Beyond what git CLI provides:

Function What it detects
GitChurn Per-file commit counts over the last N commits
GitCochange File pairs that change together (temporal coupling)
HiddenCoupling File pairs with high co-change but no import edge — implicit coupling invisible in the static graph
ShotgunSurgery Files ranked by co-change dispersion: changing them historically required simultaneous changes across many unrelated files
Semidiff Function-level diff between two commits (not just line-level)
Evolution Architectural health snapshots across git history — how your health score has moved over the last N days

These feed getHotspots, the coupling check in reviewPR, the dead-code check (via unreferenced symbol discovery), and the co-change dispersion tool.

Dead Code Detection

UnreferencedSymbols finds public symbols that appear nowhere across the project — without needing a SCIP index. It's used as a Cartographer-tier fallback for reviewPR's dead-code check when SCIP isn't available.

Blast Radius

BlastRadius computes the graph-theoretic blast radius of a module or file: direct dependents, transitive dependents, and a maximum-related limit. Used by get_blast_radius and the blast-radius check in reviewPR.

Architecture Rendering (Cartographer 3.0.0, v9.2)

RenderGraph walks the same module graph that powers getArchitecture and emits diagram syntax — Mermaid for inline rendering in GitHub/GitLab/Notion, Graphviz DOT for dot -Tsvg pipelines. Powers the renderArchitecture MCP tool and ckb arch render CLI.


Which MCP Tools Use It

Tool Cartographer functions used
getArchitecture MapProject, Health, CheckLayers
renderArchitecture MapProject, RenderGraph
getModuleOverview MapProject, GetModuleContext
analyzeImpact SimulateChange
analyzeOutgoingImpact (LIP query_outgoing_impact — Cartographer not on this path)
getHotspots GitChurn, GitCochange
get_blast_radius BlastRadius
reviewPR (arch-health check) Health, MapProject
reviewPR (coupling check) HiddenCoupling
reviewPR (dead-code check) UnreferencedSymbols
reviewPR (layer check) CheckLayers
reviewPR (split check) Semidiff
explainFile SkeletonMap, RankedSkeleton
understand / explore QueryContext
watch_graph MapProject (periodic)
listKeyConcepts BM25Search, RankedSkeleton
Shotgun surgery detection ShotgunSurgery
Architectural evolution Evolution

When Cartographer is not compiled in, these tools degrade gracefully — they fall back to SCIP-only analysis, git CLI, or return reduced results. No errors.


Without Cartographer

CKB works fine without Cartographer for:

  • All SCIP-based symbol queries (search, refs, callgraph, impact via SCIP graph)
  • Ownership, decisions, ADRs
  • Secret detection
  • Documentation intelligence
  • Federation / multi-repo
  • LIP and LSP integration

Cartographer is additive. If you don't build with it, you lose the architectural intelligence layer and the git-history coupling analysis — everything else is unaffected.


Do You Already Have It?

On macOS and Linux, yes — the released binaries ship with Cartographer linked in. Since v9.3 the release pipeline builds darwin/arm64, darwin/amd64, linux/amd64 and linux/arm64 with CGo on native runners, linking a pinned, checksum-verified prebuilt library (currently v4.0.2). That covers both distribution channels:

npm install -g @tastehub/ckb        # fast tier included (macOS/Linux)
brew install simplyliz/ckb/ckb      # fast tier included (macOS/Linux)

Windows ships the pure-Go stub tier — there is no prebuilt Cartographer library for Windows upstream. Everything still works; the architectural intelligence layer degrades as described in Without Cartographer.

You only need the source build below if you're on Windows, developing CKB itself, or pinning a different Cartographer version.

Verify Which Tier You Have

ckb doctor

Since v9.3 doctor reports the tier explicitly:

✓ cartographer: Cartographer engine linked (v4.0.2) — fast structural tier active
⚠ cartographer: Cartographer engine not linked — fast structural tier unavailable
                (this build is CGO-free). Structural navigation falls back to SCIP/LSP.

Before v9.3 a binary could silently run without the fast tier with no way to confirm it.


Building with Cartographer

Building from source requires a Rust toolchain (stable channel). The library lives in third_party/cartographer/.

Prerequisites

  • Go 1.21+
  • Rust (rustup install stable)
  • A C compiler (Xcode Command Line Tools on macOS, build-essential on Debian/Ubuntu)

To skip Rust entirely, scripts/fetch-cartographer-lib.sh <goos> <goarch> downloads the same pinned, checksum-verified static library the release pipeline uses, then build with -tags cartographer.

Build

cd src

# Recommended: build with Cartographer (default make target)
make build

# This is equivalent to:
make build-cartographer        # compiles Rust → libcartographer.a
go build -tags cartographer -o bin/ckb ./cmd/ckb/...

Build Without Cartographer (no Rust required)

cd src
make build-fast
# or:
go build -o bin/ckb ./cmd/ckb/...

The stub (internal/cartographer/bridge_stub.go) is compiled instead: every function returns an "unavailable" error, and all callers in the query engine check cartographer.Available() before calling through.

Verify

ckb doctor is the direct check (see Verify Which Tier You Have). ckb status shows the same thing from the analysis side:

ckb status

Look for the Analysis Tier line:

Analysis Tier: Full (SCIP + Cartographer)   ← Cartographer compiled in
Analysis Tier: Standard (SCIP)              ← without Cartographer
Analysis Tier: Fast (tree-sitter)           ← no SCIP index either

Run Tests with Cartographer

cd src
make test-cartographer

How It's Embedded

Cartographer is statically linked into the CKB binary via CGo. There are no runtime dependencies — no shared library to install, no daemon to start.

CKB binary
  └── cartographer (static, -lcartographer)
        ├── libcartographer.a     (compiled from Rust sources in third_party/)
        └── cartographer.h        (C FFI header)

The FFI boundary uses JSON over C strings — each function returns a *C.char pointing at a JSON {"ok": true, "data": ...} envelope. Go decodes it and returns typed structs. The string is freed by cartographer_free_string() immediately after decoding.

The build tag cartographer selects between bridge.go (real CGo) and bridge_stub.go (no-ops). Both export the same Go API, so the rest of CKB is tag-agnostic.


Third-Party Directory Layout

src/
  third_party/
    cartographer/
      mapper-core/
        cartographer/
          src/         ← Rust sources (extractor, mapper, api, etc.)
          include/
            cartographer.h
          target/
            release/
              libcartographer.a   ← compiled output (git-ignored)
  internal/
    cartographer/
      bridge.go        ← CGo bindings (build tag: cartographer)
      bridge_stub.go   ← no-op stubs  (build tag: !cartographer)
      types.go         ← shared Go types

The Rust sources are a vendored snapshot of the CodeCartographer repository. scripts/sync-cartographer.sh is the only supported path for updating them — manual file-by-file copies drift silently (before v9.2 the vendored tree had fallen 391 lines behind on diagram.rs alone):

scripts/sync-cartographer.sh <path-to-upstream-cartographer-checkout>

It rsyncs an explicit path list and prints the next-step commands. The prebuilt static library used by release builds is fetched separately and pinned by scripts/fetch-cartographer-lib.sh (currently v4.0.2), which verifies a sha256 before staging.


Large-Repository Robustness (v9.3)

Cartographer 4.0.0 hardened the recursive graph passes after the engine aborted the whole CKB process — via the FFI — on a full Linux-kernel checkout (~64k C/H files). Two unbounded recursions overflowed the stack. The fixes:

  • Recursive tree-sitter walkers on deeply nested (often macro-generated) C now run on a 256 MB-stack pool.
  • Recursive tarjan_scc cycle detection was replaced with an iterative implementation.
  • The walkers carry a hard depth ceiling of 50,000 as a belt against adversarial or generated input. For reference, the Linux kernel's measured real peak is 3,348.

Because the bridge is CGo, a panic on the Rust side takes the host process with it — so this class of bug is fatal rather than degrading. Health("/tmp/linux") through the FFI now completes without crashing, covered by a regression test in internal/cartographer.