What is codeanalyzer-typescript?
codeanalyzer-typescript is a static-analysis tool for TypeScript and JavaScript source code. You point it at a project directory and it produces one typed artifact — a TSApplication — that captures the project’s symbol table (modules, classes, interfaces, enums, type aliases, callables), its call graph (who-calls-whom), and the external symbols it reaches (phantom stubs for imported-library targets). You stop grepping source by hand and start querying a structured model of the program.
It is the TypeScript backend behind CLDK, the multilingual analysis SDK — the same role codeanalyzer-python and codeanalyzer play for Python and Java. You can use it through CLDK’s typed facade, or directly as a CLI that writes analysis.json.
The mental model
Section titled “The mental model”Every run follows the same shape: point at a project, build the artifact, consume the typed model.
-
Point at a project.
codeanalyzer-typescript --input ./my-project. The tool discovers every.ts/.tsx/.jsfile (test trees excluded by default) and, by default, materializes the project’snode_modulesso the compiler can resolve imported types and call targets. -
It builds a
TSApplication. The TypeScript compiler — driven through ts-morph — extracts the symbol table; the same checker resolves each call site into the call graph, with Rapid Type Analysis expanding virtual dispatch and phantom nodes capturing external calls. -
Consume the typed model. Get
analysis.json(or msgpack) on disk, or pipe the JSON straight tojq. Everything is one typed document:symbol_table,call_graph,external_symbols,entrypoints.
flowchart LR
A["codeanalyzer-typescript
--input"] --> B["materialize
node_modules"]
B --> C[Symbol table<br/>ts-morph checker]
C --> D[Call graph<br/>resolver + RTA]
D --> E[External symbols<br/>phantom nodes]
D -.->|-a 2| F[CodeQL edges]
E --> G["TSApplication
analysis.json / msgpack"]
F -.-> G
What you get back
Section titled “What you get back”The artifact is a single TSApplication with four top-level pieces:
| Field | Type | What it holds |
|---|---|---|
symbol_table | Record<string, TSModule> | One TSModule per source file — its imports, exports, classes, interfaces, enums, type aliases, functions, namespaces, and variables. |
call_graph | TSCallEdge[] | Identity-keyed source -> target edges (by TSCallable.signature) with a weight, provenance, and tags. |
external_symbols | Record<string, TSExternalSymbol> | Phantom stubs for call targets outside the project — imported libraries and Node builtins. |
entrypoints | Record<string, TSEntrypoint[]> | Framework-dispatched roots, keyed by framework name. Empty at level 1. |
How identity works
Section titled “How identity works”A single canonicalizer, signatureOf, computes both caller- and callee-side identifiers, so a call graph source/target value byte-matches the corresponding symbol_table (or external_symbols) key. A signature is the project-relative file path (without extension) dot-joined with the member path — e.g. src/user.UserService.getUser. Constructors normalize to <ClassSignature>.constructor. See Core concepts.
Two ways to use it
Section titled “Two ways to use it”# Write analysis.json to ./outcodeanalyzer-typescript --input ./my-project --output ./out
# Or stream JSON to stdout (no --output)codeanalyzer-typescript --input ./my-project | jq '.call_graph | length'# Run the analyzer directly with Bun, no compile stepbun run start -- --input ./my-project --output ./outfrom cldk import CLDKfrom cldk.analysis import AnalysisLevel
analysis = CLDK(language="typescript").analysis( project_path="my-project", analysis_level=AnalysisLevel.call_graph,)print(analysis.get_call_graph()) # -> networkx.DiGraphWhy a dedicated tool
Section titled “Why a dedicated tool”A code LLM asked “what calls this function?” without analysis crawls: file read after file read, grep after grep, burning tokens on an answer it still can’t be sure of. codeanalyzer-typescript resolves that once, statically, into a graph — so the answer is a lookup, not a guess. The TypeScript compiler gives you precise resolution for free on every run; RTA recovers the virtual-dispatch targets a naive resolver would miss; phantom nodes keep the calls into third-party libraries visible instead of silently dropped.