A local NPM registry system using Verdaccio for completely offline package management. This allows you to cache NPM packages locally and work without internet access or the global NPM registry.
./npm-cache/ # Project directory
├── serve # Start the local registry server
├── add-npm # Download and cache NPM packages
├── scan_projects # Scan projects and cache their dependencies
├── add-package # Add a local package to the cache
├── config.yaml # Verdaccio configuration
└── package.json # Project dependencies
~/npm-cache/ # Storage directory (where packages are cached)
-
Install dependencies (already done):
cd ./npm-cache npm install -
Ensure scripts are executable (already done):
chmod +x serve add-npm scan_projects add-package
./npm-cache/serveThis will:
- Start Verdaccio on
http://localhost:4873 - Store packages in
~/npm-cache - Display the web interface at
http://localhost:4873
Leave this running in a terminal window.
In a new terminal, set your NPM registry:
Option A: Environment variable (temporary)
export NPM_CONFIG_REGISTRY=http://localhost:4873/Option B: NPM config (persistent)
npm config set registry http://localhost:4873/Option C: Project-specific (.npmrc)
Create a .npmrc file in your project:
registry=http://localhost:4873/
./npm-cache/add-npm <package-name>[@version-spec]Supports version ranges and pinning:
./npm-cache/add-npm express # Latest version
./npm-cache/add-npm express@4.18.0 # Exact version (pinned)
./npm-cache/add-npm express@^4.18.0 # Caret range (^)
./npm-cache/add-npm express@~4.18.0 # Tilde range (~)
./npm-cache/add-npm @types/node@>=20.0.0 # Greater than or equal
./npm-cache/add-npm @types/node # Latest versionThis will:
- Download the package from NPM, respecting the exact version spec
- Cache it in
~/npm-cache - Recursively cache all dependencies with their pinned versions
./npm-cache/scan_projects [directory]Examples:
./npm-cache/scan_projects # Scan current directory
./npm-cache/scan_projects ~/Projects # Scan specific directoryThis will:
- Find all
package.jsonfiles (excluding node_modules) - Extract all dependencies with their exact version specs from package.json
- Cache each unique package@version combination
- Respects pinned versions and version ranges (^, ~, >=, etc.)
- If different projects use different versions of the same package, all versions are cached
./npm-cache/add-package <path-to-package>Examples:
./npm-cache/add-package ./my-local-package
./npm-cache/add-package ~/Projects/my-libThis will:
- Pack the local package using
npm pack - Store it in the local cache
- Make it available for installation
Once the registry is running and configured, use npm normally:
npm install express
npm installPackages will be fetched from your local cache instead of the global NPM registry.
- Storage:
~/npm-cache- All packages are stored here - Uplinks: Empty (
{}) - No upstream registries (fully offline) - Packages:
access: $all- Anyone can read packagespublish: $authenticated- Only authenticated users can publishproxy: []- No proxying to external registries
- Server: Listens on
http://0.0.0.0:4873
# Set registry
export NPM_CONFIG_REGISTRY=http://localhost:4873/
# Alternative for yarn
export YARN_REGISTRY=http://localhost:4873/# Using environment variable
unset NPM_CONFIG_REGISTRY
# Using npm config
npm config delete registry
# Or manually set to default
npm config set registry https://registry.npmjs.org/# 1. Start the local registry
./npm-cache/serve &
# 2. Configure NPM
export NPM_CONFIG_REGISTRY=http://localhost:4873/
# 3. Scan and cache all dependencies from your projects
./npm-cache/scan_projects ~/Projects
# 4. Now you can work offline - all packages are cached# Registry is running and configured
# Add a specific package
./npm-cache/add-npm lodash
# Now install it in your project
cd ~/Projects/my-app
npm install lodash# Add your local package to the cache
./npm-cache/add-package ~/Projects/my-library
# Install it in another project
cd ~/Projects/my-app
npm install my-library- Ensure the registry server is running (
./npm-cache/serve) - Verify NPM is configured:
npm config get registry - Check if the package was cached:
ls ~/npm-cache
- Make sure
./npm-cache/serveis running - Check if port 4873 is available:
lsof -i :4873
- First login:
npm adduser --registry http://localhost:4873 - Create a user when prompted
# Stop the server (Ctrl+C)
rm -rf ~/npm-cache
# Restart the server
./npm-cache/serve- Version pinning is fully respected: The scripts honor exact versions and ranges (^, ~, >=) from package.json files
- The
add-npmscript recursively downloads dependencies with their pinned versions scan_projectscaches the exact version specs specified in your package.json files- Scoped packages (e.g.,
@types/node) are fully supported - The system is designed for offline use -
uplinks: {}ensures no external registry calls - For production use, consider using HTTPS and proper authentication
The system intelligently avoids duplicate downloads at multiple levels:
- scan_projects: Deduplicates package@version specs across all scanned projects
- In-memory cache: Within a single run, packages are only downloaded once
- On-disk cache: Checks if packages already exist before downloading (works across multiple runs)
You can safely:
- Run
scan_projectsmultiple times - already cached packages are skipped - Add individual packages that may already be cached - they'll be skipped if present
- Dependencies shared across packages are only downloaded once
- No automatic package updates - you must manually re-cache packages when you want newer versions
- Authentication is basic (htpasswd file)