Lopper is a local-first CLI/TUI for measuring dependency surface area in source repos. It compares imported dependencies to actual usage and reports waste, risk cues, and recommendations.
macOS/Linux (Homebrew tap, stable):
brew tap ben-ranford/tap
brew install loppermacOS/Linux (Homebrew tap, rolling):
brew install ben-ranford/tap/lopper-rollinglopper-rolling tracks main and is not a stable semver release.
Windows (GitHub Releases):
# Open latest release page and download the Windows asset for your platform.
gh release view --repo ben-ranford/lopper --webGenerate a local manpage:
make manpageThe generated manpage is available as docs/man/lopper.1 and is installed automatically by the Homebrew formulas.
Run without local install:
docker run --rm ghcr.io/ben-ranford/lopper:latest --helpAnalyze one dependency:
lopper analyse lodash --repo . --language js-tsRank top dependencies by waste:
lopper analyse --top 20 --repo . --language all --format tableEmit JSON:
lopper analyse --top 20 --repo . --language all --format jsonEmit CSV for spreadsheet or pipeline ingestion:
lopper analyse --top 20 --repo . --language all --format csv > lopper.csvEmit SARIF for code scanning:
lopper analyse --top 20 --repo . --language all --format sarif > lopper.sarifLaunch the interactive TUI:
lopper tui --repo . --language allTune thresholds and score weights:
lopper analyse --top 20 \
--repo . \
--language all \
--threshold-fail-on-increase 2 \
--threshold-low-confidence-warning 35 \
--threshold-min-usage-percent 45 \
--score-weight-usage 0.50 \
--score-weight-impact 0.30 \
--score-weight-confidence 0.20Save an immutable baseline snapshot keyed by commit:
lopper analyse --top 20 \
--repo . \
--language all \
--format json \
--baseline-store .artifacts/lopper-baselines \
--save-baselineSave using a human label key:
lopper analyse --top 20 \
--repo . \
--language all \
--format json \
--baseline-store .artifacts/lopper-baselines \
--save-baseline \
--baseline-label release-candidateCompare against a stored baseline key and gate CI:
lopper analyse --top 20 \
--repo . \
--language all \
--format json \
--baseline-store .artifacts/lopper-baselines \
--baseline-key commit:abc123 \
--threshold-fail-on-increase 2Generate an org-level dashboard across multiple repos:
lopper dashboard \
--repos "./api,./frontend,./worker" \
--format html \
--output org-report.htmlUse a dashboard config file:
lopper dashboard --config lopper-org.yml --format json- Supported adapters:
js-ts,python,cpp,jvm,kotlin-android,go,php,ruby,rust,dotnet,elixir,swift,dart,powershell js-tsmerges workspace-level declarations frompnpm-workspace.yaml,package.json#workspaces, and Yarn.yarnrc.ymlcatalogs.- Source of truth for adapter IDs:
lopper --help - Language modes:
auto: choose highest-confidence adapterall: run all matching adapters and merge results<id>: force one adapter
Repo-level config example (.lopper.yml):
policy:
packs:
- ./policies/org-defaults.yml
- https://example.com/lopper/policy.yml#sha256=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
thresholds:
fail_on_increase_percent: 2
low_confidence_warning_percent: 35
min_usage_percent_for_recommendations: 45
removal_candidate_weight_usage: 0.50
removal_candidate_weight_impact: 0.30
removal_candidate_weight_confidence: 0.20Threshold defaults:
fail_on_increase_percent: 0(disabled unless set above0)low_confidence_warning_percent: 40min_usage_percent_for_recommendations: 40removal_candidate_weight_usage: 0.50removal_candidate_weight_impact: 0.30removal_candidate_weight_confidence: 0.20
Threshold ranges:
fail_on_increase_percentmust be>= 0low_confidence_warning_percentmust be between0and100min_usage_percent_for_recommendationsmust be between0and100- removal candidate weights must be
>= 0and at least one must be greater than0
Precedence is CLI > repo config > imported policy packs > defaults.
Additional guides:
docs/threshold-tuning.mddocs/notifications.mddocs/feature-flags.md
Launch TUI:
lopper tui --repo . --language allCapture a runtime trace:
export LOPPER_RUNTIME_TRACE=.artifacts/lopper-runtime.ndjson
export LOPPER_ROOT=/path/to/lopper
export NODE_OPTIONS="--require ${LOPPER_ROOT}/scripts/runtime/require-hook.cjs --loader ${LOPPER_ROOT}/scripts/runtime/loader.mjs"
npm testUse the hook files from the lopper checkout or install tree. Relative hook paths resolve from the repo running npm test, not from lopper itself.
Or let Lopper run the test command and capture the trace automatically:
lopper analyse --top 20 --repo . --language js-ts --runtime-test-command "npm test"Use trace in analysis:
lopper analyse --top 20 --repo . --language js-ts --runtime-trace .artifacts/lopper-runtime.ndjsonWith runtime traces enabled:
runtimeUsage.correlationmarks each JS/TS dependency asstatic-only,runtime-only, oroverlap.runtimeUsage.modulesincludes runtime-loaded module paths.runtimeUsage.topSymbolsincludes best-effort runtime symbol hits.
If --runtime-trace points to a missing file, analysis continues with static results and adds a warning.
See CONTRIBUTING.md for development setup and commands.
For watched hotspot packages, run make mem-profiles to capture alloc-space summaries before or after performance-sensitive changes.
- Report schema:
docs/report-schema.json,docs/report-schema.md - Multi-repo dashboard:
docs/dashboard.md - Memory profiling workflow:
docs/memory-profiling.md - SARIF code scanning:
docs/sarif-code-scanning.md - Threshold tuning:
docs/threshold-tuning.md - Runtime trace annotations:
scripts/runtime/ - Adapter and architecture extensibility:
docs/extensibility.md - CI and release workflow:
docs/ci-usage.md - Contribution guide:
CONTRIBUTING.md


