Skip to main content

Prebuilt codeanalyzer-typescript backend binary for CLDK (codellm-devkit).

Project description

CodeLLM-DevKit

codeanalyzer-typescript (cants)

A TypeScript/JavaScript static-analysis toolkit — the CLDK backend that emits a canonical symbol table and call graph, as analysis.json or a Neo4j property graph.

PyPI Python Release License


cants is a static analyzer for TypeScript/JavaScript built on the TypeScript compiler (via ts-morph). It produces the canonical CodeLLM-DevKit (CLDK) analysis.json — a symbol table plus a resolver-based call graph — and can project that same analysis into a Neo4j property graph. It is the TypeScript backend behind CLDK, mirroring its Python and Java siblings.

The call graph defaults to the TypeScript compiler's resolver, but the cants binary also embeds Jelly — a flow-based analyzer that resolves higher-order and callback edges the resolver misses — as an experimental backend (--call-graph-provider jelly, or both to diff them). No extra install is needed; Jelly ships inside the binary.

Table of Contents

Features

  • Symbol table — modules, classes, interfaces, enums, type aliases, namespaces, functions, methods, variables, decorators, and JSDoc, with precise source spans.
  • Call graph — the TypeScript compiler's resolver plus Rapid Type Analysis (RTA), with phantom (external) nodes for calls into imported libraries and Node builtins.
  • Pluggable call-graph backend — the tsc resolver by default, the embedded Jelly flow analyzer, or both to compare edge sets.
  • Neo4j output — project the analysis into a labeled property graph: a self-contained graph.cypher snapshot, or an incremental push to a live database over Bolt.
  • Versioned schema — a machine-readable, version-stamped Neo4j schema contract (--emit schema), bundled in every release and enforced by a conformance test.
  • Self-contained binary — no Bun or Node required at runtime; install via pip, Homebrew, or a one-line shell script.
  • Incremental — content-hash caching so re-analyzing (and re-loading the graph) only touches what changed.

Installation

Prerequisites

Running a prebuilt cants binary requires nothing — it is fully self-contained. To analyze a project, that project should be a normal Node/TypeScript project (so the compiler can resolve types and imports). Building cants from source requires Bun 1.0+.

Install via shell script

Download and install the prebuilt binary for your platform from the latest release:

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/codellm-devkit/codeanalyzer-typescript/releases/latest/download/cants-installer.sh | sh

The installer drops cants into ~/.local/bin (override with CANTS_INSTALL_DIR) and can pin a version with CANTS_VERSION=vX.Y.Z. Supports macOS (arm64/x86_64) and Linux (x86_64/aarch64).

Install via Homebrew

brew install codellm-devkit/homebrew-tap/codeanalyzer-typescript

Install via pip (PyPI)

The wheel bundles the prebuilt, self-contained binary for your platform (no Bun or Node required):

pip install codeanalyzer-typescript
cants --help

This is also the package CLDK's Python SDK depends on to locate the analyzer backend; it exposes codeanalyzer_typescript.bin_path() and schema_path().

Build from source

# Install Bun, then:
git clone https://github.com/codellm-devkit/codeanalyzer-typescript
cd codeanalyzer-typescript
bun install
bun run build      # → dist/cants (standalone native binary)

You can also run the analyzer directly from source without compiling:

bun run start -- --input /path/to/typescript/project

Usage

cants --input /path/to/typescript/project

With no --output, the analysis is printed to stdout as compact JSON; with --output <dir> it is written to analysis.json (or graph.cypher for --emit neo4j) in that directory.

Options

Usage: cants [options]

CLDK TypeScript analyzer — emits the canonical analysis.json (symbol table +
resolver call graph), or a Neo4j graph.

Options:
  -i, --input <path>             project root to analyze (not required for
                                 --emit schema)
  -o, --output <dir>             output directory (omit ⇒ compact output to
                                 stdout)
  --emit <target>                output target: json (analysis.json, default) |
                                 neo4j (graph.cypher or live push) | schema (the
                                 Neo4j schema.json contract) (default: "json")
  --app-name <name>              logical application name for the graph
                                 :Application anchor (default: input dir name)
  --neo4j-uri <uri>              push the graph to a live Neo4j over Bolt
                                 (incremental); omit to write graph.cypher
  --neo4j-user <user>            Neo4j username (default: "neo4j")
  --neo4j-password <password>    Neo4j password (default: "neo4j")
  --neo4j-database <db>          Neo4j database name (default: server default)
  -a, --analysis-level <n>       analysis depth: 1 = symbol table + tsc resolver
                                 call graph + RTA (default); 2 = call graph
                                 (default: "1")
  -t, --target-files <paths...>  restrict analysis to specific files
                                 (incremental)
  --skip-tests                   skip test trees (default)
  --include-tests                include test trees
  --eager                        force a clean rebuild instead of reusing the
                                 cache
  --lazy                         reuse the cache (default)
  --no-build                     skip dependency materialization (use a prepared
                                 node_modules)
  --no-phantoms                  disable phantom (external) nodes for
                                 imported/required library calls
  --call-graph-provider <name>   call-graph backend: tsc (default) | jelly |
                                 both (default: "tsc")
  -c, --cache-dir <dir>          cache/intermediate directory
  -v, --verbose                  increase verbosity (repeatable)
  -h, --help                     display help for command

Examples

  1. Basic analysis to stdout, or to a file:

    cants --input ./my-ts-project                         # compact JSON on stdout
    cants --input ./my-ts-project --output ./out          # → ./out/analysis.json
    
  2. Emit a Neo4j snapshot, or push to a live database:

    cants --input ./my-ts-project --emit neo4j --output ./out     # → ./out/graph.cypher
    cants --input ./my-ts-project --emit neo4j \
      --neo4j-uri bolt://localhost:7687 --neo4j-user neo4j --neo4j-password secret
    
  3. Incremental analysis of specific files:

    cants --input ./my-ts-project --target-files src/a.ts src/b.ts
    
  4. Compare call-graph backends:

    cants --input ./my-ts-project --call-graph-provider both
    
  5. Force a clean rebuild with a custom cache directory:

    cants --input ./my-ts-project --eager --cache-dir /path/to/custom-cache
    

Output targets

cants builds one analysis in memory and can emit it three ways (--emit):

analysis.json (default)

A TSApplication document — the canonical CLDK contract the Python SDK parses:

{
  "symbol_table":     { /* file path → module (classes, interfaces, enums,
                           type aliases, functions, namespaces, variables, …) */ },
  "call_graph":       [ /* CALL_DEP edges: { source, target, type, weight,
                           provenance, tags } keyed by callable signature */ ],
  "external_symbols": { /* phantom stubs for call targets outside the project */ }
}

Caller- and callee-side identifiers come from a single signature canonicalizer, so call-graph source/target values byte-match the corresponding symbol_table / external_symbols keys.

Neo4j graph

--emit neo4j projects the same analysis into a labeled property graph (declarations keyed by their signature under a shared :Symbol label; calls, imports, inheritance, decorators, and call sites as relationships):

  • Without --neo4j-uri — writes a self-contained graph.cypher (constraints + indexes, a scoped wipe, then batched MERGEs). Load it with cypher-shell < graph.cypher.
  • With --neo4j-uri — pushes to a live Neo4j over Bolt incrementally: only modules whose content hash changed are rewritten, and on a full run modules whose source file vanished are pruned. Every graph carries a schema_version on its :Application node.

Schema contract

--emit schema writes the machine-readable, version-stamped Neo4j schema (schema.json: node labels, relationships, properties, constraints, and indexes). It needs no project and is bundled in every release (as a wheel asset and a GitHub Release asset), so a consumer can validate producer/consumer compatibility without invoking the binary.

cants --emit schema                 # print to stdout
cants --emit schema --output ./out  # → ./out/schema.json

Development

This project uses Bun as its toolchain.

bun install
bun run start -- --input /path/to/project   # run from source
bun run typecheck                            # type-check
bun test                                     # tests (the Neo4j bolt test is opt-in; see below)
bun run test:container                       # Neo4j bolt tests — needs Docker/Podman (opt-in)
bun run gen:schema                           # regenerate schema.neo4j.json
bun run gen:readme                           # regenerate the cants --help block above

License

Apache 2.0 — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

codeanalyzer_typescript-0.4.0-py3-none-win_amd64.whl (42.9 MB view details)

Uploaded Python 3Windows x86-64

codeanalyzer_typescript-0.4.0-py3-none-macosx_11_0_arm64.whl (28.7 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

codeanalyzer_typescript-0.4.0-py3-none-macosx_10_12_x86_64.whl (31.0 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file codeanalyzer_typescript-0.4.0-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for codeanalyzer_typescript-0.4.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 95d4d228c17b5bd44f83a4dd15e7e33cbf362d980b17fe9d740e1cd2ab68a9c3
MD5 85cc6b12ab98ea667577dd556b173f9b
BLAKE2b-256 ab17c619bbfb9db1b1b8612a4bb5a2d21dfbe863ddf7ec1f7ba9e1c6f06e4e13

See more details on using hashes here.

Provenance

The following attestation bundles were made for codeanalyzer_typescript-0.4.0-py3-none-win_amd64.whl:

Publisher: release.yml on codellm-devkit/codeanalyzer-typescript

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codeanalyzer_typescript-0.4.0-py3-none-manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for codeanalyzer_typescript-0.4.0-py3-none-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 25b6596e18483e807e157494ceb692b8a348610304f1e6658024fe99c56338ff
MD5 9985946e03e00256ec4b37825d5cda03
BLAKE2b-256 00bb68292380194671e674d3b6dbc15659f0bb90d2bb6270fdd159e93a661a4a

See more details on using hashes here.

Provenance

The following attestation bundles were made for codeanalyzer_typescript-0.4.0-py3-none-manylinux2014_x86_64.whl:

Publisher: release.yml on codellm-devkit/codeanalyzer-typescript

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codeanalyzer_typescript-0.4.0-py3-none-manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for codeanalyzer_typescript-0.4.0-py3-none-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 1ee5c678c7d19b91665e03af3008d091a7fd89112fa72c12937d8508c95fba17
MD5 0bd1142cfa2a3180723fa1af59e527f5
BLAKE2b-256 4ef710ccfb06a19e608b0745e6195a71f3728c0abbec8718eed5f8411544ed8e

See more details on using hashes here.

Provenance

The following attestation bundles were made for codeanalyzer_typescript-0.4.0-py3-none-manylinux2014_aarch64.whl:

Publisher: release.yml on codellm-devkit/codeanalyzer-typescript

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codeanalyzer_typescript-0.4.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for codeanalyzer_typescript-0.4.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a5e23461301f3206ebe5f71a04ab5e3f7e1e38a447660e6de1cd667ec65e69c7
MD5 56717078c3ea54d1d79b6af479dedb6c
BLAKE2b-256 5f8ec02efa6d5bbdc2ce3bf21f2e312c6152dd60c2b53924e9160c3ae87ec23d

See more details on using hashes here.

Provenance

The following attestation bundles were made for codeanalyzer_typescript-0.4.0-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on codellm-devkit/codeanalyzer-typescript

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file codeanalyzer_typescript-0.4.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for codeanalyzer_typescript-0.4.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 01bd9ff546302b105656a6b38c4039bab1a61f9c3c98f087d53990d3fc750a50
MD5 1e41534e607af96456ffd58d979ba4ec
BLAKE2b-256 b081da7f318dc2465fe0a37c072746cabc6f44ae6f4a541898390055285e6db1

See more details on using hashes here.

Provenance

The following attestation bundles were made for codeanalyzer_typescript-0.4.0-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yml on codellm-devkit/codeanalyzer-typescript

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page