local-package-tester
v1.1.0
Published
Local package testing without symlink headaches. A tarball-based npm link replacement that works with Vite, Nuxt, and modern bundlers.
Downloads
22
Maintainers
Readme
lpt — Local Package Tester
Test local packages without symlink headaches. lpt uses npm pack + npm install to create real tarball installations that work with Vite, Nuxt, Next.js, SvelteKit, Astro, and every other modern bundler.
Why not npm link?
npm link creates symlinks. Symlinks break with:
| Problem | npm link | yalc | lpt | |---------|----------|------|-----| | Vite/Nuxt/Next.js resolve errors | Broken | Works | Works | | Duplicate peer dependencies | Common | Rare | Never | | node_modules nesting issues | Yes | Sometimes | Never | | Works with all package managers | npm only | npm/yarn | npm/pnpm/yarn/bun | | Multiple targets at once | Manual | Manual | Built-in | | File watching + auto-rebuild | No | Plugin | Built-in | | HMR triggering | No | No | Auto-detected |
lpt installs your package the same way your users will — as a tarball. No symlinks, no resolution hacks, no surprises.
Quick Start
# Install globally
npm install -g local-package-tester
# In your package directory, link to a target project
cd ~/projects/my-ui-library
lpt link ../my-app
# Build, pack, and install in one step
lpt dev
# Or watch for changes and auto-rebuild
lpt watchCommands
lpt link <target>
Link the current package to a target project. Run from your package's root directory.
# Link to one project
lpt link ../my-app
# Link to multiple projects
lpt link ../my-app
lpt link ../my-other-applpt unlink [target]
Remove a link. Omit the target to remove all links for the current package.
# Remove specific target
lpt unlink ../my-app
# Remove all targets
lpt unlinklpt dev
One-shot build + pack + install to all linked targets.
lpt dev
# Preview what would happen without executing
lpt dev --dry-runlpt watch
Watch for file changes and auto-rebuild. Includes debouncing and a rebuild queue so rapid saves don't cause overlapping builds.
lpt watch
# Custom watch paths (comma-separated)
lpt watch --paths "src/**/*,lib/**/*"
# Custom debounce interval
lpt watch --debounce 500
# Preview configuration
lpt watch --dry-runlpt list
Show all linked packages and their targets.
lpt listlpt status
Health check for all links. Shows validation status, last install time, detected package manager, build command, and watch paths.
lpt statusOutput:
Package: @myorg/ui-components
Source: ~/projects/ui-components (valid)
Targets:
→ ~/projects/web-app (valid, last installed 2m ago)
→ ~/projects/mobile-app (valid, never installed)
Package manager: pnpm (detected)
Watch paths: src/**/* lib/**/* package.jsonGlobal Flags
| Flag | Description |
|------|-------------|
| --verbose | Show detailed output including build logs |
| --quiet | Only show errors |
| --version | Show version |
| --help | Show help |
Configuration
.lptrc
Create a .lptrc file in your package root to customize behaviour:
{
"watch": ["src/**/*", "lib/**/*", "package.json"],
"buildCommand": "npm run build:lib",
"skipBuild": false,
"packageManager": "auto",
"debounce": 300,
"hmr": {
"strategy": "auto",
"files": ["src/trigger.ts"]
},
"hooks": {
"preBuild": "npm run lint",
"postInstall": "echo done"
}
}| Option | Default | Description |
|--------|---------|-------------|
| watch | ["src/**/*", "lib/**/*", "package.json"] | Glob patterns to watch for changes |
| buildCommand | Auto-detected (npm run build, etc.) | Custom build command |
| skipBuild | false | Skip the build step entirely |
| packageManager | "auto" | Force a package manager (npm, pnpm, yarn, bun) |
| debounce | 300 | Milliseconds to wait before rebuilding after a change |
| hmr.strategy | "auto" | HMR trigger strategy: "auto", "touch", or "none" |
| hmr.files | — | Files to touch when strategy is "touch" |
| hooks.preBuild | — | Command to run before building |
| hooks.postInstall | — | Command to run after installing |
Package Manager Detection
lpt automatically detects the package manager for both source and target projects:
- Lock file (
pnpm-lock.yaml,yarn.lock,bun.lockb,package-lock.json) packageManagerfield inpackage.json(corepack)- Falls back to
npm
The source and target can use different package managers — lpt handles the translation.
HMR Triggering
After installing, lpt automatically triggers hot module replacement by touching a framework-specific file:
| Framework | File touched |
|-----------|-------------|
| Nuxt | app.vue |
| Vite | vite.config.ts |
| Next.js | next.config.js |
| SvelteKit | svelte.config.js |
| Astro | astro.config.mjs |
Set hmr.strategy to "none" to disable, or "touch" with custom hmr.files to control which files are touched.
How It Works
lpt dev
1. Build → npm run build (in your package)
2. Pack → npm pack (creates a tarball)
3. Install → npm install pkg.tgz (in each target)
4. HMR → touch app.vue (triggers hot reload)
5. Cleanup → remove tarballThis is the same installation path your users take when they npm install your published package. No symlinks, no resolution quirks.
