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

ui-lineage

v0.6.1

Published

React & TypeScript static analysis that maps every UI component to the APIs, state, and events behind it — and serves that context to AI coding agents over MCP. Screenshot or ticket in; component, data lineage, user journeys, and blast radius out. Determi

Readme

ui-lineage — React data lineage & codebase context for AI coding agents

npm version npm downloads license node

Map every UI component to the APIs, state, and events behind it — trace any screenshot or Jira ticket back to the exact React component, its data lineage, user journeys, and blast radius. Deterministic TypeScript static analysis: no LLM in the core, no network calls, byte-identical output on every run.

Ships an MCP server (ui-lineage-mcp), so Claude Code, Cursor, Windsurf, or any Model Context Protocol client can query your codebase's data flow as structured context instead of re-reading files.

ui-lineage scans a React codebase into a lineage graph and answers three questions:

  1. match — text or structure seen on screen → the component(s) that render it (rarity-weighted, fuzzy/OCR-tolerant, structure-aware, with business-vocab aliases and human corrections, and calibrated confidence).
  2. trace — a component → every API, state slice, and event that feeds it, attributed per instance (a shared <DataTable> reports /api/users on the Users page and /api/invoices on Invoices).
  3. journeys — a page → the user-action paths out of it (click → navigate → click…), lazily expanded and cycle-safe, with flag/role conditions.

Use it to

  • Give an AI coding agent real context — over MCP, so it edits the right component instead of guessing from file names.
  • Answer "where does this number come from?" — screenshot or UI text → component → the exact endpoint feeding it.
  • Scope a change before making it — blast radius of an API, component, or route across the whole app.
  • Onboard onto an unfamiliar React codebase — see which APIs feed which screens, and how users navigate between them.
  • Triage a bug ticket — text in, ranked components out, with confidence and evidence (or an honest "ambiguous").

Install

npm install -g ui-lineage      # CLI
npm install ui-lineage         # library

Requires Node ≥ 20.

CLI

ui-lineage scan ./src -o app.graph.json          # scan a React app into a graph
ui-lineage scan ./src --openapi openapi.json     # …and link data sources to response types
ui-lineage find "All invoices" -g app.graph.json # text → component
ui-lineage find "invoice widget" -a aliases.yaml # resolve business vocabulary
ui-lineage trace InvoicesPage -g app.graph.json  # component → data/state/events
ui-lineage journeys /users -g app.graph.json     # user-journey paths from a page
ui-lineage impact /api/users -g app.graph.json   # blast radius: everything that depends on a node
ui-lineage resolve "cart total is wrong"         # classify a ticket, then match it to components
ui-lineage bundle "cart total is wrong" -b 4000  # a budgeted context bundle (JSON) for an agent
ui-lineage correct BillingCard "amount owed"     # record a correction for next time
ui-lineage visualize -g app.graph.json -o app.galaxy.html  # interactive HTML graph explorer

visualize renders the whole graph as a single self-contained HTML file — the graph JSON plus all CSS/JS inlined, zero network dependencies — that opens in any browser (open app.galaxy.html, no server needed). Nodes are laid out as a canvas force-directed "galaxy", color-coded by kind (component, instance, hook, data-source, state, event, route, external, test); components are the stars, their data/state/events cluster around them, routes act as gravitational centers. Toggle node and edge kinds, search a node and fly to it, click a node for its details plus a highlighted neighborhood (a visual blast radius), drag to pin, scroll to zoom, and pause the physics. Built to stay responsive at real-codebase scale (thousands of nodes).

impact <node> takes a component name, an API endpoint, a state name, or a route path, and lists every node that depends on it (reverse traversal), each indented by its distance — so a change can be reviewed for what it might break:

  [instance-of] instance DataTable  (pages/UsersPage.tsx:17)
    [renders] component UsersPage   (pages/UsersPage.tsx:5)

journeys reads left-to-right, with ↩ cycle where a list ⇄ detail loop closes:

  ▸ /users  • onClick()  → /users/:id  ▸ /users/:id  • onClick()  → /users  ▸ /users  ↩ cycle
  ▸ /users  • onClick()  ⇢ fetch /api/users

MCP server

ui-lineage also ships an MCP (Model Context Protocol) server, so an agent can query a pre-built graph over stdio. Build a graph, then point an MCP client at the ui-lineage-mcp bin with the graph path in CODERADAR_GRAPH:

// e.g. an MCP client config
{
  "mcpServers": {
    "coderadar": {
      "command": "ui-lineage-mcp",
      "env": { "CODERADAR_GRAPH": "/abs/path/to/app.graph.json" }
    }
  }
}

Tools: resolve_context(ticket) (→ a budgeted context bundle), find_component(terms), trace_lineage(id), journeys(start, depth?), blast_radius(node, depth?). Every tool returns a QueryResult envelope — ranked candidates with confidence, or an honest ambiguous / declined. There is no LLM in the server; it is a deterministic context provider.

Library

import {
  scanReact, resolveHookEdges,
  matchComponents, traceLineage, journeys,
  recordCorrection, loadCorrections,
} from "ui-lineage";

const graph = resolveHookEdges(scanReact({ root: "./src" }));

const match = matchComponents(graph, { terms: ["All invoices"] });
const lineage = traceLineage(graph, match.candidates[0].value.component.id);
const paths = journeys(graph, "/users", { depth: 3 });

Every query returns a QueryResult envelope — ranked candidates with evidence and confidence, or an honest ambiguous (with a disambiguation question built from the candidates' differences) / declined (machine-readable reason).

Screenshots (ui-lineage/vision)

import { StubVisionAdapter, matchFromVision } from "ui-lineage/vision";

Turn a screenshot into { terms, structure, annotations } and match it — terms the user circled are weighted 3×; a non-app image declines. The Claude-vision adapter needs @anthropic-ai/sdk installed separately; the stub and matching helpers do not. Images are processed in memory, never persisted.

What it understands

Endpoints (constants, templates, API wrappers, react-query/SWR/RTK Query), GraphQL operations, WebSocket/SSE push channels, Next.js server-side data (RSC async components, getServerSideProps/getStaticProps), i18n text, cross-file instance trees & per-instance prop-flow, Redux/Zustand stores, portals/modals/toasts, React Router & Next.js routes, action effects (navigate/fetch/dispatch/setState), form libraries & non-JSX events (react-hook-form, addEventListener, hotkeys), and feature-flag/role conditions.

New in 0.6.0

Wider data-source coverage — the graph now sees the ways modern React apps actually fetch, beyond REST calls in the component body:

  • GraphQL — Apollo/urql operations become data sources, keyed by operation name and typed by operation (query / mutation / subscription). Works with an inline gql tag or an imported/co-located gql const (resolved across files), and is disambiguated from react-query, which shares the useQuery/useMutation hook names.
  • Push channelsnew WebSocket(url) and new EventSource(url) become websocket / sse data sources, so a component fed by a live channel shows that channel in its lineage.
  • Next.js server data — a page's server-side fetching is attributed to the page even when it isn't in the component body: pages-router getServerSideProps / getStaticProps / getStaticPaths, alongside app-router async RSC server components.

New in 0.5.0

Phase 6 — lifecycle, scale, and hardening (production-grade: incremental, fast, deterministic, versioned):

  • Incremental re-scanscan --update re-parses only files whose contents changed (byte-identical to a full re-scan by construction) and skips work entirely when nothing changed; scan --watch re-emits the graph on each save. Per-file content hashes recorded in GraphMeta.
  • Determinism — nodes, edges, and candidates emit in stable, explicit sort order regardless of filesystem/platform; the eval runner hard-gates two-run byte-identity.
  • Version skew & rename tracking — a SHA-keyed graph store (.coderadar/graphs/<sha>.json + latest); bundle --against <sha|latest> warns when the matched component was renamed/moved in the current code (“matched InvoiceCard; renamed BillingCard”).
  • Generated-code classification — machine-generated files (@generated/DO NOT EDIT banners, __generated__/ paths, .generated. infixes, minified) are kept in lineage as API metadata but excluded from match candidates.
  • PII policy — screenshots are ephemeral (never persisted, embedded, or logged); the graph and corrections store hold terms only. Documented in docs/security.md and enforced by a test.
  • Scale — a ~2,000-file synthetic benchmark with a nightly, budget-gated perf CI job (< 5 min scan, < 4 GB RSS).

New in 0.4.1

Second field-hardening round, validated by self-running against Grafana's frontend (6,461 files → 15,334-node graph in 72 s: 55 RTK-query data sources, 32 routes, 1,009 test-coverage edges):

  • Stopword & rare-literal scoring — a component rendering a bare BY (a rare literal with high IDF) no longer outranks the component that renders the whole phrase; stopword-only queries decline no-signal.
  • HTML-entity rendered text&nbsp; / &#34; / &gt; are decoded during extraction (as React does), so they stop producing junk match tokens and false matches.
  • coverage-unmapped note — when test files exist but almost none map to a component, bundles emit one honest graph-level note instead of a near-universal false untested.
  • visualize — self-contained interactive HTML galaxy of the whole graph (ui-lineage visualize -g app.graph.json -o app.galaxy.html), responsive at 15k+ nodes.

New in 0.4.0

Field-hardening from real-codebase validation (React 18 · Redux Toolkit · RTK Query · MUI · React Router):

  • Matcher fix — rendered text that normalizes to empty (|, /, -) no longer acts as a universal wildcard; gibberish now declines no-signal instead of returning false high-confidence matches.
  • Instance resolution — tsconfig-path aliases (@ui), multi-hop rename barrels, and Loadable(lazy(() => import())) page wrappers now resolve to their definitions, so blast_radius and the render graph are complete.
  • RTK QuerycreateApi / injectEndpoints / builder.query|mutation become data sources (baseUrl-joined, :param-normalized); generated hooks (useGetUsersQuery) wire per-component fetches-from edges.
  • Object-config routescreateBrowserRouter with an imported/spread-composed config and lazy-wrapped elements now emits route nodes, so journeys("/path") works.
  • Scoring — terms that also name a component (name/props/file) outrank incidental text; every candidate carries a top-line score next to confidence.
  • visualize — new command renders the graph as a self-contained interactive HTML galaxy (ui-lineage visualize -g app.graph.json -o app.galaxy.html).

New in 0.3.0

The agent interface: resolve/bundle produce a budgeted context bundle (match → lineage → journeys → blast radius → tests → response types → git history) · impact blast-radius traversal · test-coverage mapping · response-schema linking (generic / annotation / OpenAPI, via scan --openapi) · and the ui-lineage-mcp MCP server exposing resolve_context · find_component · trace_lineage · journeys · blast_radius over stdio.

Previously (0.2.0)

User journeys · action effects · form & non-JSX events · flag/role conditions · a real matching engine (rarity + fuzzy/OCR + structural + most-specific-subtree) · screenshot/vision adapter · alias glossary + corrections store · calibrated confidence with honesty metrics.

Status

Pre-1.0. Output is deterministic and language-agnostic (a plain JSON graph), designed to feed AI agents as a context provider — not to be one. Lifecycle/scale hardening (incremental scan, determinism, versioning) landed in 0.5.0; next is backend lineage (pixel → API handler).

License

MIT