A layer on top of Neovim's native vim.pack, adding support for lazy-loading and the widely adopted lazy.nvim-like declarative spec.
Requirements: Neovim 0.12+
| Document | Description |
|---|---|
| Getting Started | Quick start guide |
| Installation | Detailed installation options |
| Configuration | All configuration options |
| Plugin Spec | Complete plugin specification reference |
| Lazy Loading | Lazy loading triggers and patterns |
| Commands | CLI commands reference |
| API | Lua API reference |
| Migrating | Migration guide from lazy.nvim |
Add this to the top of your init.lua:
-- Setup leanpack.nvim plugin manager
vim.pack.add({ { src = "https://github.com/ntk148v/leanpack.nvim" } })
-- Setup leanpack with import from lua/plugins/
require("leanpack").setup({
{ import = "plugins" },
defaults = {
lazy = true,
},
performance = {
vim_loader = true,
rtp_prune = true,
},
})Create your plugin specs in lua/plugins/:
-- lua/plugins/treesitter.lua
return {
'nvim-treesitter/nvim-treesitter',
build = ':TSUpdate',
config = function()
require('nvim-treesitter.configs').setup({ highlight = { enable = true } })
end,
}vim.pack (Neovim 0.12+) is a solid native foundation β leanpack builds on top of it, not around it. Here's what you get:
| Feature | bare vim.pack |
leanpack.nvim |
|---|---|---|
| Spec format | Raw vim.pack.add() calls |
lazy.nvim-compatible declarative spec ('user/repo', opts = {}, config = fn) |
| Lazy-loading | Manual β write your own VimEnter queues and autocmds per plugin | Built-in triggers: event, cmd, keys, ft, module (require-based) |
| Dependencies | Manual ordering | Automatic resolution with topological sort |
| Build hooks | None | build = ':TSUpdate' or build = function() ... end |
| Plugin management UI | None | :Leanpack floating window with filtering, load/update/delete |
| Install/Update | Manual vim.pack.add() + restart |
Background jobs via headless Neovim, no restart needed |
| ftdetect sourcing | Manual | Automatic for lazy-loaded plugins |
| Config from multiple files | Manual require chains |
{ import = "plugins" } auto-discovers lua/plugins/*.lua |
In short: if you're happy writing ~250 lines of helper code (lazyload queues, deep merge, local dev support) around vim.pack for every config, you don't need leanpack. If you want a lazy.nvim-style declarative experience on top of native vim.pack, that's exactly what this is.
- Native Core: Builds on top of
vim.packβ no custom package management, no fork. - Lazy-loading: Load plugins on demand via events, commands, keymaps, filetypes, or
require(). - lazy.nvim Compatible: Uses the same declarative spec format you already know.
- Dependency Management: Automatic resolution and topological loading.
- Build Hooks: Run commands or Lua functions on install/update.
- Performance: Built-in
vim.loaderintegration and RTP pruning.
:Leanpack- Open the UI (supports/filtering):Leanpack sync- Sync all plugins (update + clean):Leanpack update- Update all or specific plugin:Leanpack clean- Remove unused plugins:Leanpack build!- Run all build hooks:Leanpack load!- Load all pending plugins
See Commands for details.
require('leanpack').setup({
defaults = {
confirm = true,
},
performance = {
vim_loader = true,
rtp_prune = true, -- Disable built-in plugins for faster startup
},
})See Configuration for more options.
Most of your lazy.nvim plugin specs will work as-is with leanpack. Key differences are documented in Migrating.
- version pinning: leanpack's
versionfield supports both semantic versioning (e.g.,1.*) and literal git references (branch/tag/commit). - dev mode: Use
dev = truewithdir = '~/projects/plugin-name'for local development - optional: Use
optional = truefor dependencies that won't block plugin loading - module trigger: leanpack automatically supports require()-based lazy loading matching the auto-detected or explicit
mainmodule names.
- Inspired by lazy.nvim for the declarative spec design
