First scan
Five commands from a cold machine to a populated dashboard.
# 1. Write a conservative .packguard.yml at the repo root.
packguard init
# 2. Scan — walks the lockfiles, fetches registry data, persists to SQLite.
packguard scan
# 3. Refresh supply-chain intel (OSV + GHSA + malware + typosquat lists).
packguard sync
# 4. Audit — prints every CVE / malware / typosquat finding.
packguard audit
# 5. Open the dashboard — same store, interactive view.
packguard uiThat’s it. The store lives at ~/.packguard/store.db by default — override with --store <path> on any command.
What each step does
init drops a .packguard.yml with offset: { major: 0, minor: -1, patch: 0 } (latest major, one minor behind, always take patches), stability: stable, min_age_days: 7, and blocking on high/critical CVEs + malware + deprecated + yanked. Typosquat defaults to warn (noisy signal, human-in-the-loop review).
scan parses package-lock.json / pnpm-lock.yaml / poetry.lock / uv.lock, hits the registry for full version history + stability metadata, and persists everything into the store. A SHA-256 fingerprint of (manifest + lockfiles) short-circuits unchanged re-runs.
sync pulls the OSV dump, a shallow github/advisory-database clone, the top-PyPI reference list, and — if PACKGUARD_SOCKET_TOKEN is set — per-version Socket.dev alerts. Conditional GET and git fast-forward keep the hot path under 10 seconds.
audit reads the store (no network, unless the OSV live fallback fires) and prints three grouped sections: CVE table, Malware table, Typosquat suspects. Use --focus cve|malware|typosquat to narrow.
ui boots an embedded axum server on :5174 and auto-opens your browser. The dashboard reads the same SQLite store the CLI wrote, so there’s no re-fetching.
From here
- Tune the policy — see Offset policy for the
.packguard.ymlreference. - Wire a CI gate — the GitHub Actions or GitLab CI recipe is a copy-paste job.
- Explore the dashboard — Overview is the first screen.