Evaluating Dependencies
Evaluate packages before installation — across ecosystems — to make informed decisions about footprint, maintenance, alternatives, license, and security.
Universal decision framework
Run these checks regardless of ecosystem. Tools differ; the questions don't.
Evaluation Progress:
- [ ] 1. Need check — do we actually need it? is it already in deps?
- [ ] 2. Alternatives — identify 2-4 options if no specific package requested
- [ ] 3. Footprint — size/impact (bundle, binary, import cost)
- [ ] 4. Maintenance — last release, release cadence, deprecation status
- [ ] 5. Security — known CVEs, audit results
- [ ] 6. License — compatible with the project
- [ ] 7. Recommend — pick one, justify briefly
- [ ] 8. Install — pinned version, correct dep category
1. Need check
Before considering which package, ask whether:
- Is it already installed? (
package.json,Cargo.toml,pyproject.toml,go.mod,*.csproj,Directory.Packages.props) - Can the stdlib do it? (
Datein JS,datetimein Python,timein Go,chronoin modern Rust projects) - Is it a one-liner we can inline?
Adding a dep is a commitment — maintenance, security surface, lock file churn. Default to no.
2. Alternatives
If the user gave a specific package, proceed to Step 3 with it. Mention obvious alternatives if relevant.
If the user gave a generic need ("a date library", "a JSON parser"), identify 2-4 well-known options so the comparison is real.
3. Footprint
"Footprint" is ecosystem-specific:
| Ecosystem | What to measure | How |
|---|---|---|
| npm/pnpm/yarn/bun | Gzipped bundle size + dep count | bundlephobia API |
| cargo | Compiled binary impact, transitive deps | cargo tree, crates.io stats |
| pip/uv | Install size, transitive deps | pip show, pypi metadata |
| go | Transitive modules | go mod graph, pkg.go.dev |
| nuget | Download size, transitive deps | dotnet list package --include-transitive |
4. Maintenance
Red flags (any ecosystem):
- Last release > 2 years ago with no activity
- Deprecated (marked in registry, or replaced by a successor package)
- Single maintainer with no recent activity
- Issue tracker full of unanswered recent reports
Green flags:
- Released within the last ~6 months
- Multiple maintainers or org-backed
- Recent commits on the default branch
5. Security
Run an audit tool for the ecosystem (see "Ecosystem playbooks" below). CVE-laden dependencies are worth a hard no — look for an alternative.
6. License
Quick sanity check. MIT / Apache-2.0 / BSD are safe defaults. GPL/AGPL in a proprietary project is a conversation.
7. Recommend
Present in this format:
Option 1: <package> (recommended)
- Footprint: <size / deps>
- Latest: <version>
- Last updated: <timeframe>
- License: <spdx>
- Why: <smallest / most maintained / best types / etc.>
Option 2: <alternative>
- …
- Why not: <…>
Recommendation: install <package>@<version>
8. Install
Pin the version. Detect the package manager from lockfiles, never guess.
Ecosystem playbooks
npm / pnpm / yarn / bun
Detect the package manager:
if [ -f "bun.lockb" ]; then PM=bun
elif [ -f "pnpm-lock.yaml" ]; then PM=pnpm
elif [ -f "yarn.lock" ]; then PM=yarn
else PM=npm
fi
Footprint — bundlephobia:
curl -s "https://bundlephobia.com/api/size?package=<pkg>@latest" | jq '{size, gzip, dependencyCount}'
Compare alternatives:
for pkg in dayjs date-fns luxon; do
curl -s "https://bundlephobia.com/api/size?package=$pkg@latest" | jq --arg p "$pkg" '{pkg: $p, gzip}'
done
Version, dates, deprecation:
npm view <pkg> version
npm view <pkg> time.modified
npm view <pkg> deprecated
npm view <pkg> dist-tags --json
Downloads (popularity):
curl -s "https://api.npmjs.org/downloads/point/last-week/<pkg>" | jq '.downloads'
Security:
npm audit # after install
# or pre-install:
npx npq install <pkg> # sanity-checker
Install (pinned):
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies npm install <pkg>@<version> # -D for dev
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies pnpm add <pkg>@<version> # -D for dev
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies yarn add <pkg>@<version> # -D for dev
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies bun add <pkg>@<version> # -d for dev
The SKILL_ACK=<nonce>:evaluating-dependencies prefix signals to the skill-advisor hook that this skill has been consulted. The nonce is generated per session and prevents bypassing the skill.
Common categories:
| Need | Top options | Default pick |
|---|---|---|
| Date | dayjs, date-fns, luxon | dayjs (smallest) |
| HTTP | axios, ky, undici, got | ky (modern) or axios (ecosystem) |
| Validation | zod, valibot, yup | zod (TS-first) or valibot (smaller) |
| Testing | vitest, jest, uvu | vitest |
| State (React) | zustand, jotai, redux | zustand |
| Forms (React) | react-hook-form, formik | react-hook-form |
| UUID | uuid, nanoid | nanoid |
| Icons (React) | lucide-react, react-icons | lucide-react |
Bundle thresholds (gzipped):
| Size | Action |
|---|---|
| < 5 KB | Safe |
| 5–20 KB | Usually fine |
| 20–50 KB | Consider alternatives |
| 50–100 KB | Justify |
| > 100 KB | Look for something lighter |
cargo (Rust)
Check the registry:
cargo search <crate>
cargo info <crate> # cargo 1.76+
Otherwise: https://crates.io/api/v1/crates/<crate> returns JSON with downloads, versions, license, repository.
Version + metadata via crates.io API:
curl -s "https://crates.io/api/v1/crates/<crate>" | jq '{
latest: .crate.max_stable_version,
downloads: .crate.downloads,
recent: .crate.recent_downloads,
updated: .crate.updated_at,
license: .versions[0].license
}'
Dep tree + size context:
cargo tree -p <crate> # transitive deps
cargo bloat --release --crates # after adding, if binary size matters
Security:
cargo install cargo-audit # one-time
cargo audit
cargo install cargo-deny # license + advisory policy
cargo deny check
Outdated / deprecated:
cargo install cargo-outdated
cargo outdated
Install (pinned, via cargo add):
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies cargo add <crate>@<version>
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies cargo add <crate>@<version> --features "a,b"
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies cargo add <crate>@<version> --dev
Reference: lib.rs is a better UX than crates.io for browsing; it surfaces maintenance signals and usage counts.
pip / uv (Python)
Prefer uv for speed and reproducibility.
Version + metadata via PyPI JSON API:
curl -s "https://pypi.org/pypi/<pkg>/json" | jq '{
latest: .info.version,
license: .info.license,
requires_python: .info.requires_python,
last_release: .releases | to_entries | max_by(.value[0].upload_time) | .key,
home: .info.home_page
}'
Install size + transitive deps:
pip show <pkg> # after install
pip show <pkg> | grep Requires
# or without installing:
pip install --dry-run <pkg> 2>&1 | head -30
Security:
pip install pip-audit # one-time
pip-audit
pip install safety
safety check
Install (pinned):
# pip
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies pip install '<pkg>==<version>'
# uv (preferred)
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies uv add '<pkg>==<version>'
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies uv add --dev '<pkg>==<version>'
go modules
Metadata via pkg.go.dev (no JSON API — use the web page or proxy):
# Resolve latest version
go list -m -versions <module>
# Module info
curl -s "https://proxy.golang.org/<module>/@latest" | jq
Security:
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
Transitive deps:
go mod graph | grep <module>
go list -m -u all # outdated
Install (pinned):
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies go get <module>@<version>
go mod tidy
go get without @version pulls latest — always pin.
nuget (.NET)
Version + metadata via NuGet API:
# Latest stable version
curl -s "https://api.nuget.org/v3-flatcontainer/<package>/index.json" | jq '.versions | last'
# Full metadata
curl -s "https://api.nuget.org/v3/registration5-semver1/<package>/index.json" | jq
Dep tree + vuln scan (via dotnet CLI):
dotnet list package --include-transitive
dotnet list package --vulnerable --include-transitive
dotnet list package --deprecated
dotnet list package --outdated
Install (pinned):
SKILL_ACK=$(cat ~/.claude/.skill-nonce):evaluating-dependencies dotnet add package <Name> --version <ver>
For install mechanics (Central Package Management, version variables, workspaces), defer to the nuget-package-management skill.
Anti-patterns (cross-ecosystem)
Installing without pinning the version. Always install with an explicit version.
Skipping the footprint check because "it's probably small".
moment was 289 KB gzipped; the author thought it was small too. Check.
Treating transitive deps as free.
A 2 KB wrapper around a 200 KB tree is a 200 KB dep. cargo tree, npm ls, pip show, etc.
Picking the popular one reflexively.
Popular ≠ maintained. moment (maintenance mode) and request (deprecated) were once the default picks.
Adding a lib for one function. A 6-line utility isn't worth a dep. Especially in TS/Rust where monomorphization + tree-shaking mean the cost shows up in build time anyway.
Examples
npm: generic request
User: "Add a date library"
- Alternatives: dayjs, date-fns, luxon
- Footprint (gzipped): dayjs 2.9 KB, date-fns 13 KB, luxon 25 KB
- All actively maintained
- Licenses all MIT
- Recommend: dayjs (smallest, good DX).
npm install dayjs@1.11.10
cargo: specific crate
User: "Add tokio"
- Need check: async runtime required for this server? yes.
- Metadata: crates.io API → latest 1.37.0, license MIT, updated this month, 100M+ downloads
- Feature footprint:
tokio = { version = "1.37", features = ["rt-multi-thread", "macros"] }(avoidfull— pulls everything). - Security:
cargo auditclean. - Install:
cargo add tokio@1.37 --features rt-multi-thread,macros
pip: bundle replacement
User: "Our Python deploys are slow, image is 2GB"
- Check
pip list+pip show <pkg>for largest installs - Flag candidates: pandas (heavy), scipy (heavy)
- Suggest: if only using
read_csv, considerpolars(smaller, faster) or stdlibcsv - Measure after swap.
nuget: package with CPM
User: "Add Serilog"
- Delegate install mechanics to
nuget-package-management(CPM, shared version vars) - Metadata: nuget.org → latest 4.0.0, license Apache-2.0, actively maintained
- Vuln scan:
dotnet list package --vulnerableclean - Install: use
dotnet add package Serilog(CPM will pick the shared version)
References
- npm: bundlephobia, npmtrends, Snyk advisor
- cargo: lib.rs, crates.io, rustsec advisory DB
- python: pypi, Snyk advisor
- go: pkg.go.dev, osv.dev
- nuget: nuget.org, GitHub Advisory DB
Related skills:
nuget-package-management— .NET install mechanics (CPM, version variables)node-package-management— npm/pnpm install mechanics, workspaces