A faster, smarter package manager for Node.js — built on a pure Rust core.
Benchmarked on a real project with 15 dependencies (145 resolved packages):
| Tool | Warm Install | Cold Install | vs better |
|---|---|---|---|
| better | 75ms | ~400ms | - |
| bun | 198ms | ~500ms | 2.6x slower |
| npm | 1,749ms | ~8,000ms | 23x slower |
How it works
| Layer | Technique | Impact |
|---|---|---|
| Binary | Pure Rust — zero Node.js startup | saves ~265ms vs JS tools |
| I/O | macOS clonefile() — APFS copy-on-write |
near-instant materialization |
| Concurrency | rayon-powered parallel everything | resolution, fetch, extract, link |
| Storage | SHA-512 package cache + SHA-256 file CAS | dedup across projects |
| Fallback | 3-tier: clonefile > CAS hardlinks > copy | works on all filesystems |
Cross-project dedup (--dedup)
Share node_modules files across projects via hardlinks from a global store:
better install --dedup| Projects | Without dedup | With --dedup | Savings |
|---|---|---|---|
| 2 | 28MB | ~16MB | 43% |
| 5 | 70MB | ~18MB | 74% |
| 10 | 140MB | ~20MB | 86% |
Files share the same inode — editing one won't affect others (copy-on-write at the filesystem level).
# Quick install (recommended)
curl -fsSL https://raw.githubusercontent.com/EfeDurmaz16/better-npm/main/scripts/install.sh | sh
# Via npm
npm install -g better
# Via Homebrew
brew install EfeDurmaz16/tap/better
# From source
cd crates && cargo build --release -p better-corebetter install # Install dependencies (auto-selects fastest strategy)
better install --dedup # Install with cross-project file dedup
better install --no-scripts # Skip lifecycle scripts
better analyze # Dependency attribution, duplicates, depth analysis
better scan # Low-level lockfile scanbetter run <script> # Run package.json scripts (node_modules/.bin on PATH)
better run lint test build # Run multiple scripts in parallel
better run dev --watch # Run with file watching (auto-restart on changes)
better test # Alias: better run test
better lint # Alias: better run lint
better dev # Alias: better run dev (watch mode by default)
better build # Alias: better run build
better start # Alias: better run startScripts automatically load
.envand.env.localfiles from the project root.
better why <package> # Trace why a package is installed (dependency paths)
better outdated # Check for newer versions on npm registry
better dedupe # Detect duplicate packages with dedup analysis
better license # Scan all package licenses
better license --allow MIT,ISC # Allow only specific licenses
better license --deny GPL-3.0 # Deny specific licenses
better audit # Security vulnerability scan via OSV.dev
better audit --min-severity high # Filter by severityHealth & Diagnostics
better doctor # Health score (0-100) with actionable findings
better doctor --threshold 80 # Fail if score below threshold
better benchmark # Comparative install timing across package managers
better benchmark --rounds 5 # Number of benchmark rounds
better benchmark --pm npm,bun # Select package managers to compare
better env # Show Node.js version, platform, project info
better env check # Validate engines constraints from package.jsonCache Management
better cache stats # Cache size, package count, storage breakdown
better cache gc # Garbage collect old entries
better cache gc --max-age 30 # Remove entries older than N days
better cache gc --dry-run # Preview what would be removedControl which packages can run lifecycle scripts (preinstall, install, postinstall, prepare):
better scripts scan # Scan node_modules for lifecycle scripts
better scripts allow <package> # Whitelist a package
better scripts block <package> # Blacklist a packagePolicy stored in .better-scripts.json — configure trusted scopes, allowed/blocked packages, and permitted script types.
Automated dependency health scoring with configurable rules:
better policy check # Run rules → score 0-100
better policy init # Generate .betterrc.json with defaults| Rule | Default | Severity |
|---|---|---|
no-deprecated |
enabled | warning (-5) |
max-duplicates |
3 instances | warning (-5) |
max-depth |
15 levels | warning (-5) |
Fails CI if score < threshold (default: 70). Supports waivers per-package.
Deterministic lockfile verification for CI:
better lock generate # Hash lockfile + platform → better.lock.json
better lock verify # Verify nothing changed (exit 1 on drift)Cache key = SHA-256(lockfile_hash + platform + arch + node_major).
Monorepo-native with topological ordering:
better workspace list # List packages with inter-dependencies
better workspace graph # Topological sort + parallelizable levels
better workspace changed --since HEAD~1 # Git-aware change detection
better workspace run "npm test" # Execute in dependency orderReads package.json#workspaces globs. Uses Kahn's algorithm with cycle detection.
Software Bill of Materials for supply chain compliance:
better sbom # CycloneDX 1.5 JSON (default)
better sbom --format spdx # SPDX 2.3 JSONIncludes PURL identifiers (pkg:npm/name@version), license data, and integrity hashes.
Zero-config .npmrc integration:
# .npmrc
@myorg:registry=https://npm.myorg.com/
//npm.myorg.com/:_authToken=${NPM_TOKEN}
Automatically detected during better install — scoped registries, auth tokens, and NPM_CONFIG_REGISTRY env var.
Developer Tools
better hooks install # Install git hooks (from package.json#better.hooks)
better exec <script.ts> # Run TS/JS (tsx > esbuild-runner > swc-node > ts-node > node)
better init # Initialize a new project
better init --template react # Scaffold React + Vite + TypeScript
better init --template next # Scaffold Next.js + TypeScript
better init --template express # Scaffold Express + TypeScriptGit Hooks — configure in package.json:
{
"better": {
"hooks": {
"pre-commit": "better-core run lint",
"pre-push": "better-core run test",
"commit-msg": "conventional-commit"
}
}
}| Alias | Expands to |
|---|---|
better i |
better install |
better t |
better run test |
better x |
better exec |
better ws |
better workspace |
better dedup |
better dedupe |
better bench |
better benchmark |
All commands output structured JSON for piping and automation.
graph TB
subgraph "CLI Layer"
A["bin/better.js<br><sub>Node.js entry</sub>"] --> B["src/cli.js<br><sub>Command router</sub>"]
B --> C["src/lib/core.js<br><sub>Rust bridge</sub>"]
end
subgraph "Rust Core (25 commands)"
D["main.rs<br><sub>CLI parser + dispatch</sub>"]
E["lib.rs<br><sub>Core engine</sub>"]
D --> E
end
subgraph "Engine"
E --> F["Resolve<br><sub>lockfile parser</sub>"]
E --> G["Fetch<br><sub>parallel downloads</sub>"]
E --> H["Materialize<br><sub>clonefile/CAS/copy</sub>"]
E --> I["Analysis<br><sub>license, audit, dedupe</sub>"]
E --> J["Enterprise<br><sub>policy, SBOM, workspace</sub>"]
end
C --> D
B --> K["JS Engine<br><sub>fallback</sub>"]
style D fill:#0f0f23,stroke:#00d4aa,color:#fff
style E fill:#0f0f23,stroke:#00d4aa,color:#fff
style F fill:#1a1a3e,stroke:#00b4d8,color:#fff
style G fill:#1a1a3e,stroke:#00b4d8,color:#fff
style H fill:#1a1a3e,stroke:#00b4d8,color:#fff
style I fill:#1a1a3e,stroke:#00b4d8,color:#fff
style J fill:#1a1a3e,stroke:#00b4d8,color:#fff
crates/
better-core/ Pure Rust binary
src/lib.rs Core library (resolve, fetch, materialize, CAS, bin links,
license scan, audit, outdated, doctor, benchmark,
scripts policy, workspace, SBOM, lock fingerprint, ...)
src/main.rs CLI binary (25 commands + aliases, watch mode, templates)
better-napi/ Node.js native addon (NAPI bridge)
apps/
landing/ Next.js landing page
# Build Rust core
cd crates && cargo build --release -p better-core
# Run tests
node --test test/better-engine.test.js
# Lint & format
npm run lint
npm run format:checkMIT License