Graph
Cytoscape-rendered transitive dependency graph — dagre + cose-bilkent layouts, URL-driven filters, focus-CVE contamination mode.
Default view

Cose-bilkent layout by default — force-directed, clusters nodes by coupling so tightly-connected subgraphs visually group together. Dagre (left-to-right DAG) stays available in the Layout dropdown for reviews that favour hierarchy over cohesion. Node fills encode ecosystem (npm blue / pypi green / malware purple / typosquat magenta / CVE ember). Edge styles encode kind (runtime solid / dev stroked / peer dashed / optional dotted).
Filters
| Control | Effect |
|---|---|
| Kind | Toggle runtime / dev / peer / optional edges. Defaults to runtime only. |
| Depth | Limit the BFS depth from workspace roots. Default 2 — direct deps + one transitive level. Raise the slider to go deeper on large monorepos. |
| Layout | dagre (DAG-style) / cose-bilkent (force-directed). |
| Search | Highlights any node whose name substring-matches. |
Every filter is in the URL, so a shared link reproduces the same view.
Legend — dynamic and clickable
The legend only surfaces categories actually present in the current render (post-filter, post-depth). If no optional edges are in view, the optional item isn’t in the legend — no dead controls. Click an item to hide that category from the canvas; the item desaturates with a strikethrough so you keep the handle to restore it. Re-click to bring it back.
The state lives in the URL: ?hide=<keys> for client-side categories (ecosystem / status), ?kind= for edge kinds (shared source of truth with the Kind row above). Share a URL, share the exact filtered view.
Focus-CVE contamination mode

Press Cmd+K (or Ctrl+K on Linux / Windows) to open the CVE command palette. Fuzzy search across every advisory present in the current workspace scope — each row shows CVE-YYYY-NNNNN · <package> · <severity> · <N chains>. Arrow keys to navigate, Enter to select, Escape to close without touching the URL.
Selecting an entry writes ?focus_cve=<id> into the URL and the graph:
- Looks up every
(ecosystem, name, version)touched by the advisory in the local store. - Runs the inverse contamination BFS — same algorithm as
packguard graph --contaminated-by. - Highlights every root-to-leaf chain in ember red, dims everything else.
The banner at the top tells you how many packages were hit and how many chains were surfaced — CVE-2026-4800: 1 package hit · 3 contamination chains · cached.
Cache is per-advisory, 15 minutes — a subsequent trace of the same CVE is instant. When the store has no advisories in scope, the palette shows a callout pointing at packguard sync to fetch the database.
Empty state
A freshly-scanned workspace with zero transitive edges (yarn.lock-only, or pip declared-only with no lock) shows a banner pointing at the limitation. The scanner will surface the workspace roots and their direct deps but can’t render transitive chains without a real lockfile.
Performance
- ~5000 nodes renders in well under a second on a mid-range laptop.
- Above that, the dashboard warns and suggests toggling off peer + optional edges to slim the graph before rendering.
- The BFS cache is shared with the CLI — same store, same traversal, same result.
Related
packguard graph— CLI equivalent, same data, multiple formats.- Supply-chain intel — how advisories reach the store the graph reads.