bun-relink
v0.1.4
Published
Force-symlink local package source into node_modules so it survives every `bun install` — fixes bun's local-linking gaps (clobbered `bun link`, broken `file:`, workspace semver fallback) during dev.
Maintainers
Readme
bun-relink
Force-symlink local package source into node_modules so local source always wins during dev, surviving every bun install.
Bun 1.3.x doesn't reliably persist a local source symlink: bun link gets clobbered on reinstall, file:../path is broken, and the workspace approach falls back to the registry version when the local source's version is below the declared semver range. bun-relink ignores semver and re-establishes the symlink — with zero leakage into shared repos or CI.
How it works
Run bun-relink from inside any repo. It:
- Reads machine-level config
~/.bun-relink.json. - For each configured package, resolves the local source path (skips silently if it doesn't exist on this machine).
- Only links a package the current repo actually declares (
dependencies/devDependencies/peerDependencies) — never pollutes unrelated repos. - Force-symlinks
node_modules/<pkg>→ source (handles@scope/name), removing any existing dir/symlink first. - Is idempotent (skips when already correctly linked) and logs each link it makes.
No config → clean no-op. No node_modules → no-op. It never crashes an install (always exits 0).
Config
~/.bun-relink.json — package name → absolute local source path (~ is expanded):
{
"my-lib": "/Users/me/Projects/my-lib",
"@scope/pkg": "~/Projects/pkg"
}This file is machine-local (never committed), so it's safe: a teammate or CI without the file just gets the registry version.
Install
Put the binary on PATH, then run setup — it installs the zsh wrapper and seeds the config for you:
bun add -g bun-relink # global install from npm
bun-relink setup # installs the zsh bun() wrapper + seeds ~/.bun-relink.json
source ~/.zshrc # (or open a new shell)setup is idempotent: it manages a marker-fenced block in ~/.zshrc (migrating any older hand-added wrapper), never duplicates it, and leaves an existing ~/.bun-relink.json untouched.
Add a link entry without hand-editing JSON — the package name is inferred from the source's package.json:
bun-relink add ~/Projects/my-lib # name read from my-lib/package.json
bun-relink add my-lib ~/Projects/my-lib # or pass the name explicitlyThe wrapper it installs runs bun-relink automatically after every install-mutating command:
bun() {
case "$1" in
install|i|add|remove|rm) command bun "$@" && bun-relink ;;
*) command bun "$@" ;;
esac
}Programmatic
import { Relinker } from 'bun-relink';
await new Relinker({ cwd: '/path/to/repo' }).run();