a fast neovim plugin manager. single rust binary, no neovim required to install. declarative pluvgo.toml, deterministic lockfile, parallel git, lua runtime shim.
every existing neovim plugin manager (lazy.nvim, mini.nvim, paq-nvim, vim-plug, rocks.nvim) runs inside neovim, in lua. that's fine if you live in your editor, but it puts a hard dependency on having neovim around to install plugins. fresh machine, ci runner, dockerfile, dotfiles bootstrap, ansible playbook, the answer is "first install neovim, then run a bunch of lua to install plugins, then start neovim again."
pluvgo decouples the install step from the editor:
brew install pluvgo # or: cargo install pluvgo
pluvgo install # clone everything in pluvgo.toml, write the lock
nvim # plugins are already on runtimepath via the lua shimthe rust binary owns clone, lockfile, parallelism. neovim only loads a tiny generated lua shim (pluvgo_runtime.lua, ~15 lines) that does vim.opt.runtimepath:prepend(...) for each plugin. nothing fancy, no event hooks, no opaque scheduler, lua for the runtime side and rust for the plumbing.
cargo install pluvgoa precompiled binary is on the github releases page once the next tag lands.
pluvgo init # writes a starter ~/.config/nvim/pluvgo.toml
$EDITOR ~/.config/nvim/pluvgo.toml
pluvgo installthen add one line to your init.lua:
require('pluvgo_runtime')that's it. pluvgo install can run in ci before nvim is ever invoked, the runtime shim works at startup time without any further plumbing.
# install_dir = "$XDG_DATA_HOME/nvim/pluvgo" default
# shim_path = "$XDG_CONFIG_HOME/nvim/lua/pluvgo_runtime.lua" default
[[plugin]]
repo = "nvim-treesitter/nvim-treesitter"
build = "make"
[[plugin]]
repo = "nvim-telescope/telescope.nvim"
rev = "0.1.x"
[[plugin]]
repo = "folke/tokyonight.nvim"
[[plugin]]
repo = "neovim/nvim-lspconfig"
enabled = false # cloned, but not added to runtimepathrev is a branch, tag, or sha. the install path uses git fetch --depth=1 against that ref. omit it and pluvgo tracks the upstream default branch.
| command | what it does |
|---|---|
pluvgo init |
scaffold a starter pluvgo.toml |
pluvgo install |
clone every plugin, write pluvgo.lock, regenerate the lua shim |
pluvgo update |
pull each plugin to its branch tip (or fetch its tag/sha), refresh the lock |
pluvgo lock |
rewrite the lockfile from the on-disk shas without touching the network |
pluvgo list |
print installed plugins with their short sha |
pluvgo shim |
regenerate the lua shim from the current spec and lock |
pluvgo doctor |
print resolved paths plus the detected nvim/git version |
pluvgo.lock is a TOML file you commit alongside pluvgo.toml:
[plugins."tokyonight.nvim"]
repo = "folke/tokyonight.nvim"
rev = "main"
sha = "cdc07ac78467a233fd62c493de29a17e0cf2b2b6"pluvgo install resolves to whatever the spec says today (so a fresh clone tracks the upstream branch tip). when you want bit-identical reproducible installs, run pluvgo install in ci, commit the lock, and pin rev to the resolved sha in the spec.
- not a runtime loader. neovim still owns lazy-loading and event triggers; pluvgo only generates a
prepend(runtimepath)for each plugin. if you want lazy-loading, layer that yourself in lua, or call into lazy.nvim alongside. - not a luarocks shim. plugins that publish through luarocks are still installed via your existing pipeline.
- not yet a binary release.
cargo install pluvgofor now; a github releases pipeline is coming.
other small rust pieces shipped alongside this one:
bashwardcheckpoint and rewind for bash side-effects in claude codeskill-scanlocal prompt-injection scanner for claude skills, MCP, AGENTS.mdmlkem-rsFIPS 203 ML-KEM (post-quantum kem) in pure rustmlkem-tlsX25519MLKEM768/1024 hybrid kem per draft-ietf-tls-ecdhe-mlkemsklpackage manager for AI agent skills
dual-licensed under MIT or Apache-2.0, at your option.