A thin layer on top of Neovim's native vim.pack, adding support for lazy-loading and the widely adopted lazy.nvim-like declarative spec.
Why zpack? | Commands | Spec Examples | Spec Reference | Tips & Migration
- Neovim 0.12.0+
-- install with vim.pack directly
vim.pack.add({ 'https://github.com/zuqini/zpack.nvim' })-- Make sure to setup `mapleader` and `maplocalleader` before loading
-- zpack.nvim so that keymaps referenced from zpack.Spec are aware
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"
-- automatically import specs from `./lua/plugins/`
require('zpack').setup()Under the default setting, create plugin specs in lua/plugins/:
lua/
plugins/
treesitter.lua
lsp.lua
...
Each file should return a spec or list of specs (see spec examples or spec reference):
-- ./lua/plugins/fundo.lua
return {
'kevinhwang91/nvim-fundo',
dependencies = { "kevinhwang91/promise-async" },
cond = not vim.g.vscode,
version = 'main',
build = function() require('fundo').install() end,
opts = {},
config = function(_, opts)
vim.o.undofile = true
require('fundo').setup(opts)
end,
}zpack provides a single user command, :ZPack, with subcommands. Rename via cmd_name — a short name like Z or Zp is recommended for ease of use (:Z update, :Zp clean).
| Command | Description |
|---|---|
:ZPack[!] update [plugin] |
Update all plugins, or one; ! skips the confirm buffer |
:ZPack[!] restore [plugin] |
Restore plugins to the lockfile state; ! skips the confirm buffer |
:ZPack clean |
Remove plugins no longer in your spec |
:ZPack[!] build [plugin] |
Run a plugin's build hook; ! runs every plugin's build hook |
:ZPack[!] load [plugin] |
Load an unloaded plugin; ! loads all unloaded plugins |
:ZPack[!] delete [plugin] |
Remove a plugin; ! removes all plugins |
:ZPack sync |
Bulk update + clean (lazy.nvim parity) |
:ZPack reload {plugin} |
Re-source a plugin (lazy.nvim parity) |
require('zpack').setup({
-- { import = 'plugins' } -- default import spec if not explicitly passed in via [1] or spec
defaults = {
confirm = true, -- set to false to skip vim.pack install prompts (default: true)
cond = nil, -- global condition for all plugins, e.g. not vim.g.is_vscode (default: nil)
lazy = false, -- make every spec lazy-load by default unless it sets lazy=false (lazy.nvim parity, default: false)
version = nil, -- default version applied when a spec has no version/sem_version/branch/tag/commit (lazy.nvim parity, default: nil)
},
performance = {
vim_loader = true, -- enables vim.loader for faster startup (default: true)
},
cmd_name = 'ZPack', -- name of the user command (default: 'ZPack'). Use as: :ZPack update, :ZPack clean, etc.
-- set a shorter name like 'Z' or 'Zp' for fewer keystrokes (:Z update, :Zp clean)
})Plugin-level settings always take precedence over defaults.
-- automatically import specs from `./lua/plugins/`
require('zpack').setup()
-- or import from a custom directory e.g. `./lua/a/b/plugins/`
require('zpack').setup({ { import = 'a.b.plugins' } })
-- or add your specs inline in setup
require('zpack').setup({
{ 'neovim/nvim-lspconfig', config = function() ... end },
...
{ import = 'plugins.mini' }, -- or additionally import from `./lua/plugins/mini/`
})
-- or via the spec field
require('zpack').setup({
spec = {
{ 'neovim/nvim-lspconfig', config = function() ... end },
...
},
})Neovim 0.12+ includes a built-in package manager (vim.pack) that handles plugin installation, updates, and version management. zpack is a thin layer that adds lazy-loading capabilities and support for a lazy.nvim-like declarative spec while completely leveraging the native infrastructure.
- 'zpack' is completely native
- Install and manage your plugins (including zpack) all within
vim.pack - zpack shares the same native user experience as
vim.pack— cloning, updates, lockfile, and version management. Your editor stays aligned with Neovim core's design philosophy and evolves with it
- Install and manage your plugins (including zpack) all within
- '
pack' is "batteries included"
- Add plugins using the same lazy.nvim spec provided by plugin authors you know and love
- Minimal configurations necessary
- '💤pack' powers up
vim.packwithout the frills- Powerful lazy-loading triggers
- Build triggers for installation/updates
- Plugin management commands
zpack might be for you if:
- you want your plugin management to stay aligned with Neovim core's design philosophy, but you need a bit more out of the box
- you're a lazy.nvim user but don't use most of its advanced features. You just want a light plugin manager that works, backed by what's already built-in
- you want a manager that supports the lazy.nvim specs plugin authors already provide
- you simplified your config to use
vim.packas-is, but you miss lazy-loading, build hooks, plugin management commands, or drop-in lazy plugin specs
As a thin layer, zpack does not provide:
- UI dashboard for your plugins (see Extensions for community solutions)
- Advanced profiling, file-watch / auto-reload, change-detection, etc.
(
dev = truerewrites a spec's source to a local checkout undersetup({ dev = { path } }); live file-watch is out of scope.:ZPack reload {plugin}is a manual command, not an autocmd-driven reload.)
If you're a lazy.nvim user, see Migrating from lazy.nvim
See Spec Examples for a full set of examples covering lazy-loading, version pinning, build hooks, dependencies, and more.
See Spec Reference for the full spec definition, including zpack.Plugin, zpack.EventSpec, and zpack.KeySpec.
See Tips & Migration for lazy.nvim migration guide and compatibility notes for popular plugins (Snacks.nvim dashboard, noice.nvim, etc.).
See Public API for the supported introspection surface used by third-party tooling like dashboards and status UIs. Also available as :help zpack-public-api.
- zshow.nvim — A floating window UI for viewing installed plugins, grouped by load status.
zpack's spec design and several features are inspired by lazy.nvim. Credit to folke for the excellent plugin manager that influenced this project.
zpack's logo is designed by DodolCat.