Skip to content

pedrosousa13/lnpm

Repository files navigation

lnpm

Fast, reliable local npm package development tool — a better alternative to yalc.

CI Go Report Card License: MIT

Features

  • Blazing fast — Reflink/CoW + hard links for instant operations on large packages
  • Smart linking — Automatically uses the fastest method: reflink → hardlink → parallel copy
  • Watch mode — Auto-sync changes to all linked projects
  • Monorepo support — Publish all workspace packages at once
  • Cross-platform — Works on Linux, macOS, and Windows
  • All package managers — npm, yarn, pnpm, and bun
  • Full visibility — Know exactly what's linked where

Installation

Quick Install (Linux/macOS)

curl -fsSL https://raw.githubusercontent.com/pedrosousa13/lnpm/main/install.sh | sh

Go

go install github.com/pedrosousa13/lnpm/cmd/lnpm@latest

From Source

git clone https://github.com/pedrosousa13/lnpm.git
cd lnpm
make install

Quick Start

# In your library package
cd ~/code/my-library
lnpm publish

# In your app that uses the library
cd ~/code/my-app
lnpm add my-library

# Make changes to my-library, then push updates
cd ~/code/my-library
lnpm push

# Or use watch mode for auto-sync
lnpm watch

Documentation

  • Monorepo Guide — Turborepo, Nx, PNPM/NPM/Yarn workspaces integration
  • Architecture — System design and implementation details
  • Changelog — Version history and updates
  • Roadmap — Planned features and improvements

Commands

Command Description
lnpm publish Publish package to local store
lnpm add <pkg> Add package from store to project
lnpm remove <pkg> Remove linked package
lnpm push Push changes to all linked projects
lnpm watch Auto-sync on file changes
lnpm status Show current project's links
lnpm list List packages in store
lnpm doctor Diagnose issues
lnpm gc Garbage collect unused packages
lnpm retreat Remove all lnpm changes
lnpm config View/edit configuration
lnpm completion Generate shell completions

Usage Examples

Basic Workflow

# Publish a package
lnpm publish

# Add to a project
lnpm add my-package

# Push updates after making changes
lnpm push

# Or watch for auto-sync
lnpm watch --exec "npm run build"

Monorepo Support

lnpm integrates seamlessly with Turborepo, Nx, and all workspace managers:

# lnpm is installed globally (one-time system install)
# See installation section above

# Publish all workspace packages
lnpm publish --all

# Watch and rebuild with your task runner
lnpm watch --exec "turbo run build --filter=@my/ui"
lnpm watch --exec "nx build my-lib"

📖 See MONOREPO.md for complete guides on:

  • Turborepo integration
  • Nx integration
  • PNPM/NPM/Yarn workspaces
  • Best practices and troubleshooting

Before Publishing to npm

# Remove all lnpm links and restore original dependencies
lnpm retreat --force
npm install  # Restore original packages
npm publish

Shell Completions

Quick setup (recommended):

lnpm completion install

This auto-detects your shell and installs completions. Follow the on-screen instructions to enable.

Alternative - Dynamic loading (add to shell config):

# Zsh (~/.zshrc)
eval "$(lnpm completion zsh)"

# Bash (~/.bashrc)
eval "$(lnpm completion bash)"

# Fish (~/.config/fish/config.fish)
lnpm completion fish | source

Manual installation:

# Zsh
lnpm completion zsh > ~/.zsh/completions/_lnpm

# Bash
lnpm completion bash > /etc/bash_completion.d/lnpm

# Fish
lnpm completion fish > ~/.config/fish/completions/lnpm.fish

Configuration

Configuration file: ~/.lnpm/config.yaml

# Custom store location (default: ~/.lnpm)
store_path: /path/to/store

# Link mode: "hardlink" (try reflink/hardlink) or "copy" (force copy)
# Default: hardlink
link_mode: hardlink

# Watch debounce in milliseconds (default: 100)
debounce_ms: 100

# Auto-manage .gitignore (add/remove .lnpm/ entry)
# Default: true
manage_gitignore: true

# Patterns to always ignore
default_ignore:
  - node_modules
  - .git
  - "*.log"

# Build scripts and hooks
hooks:
  # Skip prepare scripts (prepare, prepublishOnly, prepack)
  skip_prepare: false      # Default: false (run scripts)

  # Skip post-add hook (npm install after add)
  skip_post_add: false     # Default: false (run npm install)

  # Custom hooks (optional)
  pre_publish: npm run build
  post_add: npm install

View/modify config:

lnpm config                     # Show all
lnpm config store_path          # Get value
lnpm config store_path /data    # Set value
lnpm config --path              # Show config file path

Build Workflows & Hooks

lnpm automatically runs build scripts and dependency installation to ensure packages work correctly when linked.

Prepare Scripts

Before publishing or pushing, lnpm runs these scripts from your package.json (in order of precedence):

  1. prepare — General build script
  2. prepublishOnly — Runs only on publish
  3. prepack — Runs before packing files

Example package.json:

{
  "name": "my-library",
  "scripts": {
    "build": "tsc",
    "prepare": "npm run build"
  }
}

Commands:

lnpm publish              # Runs prepare, then publishes
lnpm push                 # Runs prepare, then pushes
lnpm publish --skip-hooks # Skip prepare scripts

Post-Add Hook

After adding a package, lnpm automatically runs npm install (or your package manager) to resolve peer dependencies and install linked package dependencies.

lnpm add my-package       # Adds package, then runs npm install
lnpm add --skip-hooks     # Skip post-add npm install

Package Validation

lnpm validates packages before publishing:

  • Checks package.json has name and version
  • Verifies main entry point exists (if declared)
lnpm publish                  # With validation
lnpm publish --skip-validation # Skip validation (for broken packages)

TypeScript Workflow Example

# In your TypeScript library
cd my-library
# package.json has "prepare": "tsc"

lnpm publish    # Automatically builds TypeScript → dist/

# In your app
cd my-app
lnpm add my-library   # Links and runs npm install

# Make changes to library
cd my-library
# Edit src/index.ts
lnpm push       # Rebuilds and updates all linked projects

Troubleshooting

Husky/git hooks fail during npm install:

  • lnpm strips prepare and prepublish scripts from stored packages (like yalc)
  • If you see husky errors, re-publish the package: lnpm publish

Duplicate React or other peer dependency issues:

  • Don't use --install flag; run npm install manually with your preferred flags
  • Or configure npm: npm config set legacy-peer-deps true

npm ERESOLVE peer dependency errors:

  • npm has a bug where file: dependencies show as @undefined (npm/cli#2199)
  • When using --install, lnpm uses --legacy-peer-deps automatically
  • Or run npm install --legacy-peer-deps manually

Retreat restores wrong version:

  • Fixed in latest version - lnpm now properly tracks original versions
  • If stuck, manually edit package.json and delete lnpm.lock

Debugging

Enable debug mode for verbose logging:

# Flag
lnpm --debug publish
lnpm -d status

# Environment variable
LNPM_DEBUG=1 lnpm publish

Debug output goes to stderr with timestamps, useful for diagnosing slow operations or unexpected behavior.

How It Works

  1. Publish — Uses npm pack rules to determine files, strips lifecycle scripts (prepare/prepublish), then links or copies to ~/.lnpm/store/{name}/{hash}/
  2. Add — Creates reflinks or hard links from store to project/.lnpm/{package}/, updates package.json to file:.lnpm/{package}
  3. Symlink — Links node_modules/{package}.lnpm/{package}
  4. Push/Watch — Updates store and re-links changed files
  5. Auto .gitignore — Optionally manages .lnpm/ in .gitignore (enabled by default)

Note: Unlike some tools, lnpm does NOT run npm install automatically (matches yalc). Use --install flag or run manually if needed.

Source Package          Store                    Project
──────────────          ─────                    ───────
src/index.ts    ──►   (reflink/hardlink)
dist/index.js   ──►     ~/.lnpm/store/      ══► .lnpm/pkg/     ──► node_modules/pkg
package.json    ──►       pkg/abc123/      (reflink/hardlink)     (symlink)

File Filtering

lnpm uses npm's standard packing rules (via npm pack --dry-run) to determine which files to include, ensuring consistency with actual npm publish behavior. This means:

  • Respects package.json files field
  • Honors .npmignore or falls back to .gitignore
  • Follows npm's default exclusions (.git, node_modules, etc.)
  • Additional safety: Explicit .git filtering prevents any VCS files from being linked
  • Automatic fallback to custom filtering if npm is unavailable

This approach prevents issues with git hooks (like Husky) running in linked packages and ensures lnpm behaves identically to npm publish.

Automatic .gitignore Management

lnpm automatically manages .gitignore entries to prevent committing linked packages (enabled by default, configurable via manage_gitignore: false):

  • On lnpm add — Adds .lnpm/ to .gitignore with marker comment # Added by lnpm
  • On lnpm retreat — Removes .lnpm/ entry and marker from .gitignore
  • Smart detection — Skips if pattern already exists
  • Atomic writes — Uses temp file + rename to prevent corruption
  • Configurable — Set manage_gitignore: false in config to disable

Smart Linking Strategy

lnpm uses an intelligent priority system for maximum performance:

Priority Order: Reflink → Hard Link → Parallel Copy

Method Speed Platform Support Disk Usage
Reflink (CoW) Instant macOS APFS, Linux Btrfs/XFS Zero (copy-on-write)
Hard Link Instant Same filesystem Zero (shared inodes)
Parallel Copy Fast Always works Full copy (8 workers)

Benefits:

  • 10,000+ files? Instant with reflink or hard links
  • 🔄 Copy-on-write — Modify files safely without affecting store
  • 🚀 Parallel copying — 4-8x faster when copying is needed
  • 💾 Space efficient — No duplication on modern filesystems

lnpm automatically detects the best method and falls back gracefully with helpful warnings.

Comparison with yalc

Feature lnpm yalc
Link method Reflink → Hard link → Parallel copy Sequential copy only
Large packages (10k+ files) Instant (~5ms) on APFS/Btrfs Slow (~5s+)
Watch mode Built-in Requires chokidar
State tracking bbolt database Hash files
Monorepo Native support Manual
Speed ~10ms startup ~100ms startup
Cross-filesystem Parallel copy (4-8x faster) Sequential copy
Visibility lnpm status Limited

Platform Support

  • Linux — amd64, arm64
  • macOS — amd64 (Intel), arm64 (Apple Silicon)
  • Windows — amd64

Requirements

  • Go 1.22+ (for building from source)
  • Node.js project with package.json

Contributing

Contributions are welcome! Please read our contributing guidelines first.

# Clone and build
git clone https://github.com/pedrosousa13/lnpm.git
cd lnpm
make deps
make build
make test

License

MIT License — see LICENSE for details.


Disclaimer

Note: This project was built with assistance from Claude (Anthropic's AI assistant). The architecture, implementation, and documentation were developed through an AI-assisted development process. While the code has been reviewed and tested, users should evaluate it according to their own requirements and standards before use in production environments.


Acknowledgments

About

No description, website, or topics provided.

Resources

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •