⚠️ This plugin is currently in beta
Tested end-to-end (install + LSP attach + cold-start survival) with cspell-lsp (LSP server) and prettier (formatter with native platform binary resolution), on Arch Linux. Has zero automated test coverage
When node is not found on $PATH, swapson.nvim creates a shell wrapper at
<mason_install_root>/bin/node that delegates to bun, so npm-published
packages with #!/usr/bin/env node shebangs still resolve
A companion plugin for mason.nvim that routes package installs through faster alternative package managers instead of the defaults (npm, pip).
| mason manager | Default tool | Swapped tool |
|---|---|---|
| npm | npm | bun |
| pip (pypi) | pip | uv |
bun add is significantly faster than npm install for installing npm packages.
Since mason.nvim installs hundreds of LSP servers, linters, and formatters from
npm, using bun cuts install time dramatically on a fresh setup.
uv pip install is significantly faster than pip install for Python packages,
and uv venv creates virtual environments much faster than python -m venv.
mason.nvim's maintainers have (reasonably) declined to add native alternative toolchain support upstream, as it would introduce dependencies on external toolchains with overlapping but not identical semantics.
swapson.nvim monkeypatches mason.nvim's internal manager modules at runtime,
replacing the init, install, and uninstall functions with tool-specific
alternatives.
This is the same technique used by mason-lspconfig.nvim and mason-tool-installer.nvim to extend mason.nvim without forking it.
The patches are applied to the module tables cached in package.loaded, which
every mason.nvim internal that requires the same module path shares. No files are
modified.
bun installed and on $PATH (for npm swaps)uv installed and on $PATH (for pip swaps)The recommended shorthand is opts = {...}, since it's simpler when no extra
logic beyond setup() is needed:
{
"Senal-D-A-Gunaratna/swapson.nvim",
dependencies = {
"mason-org/mason.nvim",
},
opts = {
npm = {
enabled = true,
tool = "bun",
patch_version_lookup = true,
},
pip = {
enabled = true,
tool = "uv",
},
},
}
The opts form is safe to use regardless of load order. swapson.nvim's
setup() includes a load-order safety guard: it checks
require("mason").has_setup before applying any patches. If mason.nvim has not
completed its own setup yet, swapson defers patching via vim.schedule() and
retries once. This ensures patches are only applied against a fully initialized
mason.nvim state.
The dependencies key ensures mason.nvim loads before swapson.nvim, which is
required since swapson.nvim patches mason.nvim's already-loaded modules.
Omitting any field falls back to the defaults inside init.lua.
require("swapson").setup(opts) accepts an optional table:
require("swapson").setup({
npm = {
enabled = true, -- set false to skip npm->bun patching
tool = "bun", -- the bun binary name/path
-- Whether to also patch mason's npm version-lookup client
-- (npm view --json) — needed on systems with NO npm installed at all,
-- since version lookups would otherwise still shell out to npm
patch_version_lookup = true,
},
pip = {
enabled = true, -- set false to skip pip->uv patching
tool = "uv", -- the uv binary name/path
},
})
Each manager falls back gracefully to mason's default behavior if its
configured tool is not found on $PATH, with a vim.notify() warning.
Run :checkhealth swapson to diagnose your swapson.nvim setup:
bun and uv binaries are on $PATHnode is available or a bun-based node shim will be createdpatch_version_lookup is active (registry API vs. shelling out to npm)The health check is read-only: it never creates, modifies, or removes files.
Call require("swapson").restore() to restore all mason.nvim manager functions
to their originals. Useful for A/B testing or if a swapped install misbehaves.
swapson.nvim patches private Lua modules internal to mason.nvim
(e.g. mason-core.installer.managers.npm,
mason-core.installer.managers.pypi, and optionally
mason.providers.client.npm). These modules are not part of mason.nvim's
public API. Future mason.nvim releases may refactor or rename them without a
semver-major bump, which could break swapson.nvim silently.
If swapson.nvim stops working after a mason.nvim update, check mason.nvim's changelog for internal module changes and file an issue.
The following packages have been verified end-to-end (install via bun, LSP/tool attach, cold-start survival) on Arch Linux:
#!/usr/bin/env node shebangs via
the node shim and that mason's bin-linking step produces a working symlink
chainPackages with node-gyp native addons, npm-specific postinstall hooks, or
deep scoped dependency trees remain unverified.
MIT