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.

By default the call graph is the union of two backends: the TypeScript compiler's resolver and Jelly — a flow-based analyzer that resolves higher-order and callback edges the resolver misses, embedded in the cants binary (no extra install). Merged edges keep a provenance tag (tsc / jelly), so you can still tell the two apart. Pass --tsc-only to drop Jelly and run the resolver alone, or --call-graph-provider jelly for Jelly alone.

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 union of the tsc resolver and the embedded Jelly flow analyzer by default (--tsc-only for the resolver alone, --call-graph-provider jelly for Jelly alone).
  • 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 (env:
                                 NEO4J_URI)
  --neo4j-user <user>            Neo4j username (default: "neo4j", env:
                                 NEO4J_USERNAME)
  --neo4j-password <password>    Neo4j password (prefer the env var; a flag is
                                 visible in shell history / process list)
                                 (default: "neo4j", env: NEO4J_PASSWORD)
  --neo4j-database <db>          Neo4j database name (env: NEO4J_DATABASE)
  -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: union (default, tsc ∪
                                 jelly) | tsc | jelly | both (deprecated alias
                                 of union) (default: "union")
  --tsc-only                     use the tsc resolver only — opt out of Jelly
                                 edges (overrides --call-graph-provider)
  -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. Resolver-only call graph (opt out of Jelly):

    cants --input ./my-ts-project --tsc-only
    
  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.

The connection options also read the standard Neo4j environment variables — NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD, NEO4J_DATABASE — when the corresponding flag is omitted (an explicit flag wins). Prefer the env var for the password so it doesn't land in shell history or the process list:

export NEO4J_URI=bolt://localhost:7687
export NEO4J_PASSWORD=secret
cants --input ./my-ts-project --emit neo4j     # credentials picked up from the environment

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.5.0-py3-none-win_amd64.whl (42.9 MB view details)

Uploaded Python 3Windows x86-64

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

Uploaded Python 3macOS 11.0+ ARM64

codeanalyzer_typescript-0.5.0-py3-none-macosx_10_12_x86_64.whl (31.1 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

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

File metadata

File hashes

Hashes for codeanalyzer_typescript-0.5.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 3eef8a984158e3d3fb23ce31bd786fbb6d77fc4974d87c70dba0b8e8d6a619f5
MD5 61657a760f32459021900320a6a16365
BLAKE2b-256 dd666763ad794a1403193785f3693c4c00d00588d39f2081f3302101aa6f62c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for codeanalyzer_typescript-0.5.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.5.0-py3-none-manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for codeanalyzer_typescript-0.5.0-py3-none-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6ebaca200dc8c33b7bc72f30b242a302e4ea49ba963461a5f39eda50531680a8
MD5 757361a3b254e071310cbe05e43e85f6
BLAKE2b-256 f69a4408359928fe36b49652632f041b60a87938273523aeda6c8e01c5e662b6

See more details on using hashes here.

Provenance

The following attestation bundles were made for codeanalyzer_typescript-0.5.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.5.0-py3-none-manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for codeanalyzer_typescript-0.5.0-py3-none-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 3200a5d5e393515cf2bd5de7609d37cdbd432db8e205ed3b8ce33a63c963f84d
MD5 1aa13c849e1c9bd5561f78b907cb71e2
BLAKE2b-256 4ada1321e503c3bda6ea56fbe11dce8184c5b7fd179660f023f7d2f7994e23bb

See more details on using hashes here.

Provenance

The following attestation bundles were made for codeanalyzer_typescript-0.5.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.5.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for codeanalyzer_typescript-0.5.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 aa3be868e13ed1dae2f47c5f18d499f97718ee153df1bb6f7f6d606d75ba7a1c
MD5 262963bcc14472323790edc53d0a52c0
BLAKE2b-256 834b9d19e116a3d4a92a49250b5dbf45437007b5d0e2738f9f68a8dd4e81f75e

See more details on using hashes here.

Provenance

The following attestation bundles were made for codeanalyzer_typescript-0.5.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.5.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for codeanalyzer_typescript-0.5.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 c8a5225eaac0f010f1a6935fe3314362e3b9534f48569c27ae160969943d7e47
MD5 2400a7989638be91baca07fff57781b9
BLAKE2b-256 a7f01b894e05144532bf8e025478071dcf2a6aa104b57439c38637918014f6e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for codeanalyzer_typescript-0.5.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