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

depmod-ui

v0.4.3

Published

Visualise the dependency graph of a JavaScript / TypeScript project from your terminal.

Readme

depmod

See the shape of your codebase. A terminal-launched, browser-rendered dependency graph explorer for TypeScript and JavaScript projects.

npm version npm downloads CI License: MIT Node


What is depmod?

depmod is a small CLI that reads your TypeScript or JavaScript project, builds an import graph, and opens an interactive dashboard in your browser. It works on single apps, monorepos, and most setups that ts-morph can parse. Nothing is uploaded anywhere; parsing and the UI stay on your machine.

(Not the Linux depmod command, and not Depeche Mode, though I do love them :D)

Try the live demo — the dashboard exploring depmod's own dependency graph, updated on every release.

It is meant for the moment you land in a repo and need answers quickly:

  • Who sits in the middle of the graph? Martin coupling (Ca, Ce, instability)
  • If I change this file, what breaks? Blast radius (reverse reachability on the import graph)
  • What does this module actually pull in? Focus mode around a node
  • Where are the import cycles? Tarjan SCCs, with isolation per cycle
  • What looks unused? Unreferenced files, type-only imports, thin stubs
  • What is declared in package.json but never imported? Per-workspace static check

Quickstart

Install

Global (recommended if you reach for it often):

npm install -g depmod-ui
# or: pnpm add -g depmod-ui
# or: yarn global add depmod-ui

One-off (no install):

npx depmod-ui

Run

After a global install, depmod-ui is on your PATH. With npx, prefix commands the same way.

# Current directory
depmod-ui

# Any project path
depmod-ui /path/to/project

# Re-parse when files change
depmod-ui . --watch

By default the dashboard listens on http://127.0.0.1:45455. If that port is busy, depmod-ui tries the next one so you can run several projects side by side.

Features

| | | | --- | --- | | Two canvases | 2D Cytoscape (WebGL) for large graphs; 3D force-directed view for exploration. Switch with one click. | | Classification | Modules tagged as page, api, hook, component, lib, test, or config. Filter, dim, solo, or hide by class. | | Path mask | Comma-separated globs on the canvas, e.g. **/*.tsx,!**/*.test.* | | Inspector | LOC, size, Ca / Ce, instability, exports, dependents, dependencies, rough bundle hint, cycle membership | | Blast radius | Press B on a selection to highlight everything that depends on it | | Focus mode | Press F to keep only an N-hop neighbourhood (even across hidden classes) | | Cycle isolation | List cycles and isolate one to trace the loop | | Dead-code hints | No importers, no exports, type-only usage, near-empty files | | Unused-deps report | Compares package.json to real imports; respects monorepo paths | | Code viewer | Press C or open source in a Monaco panel | | Live reload | With --watch, saves trigger a re-parse over SSE; filters and selection stick | | Layout cache | First layout can take a moment; later loads reuse cached positions per graph version |

Commands

| Command | Purpose | | --- | --- | | depmod-ui [path] | Parse, serve, open browser (default) | | depmod-ui serve [path] | Same as default | | depmod-ui analyze <path> | Write graph.json and metrics.json to disk | | depmod-ui check <path> --fail-on <rules> | Exit non-zero when rules fail (CI-friendly) |

Useful flags

depmod-ui .
depmod-ui /repo --watch
depmod-ui /repo --port 51000
depmod-ui /repo --no-open
depmod-ui /repo --include "src/**"
depmod-ui /repo --exclude "**/*.test.*"
depmod-ui /repo --no-gitignore
depmod-ui /repo --exclude-tests
depmod-ui /repo --no-cache

depmod-ui check .
depmod-ui check . --fail-on cycles,unused-deps
depmod-ui check . --fail-on instability:>0.7

Development

Requirements

  • Node 20.18 or newer (.nvmrc pins 24.14)
  • pnpm 10+ (corepack enable is enough)

Setup

nvm use
corepack enable
pnpm install
pnpm build
pnpm depmod-ui .

Daily loop

pnpm -r test
pnpm typecheck
pnpm lint
pnpm format
pnpm --filter web dev

GitHub Pages static demo

Build the static export locally (same pipeline as release deploy):

pnpm build:pages
npx serve apps/web/out -p 3000
# open http://localhost:3000/depmod/

Workspace layout

| Path | Role | Published? | | --- | --- | --- | | packages/types | Zod Graph schema shared by CLI and web | private | | packages/parser | Static analysis, metrics, cycles, dead-code, unused-deps | private | | packages/cli | depmod-ui command; bundles parser and dashboard | npm: depmod-ui | | apps/web | Next.js dashboard (Cytoscape, three.js, inspector) | bundled in the CLI tarball | | bench | Benchmarks on OSS repos | private |

How it works

┌────────────────────────┐     ┌─────────────────────────┐     ┌─────────────────────┐
│      depmod-ui         │     │   Next.js server        │     │       browser       │
│  (CLI process)         │     │   (spawned by CLI)      │     │                     │
│                        │     │                         │     │                     │
│  1. parse (ts-morph)   │────▶│  /api/graph reads       │────▶│  Cytoscape / 3D     │
│  2. write session file │     │     session JSON        │     │  Inspector, etc.    │
│  3. spawn server       │     │  /api/events (watch)    │────▶│  live updates       │
└────────────────────────┘     └─────────────────────────┘     └─────────────────────┘

The parser is a pure function: (rootDir) -> Graph. The web app does not re-parse; it only reads what the CLI wrote. Same input should match between the terminal summary and the dashboard.

A few implementation details:

  • Path aliases: each workspace tsconfig paths map is applied when resolving imports (workspace-aliases.ts).
  • Externals: imports resolved to node_modules types are tracked for the unused-deps report, not dropped.
  • Focus / blast: out-of-scope nodes use display: none, not opacity, so the view matches the question you asked.
  • Incremental cache: per-file slices in .depmod-cache; bump PARSER_VERSION in the parser to invalidate.

More design notes: docs/specs/.

Benchmark snapshot

Cold analyze() on real OSS repos (parser 0.3.0, incremental cache off). Wall-clock parse time; full metrics in bench/results/.

| Target | Tier | Files | Edges | Cycles | LOC | Parse | | --- | --- | ---: | ---: | ---: | ---: | ---: | | vercel-commerce | primary | 65 | 120 | 1 | 3,896 | 407 ms | | shadcn-taxonomy | medium | 127 | 247 | 0 | 7,730 | 350 ms | | create-t3-turbo | medium | 74 | 62 | 1 | 3,370 | 331 ms | | unkey | medium | 1,921 | 2,914 | 10 | 180,304 | 2.7 s | | react-email | medium | 1,089 | 1,785 | 7 | 200,826 | 1.6 s | | documenso | stress | 1,855 | 3,540 | 25 | 233,359 | 2.9 s | | dub | stress | 3,913 | 10,897 | 19 | 435,857 | 4.7 s | | cal-web | stress | 988 | 1,287 | 9 | 126,331 | 1.6 s | | cal.com | stretch | 4,999 | 9,157 | 24 | 546,207 | 7.1 s | | music.eduardlupu.com | stretch | 41 | 77 | 0 | 7,677 | 1.3 s |

cal-web analyzes only apps/web from the Cal.com monorepo (shared clone). Re-run with pnpm bench or smoke-test with pnpm bench:quick; see bench/README.md.

Contributing

See CONTRIBUTING.md for setup, changesets, and the release flow. Before a PR:

  1. pnpm typecheck, pnpm -r test, and pnpm lint should pass.
  2. Add or update tests next to the code you change.
  3. User-visible CLI changes need a changeset (pnpm changeset).

For larger ideas, open an issue first.

License

MIT © Eduard Lupu