npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cgg-callgraphgenerator

v0.10.1

Published

Offline, deterministic call-graph generation for 44 languages. Point it at a directory, get a mermaid diagram.

Readme

cgg — Node.js bindings

Offline, deterministic call graphs for 46 languages, in-process.

Not on npm yet. npm install cgg-callgraphgenerator does not work today — the name is reserved for this package but nothing has been published under it. Until it is, build the module from the repository:

git clone https://github.com/NeuralNotwerk/cgg && cd cgg/crates/cgg-node
npm install && npm run build      # writes index.js, index.d.ts, cgg.<platform>.node

Then require("./index.js") — or require("<path>/cgg-node") — wherever the samples below say require("cgg-callgraphgenerator"). Everything else on this page is what that build gives you.

The Rust CLI (cargo install cgg) and the Python module (pip install cgg-callgraphgenerator) are published and usable now.

const cgg = require("cgg-callgraphgenerator");

const g = await cgg.analyze("./src");
console.log(g.toMermaid());

No network calls, no language servers, no build artifacts required. The analysis is the same Rust pipeline the cgg command-line tool runs, in the same order, so the two cannot disagree — the test suite compares this module's output against the binary's on the same tree, across the option surface, and fails if they diverge.

The package name is cgg-callgraphgenerator; cgg on npm is an unrelated project — a wrapper for the ChampionGG API. Same name as on PyPI, so the two bindings are findable by the same string.

Usage

const cgg = require("cgg-callgraphgenerator");

// Whole tree.
const g = await cgg.analyze("./src");

// A neighbourhood around what you care about.
const near = await cgg.analyze("./src", { filter: ["handleRequest$"], hops: 2 });

// Several roots, one graph.
const both = await cgg.analyze(["./api", "./worker"], { lang: ["typescript", "go"] });

g.toMermaid();   // -> string, byte-identical to `cgg -t mermaid`
g.toJson();      // -> string, `cgg.graph.v2`
g.toDot();
g.toGraphml();

g.callableCount;         // without materializing anything
g.callables;             // [{ id, qualifiedName, kind, language, file, startLine, … }]
g.edges;                 // [{ src, dst, siteLine, siteByte, confidence, via }]
g.files;                 // [{ id, path }] — match `callable.file` by id, not array offset
g.metrics;               // whole-run counters
g.notices;               // what the CLI would print to stderr
g.jobs;                  // worker threads actually used

analyze returns a promise and runs the pipeline on a background thread (tokio::task::spawn_blocking, via napi's tokio_rt), so the event loop stays responsive for the ~130 ms a tree the size of cgg's own crates/ costs. analyzeSync is there for scripts, where blocking is the point — it blocks the loop for the whole analysis.

TypeScript definitions ship with the package and are generated from the Rust, so they cannot drift from what the module actually exposes.

Options

Every option that changes the graph is a key on the second argument, with one rename from the CLI — entryNodes: true rather than --no-entry-nodes. Same default; a keyword has no reason to be a double negative.

{
  filter, hops, maxPaths,
  excludePartial, excludeGlob, excludeRegex,
  lang, jobs, ignoreFile, since, roots,
  skipMinified, includeExternal, includeStdlib, dynamicDispatch, referenceEdges,
  entryNodes, includeTests,
  deadCode, deadCodeConfidence, ignoreNames, ignoreAttributes,
}

An out-of-range value is an error naming what was expected — deadCodeConfidence: "nope" fails with must be "high", "medium" or "low" rather than being quietly coerced.

An unrecognised key is silently ignored, though, because that is how napi deserializes an options object: { hopz: 2 } analyzes with defaults and reports nothing. Check spelling against the list above, or use the TypeScript definitions, which do catch it. (The C ABI rejects unknown keys outright; this binding cannot yet.)

Concurrency

analyze takes no locks and keeps no process-global state, so concurrent calls do not interfere — each gets its own worker pool sized by jobs.

Findings are hypotheses

deadCode: true reports callables nothing appears to call. It is best effort: reflection, dynamic dispatch and framework magic are exactly what a static tool cannot see, so every finding is something to check, not a fact. g.notices carries the coverage disclosure, including which frameworks cgg recognised and which it saw but could not enumerate.

Not in this release

--why-live proofs, the --write-roots baseline and the audit event stream are reachable from the Rust API but have no option key and no Graph getter here. Use the CLI for those.

The framework-coverage table is not missing — as the section above says, it arrives rendered as one of the strings in g.notices. What is missing is a structured object; parse the notice or use cgg --framework-coverage if you need fields.

Full documentation: https://github.com/NeuralNotwerk/cgg

Licensed Apache-2.0 OR MIT.